rusteerio 0.0.0-stage → 0.1.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 (206) hide show
  1. package/CONTRIBUTING.md +73 -0
  2. package/Cargo.lock +1051 -0
  3. package/Cargo.toml +36 -0
  4. package/LICENSE +21 -0
  5. package/README.md +252 -2
  6. package/RELEASING.md +138 -0
  7. package/THIRD_PARTY_NOTICES.md +7443 -0
  8. package/build.rs +3 -0
  9. package/dist/chunk-DKULX6VO.mjs +3185 -0
  10. package/dist/chunk-DKULX6VO.mjs.map +1 -0
  11. package/dist/chunk-OHPGEY3E.mjs +32 -0
  12. package/dist/chunk-OHPGEY3E.mjs.map +1 -0
  13. package/dist/index.cjs +3230 -0
  14. package/dist/index.cjs.map +1 -0
  15. package/dist/index.d.mts +113 -0
  16. package/dist/index.d.ts +113 -0
  17. package/dist/index.mjs +38 -0
  18. package/dist/index.mjs.map +1 -0
  19. package/dist/slim.cjs +2441 -0
  20. package/dist/slim.cjs.map +1 -0
  21. package/dist/slim.d.mts +11 -0
  22. package/dist/slim.d.ts +11 -0
  23. package/dist/slim.mjs +19 -0
  24. package/dist/slim.mjs.map +1 -0
  25. package/dist/types-BP6TpxE5.d.mts +532 -0
  26. package/dist/types-BP6TpxE5.d.ts +532 -0
  27. package/dist/utils.cjs +61 -0
  28. package/dist/utils.cjs.map +1 -0
  29. package/dist/utils.d.mts +13 -0
  30. package/dist/utils.d.ts +13 -0
  31. package/dist/utils.mjs +17 -0
  32. package/dist/utils.mjs.map +1 -0
  33. package/native/src/arena.rs +1781 -0
  34. package/native/src/attributes.rs +923 -0
  35. package/native/src/codec.rs +172 -0
  36. package/native/src/diagnostics.rs +1249 -0
  37. package/native/src/extraction.rs +226 -0
  38. package/native/src/gc.rs +166 -0
  39. package/native/src/hook_sink.rs +727 -0
  40. package/native/src/hook_stream.rs +513 -0
  41. package/native/src/lib.rs +2095 -0
  42. package/native/src/location.rs +392 -0
  43. package/native/src/runtime.rs +189 -0
  44. package/native/src/selector.rs +1287 -0
  45. package/native/src/sink.rs +261 -0
  46. package/native/src/stream.rs +334 -0
  47. package/native/src/tokenizer.rs +355 -0
  48. package/native/src/tracker.rs +232 -0
  49. package/native/vendor/README.md +25 -0
  50. package/native/vendor/html5ever-0.35.0/.cargo_vcs_info.json +6 -0
  51. package/native/vendor/html5ever-0.35.0/Cargo.lock +828 -0
  52. package/native/vendor/html5ever-0.35.0/Cargo.toml +85 -0
  53. package/native/vendor/html5ever-0.35.0/LICENSE-APACHE +201 -0
  54. package/native/vendor/html5ever-0.35.0/LICENSE-MIT +25 -0
  55. package/native/vendor/html5ever-0.35.0/README.md +60 -0
  56. package/native/vendor/html5ever-0.35.0/benches/html5ever.rs +86 -0
  57. package/native/vendor/html5ever-0.35.0/data/bench/lipsum-zh.html +19 -0
  58. package/native/vendor/html5ever-0.35.0/data/bench/lipsum.html +40 -0
  59. package/native/vendor/html5ever-0.35.0/data/bench/medium-fragment.html +24 -0
  60. package/native/vendor/html5ever-0.35.0/data/bench/small-fragment.html +7 -0
  61. package/native/vendor/html5ever-0.35.0/data/bench/strong.html +1 -0
  62. package/native/vendor/html5ever-0.35.0/data/bench/tiny-fragment.html +1 -0
  63. package/native/vendor/html5ever-0.35.0/examples/arena.rs +356 -0
  64. package/native/vendor/html5ever-0.35.0/examples/capi/tokenize.c +74 -0
  65. package/native/vendor/html5ever-0.35.0/examples/noop-tokenize.rs +47 -0
  66. package/native/vendor/html5ever-0.35.0/examples/noop-tree-builder.rs +132 -0
  67. package/native/vendor/html5ever-0.35.0/examples/print-tree-actions.rs +185 -0
  68. package/native/vendor/html5ever-0.35.0/examples/tokenize.rs +111 -0
  69. package/native/vendor/html5ever-0.35.0/src/driver.rs +148 -0
  70. package/native/vendor/html5ever-0.35.0/src/lib.rs +30 -0
  71. package/native/vendor/html5ever-0.35.0/src/macros.rs +34 -0
  72. package/native/vendor/html5ever-0.35.0/src/serialize/mod.rs +255 -0
  73. package/native/vendor/html5ever-0.35.0/src/tokenizer/char_ref/mod.rs +451 -0
  74. package/native/vendor/html5ever-0.35.0/src/tokenizer/interface.rs +99 -0
  75. package/native/vendor/html5ever-0.35.0/src/tokenizer/mod.rs +2305 -0
  76. package/native/vendor/html5ever-0.35.0/src/tokenizer/states.rs +97 -0
  77. package/native/vendor/html5ever-0.35.0/src/tree_builder/data.rs +170 -0
  78. package/native/vendor/html5ever-0.35.0/src/tree_builder/mod.rs +1848 -0
  79. package/native/vendor/html5ever-0.35.0/src/tree_builder/rules.rs +1494 -0
  80. package/native/vendor/html5ever-0.35.0/src/tree_builder/tag_sets.rs +114 -0
  81. package/native/vendor/html5ever-0.35.0/src/tree_builder/types.rs +91 -0
  82. package/native/vendor/html5ever-0.35.0/src/util/str.rs +52 -0
  83. package/native/vendor/html5gum-0.8.4/Cargo.lock +1006 -0
  84. package/native/vendor/html5gum-0.8.4/Cargo.toml +109 -0
  85. package/native/vendor/html5gum-0.8.4/LICENSE +19 -0
  86. package/native/vendor/html5gum-0.8.4/README.md +110 -0
  87. package/native/vendor/html5gum-0.8.4/benches/files/0050.html +2131 -0
  88. package/native/vendor/html5gum-0.8.4/benches/files/6D30.html +1004 -0
  89. package/native/vendor/html5gum-0.8.4/benches/files.rs +32 -0
  90. package/native/vendor/html5gum-0.8.4/benches/patterns.rs +31 -0
  91. package/native/vendor/html5gum-0.8.4/src/arrayvec.rs +29 -0
  92. package/native/vendor/html5gum-0.8.4/src/char_validator.rs +134 -0
  93. package/native/vendor/html5gum-0.8.4/src/emitters/callback.rs +676 -0
  94. package/native/vendor/html5gum-0.8.4/src/emitters/default.rs +207 -0
  95. package/native/vendor/html5gum-0.8.4/src/emitters/emitter.rs +344 -0
  96. package/native/vendor/html5gum-0.8.4/src/emitters/html5ever.rs +306 -0
  97. package/native/vendor/html5gum-0.8.4/src/emitters/mod.rs +25 -0
  98. package/native/vendor/html5gum-0.8.4/src/entities.rs +3342 -0
  99. package/native/vendor/html5gum-0.8.4/src/error.rs +96 -0
  100. package/native/vendor/html5gum-0.8.4/src/htmlstring.rs +130 -0
  101. package/native/vendor/html5gum-0.8.4/src/lib.rs +66 -0
  102. package/native/vendor/html5gum-0.8.4/src/machine.rs +2136 -0
  103. package/native/vendor/html5gum-0.8.4/src/machine_helper.rs +277 -0
  104. package/native/vendor/html5gum-0.8.4/src/read_helper.rs +244 -0
  105. package/native/vendor/html5gum-0.8.4/src/reader.rs +440 -0
  106. package/native/vendor/html5gum-0.8.4/src/span.rs +98 -0
  107. package/native/vendor/html5gum-0.8.4/src/state.rs +16 -0
  108. package/native/vendor/html5gum-0.8.4/src/testutils.rs +71 -0
  109. package/native/vendor/html5gum-0.8.4/src/tokenizer.rs +189 -0
  110. package/native/vendor/html5gum-0.8.4/src/utils.rs +88 -0
  111. package/native/vendor/markup5ever-0.35.0/.cargo_vcs_info.json +6 -0
  112. package/native/vendor/markup5ever-0.35.0/Cargo.toml +45 -0
  113. package/native/vendor/markup5ever-0.35.0/LICENSE-APACHE +201 -0
  114. package/native/vendor/markup5ever-0.35.0/LICENSE-MIT +25 -0
  115. package/native/vendor/markup5ever-0.35.0/interface/mod.rs +422 -0
  116. package/native/vendor/markup5ever-0.35.0/interface/tree_builder.rs +280 -0
  117. package/native/vendor/markup5ever-0.35.0/lib.rs +59 -0
  118. package/native/vendor/markup5ever-0.35.0/serialize.rs +77 -0
  119. package/native/vendor/markup5ever-0.35.0/util/buffer_queue.rs +333 -0
  120. package/native/vendor/markup5ever-0.35.0/util/smallcharset.rs +88 -0
  121. package/package.json +137 -4
  122. package/rusteerio.darwin-arm64.node +0 -0
  123. package/rusteerio.darwin-x64.node +0 -0
  124. package/rusteerio.linux-arm64-gnu.node +0 -0
  125. package/rusteerio.linux-arm64-musl.node +0 -0
  126. package/rusteerio.linux-x64-gnu.node +0 -0
  127. package/rusteerio.linux-x64-musl.node +0 -0
  128. package/rusteerio.win32-arm64-msvc.node +0 -0
  129. package/rusteerio.win32-x64-msvc.node +0 -0
  130. package/scripts/check-native.mjs +15 -0
  131. package/scripts/check-release.mjs +235 -0
  132. package/scripts/fix-declarations.mjs +27 -0
  133. package/scripts/generate-notices.mjs +176 -0
  134. package/scripts/notices/README.md +13 -0
  135. package/scripts/notices/cheerio-MIT.txt +21 -0
  136. package/scripts/notices/html5ever-AUTHORS.txt +20 -0
  137. package/scripts/notices/html5ever-COPYRIGHT.txt +8 -0
  138. package/scripts/notices/html5ever-LICENSE-APACHE.txt +201 -0
  139. package/scripts/notices/html5ever-LICENSE-MIT.txt +25 -0
  140. package/scripts/notices/napi-rs-MIT.txt +43 -0
  141. package/scripts/notices/neon-MIT.txt +19 -0
  142. package/scripts/notices/runtime-01c266bced4a434da005.txt +3 -0
  143. package/scripts/notices/runtime-0a54e647fe54104658b5.txt +14 -0
  144. package/scripts/notices/runtime-0b74dfa0bcee5c420c6b.txt +25 -0
  145. package/scripts/notices/runtime-0d542e0c8804e39aa7f3.txt +177 -0
  146. package/scripts/notices/runtime-0f96a83840e146e43c0e.txt +21 -0
  147. package/scripts/notices/runtime-123a331b5dbf04c30097.txt +25 -0
  148. package/scripts/notices/runtime-172020dbfd5b53a226df.txt +34 -0
  149. package/scripts/notices/runtime-209fbbe0ad52d9235e37.txt +26 -0
  150. package/scripts/notices/runtime-23f18e03dc49df91622f.txt +23 -0
  151. package/scripts/notices/runtime-268872b9816f90fd8e85.txt +220 -0
  152. package/scripts/notices/runtime-35242e7a83f69875e6ed.txt +176 -0
  153. package/scripts/notices/runtime-378f5840b258e2779c39.txt +25 -0
  154. package/scripts/notices/runtime-4108245a1f2df9d4e94d.txt +25 -0
  155. package/scripts/notices/runtime-4455bf75a91154108304.txt +21 -0
  156. package/scripts/notices/runtime-553fffcd9b1cb158bc3e.txt +13 -0
  157. package/scripts/notices/runtime-62c7a1e35f56406896d7.txt +176 -0
  158. package/scripts/notices/runtime-6485b8ed310d3f0340bf.txt +25 -0
  159. package/scripts/notices/runtime-69fef7b0f322a6555415.txt +201 -0
  160. package/scripts/notices/runtime-6df43f6f4b5d4587f3d8.txt +187 -0
  161. package/scripts/notices/runtime-799e9ca9d179295ef372.txt +24 -0
  162. package/scripts/notices/runtime-7b63ecd5f1902af1b637.txt +25 -0
  163. package/scripts/notices/runtime-7bc7d5de2a0b793d4e1a.txt +21 -0
  164. package/scripts/notices/runtime-7e12e5df4bae12cb2158.txt +24 -0
  165. package/scripts/notices/runtime-861399f8c21c042b1105.txt +12 -0
  166. package/scripts/notices/runtime-8ada45cd9f843acf64e4.txt +201 -0
  167. package/scripts/notices/runtime-90eb64f0279b0d9432ac.txt +12 -0
  168. package/scripts/notices/runtime-a60eea817514531668d7.txt +201 -0
  169. package/scripts/notices/runtime-a7c936ff1ed8fa340172.txt +25 -0
  170. package/scripts/notices/runtime-ab6eec6caf0fa5775e41.txt +275 -0
  171. package/scripts/notices/runtime-b1181a40b2a7b25cf66f.txt +19 -0
  172. package/scripts/notices/runtime-b71bd43a069ca0641a9e.txt +25 -0
  173. package/scripts/notices/runtime-c16f8dcf1a368b83be78.txt +201 -0
  174. package/scripts/notices/runtime-c2cfccb812fe482101a8.txt +21 -0
  175. package/scripts/notices/runtime-e99d88d232bf57d70f0f.txt +25 -0
  176. package/scripts/notices/runtime-f32fb3b417a194167cfa.txt +9 -0
  177. package/scripts/notices/runtime-f5062c9a188d81dfe66b.txt +39 -0
  178. package/scripts/notices/runtime-f9070a832833fa7488fd.txt +4 -0
  179. package/scripts/notices/runtime-fab3dd6bdab226f1c086.txt +373 -0
  180. package/scripts/notices/runtime-fba3318d0c600380177e.txt +62 -0
  181. package/scripts/notices/runtime-ff8f68cb076caf8cefe7.txt +25 -0
  182. package/scripts/notices/runtime-ff92bed461f50338dd70.txt +74 -0
  183. package/scripts/notices/runtime.json +1632 -0
  184. package/scripts/notices/sources.json +555 -0
  185. package/scripts/notices/xray-MIT.txt +21 -0
  186. package/src/attributes.ts +271 -0
  187. package/src/codec.ts +74 -0
  188. package/src/dom.ts +87 -0
  189. package/src/extract-plan.ts +97 -0
  190. package/src/extract.ts +130 -0
  191. package/src/hooks.ts +220 -0
  192. package/src/index.ts +223 -0
  193. package/src/io.ts +491 -0
  194. package/src/native.ts +135 -0
  195. package/src/nodes.ts +290 -0
  196. package/src/parse.ts +53 -0
  197. package/src/parser-types.ts +157 -0
  198. package/src/router.ts +327 -0
  199. package/src/selection.ts +566 -0
  200. package/src/slim.ts +12 -0
  201. package/src/transport.ts +104 -0
  202. package/src/types.ts +186 -0
  203. package/src/utils.ts +29 -0
  204. package/src/workers.ts +21 -0
  205. package/tsconfig.json +15 -0
  206. package/tsup.config.ts +16 -0
@@ -0,0 +1,3185 @@
1
+ import {
2
+ isHtml
3
+ } from "./chunk-OHPGEY3E.mjs";
4
+
5
+ // src/native.ts
6
+ import { createRequire } from "module";
7
+ import { existsSync } from "fs";
8
+ import { dirname, join } from "path";
9
+ import { fileURLToPath } from "url";
10
+
11
+ // src/codec.ts
12
+ var reserved = /[\ud800-\ue800]/;
13
+ var encoded = /[\ue000-\ue800]/;
14
+ var escapeUnit = 59392;
15
+ var isWellFormed = String.prototype.isWellFormed;
16
+ function encodeString(value) {
17
+ if (!encoded.test(value) && (isWellFormed ? isWellFormed.call(value) : !reserved.test(value))) return value;
18
+ const parts = [];
19
+ let start = 0;
20
+ for (let index = 0; index < value.length; index++) {
21
+ const unit = value.charCodeAt(index);
22
+ if (unit >= 55296 && unit <= 56319) {
23
+ const next = value.charCodeAt(index + 1);
24
+ if (next >= 56320 && next <= 57343) {
25
+ index++;
26
+ continue;
27
+ }
28
+ }
29
+ let replacement;
30
+ if (unit >= 55296 && unit <= 57343) replacement = String.fromCharCode(57344 + unit - 55296);
31
+ else if (unit >= 57344 && unit <= escapeUnit) replacement = "\uE800" + value[index];
32
+ if (replacement !== void 0) {
33
+ parts.push(value.slice(start, index), replacement);
34
+ start = index + 1;
35
+ }
36
+ }
37
+ return start === 0 ? value : parts.join("") + value.slice(start);
38
+ }
39
+ function decodeString(value) {
40
+ if (!encoded.test(value)) return value;
41
+ const parts = [];
42
+ let start = 0;
43
+ for (let index = 0; index < value.length; index++) {
44
+ const unit = value.charCodeAt(index);
45
+ if (unit < 57344 || unit > escapeUnit) continue;
46
+ const next = value.charCodeAt(index + 1);
47
+ if (unit === escapeUnit) {
48
+ if (next < 57344 || next > escapeUnit || Number.isNaN(next)) continue;
49
+ parts.push(value.slice(start, index), value[++index]);
50
+ } else parts.push(value.slice(start, index), String.fromCharCode(55296 + unit - 57344));
51
+ start = index + 1;
52
+ }
53
+ return start === 0 ? value : parts.join("") + value.slice(start);
54
+ }
55
+ var stringToken = /"(?:[^"\\]|\\[\s\S])*"/g;
56
+ var encodeJsonCandidate = /[\ud800-\ue800]|\\u(?:d[89a-f][\da-f]{2}|e[0-8][\da-f]{2})/i;
57
+ var escapedJsonCandidate = /\\u(?:d[89a-f][\da-f]{2}|e[0-8][\da-f]{2})/i;
58
+ var decodeJsonCandidate = /[\ue000-\ue800]|\\ue[0-8][\da-f]{2}/i;
59
+ function encodeJson(value) {
60
+ if (!encodeJsonCandidate.test(value)) return value;
61
+ if (isWellFormed?.call(value) && !encoded.test(value) && !escapedJsonCandidate.test(value)) return value;
62
+ return value.replace(stringToken, (token) => JSON.stringify(encodeString(JSON.parse(token))));
63
+ }
64
+ function decodeJson(value) {
65
+ return decodeJsonCandidate.test(value) ? value.replace(stringToken, (token) => JSON.stringify(decodeString(JSON.parse(token)))) : value;
66
+ }
67
+ function encodeOptions(value) {
68
+ if (value === void 0) return '{"__utf16Codec":true}';
69
+ const json = encodeJson(value);
70
+ if (!json.trimStart().startsWith("{")) return '{"__utf16Codec":true}';
71
+ const end = json.lastIndexOf("}");
72
+ const prefix = json.slice(0, end);
73
+ return prefix + (prefix.trimEnd().endsWith("{") ? "" : ",") + '"__utf16Codec":true' + json.slice(end);
74
+ }
75
+
76
+ // src/transport.ts
77
+ var registryKey = /* @__PURE__ */ Symbol.for("rusteerio.native-transport.v1");
78
+ var globals = globalThis;
79
+ var registry = globals[registryKey] ??= { documents: /* @__PURE__ */ new WeakMap(), originals: /* @__PURE__ */ new WeakMap(), userErrors: /* @__PURE__ */ new WeakSet() };
80
+ function wrapNativeBinding(binding) {
81
+ const raw = binding;
82
+ const { documents, originals, userErrors } = registry;
83
+ const restoreError = (error) => {
84
+ if (error instanceof Error && !userErrors.has(error)) {
85
+ const message = decodeString(error.message);
86
+ if (message !== error.message) {
87
+ const stack = error.stack;
88
+ error.message = message;
89
+ if (stack) error.stack = decodeString(stack);
90
+ }
91
+ }
92
+ throw error;
93
+ };
94
+ const invoke = (call) => {
95
+ try {
96
+ const result = call();
97
+ return result instanceof Promise ? result.catch(restoreError) : result;
98
+ } catch (error) {
99
+ return restoreError(error);
100
+ }
101
+ };
102
+ const wrapBridge = (bridge) => (request) => {
103
+ try {
104
+ return encodeJson(bridge(decodeJson(request)));
105
+ } catch (error) {
106
+ if (error !== null && (typeof error === "object" || typeof error === "function")) userErrors.add(error);
107
+ throw error;
108
+ }
109
+ };
110
+ const jsonMethods = /* @__PURE__ */ new Set(["op", "node", "exportTree", "parserDiagnostics", "adopt"]);
111
+ const wrapDocument = (document) => {
112
+ const cached2 = documents.get(document);
113
+ if (cached2) return cached2;
114
+ const methods = /* @__PURE__ */ new Map();
115
+ const wrapped2 = new Proxy(document, {
116
+ get(target, property2) {
117
+ const value = Reflect.get(target, property2, target);
118
+ if (typeof value !== "function") return value;
119
+ if (property2 === "constructor") return value;
120
+ if (methods.has(property2)) return methods.get(property2);
121
+ const method = (...input) => invoke(() => {
122
+ const args = input.slice();
123
+ if (property2 === "op") args[1] = encodeJson(args[1]);
124
+ else if (property2 === "create") {
125
+ args[0] = encodeString(args[0]);
126
+ if (typeof args[2] === "string") args[2] = encodeOptions(args[2]);
127
+ } else if (property2 === "select" || property2 === "matches") args[0] = encodeString(args[0]);
128
+ else if (property2 === "attr") args[1] = encodeString(args[1]);
129
+ else if (property2 === "adopt") args[0] = originals.get(args[0]) ?? args[0];
130
+ const result = Reflect.apply(value, target, args);
131
+ if (property2 === "op" && args[0] === "serialize" && typeof result === "string" && result.startsWith("{")) {
132
+ const error = JSON.parse(result).__nativeError;
133
+ if (error?.name === "URIError") throw new URIError(error.message);
134
+ }
135
+ return typeof result === "string" ? jsonMethods.has(String(property2)) ? decodeJson(result) : decodeString(result) : result;
136
+ });
137
+ methods.set(property2, method);
138
+ return method;
139
+ }
140
+ });
141
+ documents.set(document, wrapped2);
142
+ originals.set(wrapped2, document);
143
+ return wrapped2;
144
+ };
145
+ const wrapStream = (stream) => {
146
+ let carry = "";
147
+ return {
148
+ async write(chunk) {
149
+ let source = carry + chunk;
150
+ carry = "";
151
+ const last = source.charCodeAt(source.length - 1);
152
+ if (last >= 55296 && last <= 56319) {
153
+ carry = source.slice(-1);
154
+ source = source.slice(0, -1);
155
+ }
156
+ if (source) await invoke(() => stream.write(encodeString(source)));
157
+ },
158
+ async finish() {
159
+ if (carry) {
160
+ const final = carry;
161
+ carry = "";
162
+ await invoke(() => stream.write(encodeString(final)));
163
+ }
164
+ return wrapDocument(await invoke(() => stream.finish()));
165
+ },
166
+ abort() {
167
+ carry = "";
168
+ return invoke(() => stream.abort());
169
+ }
170
+ };
171
+ };
172
+ const wrapConstructor = (Constructor, argumentsFor, wrap) => new Proxy(Constructor, {
173
+ construct(target, args) {
174
+ return wrap(invoke(() => Reflect.construct(target, argumentsFor(args))));
175
+ }
176
+ });
177
+ const wrapped = { ...raw };
178
+ wrapped.NativeDocument = wrapConstructor(raw.NativeDocument, ([html, isDocument2, options]) => [encodeString(html), isDocument2, encodeOptions(options)], wrapDocument);
179
+ if (raw.NativeStream) wrapped.NativeStream = wrapConstructor(raw.NativeStream, ([options, isDocument2, bridge]) => [encodeOptions(options), isDocument2, bridge && wrapBridge(bridge)], wrapStream);
180
+ if (raw.NativeHookStream) wrapped.NativeHookStream = wrapConstructor(raw.NativeHookStream, ([isDocument2, options, bridge]) => [isDocument2, encodeOptions(options), wrapBridge(bridge)], wrapStream);
181
+ if (raw.parseWithTreeAdapter) wrapped.parseWithTreeAdapter = (source, isDocument2, options, bridge) => wrapDocument(invoke(() => raw.parseWithTreeAdapter(encodeString(source), isDocument2, encodeOptions(options), wrapBridge(bridge))));
182
+ if (raw.parseAsync) wrapped.parseAsync = async (source, isDocument2, options) => wrapDocument(await invoke(() => raw.parseAsync(encodeString(source), isDocument2, encodeOptions(options))));
183
+ if (raw.parseManyAsync) wrapped.parseManyAsync = async (sources, isDocument2, threads, options) => (await invoke(() => raw.parseManyAsync(sources.map(encodeString), isDocument2, threads, encodeOptions(options)))).map(wrapDocument);
184
+ if (raw.extractPlanManyAsync) wrapped.extractPlanManyAsync = async (sources, plan, threads, options) => decodeJson(await invoke(() => raw.extractPlanManyAsync(sources.map(encodeString), encodeJson(plan), threads, encodeOptions(options))));
185
+ if (raw.extractManyAsync) wrapped.extractManyAsync = async (sources, queries, threads, isDocument2, options) => decodeJson(await invoke(() => raw.extractManyAsync(sources.map(encodeString), queries.map((query) => ({ ...query, key: encodeString(query.key), selector: encodeString(query.selector), ...query.attr === void 0 ? {} : { attr: encodeString(query.attr) } })), threads, isDocument2, encodeOptions(options))));
186
+ return wrapped;
187
+ }
188
+
189
+ // src/native.ts
190
+ var cached;
191
+ var attempted = false;
192
+ var bindingError;
193
+ function nativeBinding() {
194
+ if (attempted) return cached;
195
+ attempted = true;
196
+ const moduleDirectory = typeof __dirname === "string" ? __dirname : dirname(fileURLToPath(import.meta.url));
197
+ const require2 = createRequire(join(moduleDirectory, "rusteerio-loader.cjs"));
198
+ const directories = [moduleDirectory, dirname(moduleDirectory)];
199
+ const libc = process.platform === "linux" ? process.report?.getReport()?.header?.glibcVersionRuntime ? "gnu" : "musl" : void 0;
200
+ const platform = `${process.platform}-${process.arch}${libc ? `-${libc}` : process.platform === "win32" ? "-msvc" : ""}`;
201
+ const names = [`rusteerio.${platform}.node`, "rusteerio.node"];
202
+ const candidates = [...new Set(directories.flatMap((directory) => names.map((name) => join(directory, name))))];
203
+ for (const candidate of candidates) {
204
+ if (!existsSync(candidate)) continue;
205
+ try {
206
+ const loaded = require2(candidate);
207
+ if (typeof loaded.NativeDocument === "function") {
208
+ cached = wrapNativeBinding(loaded);
209
+ return cached;
210
+ }
211
+ } catch (error) {
212
+ bindingError ??= error;
213
+ }
214
+ }
215
+ return void 0;
216
+ }
217
+ function requireNative() {
218
+ const binding = nativeBinding();
219
+ if (binding) return binding;
220
+ throw new Error('Rusteerio could not load its Rust native binding. Reinstall rusteerio for this platform or run "npm run build:native" from a source checkout.', { cause: bindingError });
221
+ }
222
+ function nativeStatus() {
223
+ const available = !!nativeBinding();
224
+ return available ? { available } : { available, error: String(bindingError ?? "Native binding not found") };
225
+ }
226
+
227
+ // src/hooks.ts
228
+ var tokenCallbacks = ["onattribdata", "onattribentity", "onattribend", "onattribname", "oncdata", "onclosetag", "oncomment", "ondeclaration", "onend", "onopentagend", "onopentagname", "onprocessinginstruction", "onselfclosingtag", "ontext", "ontextentity"];
229
+ function createTokenizerSession(options) {
230
+ const events = [];
231
+ const callbacks = Object.fromEntries(tokenCallbacks.map((name) => [name, (...args) => {
232
+ if (name === "ontextentity" || name === "onattribentity") {
233
+ const codePoint = +args[0];
234
+ String.fromCodePoint(codePoint);
235
+ args[0] = codePoint;
236
+ }
237
+ events.push([name, ...args]);
238
+ }]));
239
+ const Constructor = options.Tokenizer;
240
+ const tokenizer = new Constructor(options, callbacks);
241
+ return {
242
+ write(chunk) {
243
+ if (tokenizer.running) tokenizer.write(chunk);
244
+ },
245
+ end() {
246
+ tokenizer.end();
247
+ const result = cleanParserOptions(options);
248
+ result.__tokenEvents = events;
249
+ return result;
250
+ }
251
+ };
252
+ }
253
+ function cleanParserOptions(options) {
254
+ const result = { ...options };
255
+ delete result.Tokenizer;
256
+ delete result.treeAdapter;
257
+ delete result.onParseError;
258
+ delete result.__tokenEvents;
259
+ if (!options._useHtmlParser2 && options.onParseError) {
260
+ result.__collectParseErrors = true;
261
+ result.sourceCodeLocationInfo = true;
262
+ }
263
+ return result;
264
+ }
265
+ function parserOptions(source, options) {
266
+ if (options._useHtmlParser2 && options.Tokenizer) {
267
+ const session = createTokenizerSession(options);
268
+ session.write(source);
269
+ return session.end();
270
+ }
271
+ return cleanParserOptions(options);
272
+ }
273
+ function deliverParseErrors(document, options) {
274
+ if (options._useHtmlParser2 || !options.onParseError) return;
275
+ const diagnostics = document.parserDiagnostics?.();
276
+ const errors = typeof diagnostics === "string" ? JSON.parse(diagnostics) : diagnostics ?? [];
277
+ for (const error of errors) options.onParseError(error);
278
+ }
279
+ function hasParserHooks(options) {
280
+ return !!(options._useHtmlParser2 ? options.Tokenizer : options.treeAdapter || options.onParseError);
281
+ }
282
+ function treeAdapterBridge(adapter, options) {
283
+ const deliveredErrors = /* @__PURE__ */ new Set();
284
+ const nodes = [];
285
+ const ids = /* @__PURE__ */ new WeakMap();
286
+ const identify = (node) => {
287
+ if (node == null) return null;
288
+ if (typeof node !== "object") throw new TypeError("treeAdapter methods must return DOM node objects");
289
+ let id = ids.get(node);
290
+ if (id === void 0) {
291
+ id = nodes.length;
292
+ ids.set(node, id);
293
+ nodes.push(node);
294
+ }
295
+ return id;
296
+ };
297
+ const nodeArgs = {
298
+ appendChild: [0, 1],
299
+ insertBefore: [0, 1, 2],
300
+ setTemplateContent: [0, 1],
301
+ getTemplateContent: [0],
302
+ setDocumentType: [0],
303
+ setDocumentMode: [0],
304
+ getDocumentMode: [0],
305
+ detachNode: [0],
306
+ insertText: [0],
307
+ insertTextBefore: [0, 2],
308
+ adoptAttributes: [0],
309
+ getFirstChild: [0],
310
+ getChildNodes: [0],
311
+ getParentNode: [0],
312
+ getAttrList: [0],
313
+ getTagName: [0],
314
+ getNamespaceURI: [0],
315
+ getTextNodeContent: [0],
316
+ getCommentNodeContent: [0],
317
+ getDocumentTypeNodeName: [0],
318
+ getDocumentTypeNodePublicId: [0],
319
+ getDocumentTypeNodeSystemId: [0],
320
+ isTextNode: [0],
321
+ isCommentNode: [0],
322
+ isElementNode: [0],
323
+ isDocumentTypeNode: [0],
324
+ setNodeSourceCodeLocation: [0],
325
+ getNodeSourceCodeLocation: [0],
326
+ updateNodeSourceCodeLocation: [0],
327
+ onItemPop: [0, 1],
328
+ onItemPush: [0]
329
+ };
330
+ const nodeReturns = /* @__PURE__ */ new Set(["createDocument", "createDocumentFragment", "createElement", "createCommentNode", "createTextNode", "getTemplateContent", "getFirstChild", "getParentNode"]);
331
+ const invoke = (method, args) => {
332
+ const fn = adapter[method];
333
+ if (typeof fn !== "function") {
334
+ if (method === "onItemPop" || method === "onItemPush") return void 0;
335
+ throw new TypeError(`treeAdapter.${method} must be a function`);
336
+ }
337
+ return Reflect.apply(fn, adapter, args);
338
+ };
339
+ const snapshot = () => {
340
+ const records = [];
341
+ for (let id = 0; id < nodes.length; id++) {
342
+ const node = nodes[id];
343
+ const element = invoke("isElementNode", [node]);
344
+ const text = invoke("isTextNode", [node]);
345
+ const comment = invoke("isCommentNode", [node]);
346
+ const doctype = invoke("isDocumentTypeNode", [node]);
347
+ const name = element ? invoke("getTagName", [node]) : doctype ? "!doctype" : node.name;
348
+ const type = element ? name === "script" || name === "style" ? name : "tag" : text ? "text" : comment ? "comment" : doctype ? "directive" : node.type ?? "root";
349
+ const children2 = element || type === "root" || type === "cdata" ? invoke("getChildNodes", [node]) ?? [] : [];
350
+ const record = { id, type, children: Array.from(children2, identify), parent: identify(invoke("getParentNode", [node])) };
351
+ if (name !== void 0) record.name = name;
352
+ if (element) {
353
+ record.namespace = invoke("getNamespaceURI", [node]);
354
+ record.attribs = /* @__PURE__ */ Object.create(null);
355
+ record.attribsNamespace = /* @__PURE__ */ Object.create(null);
356
+ record.attribsPrefix = /* @__PURE__ */ Object.create(null);
357
+ for (const attr2 of invoke("getAttrList", [node])) {
358
+ Object.defineProperty(record.attribs, attr2.name, { value: attr2.value, enumerable: true, configurable: true, writable: true });
359
+ record.attribsNamespace[attr2.name] = attr2.namespace;
360
+ record.attribsPrefix[attr2.name] = attr2.prefix;
361
+ }
362
+ } else if (text || comment) record.data = invoke(text ? "getTextNodeContent" : "getCommentNodeContent", [node]);
363
+ else if (doctype) {
364
+ record.data = node.data;
365
+ for (const [field, method] of [["x-name", "getDocumentTypeNodeName"], ["x-publicId", "getDocumentTypeNodePublicId"], ["x-systemId", "getDocumentTypeNodeSystemId"]]) record[field] = invoke(method, [node]);
366
+ }
367
+ if (type === "root" && node["x-mode"] !== void 0) record["x-mode"] = invoke("getDocumentMode", [node]);
368
+ for (const field of ["startIndex", "endIndex", "sourceCodeLocation"]) if (node[field] !== void 0) record[field] = node[field];
369
+ records.push(record);
370
+ }
371
+ return records;
372
+ };
373
+ const bridge = (request) => {
374
+ const { method, args = [] } = JSON.parse(request);
375
+ if (method === "__parseError") {
376
+ deliveredErrors.add(JSON.stringify(args[0]));
377
+ options.onParseError?.(args[0]);
378
+ return "null";
379
+ }
380
+ if (method === "__snapshot") return JSON.stringify(snapshot());
381
+ if (method === "__locations") {
382
+ for (const entry of args[0]) invoke("setNodeSourceCodeLocation", [nodes[entry.id], hydrateLocation(entry.location)]);
383
+ return "null";
384
+ }
385
+ const values = args.slice();
386
+ if (method === "setNodeSourceCodeLocation" || method === "updateNodeSourceCodeLocation") hydrateLocation(values[1]);
387
+ for (const index of nodeArgs[method] ?? []) values[index] = values[index] == null ? null : nodes[values[index]];
388
+ const result = invoke(method, values);
389
+ return JSON.stringify(method === "getChildNodes" ? Array.from(result ?? [], identify) : nodeReturns.has(method) ? identify(result) : result ?? null);
390
+ };
391
+ return { bridge, nodes, deliveredErrors };
392
+ }
393
+ function bindAdapterDocument(document, options, adapter) {
394
+ if (options.onParseError) {
395
+ const errors = document.parserDiagnostics?.();
396
+ for (const error of errors ? JSON.parse(errors) : []) if (!adapter.deliveredErrors.has(JSON.stringify(error))) options.onParseError(error);
397
+ }
398
+ const routed = routeDocument(document, options);
399
+ const globalId = routed.localNodeId.bind(routed);
400
+ for (let id = 0; id < adapter.nodes.length; id++) getNode(routed, globalId(id), adapter.nodes[id]);
401
+ return routed;
402
+ }
403
+ function createTreeAdapterSession(options, isDocument2) {
404
+ const binding = requireNative();
405
+ if (!binding.NativeHookStream) throw new Error("This native addon does not support streaming treeAdapter hooks; rebuild the Rust addon.");
406
+ const adapter = treeAdapterBridge(options.treeAdapter, options);
407
+ let hasFailure = false;
408
+ let failure;
409
+ let aborted = false;
410
+ const bridge = (request) => {
411
+ if (hasFailure || aborted) return '{"__rusteerioHookError":true}';
412
+ try {
413
+ return adapter.bridge(request);
414
+ } catch (error) {
415
+ hasFailure = true;
416
+ failure = error;
417
+ return '{"__rusteerioHookError":true}';
418
+ }
419
+ };
420
+ const parser = new binding.NativeHookStream(isDocument2, JSON.stringify(cleanParserOptions(options)), bridge);
421
+ const restoreFailure = (error) => {
422
+ if (hasFailure) throw failure;
423
+ throw error;
424
+ };
425
+ return {
426
+ async write(chunk) {
427
+ try {
428
+ await parser.write(chunk);
429
+ if (hasFailure) throw failure;
430
+ } catch (error) {
431
+ restoreFailure(error);
432
+ }
433
+ },
434
+ async end() {
435
+ try {
436
+ const document = await parser.finish();
437
+ if (hasFailure) throw failure;
438
+ return bindAdapterDocument(document, options, adapter);
439
+ } catch (error) {
440
+ return restoreFailure(error);
441
+ }
442
+ },
443
+ abort() {
444
+ aborted = true;
445
+ parser.abort();
446
+ }
447
+ };
448
+ }
449
+ function parseNativeDocument(source, options, isDocument2) {
450
+ const binding = requireNative();
451
+ const nativeOptions = parserOptions(source, options);
452
+ if (!options._useHtmlParser2 && options.treeAdapter) {
453
+ const parse2 = binding.parseWithTreeAdapter;
454
+ if (!parse2) throw new Error("This native addon does not support treeAdapter hooks; rebuild the Rust addon.");
455
+ const adapter = treeAdapterBridge(options.treeAdapter, options);
456
+ return bindAdapterDocument(parse2(source, isDocument2, JSON.stringify(nativeOptions), adapter.bridge), options, adapter);
457
+ }
458
+ const document = new binding.NativeDocument(source, isDocument2, JSON.stringify(nativeOptions));
459
+ deliverParseErrors(document, options);
460
+ return routeDocument(document, options);
461
+ }
462
+ function createDiagnosticSession(options, isDocument2 = true) {
463
+ const binding = requireNative();
464
+ if (!binding.NativeStream) throw new Error("This native addon does not support incremental parser diagnostics; rebuild the Rust addon.");
465
+ let hasFailure = false;
466
+ let failure;
467
+ let aborted = false;
468
+ const bridge = (request) => {
469
+ if (hasFailure || aborted) return '{"__rusteerioHookError":true}';
470
+ try {
471
+ const { method, args } = JSON.parse(request);
472
+ if (method === "__parseError") options.onParseError?.(args[0]);
473
+ return "null";
474
+ } catch (error) {
475
+ hasFailure = true;
476
+ failure = error;
477
+ return '{"__rusteerioHookError":true}';
478
+ }
479
+ };
480
+ const parser = new binding.NativeStream(JSON.stringify(cleanParserOptions(options)), isDocument2, bridge);
481
+ const restoreFailure = (error) => {
482
+ if (hasFailure) throw failure;
483
+ throw error;
484
+ };
485
+ return {
486
+ async write(chunk) {
487
+ try {
488
+ await parser.write(chunk);
489
+ if (hasFailure) throw failure;
490
+ } catch (error) {
491
+ restoreFailure(error);
492
+ }
493
+ },
494
+ async end() {
495
+ try {
496
+ const document = await parser.finish();
497
+ if (hasFailure) throw failure;
498
+ return routeDocument(document, options);
499
+ } catch (error) {
500
+ return restoreFailure(error);
501
+ }
502
+ },
503
+ abort() {
504
+ aborted = true;
505
+ parser.abort();
506
+ }
507
+ };
508
+ }
509
+
510
+ // src/router.ts
511
+ var registryKey2 = /* @__PURE__ */ Symbol.for("rusteerio.native-handles.v2");
512
+ var globals2 = globalThis;
513
+ var registry2 = globals2[registryKey2] ??= (() => {
514
+ const handles = /* @__PURE__ */ new Map();
515
+ const byDocument = /* @__PURE__ */ new WeakMap();
516
+ const snapshots = /* @__PURE__ */ new WeakMap();
517
+ const pending = [];
518
+ let scheduled = false;
519
+ const flush = () => {
520
+ scheduled = false;
521
+ const batches = /* @__PURE__ */ new Map();
522
+ for (const pin of pending.splice(0)) {
523
+ const document = pin.document.deref();
524
+ if (!document) continue;
525
+ const entries = byDocument.get(document);
526
+ if (entries?.get(pin.local)?.pin === pin) entries.delete(pin.local);
527
+ const ids = batches.get(document) ?? [];
528
+ ids.push(pin.local);
529
+ batches.set(document, ids);
530
+ }
531
+ for (const [document, ids] of batches) {
532
+ snapshots.delete(document);
533
+ document.release?.(ids);
534
+ document.collectGarbage?.();
535
+ }
536
+ };
537
+ return { next: 1, space: {}, handles, byDocument, snapshots, finalizer: new FinalizationRegistry((pin) => {
538
+ if (!handles.get(pin.global)?.deref()) handles.delete(pin.global);
539
+ pending.push(pin);
540
+ if (!scheduled) {
541
+ scheduled = true;
542
+ queueMicrotask(flush);
543
+ }
544
+ }) };
545
+ })();
546
+ function rawOperation(document, command, args) {
547
+ const result = document.op(command, JSON.stringify(args));
548
+ return result === "" || result === void 0 ? void 0 : JSON.parse(result);
549
+ }
550
+ function localMap(document) {
551
+ let map = registry2.byDocument.get(document);
552
+ if (!map) registry2.byDocument.set(document, map = /* @__PURE__ */ new Map());
553
+ return map;
554
+ }
555
+ function handleFor(document, local) {
556
+ const map = localMap(document);
557
+ let handle = map.get(local)?.reference.deref();
558
+ if (!handle || handle.document !== document || handle.local !== local) {
559
+ const pin = { global: registry2.next++, document: new WeakRef(document), local };
560
+ handle = { global: pin.global, document, local, pin };
561
+ document.retain?.([local]);
562
+ const reference = new WeakRef(handle);
563
+ map.set(local, { reference, pin });
564
+ registry2.handles.set(handle.global, reference);
565
+ registry2.finalizer.register(handle, pin);
566
+ }
567
+ return handle;
568
+ }
569
+ function retainNodes(document, ids) {
570
+ return document.retainNodes?.(ids) ?? {};
571
+ }
572
+ var RoutedDocument = class _RoutedDocument {
573
+ nodeSpace = registry2.space;
574
+ options;
575
+ anchor;
576
+ get raw() {
577
+ return this.anchor.document;
578
+ }
579
+ constructor(document, options = {}, anchor) {
580
+ this.options = options;
581
+ this.anchor = anchor ?? handleFor(document, document.rootId());
582
+ }
583
+ keep(handle) {
584
+ return handle.global;
585
+ }
586
+ lookup(id) {
587
+ const handle = registry2.handles.get(id)?.deref();
588
+ if (!handle) throw new RangeError(`Unknown native node handle ${id}`);
589
+ return handle;
590
+ }
591
+ global(document, local) {
592
+ return this.keep(handleFor(document, local));
593
+ }
594
+ globals(document, ids) {
595
+ return ids.map((id) => this.global(document, id));
596
+ }
597
+ retainNode(id) {
598
+ this.lookup(id);
599
+ }
600
+ retainNodes(ids) {
601
+ return ids.filter((id) => id !== void 0).map((id) => this.lookup(id));
602
+ }
603
+ nodeDocument(id) {
604
+ return new _RoutedDocument(this.raw, this.options, this.lookup(id));
605
+ }
606
+ collectGarbage() {
607
+ registry2.snapshots.delete(this.raw);
608
+ return this.raw.collectGarbage?.();
609
+ }
610
+ retainNodeData(id, data2) {
611
+ this.lookup(id).data = data2;
612
+ }
613
+ nodeData(id) {
614
+ return this.lookup(id).data;
615
+ }
616
+ nodeDataOperation(id) {
617
+ const handle = this.lookup(id);
618
+ const options = this.options;
619
+ return (command, args) => rawOperation(handle.document, command, { ...args, ids: [handle.local], options });
620
+ }
621
+ localNodeId(id) {
622
+ return this.global(this.raw, id);
623
+ }
624
+ rootId() {
625
+ return this.global(this.raw, this.raw.rootId());
626
+ }
627
+ record(document, record) {
628
+ if (!record) return null;
629
+ const view = { ...record, id: this.global(document, record.id) };
630
+ Object.defineProperty(view, "children", { enumerable: true, get: () => this.globals(document, record.children ?? []) });
631
+ for (const key of ["parent", "prev", "next"]) Object.defineProperty(view, key, { enumerable: true, get: () => record[key] == null ? null : this.global(document, record[key]) });
632
+ return view;
633
+ }
634
+ groups(ids) {
635
+ const groups = [];
636
+ for (const id of ids) {
637
+ const handle = this.lookup(id);
638
+ const last = groups[groups.length - 1];
639
+ if (last?.document === handle.document) {
640
+ last.ids.push(handle.local);
641
+ last.global.push(id);
642
+ } else groups.push({ document: handle.document, ids: [handle.local], global: [id] });
643
+ }
644
+ return groups;
645
+ }
646
+ call(document, command, args) {
647
+ if (command === "extractPlan" && JSON.stringify(args.plan).includes("innerHTML")) registry2.snapshots.delete(document);
648
+ if (Object.hasOwn(args, "value") || ["create", "createNode", "setNode", "import", "insert", "clone", "remove", "removeAttr", "removeData", "addClass", "removeClass", "toggleClass"].includes(command)) registry2.snapshots.delete(document);
649
+ return rawOperation(document, command, { ...args, options: args.options ?? this.options });
650
+ }
651
+ move(target, ids, copy = false) {
652
+ if (!copy) {
653
+ const groups = /* @__PURE__ */ new Map();
654
+ for (const id of ids) {
655
+ const handle = this.lookup(id);
656
+ const group = groups.get(handle.document) ?? [];
657
+ group.push(handle);
658
+ groups.set(handle.document, group);
659
+ }
660
+ for (const [source, handles] of groups) {
661
+ if (source === target) continue;
662
+ if (!target.adopt) throw new Error("The native addon does not support cross-document adoption. Rebuild the Rust addon.");
663
+ registry2.snapshots.delete(source);
664
+ registry2.snapshots.delete(target);
665
+ const adopted = JSON.parse(target.adopt(source, handles.map((handle) => handle.local), true));
666
+ for (const [oldLocal, newLocal] of adopted.mapping) {
667
+ const entry = localMap(source).get(oldLocal);
668
+ if (!entry) continue;
669
+ const handle = entry.reference.deref();
670
+ if (handle && (handle.document !== source || handle.local !== oldLocal)) continue;
671
+ localMap(source).delete(oldLocal);
672
+ entry.pin.document = new WeakRef(target);
673
+ entry.pin.local = newLocal;
674
+ if (handle) {
675
+ handle.document = target;
676
+ handle.local = newLocal;
677
+ }
678
+ localMap(target).set(newLocal, entry);
679
+ }
680
+ }
681
+ return ids.map((id) => this.lookup(id).local);
682
+ }
683
+ const result = [];
684
+ for (const group of this.groups(ids)) {
685
+ if (copy && group.document === target) {
686
+ result.push(...this.call(target, "clone", { ids: group.ids, deep: true }));
687
+ continue;
688
+ }
689
+ if (!target.adopt) throw new Error("The native addon does not support cross-document adoption. Rebuild the Rust addon.");
690
+ registry2.snapshots.delete(target);
691
+ const adopted = JSON.parse(target.adopt(group.document, group.ids, !copy));
692
+ result.push(...adopted.roots);
693
+ }
694
+ return result;
695
+ }
696
+ scratch(command, args, ids) {
697
+ const documents = [...new Set(ids.map((id) => this.lookup(id).document))];
698
+ const scratch = new (requireNative()).NativeDocument("", false, JSON.stringify(args.options ?? this.options));
699
+ const toScratch = /* @__PURE__ */ new Map();
700
+ const fromScratch = /* @__PURE__ */ new Map();
701
+ for (const document of documents) {
702
+ const records = JSON.parse(document.exportTree());
703
+ const roots = records.filter((record) => record.parent == null).map((record) => record.id);
704
+ if (!scratch.adopt) throw new Error("The native addon does not support native document copies.");
705
+ const copied = JSON.parse(scratch.adopt(document, roots, false));
706
+ for (const [local, copy] of copied.mapping) {
707
+ const global = this.global(document, local);
708
+ toScratch.set(global, copy);
709
+ fromScratch.set(copy, global);
710
+ }
711
+ }
712
+ const translated = { ...args };
713
+ for (const key of ["ids", "contexts"]) if (Array.isArray(args[key])) translated[key] = args[key].map((id) => toScratch.get(id)).filter((id) => id !== void 0);
714
+ if (args.pseudoMatches) translated.pseudoMatches = Object.fromEntries(Object.entries(args.pseudoMatches).map(([key, values]) => [key, values.map((id) => toScratch.get(id)).filter((id) => id !== void 0)]));
715
+ const result = this.call(scratch, command, translated);
716
+ return ["select", "matches", "uniqueSort"].includes(command) ? result.map((id) => fromScratch.get(id)).filter((id) => id !== void 0) : result;
717
+ }
718
+ select(selector, contexts) {
719
+ const ids = contexts ?? [this.rootId()];
720
+ if (!ids.length) return this.call(this.raw, "select", { selector, contexts: [] });
721
+ const groups = this.groups(ids);
722
+ if (new Set(groups.map((group2) => group2.document)).size > 1) return this.scratch("select", { selector, contexts: ids }, ids);
723
+ const group = groups[0];
724
+ const found = group.document === this.raw ? group.document.select(selector, group.ids) : this.call(group.document, "select", { selector, contexts: group.ids });
725
+ return this.globals(group.document, found);
726
+ }
727
+ text(ids) {
728
+ return this.groups(ids).map((group) => group.document.text(group.ids)).join("");
729
+ }
730
+ innerHtml(id) {
731
+ const handle = this.lookup(id);
732
+ registry2.snapshots.delete(handle.document);
733
+ return handle.document === this.raw ? handle.document.innerHtml(handle.local) : this.call(handle.document, "html", { ids: [handle.local] });
734
+ }
735
+ outerHtml(ids) {
736
+ return this.groups(ids).map((group) => group.document === this.raw ? group.document.outerHtml(group.ids) : this.call(group.document, "render", { ids: group.ids })).join("");
737
+ }
738
+ attr(id, name) {
739
+ const handle = this.lookup(id);
740
+ return this.call(handle.document, "attr", { ids: [handle.local], name }) ?? void 0;
741
+ }
742
+ tagName(id) {
743
+ const handle = this.lookup(id);
744
+ return rawOperation(handle.document, "node", { id: handle.local })?.name;
745
+ }
746
+ exportTree() {
747
+ return JSON.stringify(JSON.parse(this.raw.exportTree()).map((record) => this.record(this.raw, record)));
748
+ }
749
+ create(html, contextId) {
750
+ return JSON.parse(this.op("create", JSON.stringify({ html, contextId })));
751
+ }
752
+ op(command, json) {
753
+ return JSON.stringify(this.operate(command, JSON.parse(json)) ?? null);
754
+ }
755
+ operate(command, args) {
756
+ const options = args.options ?? this.options;
757
+ let result;
758
+ if (command === "node") {
759
+ const handle = this.lookup(args.id);
760
+ let snapshots = registry2.snapshots.get(handle.document);
761
+ if (!snapshots) registry2.snapshots.set(handle.document, snapshots = /* @__PURE__ */ new Map());
762
+ if (!snapshots.has(handle.local)) snapshots.set(handle.local, rawOperation(handle.document, "node", { id: handle.local }));
763
+ result = this.record(handle.document, snapshots.get(handle.local));
764
+ } else if (command === "createNode") result = this.global(this.raw, this.call(this.raw, command, args));
765
+ else if (command === "create") {
766
+ const context = args.contextId == null ? void 0 : this.lookup(args.contextId);
767
+ const document = context?.document ?? this.raw;
768
+ if (hasParserHooks(options)) {
769
+ const contextRecord = context ? rawOperation(context.document, "node", { id: context.local }) : void 0;
770
+ const parsed = parseNativeDocument(args.html, { ...options, ...contextRecord ? { __contextName: contextRecord.name, __contextNamespace: contextRecord.namespace } : {} }, false);
771
+ const children2 = rawOperation(parsed, "node", { id: parsed.rootId() }).children;
772
+ this.move(document, children2);
773
+ result = children2;
774
+ } else result = this.globals(document, this.call(document, command, { ...args, contextId: context?.local }));
775
+ } else if (command === "import") result = this.globals(this.raw, this.call(this.raw, command, args));
776
+ else if (command === "setNode") {
777
+ let handle = this.lookup(args.id);
778
+ let value = args.value;
779
+ if (args.field === "children") value = this.move(handle.document, value ?? []);
780
+ else if (["parent", "parentNode", "prev", "previousSibling", "next", "nextSibling"].includes(args.field) && value != null) {
781
+ const pointer = this.lookup(value);
782
+ if (pointer.document !== handle.document) {
783
+ this.move(pointer.document, [args.id]);
784
+ handle = this.lookup(args.id);
785
+ }
786
+ value = this.lookup(args.value).local;
787
+ }
788
+ result = this.call(handle.document, command, { ...args, id: handle.local, value });
789
+ } else if (command === "insert") {
790
+ const targets = args.targetIds ?? [];
791
+ const nodes = args.nodeIds ?? [];
792
+ result = [];
793
+ for (let index = 0; index < targets.length; index++) {
794
+ const target = this.lookup(targets[index]);
795
+ const local = this.move(target.document, nodes, index + 1 < targets.length);
796
+ const inserted = this.call(target.document, command, { ...args, targetIds: [target.local], nodeIds: local });
797
+ result.push(...this.globals(target.document, inserted));
798
+ }
799
+ } else if (command === "html" && Object.hasOwn(args, "value") && hasParserHooks(options)) {
800
+ result = null;
801
+ for (const id of args.ids ?? []) {
802
+ const target = this.lookup(id);
803
+ const record = rawOperation(target.document, "node", { id: target.local });
804
+ if (!["root", "tag", "script", "style", "cdata"].includes(record.type)) continue;
805
+ const parsed = parseNativeDocument(String(args.value), { ...options, __contextName: record.name, __contextNamespace: record.namespace }, false);
806
+ const children2 = rawOperation(parsed, "node", { id: parsed.rootId() }).children;
807
+ const local = this.move(target.document, children2);
808
+ result = this.call(target.document, "setNode", { id: target.local, field: "children", value: local, options });
809
+ }
810
+ } else if (command === "contains") {
811
+ const parent = this.lookup(args.container ?? args.parent);
812
+ const child = this.lookup(args.contained ?? args.child);
813
+ result = parent.document === child.document && this.call(parent.document, command, { container: parent.local, contained: child.local });
814
+ } else if (command === "prop" && Object.hasOwn(args, "value") && ["children", "childNodes", "parent", "parentNode", "prev", "previousSibling", "next", "nextSibling"].includes(args.name)) {
815
+ result = null;
816
+ for (const id of args.ids ?? []) {
817
+ let handle = this.lookup(id);
818
+ let value = args.value;
819
+ if (args.name === "children" || args.name === "childNodes") value = this.move(handle.document, value ?? []);
820
+ else if (value != null) {
821
+ const pointer = this.lookup(value);
822
+ if (pointer.document !== handle.document) {
823
+ this.move(pointer.document, [id]);
824
+ handle = this.lookup(id);
825
+ }
826
+ value = this.lookup(args.value).local;
827
+ }
828
+ result = this.call(handle.document, command, { ...args, ids: [handle.local], value });
829
+ }
830
+ } else {
831
+ const ids = command === "select" ? args.contexts ?? [this.rootId()] : args.ids ?? [];
832
+ const groups = this.groups(ids);
833
+ const mixed = new Set(groups.map((group) => group.document)).size > 1;
834
+ if (mixed && ["select", "matches", "uniqueSort", "serializeArray", "serialize", "extractPlan"].includes(command)) result = this.scratch(command, { ...args, options }, ids);
835
+ else if (command === "extractPlan") {
836
+ const group = groups[0];
837
+ result = this.call(group?.document ?? this.raw, command, { ...args, options, ids: group?.ids ?? [] });
838
+ } else if (["select", "matches", "uniqueSort", "traverse", "clone"].includes(command)) {
839
+ result = [];
840
+ if (!groups.length && (command === "select" || command === "matches")) result = this.call(this.raw, command, { ...args, options, ids: [], ...command === "select" ? { contexts: [] } : {} });
841
+ for (const group of groups) {
842
+ const values = this.call(group.document, command, { ...args, options, ids: group.ids, ...command === "select" ? { contexts: group.ids } : {}, ...args.pseudoMatches ? { pseudoMatches: Object.fromEntries(Object.entries(args.pseudoMatches).map(([key, values2]) => [key, values2.map((id) => this.lookup(id)).filter((handle) => handle.document === group.document).map((handle) => handle.local)])) } : {} });
843
+ result.push(...this.globals(group.document, values));
844
+ }
845
+ } else if (["render", "outerHtml", "text"].includes(command) && !Object.hasOwn(args, "value")) result = groups.map((group) => this.call(group.document, command, { ...args, options, ids: group.ids })).join("");
846
+ else if (command === "hasClass") result = groups.some((group) => this.call(group.document, command, { ...args, options, ids: group.ids }));
847
+ else if (["serializeArray", "serialize"].includes(command)) result = groups.length ? this.call(groups[0].document, command, { ...args, options, ids: groups[0].ids }) : command === "serializeArray" ? [] : "";
848
+ else {
849
+ if (command === "html") for (const group of groups) registry2.snapshots.delete(group.document);
850
+ const writes = Object.hasOwn(args, "value") || ["remove", "removeAttr", "removeData", "addClass", "removeClass", "toggleClass"].includes(command);
851
+ const active = writes ? groups : groups.slice(0, 1);
852
+ result = null;
853
+ for (const group of active) result = this.call(group.document, command, { ...args, options, ids: group.ids });
854
+ }
855
+ }
856
+ return result ?? null;
857
+ }
858
+ };
859
+ function routeDocument(document, options = {}) {
860
+ return document.nodeSpace === registry2.space ? document : new RoutedDocument(document, options);
861
+ }
862
+ function sameNodeSpace(first, second) {
863
+ return first === second || !!first.nodeSpace && first.nodeSpace === second.nodeSpace;
864
+ }
865
+
866
+ // src/nodes.ts
867
+ var nodeStateKey = /* @__PURE__ */ Symbol.for("rusteerio.native-node-views.v2");
868
+ var nodeGlobals = globalThis;
869
+ var nodeState = nodeGlobals[nodeStateKey] ??= { views: /* @__PURE__ */ new WeakMap(), bindings: /* @__PURE__ */ new WeakMap(), caches: /* @__PURE__ */ new WeakMap(), finalizer: new FinalizationRegistry(({ cache, id }) => {
870
+ if (!cache.get(id)?.deref()) cache.delete(id);
871
+ }) };
872
+ var { bindings, caches } = nodeState;
873
+ var arrayIndex = /^(?:0|[1-9]\d*)$/;
874
+ function operation(document, command, args = {}) {
875
+ const direct = document.operate;
876
+ if (direct) return direct.call(document, command, args);
877
+ const value = document.op(command, JSON.stringify(args));
878
+ return value === void 0 || value === "" ? void 0 : JSON.parse(value);
879
+ }
880
+ function nodeBinding(node) {
881
+ return node && typeof node === "object" ? bindings.get(node) : void 0;
882
+ }
883
+ function nodeId(node, document) {
884
+ const binding = nodeBinding(node);
885
+ return binding && (!document || sameNodeSpace(document, binding.document)) ? binding.id : void 0;
886
+ }
887
+ function hydrateLocation(location) {
888
+ if (!location || typeof location !== "object") return location;
889
+ const value = location;
890
+ if (value.attrs && typeof value.attrs === "object") Object.setPrototypeOf(value.attrs, null);
891
+ if (value.startTag?.attrs && typeof value.startTag.attrs === "object") {
892
+ Object.setPrototypeOf(value.startTag.attrs, null);
893
+ if (value.attrs && JSON.stringify(value.attrs) === JSON.stringify(value.startTag.attrs)) value.startTag.attrs = value.attrs;
894
+ }
895
+ return location;
896
+ }
897
+ function nodeRecord(document, id) {
898
+ return operation(document, "node", { id });
899
+ }
900
+ function setField(document, id, field, value) {
901
+ operation(document, "setNode", { id, field, value });
902
+ }
903
+ function attributes(document, id, field = "attribs", prototype = document.options?._useHtmlParser2 === false ? null : Object.prototype) {
904
+ const read = () => nodeRecord(document, id)?.[field] ?? {};
905
+ const target = Object.create(prototype);
906
+ return new Proxy(target, {
907
+ get(_target, key) {
908
+ return typeof key === "symbol" ? Reflect.get(target, key) : Object.hasOwn(read(), key) ? read()[key] : Reflect.get(target, key);
909
+ },
910
+ set(_target, key, value) {
911
+ setField(document, id, field, { ...read(), [key]: String(value) });
912
+ return true;
913
+ },
914
+ deleteProperty(_target, key) {
915
+ const values = { ...read() };
916
+ delete values[key];
917
+ setField(document, id, field, values);
918
+ return true;
919
+ },
920
+ ownKeys() {
921
+ return Reflect.ownKeys(read());
922
+ },
923
+ has(_target, key) {
924
+ return Object.hasOwn(read(), key) || key in target;
925
+ },
926
+ getOwnPropertyDescriptor(_target, key) {
927
+ return Object.hasOwn(read(), key) ? { value: read()[key], writable: true, enumerable: true, configurable: true } : void 0;
928
+ },
929
+ defineProperty(_target, key, descriptor) {
930
+ const values = { ...read(), [key]: String(descriptor.value) };
931
+ setField(document, id, field, values);
932
+ return true;
933
+ }
934
+ });
935
+ }
936
+ function children(document, id) {
937
+ const read = () => nodeRecord(document, id)?.children ?? [];
938
+ const snapshot = () => read().map((child) => getNode(document, child));
939
+ const save = (nodes) => setField(document, id, "children", importNodes(document, nodes));
940
+ const mutating = /* @__PURE__ */ new Set(["push", "pop", "shift", "unshift", "splice", "sort", "reverse", "copyWithin", "fill"]);
941
+ const target = [];
942
+ return new Proxy(target, {
943
+ get(_target, key, receiver) {
944
+ if (key === "length") return read().length;
945
+ if (typeof key === "string" && arrayIndex.test(key)) {
946
+ const child = read()[Number(key)];
947
+ return child === void 0 ? void 0 : getNode(document, child);
948
+ }
949
+ if (typeof key === "string" && mutating.has(key)) return (...args) => {
950
+ const values = snapshot();
951
+ const result = Reflect.apply(Array.prototype[key], values, args);
952
+ save(values);
953
+ return result === values ? receiver : result;
954
+ };
955
+ return Reflect.get(target, key, receiver);
956
+ },
957
+ set(_target, key, value) {
958
+ const values = snapshot();
959
+ if (key === "length") values.length = value;
960
+ else if (typeof key === "string" && arrayIndex.test(key)) values[Number(key)] = value;
961
+ else return Reflect.set(target, key, value);
962
+ save(values);
963
+ return true;
964
+ },
965
+ deleteProperty(_target, key) {
966
+ if (typeof key === "string" && arrayIndex.test(key)) {
967
+ const values = snapshot();
968
+ values.splice(Number(key), 1);
969
+ save(values);
970
+ return true;
971
+ }
972
+ return Reflect.deleteProperty(target, key);
973
+ },
974
+ has(_target, key) {
975
+ return typeof key === "string" && arrayIndex.test(key) ? Number(key) < read().length : Reflect.has(target, key);
976
+ },
977
+ ownKeys() {
978
+ return [...read().map((_child, i) => String(i)), "length"];
979
+ },
980
+ getOwnPropertyDescriptor(_target, key) {
981
+ if (key === "length") return { ...Reflect.getOwnPropertyDescriptor(target, "length"), value: read().length };
982
+ if (typeof key === "string" && arrayIndex.test(key) && Number(key) < read().length) return { value: getNode(document, read()[Number(key)]), writable: true, enumerable: true, configurable: true };
983
+ return Reflect.getOwnPropertyDescriptor(target, key);
984
+ }
985
+ });
986
+ }
987
+ var parentAliases = { parentNode: "parent", previousSibling: "prev", nextSibling: "next" };
988
+ var sourceFields = /* @__PURE__ */ new Set(["type", "name", "data", "namespace", "prefix", "startIndex", "endIndex", "sourceCodeLocation", "x-name", "x-publicId", "x-systemId", "x-mode"]);
989
+ var tagTypes = /* @__PURE__ */ new Set(["tag", "script", "style"]);
990
+ var parentTypes = /* @__PURE__ */ new Set(["root", "tag", "script", "style", "cdata"]);
991
+ var dataTypes = /* @__PURE__ */ new Set(["text", "comment", "directive"]);
992
+ function viewKeys(record) {
993
+ const keys = ["parent", "prev", "next", "startIndex", "endIndex"];
994
+ if (parentTypes.has(record.type)) keys.push("children");
995
+ if (record.data !== void 0) keys.push("data");
996
+ if (record.name !== void 0) keys.push("name");
997
+ if (tagTypes.has(record.type)) keys.push("attribs");
998
+ keys.push("type");
999
+ for (const field of sourceFields) if (!keys.includes(field) && field in record) keys.push(field);
1000
+ if (tagTypes.has(record.type)) {
1001
+ if ("attribsNamespace" in record) keys.push("x-attribsNamespace");
1002
+ if ("attribsPrefix" in record) keys.push("x-attribsPrefix");
1003
+ }
1004
+ return keys;
1005
+ }
1006
+ function viewValue(state, key, receiver) {
1007
+ const { document, id } = state;
1008
+ const record = nodeRecord(document, id);
1009
+ if (key === "cloneNode") return cloneNode;
1010
+ if (key === "nodeType") return { root: 9, text: 3, comment: 8, cdata: 4 }[record.type] ?? 1;
1011
+ if (key === "tagName" && tagTypes.has(record.type)) return record.name;
1012
+ if (key === "nodeValue" && dataTypes.has(record.type)) return record.data;
1013
+ const pointer = parentAliases[key] ?? key;
1014
+ if (["parent", "prev", "next"].includes(pointer)) return record[pointer] == null ? null : getNode(document, record[pointer]);
1015
+ if (["children", "childNodes", "firstChild", "lastChild"].includes(key) && parentTypes.has(record.type)) {
1016
+ const list = state.children ??= children(document, id);
1017
+ return key === "firstChild" ? list[0] ?? null : key === "lastChild" ? list[list.length - 1] ?? null : list;
1018
+ }
1019
+ if (key === "attribs" && tagTypes.has(record.type)) return state.attributes ??= attributes(document, id);
1020
+ if ((key === "x-attribsNamespace" && "attribsNamespace" in record || key === "x-attribsPrefix" && "attribsPrefix" in record) && tagTypes.has(record.type)) {
1021
+ state.maps ??= {};
1022
+ return state.maps[key] ??= attributes(document, id, key === "x-attribsNamespace" ? "attribsNamespace" : "attribsPrefix");
1023
+ }
1024
+ if (key === "attributes" && tagTypes.has(record.type)) {
1025
+ const attrs = state.attributes ??= attributes(document, id);
1026
+ return Object.keys(attrs).map((name) => ({ name, value: attrs[name], namespace: record.attribsNamespace?.[name], prefix: record.attribsPrefix?.[name] }));
1027
+ }
1028
+ if (key === "sourceCodeLocation") return hydrateLocation(record[key]);
1029
+ if (sourceFields.has(key)) return record[key] ?? (key === "startIndex" || key === "endIndex" ? null : void 0);
1030
+ return void 0;
1031
+ }
1032
+ function writeView(state, key, value) {
1033
+ const { document, id } = state;
1034
+ const record = nodeRecord(document, id);
1035
+ if (key === "tagName" && tagTypes.has(record.type)) key = "name";
1036
+ else if (key === "nodeValue" && dataTypes.has(record.type)) key = "data";
1037
+ else if (key === "childNodes") key = "children";
1038
+ else key = parentAliases[key] ?? key;
1039
+ if (sourceFields.has(key) || ["attribs", "x-attribsNamespace", "x-attribsPrefix"].includes(key)) {
1040
+ setField(document, id, key, value);
1041
+ return true;
1042
+ }
1043
+ if (key === "children" && parentTypes.has(record.type)) {
1044
+ setField(document, id, key, importNodes(document, value));
1045
+ return true;
1046
+ }
1047
+ if (["parent", "prev", "next"].includes(key)) {
1048
+ setField(document, id, key, value == null ? null : importNodes(document, [value])[0]);
1049
+ return true;
1050
+ }
1051
+ return false;
1052
+ }
1053
+ var nodeHandler = {
1054
+ get(target, key, receiver) {
1055
+ if (Reflect.getOwnPropertyDescriptor(target, key)) return Reflect.get(target, key, receiver);
1056
+ if (typeof key === "string") {
1057
+ const state = nodeState.views.get(target);
1058
+ if (key === "cloneNode" || key === "nodeType" || sourceFields.has(key) || ["tagName", "nodeValue", "parent", "prev", "next", "parentNode", "previousSibling", "nextSibling", "children", "childNodes", "firstChild", "lastChild", "attribs", "attributes", "x-attribsNamespace", "x-attribsPrefix"].includes(key)) return viewValue(state, key, receiver);
1059
+ }
1060
+ return Reflect.get(target, key, receiver);
1061
+ },
1062
+ set(target, key, value, receiver) {
1063
+ if (Reflect.getOwnPropertyDescriptor(target, key)) return Reflect.set(target, key, value, receiver);
1064
+ if (typeof key === "string" && writeView(nodeState.views.get(target), key, value)) return true;
1065
+ return Reflect.set(target, key, value, receiver);
1066
+ },
1067
+ has(target, key) {
1068
+ return Reflect.has(target, key) || typeof key === "string" && (viewKeys(nodeRecord(nodeState.views.get(target).document, nodeState.views.get(target).id)).includes(key) || ["cloneNode", "nodeType", "parentNode", "previousSibling", "nextSibling"].includes(key));
1069
+ },
1070
+ ownKeys(target) {
1071
+ const state = nodeState.views.get(target);
1072
+ return [.../* @__PURE__ */ new Set([...viewKeys(nodeRecord(state.document, state.id)), ...Reflect.ownKeys(target)])];
1073
+ },
1074
+ getOwnPropertyDescriptor(target, key) {
1075
+ const existing = Reflect.getOwnPropertyDescriptor(target, key);
1076
+ if (existing) return existing;
1077
+ const state = nodeState.views.get(target);
1078
+ if (typeof key === "string" && viewKeys(nodeRecord(state.document, state.id)).includes(key)) return { value: viewValue(state, key, void 0), configurable: true, enumerable: true, writable: true };
1079
+ return void 0;
1080
+ }
1081
+ };
1082
+ function getNode(document, id, original) {
1083
+ const cacheKey = document.nodeSpace ?? document;
1084
+ let cache = caches.get(cacheKey);
1085
+ if (!cache) caches.set(cacheKey, cache = /* @__PURE__ */ new Map());
1086
+ const existing = cache.get(id)?.deref();
1087
+ if (existing) return existing;
1088
+ document = document.nodeDocument?.(id) ?? document;
1089
+ const lease = document.retainNodes?.([id]);
1090
+ const record = nodeRecord(document, id);
1091
+ if (!record) return void 0;
1092
+ if (original === void 0) {
1093
+ const target = Object.create(nodePrototype(record.type));
1094
+ const node2 = new Proxy(target, nodeHandler);
1095
+ nodeState.views.set(target, { document, id, lease });
1096
+ cache.set(id, new WeakRef(node2));
1097
+ nodeState.finalizer.register(node2, { cache, id });
1098
+ bindings.set(node2, { document, id });
1099
+ return node2;
1100
+ }
1101
+ const node = original;
1102
+ cache.set(id, new WeakRef(node));
1103
+ nodeState.finalizer.register(node, { cache, id });
1104
+ bindings.set(node, { document, id });
1105
+ const read = () => {
1106
+ void lease;
1107
+ return nodeRecord(document, id);
1108
+ };
1109
+ const define = (key, get, set, enumerable = true) => {
1110
+ try {
1111
+ Object.defineProperty(node, key, { configurable: true, enumerable, get, ...set ? { set } : {} });
1112
+ } catch {
1113
+ }
1114
+ };
1115
+ for (const field of ["type", "name", "data", "namespace", "prefix", "startIndex", "endIndex", "sourceCodeLocation", "x-name", "x-publicId", "x-systemId", "x-mode"]) {
1116
+ if (field in record || ["type", "startIndex", "endIndex"].includes(field)) define(field, () => (field === "sourceCodeLocation" ? hydrateLocation(read()[field]) : read()[field]) ?? (field === "startIndex" || field === "endIndex" ? null : void 0), (value) => setField(document, id, field, value));
1117
+ }
1118
+ for (const field of ["parent", "prev", "next"]) define(field, () => {
1119
+ const value = read()[field];
1120
+ return value === null || value === void 0 ? null : getNode(document, value);
1121
+ }, (value) => setField(document, id, field, value == null ? null : importNodes(document, [value])[0]));
1122
+ for (const [alias, field] of [["parentNode", "parent"], ["previousSibling", "prev"], ["nextSibling", "next"]]) define(alias, () => node[field], (value) => {
1123
+ node[field] = value;
1124
+ }, false);
1125
+ if ("children" in record && ["root", "tag", "script", "style", "cdata"].includes(record.type)) {
1126
+ const list = children(document, id);
1127
+ define("children", () => list, (value) => setField(document, id, "children", importNodes(document, value)));
1128
+ define("childNodes", () => list, (value) => {
1129
+ node.children = value;
1130
+ }, false);
1131
+ define("firstChild", () => list[0] ?? null, void 0, false);
1132
+ define("lastChild", () => list[list.length - 1] ?? null, void 0, false);
1133
+ }
1134
+ if (["tag", "script", "style"].includes(record.type)) {
1135
+ const attrs = attributes(document, id, "attribs", Object.getPrototypeOf(original.attribs ?? {}));
1136
+ define("attribs", () => attrs, (value) => setField(document, id, "attribs", value));
1137
+ define("tagName", () => node.name, (value) => {
1138
+ node.name = value;
1139
+ }, false);
1140
+ for (const field of ["x-attribsNamespace", "x-attribsPrefix"]) {
1141
+ if (!((field === "x-attribsNamespace" ? "attribsNamespace" : "attribsPrefix") in record) && !Object.hasOwn(original, field)) continue;
1142
+ const values = attributes(document, id, field === "x-attribsNamespace" ? "attribsNamespace" : "attribsPrefix");
1143
+ define(field, () => values, (value) => setField(document, id, field, value));
1144
+ }
1145
+ define("attributes", () => Object.keys(attrs).map((name) => ({ name, value: attrs[name], namespace: read().attribsNamespace?.[name], prefix: read().attribsPrefix?.[name] })), void 0, false);
1146
+ }
1147
+ if (["text", "comment", "directive"].includes(record.type)) define("nodeValue", () => node.data, (value) => {
1148
+ node.data = value;
1149
+ }, false);
1150
+ define("nodeType", () => ({ root: 9, text: 3, comment: 8, cdata: 4 })[read().type] ?? 1, void 0, false);
1151
+ Object.defineProperty(node, "cloneNode", { configurable: true, enumerable: false, writable: true, value: cloneNode });
1152
+ return node;
1153
+ }
1154
+ function cloneNode(recursive = false) {
1155
+ const binding = nodeBinding(this);
1156
+ if (!binding) throw new TypeError("cloneNode requires a native DOM node receiver");
1157
+ return getNode(binding.document, operation(binding.document, "clone", { ids: [binding.id], deep: recursive })[0]);
1158
+ }
1159
+ function importNodes(document, input) {
1160
+ if (input == null || input === false) return [];
1161
+ const values = Array.isArray(input) || typeof input === "object" && "length" in input && !("type" in input) ? Array.from(input) : [input];
1162
+ const result = [];
1163
+ for (const node of values) {
1164
+ if (node == null) continue;
1165
+ const existing = nodeId(node, document);
1166
+ if (existing !== void 0) {
1167
+ document.retainNode?.(existing);
1168
+ result.push(existing);
1169
+ continue;
1170
+ }
1171
+ if (typeof node !== "object" || typeof node.type !== "string") continue;
1172
+ const records = [];
1173
+ const originals = /* @__PURE__ */ new Map();
1174
+ const visit = (value, parent) => {
1175
+ const id = records.length;
1176
+ const record = { id, type: value.type, children: [], ...parent === void 0 ? {} : { parent } };
1177
+ records.push(record);
1178
+ originals.set(id, value);
1179
+ for (const field of ["name", "data", "namespace", "prefix", "startIndex", "endIndex", "sourceCodeLocation", "x-name", "x-publicId", "x-systemId", "x-mode"]) if (value[field] !== void 0) record[field] = value[field];
1180
+ if (value.attribs) record.attribs = { ...value.attribs };
1181
+ if (value["x-attribsNamespace"]) record.attribsNamespace = { ...value["x-attribsNamespace"] };
1182
+ if (value["x-attribsPrefix"]) record.attribsPrefix = { ...value["x-attribsPrefix"] };
1183
+ record.children = (value.children ?? []).map((child) => visit(child, id));
1184
+ return id;
1185
+ };
1186
+ const root = visit(node);
1187
+ const imported = operation(document, "import", { nodes: records, roots: [root] });
1188
+ if (!imported.length) continue;
1189
+ const adopt = (oldId, newId) => {
1190
+ const source = originals.get(oldId);
1191
+ const oldChildren = records[oldId].children;
1192
+ const newChildren = nodeRecord(document, newId).children ?? [];
1193
+ getNode(document, newId, nodeBinding(source) ? void 0 : source);
1194
+ for (let i = 0; i < oldChildren.length; i++) if (newChildren[i] !== void 0) adopt(oldChildren[i], newChildren[i]);
1195
+ };
1196
+ adopt(root, imported[0]);
1197
+ result.push(imported[0]);
1198
+ }
1199
+ return result;
1200
+ }
1201
+
1202
+ // src/dom.ts
1203
+ var ElementType = Object.freeze({ Root: "root", Text: "text", Directive: "directive", Comment: "comment", Script: "script", Style: "style", Tag: "tag", CDATA: "cdata", Doctype: "doctype" });
1204
+ function initialize(node, type, fields, children2 = []) {
1205
+ const document = routeDocument(new (requireNative()).NativeDocument("", false));
1206
+ const id = operation(document, "createNode", { type, ...fields });
1207
+ if (children2.length) operation(document, "setNode", { id, field: "children", value: importNodes(document, children2) });
1208
+ return getNode(document, id, node);
1209
+ }
1210
+ var Node = class {
1211
+ static [Symbol.hasInstance](value) {
1212
+ const binding = nodeBinding(value);
1213
+ if (!binding) return Function.prototype[Symbol.hasInstance].call(this, value);
1214
+ const type = value.type;
1215
+ switch (this.name) {
1216
+ case "Node":
1217
+ return true;
1218
+ case "DataNode":
1219
+ return ["text", "comment", "directive"].includes(type);
1220
+ case "NodeWithChildren":
1221
+ return ["root", "tag", "script", "style", "cdata"].includes(type);
1222
+ case "Element":
1223
+ return ["tag", "script", "style"].includes(type);
1224
+ case "Document":
1225
+ return type === "root";
1226
+ case "CDATA":
1227
+ return type === "cdata";
1228
+ case "Text":
1229
+ return type === "text";
1230
+ case "Comment":
1231
+ return type === "comment";
1232
+ case "ProcessingInstruction":
1233
+ return type === "directive";
1234
+ default:
1235
+ return Function.prototype[Symbol.hasInstance].call(this, value);
1236
+ }
1237
+ }
1238
+ };
1239
+ var DataNode = class extends Node {
1240
+ };
1241
+ var NodeWithChildren = class extends Node {
1242
+ };
1243
+ var Text = class extends DataNode {
1244
+ constructor(data2) {
1245
+ super();
1246
+ return initialize(this, "text", { data: data2 });
1247
+ }
1248
+ };
1249
+ var Comment = class extends DataNode {
1250
+ constructor(data2) {
1251
+ super();
1252
+ return initialize(this, "comment", { data: data2 });
1253
+ }
1254
+ };
1255
+ var ProcessingInstruction = class extends DataNode {
1256
+ constructor(name, data2) {
1257
+ super();
1258
+ return initialize(this, "directive", { name, data: data2 });
1259
+ }
1260
+ };
1261
+ var Document = class extends NodeWithChildren {
1262
+ constructor(children2) {
1263
+ super();
1264
+ return initialize(this, "root", {}, children2);
1265
+ }
1266
+ };
1267
+ var CDATA = class extends NodeWithChildren {
1268
+ constructor(children2) {
1269
+ super();
1270
+ return initialize(this, "cdata", {}, children2);
1271
+ }
1272
+ };
1273
+ var Element = class extends NodeWithChildren {
1274
+ constructor(name, attribs, children2 = [], type) {
1275
+ super();
1276
+ return initialize(this, type ?? (name === "script" || name === "style" ? name : "tag"), { name, attribs }, children2);
1277
+ }
1278
+ };
1279
+ function nodePrototype(type) {
1280
+ return ({ root: Document, text: Text, comment: Comment, directive: ProcessingInstruction, cdata: CDATA, tag: Element, script: Element, style: Element }[type] ?? Node).prototype;
1281
+ }
1282
+ var isTag = (node) => ["tag", "script", "style"].includes(node.type);
1283
+ var isText = (node) => node.type === "text";
1284
+ var isComment = (node) => node.type === "comment";
1285
+ var isDirective = (node) => node.type === "directive";
1286
+ var isDocument = (node) => node.type === "root";
1287
+ var isCDATA = (node) => node.type === "cdata";
1288
+ var hasChildren = (node) => "children" in node;
1289
+ Object.defineProperties(Node.prototype, {
1290
+ cloneNode: { configurable: true, writable: true, value: cloneNode },
1291
+ parentNode: { configurable: true, get() {
1292
+ return this.parent;
1293
+ }, set(value) {
1294
+ this.parent = value;
1295
+ } },
1296
+ previousSibling: { configurable: true, get() {
1297
+ return this.prev;
1298
+ }, set(value) {
1299
+ this.prev = value;
1300
+ } },
1301
+ nextSibling: { configurable: true, get() {
1302
+ return this.next;
1303
+ }, set(value) {
1304
+ this.next = value;
1305
+ } },
1306
+ nodeType: { configurable: true, get() {
1307
+ return { root: 9, text: 3, comment: 8, cdata: 4 }[this.type] ?? 1;
1308
+ } }
1309
+ });
1310
+ Object.defineProperty(DataNode.prototype, "nodeValue", { configurable: true, get() {
1311
+ return this.data;
1312
+ }, set(value) {
1313
+ this.data = value;
1314
+ } });
1315
+ Object.defineProperties(NodeWithChildren.prototype, {
1316
+ childNodes: { configurable: true, get() {
1317
+ return this.children;
1318
+ }, set(value) {
1319
+ this.children = value;
1320
+ } },
1321
+ firstChild: { configurable: true, get() {
1322
+ return this.children[0] ?? null;
1323
+ } },
1324
+ lastChild: { configurable: true, get() {
1325
+ return this.children[this.children.length - 1] ?? null;
1326
+ } }
1327
+ });
1328
+ Object.defineProperties(Element.prototype, {
1329
+ tagName: { configurable: true, get() {
1330
+ return this.name;
1331
+ }, set(value) {
1332
+ this.name = value;
1333
+ } },
1334
+ attributes: { configurable: true, get() {
1335
+ return Object.keys(this.attribs).map((name) => ({ name, value: this.attribs[name], namespace: this["x-attribsNamespace"]?.[name], prefix: this["x-attribsPrefix"]?.[name] }));
1336
+ } }
1337
+ });
1338
+
1339
+ // src/extract-plan.ts
1340
+ import { types } from "util";
1341
+ var scalarProperties = /* @__PURE__ */ new Set([
1342
+ "textContent",
1343
+ "innerText",
1344
+ "innerHTML",
1345
+ "outerHTML",
1346
+ "tagName",
1347
+ "nodeName",
1348
+ "nodeType",
1349
+ "id",
1350
+ "class",
1351
+ "className",
1352
+ "title",
1353
+ "href",
1354
+ "src",
1355
+ "alt",
1356
+ "name",
1357
+ "value",
1358
+ "type",
1359
+ "checked",
1360
+ "selected",
1361
+ "disabled",
1362
+ "multiple",
1363
+ "readOnly",
1364
+ "required",
1365
+ "hidden",
1366
+ "open",
1367
+ "autofocus",
1368
+ "controls",
1369
+ "loop",
1370
+ "muted"
1371
+ ]);
1372
+ function dataValue(object, key) {
1373
+ for (let current = object; current; current = Object.getPrototypeOf(current)) {
1374
+ if (types.isProxy(current)) return void 0;
1375
+ const descriptor = Object.getOwnPropertyDescriptor(current, key);
1376
+ if (descriptor) return "value" in descriptor ? { value: descriptor.value } : void 0;
1377
+ }
1378
+ return { value: void 0 };
1379
+ }
1380
+ function compileExtractPlan(map, options) {
1381
+ if (options.pseudos || options.treeAdapter || options.Tokenizer || options.xml && typeof options.xml === "object" && options.xml.Tokenizer) return void 0;
1382
+ const ancestors = /* @__PURE__ */ new Set();
1383
+ const compile = (input) => {
1384
+ if (!input || typeof input !== "object" || types.isProxy(input) || ancestors.has(input) || ancestors.size >= 64) return void 0;
1385
+ for (let current = Object.getPrototypeOf(input); current; current = Object.getPrototypeOf(current)) {
1386
+ if (types.isProxy(current)) return void 0;
1387
+ }
1388
+ ancestors.add(input);
1389
+ try {
1390
+ const entries2 = [];
1391
+ for (const key in input) {
1392
+ if (key === "__proto__") return void 0;
1393
+ const inherited = Object.getOwnPropertyDescriptor(Object.prototype, key);
1394
+ if (inherited && (!("value" in inherited) || !inherited.writable)) return void 0;
1395
+ const slot = dataValue(input, key);
1396
+ if (!slot) return void 0;
1397
+ const all = Array.isArray(slot.value);
1398
+ if (slot.value && typeof slot.value === "object" && types.isProxy(slot.value)) return void 0;
1399
+ const first = all ? dataValue(slot.value, "0") : slot;
1400
+ if (!first) return void 0;
1401
+ const descriptor = first.value;
1402
+ let selector;
1403
+ let value;
1404
+ if (typeof descriptor === "string") {
1405
+ selector = descriptor;
1406
+ value = "textContent";
1407
+ } else if (descriptor && typeof descriptor === "object") {
1408
+ if (types.isProxy(descriptor)) return void 0;
1409
+ const selectorSlot = dataValue(descriptor, "selector");
1410
+ const valueSlot = dataValue(descriptor, "value");
1411
+ if (!selectorSlot || !valueSlot) return void 0;
1412
+ selector = selectorSlot.value;
1413
+ value = valueSlot.value ?? "textContent";
1414
+ } else return void 0;
1415
+ if (typeof selector !== "string") return void 0;
1416
+ if (typeof value === "string") {
1417
+ if (!scalarProperties.has(value) && !/^(?:data-|aria-).+/.test(value)) return void 0;
1418
+ entries2.push({ key, selector, all, value: { kind: "property", name: value } });
1419
+ } else {
1420
+ const nested = compile(value);
1421
+ if (!nested) return void 0;
1422
+ entries2.push({ key, selector, all, value: { kind: "map", entries: nested } });
1423
+ }
1424
+ }
1425
+ return entries2;
1426
+ } finally {
1427
+ ancestors.delete(input);
1428
+ }
1429
+ };
1430
+ const entries = compile(map);
1431
+ return entries && { version: 1, entries };
1432
+ }
1433
+ function hydrateExtractResult(result, entries) {
1434
+ const values = entries.map((entry) => Object.hasOwn(result, entry.key) ? result[entry.key] : entry.all ? [] : void 0);
1435
+ for (const entry of entries) delete result[entry.key];
1436
+ for (let index = 0; index < entries.length; index += 1) {
1437
+ const entry = entries[index];
1438
+ Object.defineProperty(result, entry.key, { value: values[index], enumerable: true, configurable: true, writable: true });
1439
+ if (entry.value.kind !== "map") continue;
1440
+ const nested = result[entry.key];
1441
+ for (const value of entry.all && Array.isArray(nested) ? nested : [nested]) {
1442
+ if (value && typeof value === "object" && !Array.isArray(value)) hydrateExtractResult(value, entry.value.entries);
1443
+ }
1444
+ }
1445
+ }
1446
+
1447
+ // src/attributes.ts
1448
+ var dataObjects = /* @__PURE__ */ new WeakMap();
1449
+ var dataFinalizer = new FinalizationRegistry(({ cache, id, reference }) => {
1450
+ const records = cache.deref();
1451
+ if (records?.get(id) === reference) records.delete(id);
1452
+ });
1453
+ function isElement(selection, id) {
1454
+ return ["tag", "script", "style"].includes(nodeRecord(selection._document, id)?.type);
1455
+ }
1456
+ function nativeValue(value) {
1457
+ const seen = /* @__PURE__ */ new WeakSet();
1458
+ const json = JSON.stringify(value, (_key, value2) => {
1459
+ if (typeof value2 === "function" || typeof value2 === "symbol" || typeof value2 === "bigint" || value2 === void 0) return { __opaqueJavaScriptValue: true };
1460
+ if (typeof value2 === "number" && !Number.isFinite(value2)) return { __nativeNumber: String(value2) };
1461
+ if (value2 && typeof value2 === "object") {
1462
+ if (seen.has(value2)) return { __opaqueJavaScriptValue: true };
1463
+ seen.add(value2);
1464
+ }
1465
+ return value2;
1466
+ });
1467
+ return json === void 0 ? { __opaqueJavaScriptValue: true } : JSON.parse(json);
1468
+ }
1469
+ function hydrateValue(value) {
1470
+ if (value && typeof value === "object") {
1471
+ if (Object.keys(value).length === 1 && typeof value.__nativeNumber === "string") return Number(value.__nativeNumber);
1472
+ for (const key of Object.keys(value)) value[key] = hydrateValue(value[key]);
1473
+ }
1474
+ return value;
1475
+ }
1476
+ function dataObject(selection, id) {
1477
+ const document = selection._document;
1478
+ const cacheKey = document.nodeSpace ?? document;
1479
+ let documents = dataObjects.get(cacheKey);
1480
+ if (!documents) dataObjects.set(cacheKey, documents = /* @__PURE__ */ new Map());
1481
+ const existingReference = documents.get(id);
1482
+ let data2 = existingReference?.deref() ?? document.nodeData?.(id);
1483
+ if (!data2) {
1484
+ const documentReference = new WeakRef(document);
1485
+ const dispatch = document.nodeDataOperation?.(id) ?? ((command, args) => {
1486
+ const document2 = documentReference.deref();
1487
+ return document2 ? JSON.parse(document2.op(command, JSON.stringify(args))) : void 0;
1488
+ });
1489
+ const target = {};
1490
+ data2 = new Proxy(target, {
1491
+ set(object, name, value) {
1492
+ Reflect.set(object, name, value);
1493
+ if (typeof name === "string") dispatch("data", { ids: [id], name, value: nativeValue(value) });
1494
+ return true;
1495
+ },
1496
+ defineProperty(object, name, descriptor) {
1497
+ Reflect.defineProperty(object, name, descriptor);
1498
+ if (typeof name === "string" && "value" in descriptor) dispatch("data", { ids: [id], name, value: nativeValue(descriptor.value) });
1499
+ return true;
1500
+ },
1501
+ deleteProperty(object, name) {
1502
+ Reflect.deleteProperty(object, name);
1503
+ if (typeof name === "string") dispatch("removeData", { ids: [id], name });
1504
+ return true;
1505
+ }
1506
+ });
1507
+ const node = getNode(selection._document, id);
1508
+ Object.defineProperty(node, "data", { configurable: true, enumerable: true, get: () => data2, set: (value) => {
1509
+ for (const key of Object.keys(data2)) delete data2[key];
1510
+ for (const key of Object.keys(value ?? {})) data2[key] = value[key];
1511
+ } });
1512
+ }
1513
+ if (existingReference?.deref() !== data2) {
1514
+ const reference = new WeakRef(data2);
1515
+ documents.set(id, reference);
1516
+ dataFinalizer.register(data2, { cache: new WeakRef(documents), id, reference });
1517
+ }
1518
+ document.retainNodeData?.(id, data2);
1519
+ return data2;
1520
+ }
1521
+ function property(selection, id, name, raw = false) {
1522
+ const result = selection.op("prop", { ids: [id], name, ...raw ? { raw: true } : {} });
1523
+ if (name === "sourceCodeLocation") return hydrateLocation(result);
1524
+ return result?.__nativeNodeProperty ? getNode(selection._document, id)[result.__nativeNodeProperty] : result === null ? void 0 : result;
1525
+ }
1526
+ function propertyValue(selection, name, value) {
1527
+ if (name === "children" || name === "childNodes") return importNodes(selection._document, value);
1528
+ if (["parent", "parentNode", "prev", "previousSibling", "next", "nextSibling"].includes(name)) return value == null ? null : importNodes(selection._document, [value])[0] ?? null;
1529
+ return value;
1530
+ }
1531
+ function attr(name, value) {
1532
+ if (typeof name === "object" || value !== void 0) {
1533
+ if (typeof value === "function") {
1534
+ if (typeof name !== "string") throw new Error("Bad combination of arguments.");
1535
+ this.ids.forEach((id, index) => {
1536
+ if (!isElement(this, id)) return;
1537
+ const node = getNode(this._document, id);
1538
+ const current = node.attribs[name];
1539
+ const next = value.call(node, index, current);
1540
+ this.op("attr", { ids: [id], name, value: next === null ? null : String(next) });
1541
+ });
1542
+ } else if (typeof name === "object") {
1543
+ for (const key of Object.keys(name)) this.op("attr", { ids: this.ids, name: key, value: name[key] === null ? null : String(name[key]) });
1544
+ } else {
1545
+ this.op("attr", { ids: this.ids, name, value: value === null ? null : String(value) });
1546
+ }
1547
+ return this;
1548
+ }
1549
+ if (arguments.length > 1) return this;
1550
+ const result = this.op("attr", { ids: this.ids, ...typeof name === "string" ? { name } : {} });
1551
+ if (result === null) return void 0;
1552
+ return !name && this.ids.length ? getNode(this._document, this.ids[0]).attribs : result;
1553
+ }
1554
+ function prop(name, value) {
1555
+ if (typeof name === "string" && value === void 0) return this.ids.length ? property(this, this.ids[0], name) : void 0;
1556
+ if (typeof name === "object" || value !== void 0) {
1557
+ if (typeof value === "function") {
1558
+ if (typeof name === "object") throw new TypeError("Bad combination of arguments.");
1559
+ this.ids.forEach((id, index) => {
1560
+ if (!isElement(this, id)) return;
1561
+ const next = value.call(getNode(this._document, id), index, property(this, id, name, true));
1562
+ this.op("prop", { ids: [id], name, value: propertyValue(this, name, next) });
1563
+ });
1564
+ } else if (typeof name === "object") {
1565
+ for (const key of Object.keys(name)) this.op("prop", { ids: this.ids, name: key, value: propertyValue(this, key, name[key]) });
1566
+ } else {
1567
+ this.op("prop", { ids: this.ids, name, value: propertyValue(this, name, value) });
1568
+ }
1569
+ return this;
1570
+ }
1571
+ return void 0;
1572
+ }
1573
+ function data(name, value) {
1574
+ const first = this.ids[0];
1575
+ if (first === void 0 || !isElement(this, first)) return void 0;
1576
+ if (name != null && (typeof name === "object" || value !== void 0)) {
1577
+ for (const id of this.ids) {
1578
+ if (!isElement(this, id)) continue;
1579
+ const record2 = dataObject(this, id);
1580
+ if (typeof name === "object") for (const key of Object.keys(name)) record2[key] = name[key];
1581
+ else if (typeof name === "string") record2[name] = value;
1582
+ }
1583
+ return this;
1584
+ }
1585
+ const record = dataObject(this, first);
1586
+ if (typeof name === "string" && Object.hasOwn(record, name)) return record[name];
1587
+ const found = this.op("data", { ids: [first], ...name == null ? {} : { name } });
1588
+ if (!found.found) return void 0;
1589
+ if (name == null) {
1590
+ for (const key of Object.keys(found.value)) if (!Object.hasOwn(record, key)) record[key] = hydrateValue(found.value[key]);
1591
+ return record;
1592
+ }
1593
+ record[name] = hydrateValue(found.value);
1594
+ return record[name];
1595
+ }
1596
+ function css(name, value) {
1597
+ if (name != null && value != null || typeof name === "object" && !Array.isArray(name)) {
1598
+ if (typeof name === "object") {
1599
+ for (const [propertyIndex, key] of Object.keys(name).entries()) {
1600
+ if (typeof name[key] === "function") {
1601
+ for (const id of this.ids) {
1602
+ if (!isElement(this, id)) continue;
1603
+ const current = this.op("css", { ids: [id], name: key }) ?? void 0;
1604
+ const next = name[key].call(getNode(this._document, id), propertyIndex, current);
1605
+ this.op("css", { ids: [id], name: key, value: next == null ? null : String(next) });
1606
+ }
1607
+ } else this.op("css", { ids: this.ids, name: key, value: name[key] == null ? null : String(name[key]) });
1608
+ }
1609
+ } else if (typeof name === "string" && typeof value === "function") {
1610
+ this.ids.forEach((id, index) => {
1611
+ if (!isElement(this, id)) return;
1612
+ const current = this.op("css", { ids: [id], name }) ?? void 0;
1613
+ const next = value.call(getNode(this._document, id), index, current);
1614
+ this.op("css", { ids: [id], name, value: next == null ? null : String(next) });
1615
+ });
1616
+ } else if (typeof name === "string") this.op("css", { ids: this.ids, name, value: value == null ? null : String(value) });
1617
+ return this;
1618
+ }
1619
+ return this.op("css", { ids: this.ids, ...name === void 0 ? {} : { name } }) ?? void 0;
1620
+ }
1621
+ function classMethod(command) {
1622
+ return function(name, state) {
1623
+ if (typeof name === "function") {
1624
+ this.ids.forEach((id, index) => {
1625
+ if (!isElement(this, id)) return;
1626
+ const node = getNode(this._document, id);
1627
+ const next = command === "toggleClass" ? name.call(node, index, node.attribs.class ?? "", state) : name.call(node, index, node.attribs.class ?? "");
1628
+ if (typeof next === "string") this.op(command, { ids: [id], name: next, ...typeof state === "boolean" ? { state } : {} });
1629
+ });
1630
+ } else if (typeof name === "string" || command === "removeClass" && arguments.length === 0) {
1631
+ this.op(command, { ids: this.ids, ...typeof name === "string" ? { name } : { all: true }, ...typeof state === "boolean" ? { state } : {} });
1632
+ }
1633
+ return this;
1634
+ };
1635
+ }
1636
+ function installAttributes(CheerioClass) {
1637
+ Object.assign(CheerioClass.prototype, {
1638
+ attr,
1639
+ prop,
1640
+ data,
1641
+ css,
1642
+ removeAttr(name) {
1643
+ this.op("removeAttr", { ids: this.ids, name });
1644
+ return this;
1645
+ },
1646
+ hasClass(name) {
1647
+ return this.op("hasClass", { ids: this.ids, name });
1648
+ },
1649
+ addClass: classMethod("addClass"),
1650
+ removeClass: classMethod("removeClass"),
1651
+ toggleClass: classMethod("toggleClass"),
1652
+ val(value) {
1653
+ if (arguments.length === 0) return this.op("val", { ids: this.ids }) ?? void 0;
1654
+ const result = this.op("val", { ids: this.ids, value: value === void 0 ? { __undefinedJavaScriptValue: true } : value });
1655
+ return result?.chain === false ? result.returnValue : result === false ? void 0 : this;
1656
+ },
1657
+ serializeArray() {
1658
+ return this.op("serializeArray", { ids: this.ids });
1659
+ },
1660
+ serialize() {
1661
+ return this.op("serialize", { ids: this.ids });
1662
+ }
1663
+ });
1664
+ }
1665
+
1666
+ // src/parse.ts
1667
+ function parseWithNative(content, options, isDocument2, context) {
1668
+ if (!isDocument2 && context) {
1669
+ const document2 = nodeBinding(context)?.document ?? routeDocument(new (requireNative()).NativeDocument("", false, JSON.stringify(cleanParserOptions(options))), options);
1670
+ const contextId = importNodes(document2, [context])[0];
1671
+ const children2 = operation(document2, "create", { html: content, contextId, options });
1672
+ const root = operation(document2, "createNode", { type: "root", options });
1673
+ operation(document2, "setNode", { id: root, field: "children", value: children2, options });
1674
+ return getNode(document2, root);
1675
+ }
1676
+ const document = parseNativeDocument(content, options, isDocument2);
1677
+ return getNode(document, document.rootId());
1678
+ }
1679
+ function parseWithParse5(content, options, isDocument2, context) {
1680
+ return parseWithNative(content, { ...options, _useHtmlParser2: false, xml: false, xmlMode: false }, isDocument2, context);
1681
+ }
1682
+ function parseWithHtmlparser2(content, options) {
1683
+ return parseWithNative(content, { ...options, _useHtmlParser2: true }, false, null);
1684
+ }
1685
+ function getParse(parser) {
1686
+ return function parse2(content, options, isDocument2, context) {
1687
+ if (Buffer.isBuffer(content)) content = content.toString();
1688
+ if (typeof content === "string") return parser(content, options, isDocument2, context);
1689
+ if (!Array.isArray(content) && content.type === "root" && nodeBinding(content)) return content;
1690
+ const document = routeDocument(new (requireNative()).NativeDocument("", false, JSON.stringify(cleanParserOptions(options))), options);
1691
+ const ids = importNodes(document, content);
1692
+ if (!Array.isArray(content) && content.type === "root") return getNode(document, ids[0]);
1693
+ operation(document, "setNode", { id: document.rootId(), field: "children", value: ids, options });
1694
+ return getNode(document, document.rootId());
1695
+ };
1696
+ }
1697
+ var parse = getParse((content, options, isDocument2, context) => options._useHtmlParser2 ? parseWithHtmlparser2(content, options) : parseWithParse5(content, options, isDocument2, context));
1698
+
1699
+ // src/selection.ts
1700
+ var numeric = /^(?:0|[1-9]\d*)$/;
1701
+ var isMarkup = (value) => /<[a-zA-Z!/?]/.test(value);
1702
+ function* customPseudoArguments(selector, name) {
1703
+ let attributeDepth = 0;
1704
+ let quote = "";
1705
+ for (let index = 0; index < selector.length; index++) {
1706
+ const character = selector[index];
1707
+ if (character === "\\") {
1708
+ index++;
1709
+ continue;
1710
+ }
1711
+ if (quote) {
1712
+ if (character === quote)
1713
+ quote = "";
1714
+ continue;
1715
+ }
1716
+ if (character === '"' || character === "'") {
1717
+ quote = character;
1718
+ continue;
1719
+ }
1720
+ if (character === "[") {
1721
+ attributeDepth++;
1722
+ continue;
1723
+ }
1724
+ if (character === "]") {
1725
+ attributeDepth--;
1726
+ continue;
1727
+ }
1728
+ if (attributeDepth || character !== ":" || selector[index - 1] === ":")
1729
+ continue;
1730
+ const start = index + 1;
1731
+ let end = start;
1732
+ while (/[\w-]/.test(selector[end] ?? "") && end < selector.length)
1733
+ end++;
1734
+ if (selector.slice(start, end).toLowerCase() !== name.toLowerCase())
1735
+ continue;
1736
+ index = end - 1;
1737
+ if (selector[end] !== "(") {
1738
+ yield void 0;
1739
+ continue;
1740
+ }
1741
+ const argumentStart = end + 1;
1742
+ let depth = 1;
1743
+ let argumentQuote = "";
1744
+ for (end++; end < selector.length; end++) {
1745
+ const next = selector[end];
1746
+ if (next === "\\") {
1747
+ end++;
1748
+ continue;
1749
+ }
1750
+ if (argumentQuote) {
1751
+ if (next === argumentQuote)
1752
+ argumentQuote = "";
1753
+ continue;
1754
+ }
1755
+ if (next === '"' || next === "'") {
1756
+ argumentQuote = next;
1757
+ continue;
1758
+ }
1759
+ if (next === "(")
1760
+ depth++;
1761
+ else if (next === ")" && --depth === 0)
1762
+ break;
1763
+ }
1764
+ if (depth)
1765
+ continue;
1766
+ yield selector.slice(argumentStart, end);
1767
+ index = end;
1768
+ }
1769
+ }
1770
+ var Cheerio = class {
1771
+ cheerio = "[cheerio object]";
1772
+ constructor(api, document, ids = [], root = null, options = {}, values) {
1773
+ Object.defineProperties(this, {
1774
+ _document: { value: document, writable: true, configurable: true },
1775
+ _api: { value: api, writable: true, configurable: true },
1776
+ _ids: { value: ids, writable: true, configurable: true },
1777
+ _values: { value: values, writable: true, configurable: true },
1778
+ _lease: { value: retainNodes(document, ids), writable: true, configurable: true },
1779
+ options: { value: options, writable: true, configurable: true, enumerable: true },
1780
+ _root: { value: root, writable: true, configurable: true, enumerable: true },
1781
+ length: { configurable: true, enumerable: true, get: () => this._values?.length ?? this._ids.length, set: (value) => {
1782
+ if (this._values)
1783
+ this._values.length = value;
1784
+ else
1785
+ this._ids.length = value;
1786
+ this._lease = retainNodes(document, this._values ? [] : this._ids);
1787
+ } }
1788
+ });
1789
+ delete this.cheerio;
1790
+ return new Proxy(this, {
1791
+ get: (target, property2, receiver) => typeof property2 === "string" && numeric.test(property2) ? target._values ? target._values[Number(property2)] : target._ids[Number(property2)] === void 0 ? void 0 : getNode(document, target._ids[Number(property2)]) : Reflect.get(target, property2, receiver),
1792
+ set: (target, property2, value, receiver) => {
1793
+ if (typeof property2 === "string" && numeric.test(property2)) {
1794
+ if (target._values)
1795
+ target._values[Number(property2)] = value;
1796
+ else {
1797
+ const id = importNodes(document, [value])[0];
1798
+ if (id === void 0) {
1799
+ target._values = target._ids.map((existing) => getNode(document, existing));
1800
+ target._values[Number(property2)] = value;
1801
+ } else
1802
+ target._ids[Number(property2)] = id;
1803
+ }
1804
+ target._lease = retainNodes(document, target._values ? [] : target._ids);
1805
+ return true;
1806
+ }
1807
+ return Reflect.set(target, property2, value, receiver);
1808
+ },
1809
+ has: (target, property2) => typeof property2 === "string" && numeric.test(property2) ? Number(property2) < target.length : Reflect.has(target, property2),
1810
+ ownKeys: (target) => [...Array.from({ length: target.length }, (_, i) => String(i)), ...Reflect.ownKeys(target)],
1811
+ getOwnPropertyDescriptor: (target, property2) => typeof property2 === "string" && numeric.test(property2) && Number(property2) < target.length ? { value: target._values ? target._values[Number(property2)] : getNode(document, target._ids[Number(property2)]), writable: true, configurable: true, enumerable: true } : Reflect.getOwnPropertyDescriptor(target, property2),
1812
+ deleteProperty: (target, property2) => {
1813
+ if (typeof property2 === "string" && numeric.test(property2)) {
1814
+ if (target._values)
1815
+ delete target._values[Number(property2)];
1816
+ else
1817
+ delete target._ids[Number(property2)];
1818
+ target._lease = retainNodes(document, target._values ? [] : target._ids);
1819
+ return true;
1820
+ }
1821
+ return Reflect.deleteProperty(target, property2);
1822
+ }
1823
+ });
1824
+ }
1825
+ /** @internal */
1826
+ get ids() {
1827
+ return this._values ? importNodes(this._document, this._values) : this._ids;
1828
+ }
1829
+ /** @internal */
1830
+ op(command, args = {}) {
1831
+ const values = args;
1832
+ return operation(this._document, command, { ...values, options: values.options ?? this.options });
1833
+ }
1834
+ /** @internal */
1835
+ _query(command, args) {
1836
+ const callbacks = Object.entries(this.options.pseudos ?? {}).filter((entry) => typeof entry[1] === "function");
1837
+ if (!callbacks.length)
1838
+ return command === "select" && !args.options ? this._document.select(args.selector, args.contexts) : this.op(command, args);
1839
+ const pseudoMatches = {};
1840
+ const candidates = [.../* @__PURE__ */ new Set([...this._document.select("*"), ...args.ids ?? [], ...args.contexts ? this._document.select("*", args.contexts) : []])];
1841
+ for (const [name, callback] of callbacks) {
1842
+ for (const argument of customPseudoArguments(args.selector, name)) {
1843
+ if (argument !== void 0 && callback.length < 2)
1844
+ throw new Error(`Pseudo-class :${name} doesn't have any arguments`);
1845
+ if (argument === void 0 && callback.length >= 2)
1846
+ throw new Error(`Pseudo-class :${name} requires an argument`);
1847
+ pseudoMatches[`${name}(${argument ?? ""})`] = candidates.filter((id) => callback(getNode(this._document, id), argument ?? null));
1848
+ }
1849
+ }
1850
+ return this.op(command, { ...args, pseudoMatches });
1851
+ }
1852
+ /** @internal */
1853
+ _fromIds(ids) {
1854
+ const result = new this._api.fn.constructor(this._api, this._document, ids, this._root, this.options);
1855
+ result.prevObject = this;
1856
+ return result;
1857
+ }
1858
+ /** @internal */
1859
+ _fromValues(values) {
1860
+ const allNodes = values.every((value) => value && typeof value === "object" && typeof value.type === "string");
1861
+ const result = new this._api.fn.constructor(this._api, this._document, allNodes ? importNodes(this._document, values) : [], this._root, this.options, allNodes ? void 0 : values);
1862
+ result.prevObject = this;
1863
+ return result;
1864
+ }
1865
+ _make(value, context) {
1866
+ const result = typeof value === "string" || value?.cheerio ? this._api(value, context) : this._fromValues(value == null ? [] : typeof value === "object" && "length" in value && !value.type ? Array.from(value) : [value]);
1867
+ result.prevObject = this;
1868
+ return result;
1869
+ }
1870
+ _parse(content, options, isDocument2, context) {
1871
+ return parse(content, options, isDocument2, context);
1872
+ }
1873
+ _render(content) {
1874
+ return this._document.outerHtml(importNodes(this._document, content));
1875
+ }
1876
+ /** @internal */
1877
+ _domIds(content, contextId) {
1878
+ if (content == null || content === false)
1879
+ return [];
1880
+ if (typeof content === "string")
1881
+ return this.op("create", { html: content, contextId, options: this.options });
1882
+ if (content?.cheerio)
1883
+ return content._document && sameNodeSpace(this._document, content._document) ? content.ids : importNodes(this._document, content.toArray());
1884
+ if (typeof content === "object" && "length" in content && !content.type)
1885
+ return Array.from(content).flatMap((item) => this._domIds(item, contextId));
1886
+ return importNodes(this._document, [content]);
1887
+ }
1888
+ _makeDomArray(content, clone = false) {
1889
+ const ids = this._domIds(content);
1890
+ return (clone ? this.op("clone", { ids, deep: true }) : ids).map((id) => getNode(this._document, id));
1891
+ }
1892
+ find(selector) {
1893
+ if (!selector)
1894
+ return this._fromIds([]);
1895
+ if (typeof selector === "string")
1896
+ return this._findBySelector(selector, Infinity);
1897
+ const ids = importNodes(this._document, selector);
1898
+ return this._fromIds(ids.filter((id) => this.ids.some((container) => this.op("contains", { container, contained: id }))));
1899
+ }
1900
+ _findBySelector(selector, limit) {
1901
+ const ids = this._query("select", { selector, contexts: this.ids });
1902
+ return this._fromIds(Number.isFinite(limit) ? ids.slice(0, limit) : ids);
1903
+ }
1904
+ /** @internal */
1905
+ _filterIds(ids, selector) {
1906
+ if (!selector)
1907
+ return ids;
1908
+ if (typeof selector === "string")
1909
+ return this._query("matches", { ids, selector, options: this.options });
1910
+ return ids.filter((id, index) => this._predicate(selector, getNode(this._document, id), index));
1911
+ }
1912
+ /** @internal */
1913
+ _predicate(selector, node, index) {
1914
+ if (typeof selector === "function")
1915
+ return !!selector.call(node, index, node);
1916
+ if (typeof selector === "string")
1917
+ return this._query("matches", { ids: importNodes(this._document, [node]), selector, options: this.options }).length > 0;
1918
+ if (selector?.cheerio)
1919
+ return selector.toArray().includes(node);
1920
+ return node === selector;
1921
+ }
1922
+ /** @internal */
1923
+ _traverse(kind, selector) {
1924
+ let ids = this.op("traverse", { ids: this.ids, kind });
1925
+ ids = this._filterIds(ids, selector);
1926
+ if (this.length > 1 && ids.length > 1) {
1927
+ if (kind === "parents" || kind === "siblings")
1928
+ ids = this.op("uniqueSort", { ids });
1929
+ else if (!["next", "prev", "contents"].includes(kind))
1930
+ ids = [...new Set(ids)];
1931
+ if (kind === "parents")
1932
+ ids.reverse();
1933
+ }
1934
+ return this._fromIds(ids);
1935
+ }
1936
+ parent(selector) {
1937
+ return this._traverse("parent", selector);
1938
+ }
1939
+ parents(selector) {
1940
+ return this._traverse("parents", selector);
1941
+ }
1942
+ next(selector) {
1943
+ return this._traverse("next", selector);
1944
+ }
1945
+ prev(selector) {
1946
+ return this._traverse("prev", selector);
1947
+ }
1948
+ nextAll(selector) {
1949
+ return this._traverse("nextAll", selector);
1950
+ }
1951
+ prevAll(selector) {
1952
+ return this._traverse("prevAll", selector);
1953
+ }
1954
+ siblings(selector) {
1955
+ return this._traverse("siblings", selector);
1956
+ }
1957
+ children(selector) {
1958
+ return this._traverse("children", selector);
1959
+ }
1960
+ contents() {
1961
+ return this._traverse("contents");
1962
+ }
1963
+ /** @internal */
1964
+ _until(kind, until, filter) {
1965
+ let ids = [];
1966
+ for (const id of this.ids)
1967
+ for (const candidate of this.op("traverse", { ids: [id], kind })) {
1968
+ if (until && this._predicate(until, getNode(this._document, candidate), ids.length))
1969
+ break;
1970
+ ids.push(candidate);
1971
+ }
1972
+ ids = this._filterIds(ids, filter);
1973
+ if (this.length > 1 && ids.length > 1)
1974
+ ids = kind === "parents" ? this.op("uniqueSort", { ids }).reverse() : [...new Set(ids)];
1975
+ return this._fromIds(ids);
1976
+ }
1977
+ parentsUntil(until, filter) {
1978
+ return this._until("parents", until, filter);
1979
+ }
1980
+ nextUntil(until, filter) {
1981
+ return this._until("nextAll", until, filter);
1982
+ }
1983
+ prevUntil(until, filter) {
1984
+ return this._until("prevAll", until, filter);
1985
+ }
1986
+ closest(selector) {
1987
+ if (!selector)
1988
+ return this._fromIds([]);
1989
+ const result = [];
1990
+ for (const id of this.ids) {
1991
+ const record = nodeRecord(this._document, id);
1992
+ const candidates = [...["tag", "script", "style"].includes(record.type) ? [id] : [], ...this.op("traverse", { ids: [id], kind: "parents" })];
1993
+ const match = candidates.find((candidate) => this._predicate(selector, getNode(this._document, candidate), 0));
1994
+ if (match !== void 0 && !result.includes(match))
1995
+ result.push(match);
1996
+ }
1997
+ return this._fromIds(result);
1998
+ }
1999
+ each(callback) {
2000
+ const length = this.length;
2001
+ for (let i = 0; i < length; i++)
2002
+ if (callback.call(this[i], i, this[i]) === false)
2003
+ break;
2004
+ return this;
2005
+ }
2006
+ map(callback) {
2007
+ const result = [];
2008
+ for (let i = 0; i < this.length; i++) {
2009
+ const value = callback.call(this[i], i, this[i]);
2010
+ if (value != null)
2011
+ result.push(...Array.isArray(value) ? value : [value]);
2012
+ }
2013
+ return this._fromValues(result);
2014
+ }
2015
+ filter(selector) {
2016
+ return typeof selector === "string" ? this._fromIds(this._query("matches", { ids: this.ids, selector, options: this.options })) : this._fromValues(this.toArray().filter((node, i) => this._predicate(selector, node, i)));
2017
+ }
2018
+ filterArray(nodes, match, xmlMode, root) {
2019
+ const matcher = match;
2020
+ if (typeof match !== "string")
2021
+ return nodes.filter((node, index) => typeof matcher === "function" ? matcher.call(node, index, node) : matcher?.cheerio ? matcher.toArray().includes(node) : matcher === node);
2022
+ const document = this?._document ?? nodeBinding(root)?.document ?? nodeBinding(nodes[0])?.document ?? new (requireNative()).NativeDocument("", false);
2023
+ const ids = importNodes(document, nodes);
2024
+ const selected = new Set(operation(document, "matches", { ids, selector: match, options: { xmlMode } }));
2025
+ return nodes.filter((node) => {
2026
+ const id = nodeId(node, document);
2027
+ return id !== void 0 && selected.has(id);
2028
+ });
2029
+ }
2030
+ not(selector) {
2031
+ if (typeof selector === "string") {
2032
+ const matched = new Set(this._query("matches", { ids: this.ids, selector, options: this.options }));
2033
+ return this._fromIds(this.ids.filter((id) => !matched.has(id)));
2034
+ }
2035
+ return this._fromValues(this.toArray().filter((node, i) => !this._predicate(selector, node, i)));
2036
+ }
2037
+ is(selector) {
2038
+ return typeof selector === "string" ? this._query("matches", { ids: this.ids, selector, options: this.options }).length > 0 : !!selector && this.toArray().some((node, i) => this._predicate(selector, node, i));
2039
+ }
2040
+ has(selector) {
2041
+ return this.filter(((_i, node) => this._make(node).find(selector).length > 0));
2042
+ }
2043
+ first() {
2044
+ return this.length > 1 ? this.slice(0, 1) : this;
2045
+ }
2046
+ last() {
2047
+ return this.length > 0 ? this.slice(-1) : this;
2048
+ }
2049
+ eq(index) {
2050
+ index = +index;
2051
+ if (index === 0 && this.length <= 1)
2052
+ return this;
2053
+ if (index < 0)
2054
+ index += this.length;
2055
+ return this._fromValues(this[index] === void 0 ? [] : [this[index]]);
2056
+ }
2057
+ get(index) {
2058
+ return index == null ? this.toArray() : this[index < 0 ? this.length + index : index];
2059
+ }
2060
+ toArray() {
2061
+ return Array.from({ length: this.length }, (_unused, i) => this[i]);
2062
+ }
2063
+ slice(start, end) {
2064
+ return this._values ? this._fromValues(this._values.slice(start, end)) : this._fromIds(this._ids.slice(start, end));
2065
+ }
2066
+ end() {
2067
+ return this.prevObject ?? this._make([]);
2068
+ }
2069
+ add(other, context) {
2070
+ return this._fromIds(this.op("uniqueSort", { ids: [...this.ids, ...this._api(other, context).ids] }));
2071
+ }
2072
+ addBack(selector) {
2073
+ return this.prevObject ? this.add(selector ? this.prevObject.filter(selector) : this.prevObject) : this;
2074
+ }
2075
+ index(selector) {
2076
+ const haystack = selector == null ? this.parent().children() : typeof selector === "string" ? this._api(selector) : this;
2077
+ const needle = selector == null || typeof selector === "string" ? this[0] : selector?.cheerio ? selector[0] : selector;
2078
+ return haystack.toArray().indexOf(needle);
2079
+ }
2080
+ splice(...args) {
2081
+ return Reflect.apply(Array.prototype.splice, this, args);
2082
+ }
2083
+ *[Symbol.iterator]() {
2084
+ for (let i = 0; i < this.length; i++)
2085
+ yield this[i];
2086
+ }
2087
+ /** @internal */
2088
+ _insert(position, content) {
2089
+ const targets = this.ids.filter((id) => ["root", "tag", "script", "style", "cdata"].includes(nodeRecord(this._document, id).type));
2090
+ if (!targets.length)
2091
+ return this;
2092
+ if (typeof content[0] === "function")
2093
+ return this.each((index, node) => {
2094
+ if (!targets.includes(this.ids[index]))
2095
+ return;
2096
+ if ((position === "before" || position === "after") && nodeRecord(this._document, this.ids[index]).parent == null)
2097
+ return;
2098
+ const value = content[0].call(node, index, this._document.innerHtml(this.ids[index]));
2099
+ let nodes2 = this._domIds(value);
2100
+ if (index < this.length - 1)
2101
+ nodes2 = this.op("clone", { ids: nodes2, deep: true });
2102
+ this.op("insert", { targetIds: [this.ids[index]], nodeIds: nodes2, position });
2103
+ });
2104
+ let nodes = this._domIds(content);
2105
+ if (targets[targets.length - 1] !== this.ids[this.ids.length - 1])
2106
+ nodes = this.op("clone", { ids: nodes, deep: true });
2107
+ this.op("insert", { targetIds: targets, nodeIds: nodes, position });
2108
+ return this;
2109
+ }
2110
+ append(...content) {
2111
+ return this._insert("append", content);
2112
+ }
2113
+ prepend(...content) {
2114
+ return this._insert("prepend", content);
2115
+ }
2116
+ before(...content) {
2117
+ return this._insert("before", content);
2118
+ }
2119
+ after(...content) {
2120
+ return this._insert("after", content);
2121
+ }
2122
+ appendTo(target) {
2123
+ this._api(target).append(this);
2124
+ return this;
2125
+ }
2126
+ prependTo(target) {
2127
+ this._api(target).prepend(this);
2128
+ return this;
2129
+ }
2130
+ /** @internal */
2131
+ _insertRelative(target, position) {
2132
+ const targets = this._api(target).ids;
2133
+ this.remove();
2134
+ const inserted = [];
2135
+ for (const id of targets) {
2136
+ if (nodeRecord(this._document, id).parent == null)
2137
+ continue;
2138
+ const clones = this.op("clone", { ids: this.ids, deep: true });
2139
+ this.op("insert", { targetIds: [id], nodeIds: clones, position });
2140
+ inserted.push(...clones);
2141
+ }
2142
+ return this._fromIds(inserted);
2143
+ }
2144
+ insertBefore(target) {
2145
+ return this._insertRelative(target, "before");
2146
+ }
2147
+ insertAfter(target) {
2148
+ return this._insertRelative(target, "after");
2149
+ }
2150
+ remove(selector) {
2151
+ this.op("remove", { ids: selector ? this.filter(selector).ids : this.ids });
2152
+ return this;
2153
+ }
2154
+ replaceWith(content) {
2155
+ return this.each((index, node) => {
2156
+ if (nodeRecord(this._document, this.ids[index]).parent == null)
2157
+ return;
2158
+ const value = typeof content === "function" ? content.call(node, index, node) : content;
2159
+ this.op("insert", { targetIds: [this.ids[index]], nodeIds: this._domIds(value), position: "replace" });
2160
+ });
2161
+ }
2162
+ empty() {
2163
+ for (const id of this.ids)
2164
+ this.op("setNode", { id, field: "children", value: [] });
2165
+ return this;
2166
+ }
2167
+ html(content) {
2168
+ if (content === void 0)
2169
+ return this.length && ["root", "tag", "script", "style", "cdata"].includes(nodeRecord(this._document, this.ids[0]).type) ? this._document.innerHtml(this.ids[0]) : null;
2170
+ if (!content?.cheerio) {
2171
+ this.op("html", { ids: this.ids, value: String(content) });
2172
+ return this;
2173
+ }
2174
+ for (const id of this.ids) {
2175
+ const nodes = content?.cheerio ? importNodes(this._document, content.toArray()) : this._domIds(String(content), id);
2176
+ this.op("setNode", { id, field: "children", value: nodes });
2177
+ }
2178
+ return this;
2179
+ }
2180
+ text(content) {
2181
+ if (content === void 0)
2182
+ return this._document.text(this.ids);
2183
+ if (typeof content !== "function") {
2184
+ this.op("text", { ids: this.ids, value: String(content) });
2185
+ return this;
2186
+ }
2187
+ for (let i = 0; i < this.ids.length; i++) {
2188
+ const id = this.ids[i];
2189
+ const value = typeof content === "function" ? content.call(getNode(this._document, id), i, this._document.text([id])) : content;
2190
+ this.op("text", { ids: [id], value: String(value) });
2191
+ }
2192
+ return this;
2193
+ }
2194
+ toString() {
2195
+ return this._document.outerHtml(this.ids);
2196
+ }
2197
+ clone() {
2198
+ return this._fromIds(this.op("clone", { ids: this.ids, deep: true }));
2199
+ }
2200
+ /** @internal */
2201
+ _deepest(id, tagsOnly = false) {
2202
+ for (; ; ) {
2203
+ const children2 = this.op("traverse", { ids: [id], kind: "children" });
2204
+ const child = tagsOnly ? children2.find((candidate) => nodeRecord(this._document, candidate).type === "tag") : children2[0];
2205
+ if (child === void 0)
2206
+ return id;
2207
+ id = child;
2208
+ }
2209
+ }
2210
+ /** @internal */
2211
+ _wrap(content, inner) {
2212
+ const lastParent = this.parents().last();
2213
+ for (let i = 0; i < this.length; i++) {
2214
+ const id = this.ids[i];
2215
+ const node = getNode(this._document, id);
2216
+ const value = typeof content === "function" ? content.call(node, i, node) : typeof content === "string" && !isMarkup(content) ? lastParent.find(content).clone() : content;
2217
+ let wrappers = this._domIds(value);
2218
+ if (i < this.length - 1)
2219
+ wrappers = this.op("clone", { ids: wrappers, deep: true });
2220
+ const wrapper = wrappers[0];
2221
+ if (wrapper === void 0 || !["root", "tag", "script", "style"].includes(nodeRecord(this._document, wrapper).type))
2222
+ continue;
2223
+ const deepest = this._deepest(wrapper);
2224
+ if (inner) {
2225
+ if (!["root", "tag", "script", "style", "cdata"].includes(nodeRecord(this._document, id).type))
2226
+ continue;
2227
+ const contents = this.op("traverse", { ids: [id], kind: "contents" });
2228
+ this.op("setNode", { id: deepest, field: "children", value: contents });
2229
+ this.op("setNode", { id, field: "children", value: [wrapper] });
2230
+ } else if (nodeRecord(this._document, id).parent != null) {
2231
+ this.op("insert", { targetIds: [id], nodeIds: [wrapper], position: "before" });
2232
+ this.op("setNode", { id: deepest, field: "children", value: [id] });
2233
+ }
2234
+ }
2235
+ return this;
2236
+ }
2237
+ wrap(content) {
2238
+ return this._wrap(content, false);
2239
+ }
2240
+ wrapInner(content) {
2241
+ return this._wrap(content, true);
2242
+ }
2243
+ unwrap(selector) {
2244
+ this.op("remove", { ids: this.parent(selector).not("body").ids, keepChildren: true });
2245
+ return this;
2246
+ }
2247
+ wrapAll(content) {
2248
+ if (!this.length)
2249
+ return this;
2250
+ const first = this[0];
2251
+ const wrappers = this._make(typeof content === "function" ? content.call(first, 0, first) : content).insertBefore(first);
2252
+ const root = [...wrappers.ids].reverse().find((id) => nodeRecord(this._document, id).type === "tag");
2253
+ if (root !== void 0)
2254
+ this.op("insert", { targetIds: [this._deepest(root, true)], nodeIds: this.ids, position: "append" });
2255
+ return this;
2256
+ }
2257
+ extract(map) {
2258
+ return extract.call(this, map);
2259
+ }
2260
+ };
2261
+ Object.defineProperty(Cheerio.prototype, "cheerio", { value: "[cheerio object]", writable: true, configurable: true });
2262
+ installAttributes(Cheerio);
2263
+ var nativeExtractionMethods = Object.freeze({
2264
+ make: Cheerio.prototype._make,
2265
+ find: Cheerio.prototype._findBySelector,
2266
+ prop: Cheerio.prototype.prop,
2267
+ extract: Cheerio.prototype.extract
2268
+ });
2269
+
2270
+ // src/extract.ts
2271
+ import { types as types2 } from "util";
2272
+ function plainKeys(map) {
2273
+ return !types2.isProxy(map) && (Object.getPrototypeOf(map) === Object.prototype || Object.getPrototypeOf(map) === null) ? Object.keys(map) : void 0;
2274
+ }
2275
+ function nativePrefix(scope, map, keys, key) {
2276
+ if (!keys || scope._make !== nativeExtractionMethods.make || scope._findBySelector !== nativeExtractionMethods.find || scope.prop !== nativeExtractionMethods.prop || scope.extract !== nativeExtractionMethods.extract) return void 0;
2277
+ const prefix = /* @__PURE__ */ Object.create(null);
2278
+ let count = 0;
2279
+ let plan;
2280
+ const index = keys.indexOf(key);
2281
+ for (let position = index; position < keys.length; position++) {
2282
+ const name = keys[position];
2283
+ const slot = Object.getOwnPropertyDescriptor(map, name);
2284
+ if (!slot || !slot.enumerable || !("value" in slot)) break;
2285
+ Object.defineProperty(prefix, name, { value: slot.value, enumerable: true, configurable: true });
2286
+ const compiled = compileExtractPlan(prefix, scope.options);
2287
+ if (!compiled) {
2288
+ delete prefix[name];
2289
+ break;
2290
+ }
2291
+ plan = compiled;
2292
+ count++;
2293
+ }
2294
+ if (!plan || !count) return void 0;
2295
+ const values = scope.op("extractPlan", { ids: scope.ids, plan });
2296
+ hydrateExtractResult(values, plan.entries);
2297
+ return { keys: Object.keys(prefix), values };
2298
+ }
2299
+ function extract(map) {
2300
+ const result = {};
2301
+ const keys = plainKeys(map);
2302
+ const processed = /* @__PURE__ */ new Set();
2303
+ for (const key in map) {
2304
+ if (processed.has(key)) continue;
2305
+ const prefix = Object.getPrototypeOf(result) === Object.prototype ? nativePrefix(this, map, keys, key) : void 0;
2306
+ if (prefix) {
2307
+ for (const name of prefix.keys) {
2308
+ Object.defineProperty(result, name, { value: prefix.values[name], enumerable: true, configurable: true, writable: true });
2309
+ processed.add(name);
2310
+ }
2311
+ continue;
2312
+ }
2313
+ const entry = map[key];
2314
+ const all = Array.isArray(entry);
2315
+ const descriptor = all ? entry[0] : entry;
2316
+ const selector = typeof descriptor === "string" ? descriptor : descriptor.selector;
2317
+ const value = typeof descriptor === "string" ? "textContent" : descriptor.value ?? "textContent";
2318
+ const selection = this._findBySelector(selector, all ? Infinity : 1);
2319
+ const read = (index) => {
2320
+ if (typeof value === "function") return value(selection[index], key, result);
2321
+ const scope = this._make === nativeExtractionMethods.make ? this._fromIds([selection.ids[index]]) : this._make(selection[index]);
2322
+ return typeof value === "string" ? scope.prop(value) : scope.extract(value);
2323
+ };
2324
+ let extracted;
2325
+ if (all) {
2326
+ const values = [];
2327
+ for (let index = 0; index < selection.length; index += 1) {
2328
+ const value2 = read(index);
2329
+ if (value2 != null) values.push(...Array.isArray(value2) ? value2 : [value2]);
2330
+ }
2331
+ extracted = values;
2332
+ } else {
2333
+ extracted = selection.length ? read(0) : void 0;
2334
+ }
2335
+ result[key] = extracted;
2336
+ }
2337
+ return result;
2338
+ }
2339
+ async function extractCooperatively(selection, map) {
2340
+ let deadline = performance.now() + 4;
2341
+ let visits = 0;
2342
+ const checkpoint = async () => {
2343
+ if (++visits % 32 || performance.now() < deadline) return;
2344
+ await new Promise((resolve) => setImmediate(resolve));
2345
+ deadline = performance.now() + 4;
2346
+ };
2347
+ const walk = async (scope, descriptors) => {
2348
+ const result = {};
2349
+ const keys = plainKeys(descriptors);
2350
+ const processed = /* @__PURE__ */ new Set();
2351
+ for (const key in descriptors) {
2352
+ if (processed.has(key)) continue;
2353
+ const prefix = Object.getPrototypeOf(result) === Object.prototype ? nativePrefix(scope, descriptors, keys, key) : void 0;
2354
+ if (prefix) {
2355
+ for (const name of prefix.keys) {
2356
+ Object.defineProperty(result, name, { value: prefix.values[name], enumerable: true, configurable: true, writable: true });
2357
+ processed.add(name);
2358
+ }
2359
+ continue;
2360
+ }
2361
+ const entry = descriptors[key];
2362
+ const all = Array.isArray(entry);
2363
+ const descriptor = all ? entry[0] : entry;
2364
+ const selector = typeof descriptor === "string" ? descriptor : descriptor.selector;
2365
+ const value = typeof descriptor === "string" ? "textContent" : descriptor.value ?? "textContent";
2366
+ const found = scope._findBySelector(selector, all ? Infinity : 1);
2367
+ const output = [];
2368
+ let single;
2369
+ const count = all ? found.length : Math.min(found.length, 1);
2370
+ for (let index = 0; index < count; index++) {
2371
+ await checkpoint();
2372
+ let extracted;
2373
+ if (typeof value === "function") extracted = value(found[index], key, result);
2374
+ else {
2375
+ const child = scope._make === nativeExtractionMethods.make ? scope._fromIds([found.ids[index]]) : scope._make(found[index]);
2376
+ extracted = typeof value === "string" ? child.prop(value) : child.extract === nativeExtractionMethods.extract ? (await walk(child, value)).value : child.extract(value);
2377
+ }
2378
+ if (all) {
2379
+ if (extracted != null) output.push(...Array.isArray(extracted) ? extracted : [extracted]);
2380
+ } else single = extracted;
2381
+ }
2382
+ result[key] = all ? output : single;
2383
+ }
2384
+ return { value: result };
2385
+ };
2386
+ return await walk(selection, map);
2387
+ }
2388
+
2389
+ // src/index.ts
2390
+ import { setImmediate as yieldToEventLoop } from "timers/promises";
2391
+ import { availableParallelism } from "os";
2392
+
2393
+ // src/workers.ts
2394
+ function configureWorkers(options) {
2395
+ const threads = typeof options === "number" ? options : options?.threads;
2396
+ if (!Number.isSafeInteger(threads) || threads < 1 || threads > 256) throw new RangeError("threads must be an integer from 1 to 256");
2397
+ const binding = requireNative();
2398
+ if (!binding.configureWorkerPool || !binding.workerPoolInfo) throw new Error("This native build does not support a shared worker pool");
2399
+ binding.configureWorkerPool(threads);
2400
+ return binding.workerPoolInfo();
2401
+ }
2402
+ function workerPoolInfo() {
2403
+ const binding = requireNative();
2404
+ if (!binding.workerPoolInfo) throw new Error("This native build does not support worker pool diagnostics");
2405
+ return binding.workerPoolInfo();
2406
+ }
2407
+
2408
+ // src/io.ts
2409
+ import { Readable, Writable } from "stream";
2410
+ import { request as requestHTTP } from "http";
2411
+ import { request as requestHTTPS } from "https";
2412
+ import { stringify as stringifyQuery } from "querystring";
2413
+ import { MIMEType } from "util";
2414
+ function encodingLabel(label) {
2415
+ if (!label) return void 0;
2416
+ if (label.trim().toLowerCase() === "x-user-defined") return "x-user-defined";
2417
+ try {
2418
+ return new TextDecoder(label.trim()).encoding;
2419
+ } catch {
2420
+ return void 0;
2421
+ }
2422
+ }
2423
+ function sniffEncoding(buffer, options = {}) {
2424
+ let label;
2425
+ if (buffer[0] === 239 && buffer[1] === 187 && buffer[2] === 191) label = "utf-8";
2426
+ else if (buffer[0] === 255 && buffer[1] === 254) label = "utf-16le";
2427
+ else if (buffer[0] === 254 && buffer[1] === 255) label = "utf-16be";
2428
+ label ??= encodingLabel(options.userEncoding);
2429
+ label ??= encodingLabel(options.transportLayerEncodingLabel);
2430
+ if (!label && buffer[0] === 0 && buffer[1] === 60 && buffer[2] === 0 && buffer[3] === 63 && buffer[4] === 0 && buffer[5] === 120) label = "utf-16be";
2431
+ if (!label && buffer[0] === 60 && buffer[1] === 0 && buffer[2] === 63 && buffer[3] === 0 && buffer[4] === 120 && buffer[5] === 0) label = "utf-16le";
2432
+ if (!label) {
2433
+ const prefix = Buffer.from(buffer.subarray(0, options.maxBytes ?? 1024)).toString("latin1").replace(/<!--[\s\S]*?(?:-->|$)/g, "");
2434
+ for (const token of prefix.matchAll(/<meta\b([^>]*)>/gi)) {
2435
+ const attributes2 = {};
2436
+ for (const attribute of token[1].matchAll(/([^\s=/'">]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'>]+)))?/g)) {
2437
+ const key = attribute[1].toLowerCase();
2438
+ if (!(key in attributes2)) attributes2[key] = attribute[2] ?? attribute[3] ?? attribute[4] ?? "";
2439
+ }
2440
+ const declared = attributes2.charset ?? (attributes2["http-equiv"]?.toLowerCase() === "content-type" ? /\bcharset\s*=\s*["']?([^\s;"']+)/i.exec(attributes2.content ?? "")?.[1] : void 0);
2441
+ label = encodingLabel(declared);
2442
+ if (label) {
2443
+ if (label === "utf-16le" || label === "utf-16be") label = "utf-8";
2444
+ if (label === "x-user-defined") label = "windows-1252";
2445
+ break;
2446
+ }
2447
+ }
2448
+ if (!label) {
2449
+ const declaration = /<\?xml\b[^>]*\bencoding\s*=\s*["']([^"']+)["']/i.exec(prefix);
2450
+ label = encodingLabel(declaration?.[1]);
2451
+ if (label === "utf-16le" || label === "utf-16be") label = "utf-8";
2452
+ }
2453
+ }
2454
+ label ??= encodingLabel(options.defaultEncoding) ?? "windows-1252";
2455
+ return label;
2456
+ }
2457
+ function decodeBuffer(buffer, options = {}) {
2458
+ const label = sniffEncoding(buffer, options);
2459
+ if (label === "x-user-defined") {
2460
+ let decoded = "";
2461
+ for (const byte of buffer) decoded += String.fromCharCode(byte < 128 ? byte : 63232 + byte);
2462
+ return decoded;
2463
+ }
2464
+ return new TextDecoder(label).decode(buffer);
2465
+ }
2466
+ function decodedInput(buffer, options) {
2467
+ const { encoding, ...parserOptions2 } = options;
2468
+ const xml = !!(options.xmlMode || options.xml);
2469
+ return [decodeBuffer(buffer, { defaultEncoding: xml ? "utf-8" : "windows-1252", ...encoding }), parserOptions2];
2470
+ }
2471
+ function loadBuffer(buffer, options = {}) {
2472
+ return load(...decodedInput(buffer, options));
2473
+ }
2474
+ function completion(callback) {
2475
+ let completed = false;
2476
+ return (error, document) => {
2477
+ if (completed) return;
2478
+ completed = true;
2479
+ callback(error, document);
2480
+ };
2481
+ }
2482
+ function requestHeaders(input) {
2483
+ if (!input) return new Headers();
2484
+ if (input instanceof Headers) return new Headers(input);
2485
+ const headers = new Headers();
2486
+ if (Array.isArray(input)) {
2487
+ if (input.length % 2) throw new TypeError("HTTP header arrays must contain name/value pairs");
2488
+ for (let index = 0; index < input.length; index += 2) headers.append(input[index], input[index + 1]);
2489
+ } else {
2490
+ const entries = Symbol.iterator in input ? input : Object.entries(input);
2491
+ for (const [name, value] of entries) {
2492
+ if (value == null) continue;
2493
+ for (const item of Array.isArray(value) ? value : [value]) headers.append(name, item);
2494
+ }
2495
+ }
2496
+ return headers;
2497
+ }
2498
+ async function requestDocument(url, method, headers, body, options, signal) {
2499
+ if (options.typeOfService != null && (!Number.isInteger(options.typeOfService) || options.typeOfService < 0 || options.typeOfService > 255)) {
2500
+ throw Object.assign(new Error("typeOfService must be an integer between 0 and 255"), { name: "InvalidArgumentError", code: "UND_ERR_INVALID_ARG" });
2501
+ }
2502
+ let payload = body;
2503
+ if (body && typeof body === "object" && !(body instanceof Uint8Array) && !(body instanceof Readable)) {
2504
+ let form;
2505
+ if (body instanceof FormData) form = body;
2506
+ else {
2507
+ form = new FormData();
2508
+ for (const [name, value] of body) {
2509
+ if (typeof value === "string") form.append(name, value);
2510
+ else if ("name" in value && typeof value.name === "string") form.append(name, value, value.name);
2511
+ else form.append(name, value);
2512
+ }
2513
+ }
2514
+ const encoded2 = new Request(url, { method: "POST", body: form });
2515
+ payload = Readable.from((async function* () {
2516
+ let previous = -1;
2517
+ let last = -1;
2518
+ for await (const chunk of Readable.fromWeb(encoded2.body)) {
2519
+ const bytes = chunk;
2520
+ if (bytes.length >= 2) previous = bytes[bytes.length - 2];
2521
+ else if (bytes.length === 1) previous = last;
2522
+ if (bytes.length) last = bytes[bytes.length - 1];
2523
+ yield bytes;
2524
+ }
2525
+ if (previous !== 13 || last !== 10) yield Buffer.from("\r\n");
2526
+ })());
2527
+ if (!requestHeaders(options.headers).has("content-type")) headers.set("content-type", encoded2.headers.get("content-type"));
2528
+ }
2529
+ if (payload != null && !(payload instanceof Readable) && !(typeof payload === "object" && "getReader" in payload) && !headers.has("content-length") && !headers.has("transfer-encoding")) {
2530
+ headers.set("content-length", String(typeof payload === "string" ? Buffer.byteLength(payload) : payload.byteLength));
2531
+ }
2532
+ const declaredLength = headers.has("content-length") ? Number(headers.get("content-length")) : void 0;
2533
+ const lengthError = () => Object.assign(new Error("Request body length does not match content-length header"), { name: "RequestContentLengthMismatchError", code: "UND_ERR_REQ_CONTENT_LENGTH_MISMATCH" });
2534
+ const knownLength = typeof payload === "string" ? Buffer.byteLength(payload) : payload instanceof Uint8Array ? payload.byteLength : void 0;
2535
+ if (declaredLength != null && knownLength != null && declaredLength !== knownLength) throw lengthError();
2536
+ if (options.reset === true && !headers.has("connection")) headers.set("connection", "close");
2537
+ return new Promise((resolve, reject) => {
2538
+ let informationalError;
2539
+ const request = (url.protocol === "https:" ? requestHTTPS : requestHTTP)(url, {
2540
+ method,
2541
+ headers: Object.fromEntries(headers),
2542
+ signal,
2543
+ ...typeof options.highWaterMark === "number" ? { highWaterMark: options.highWaterMark } : {}
2544
+ }, (response) => {
2545
+ if (informationalError) {
2546
+ response.destroy();
2547
+ return;
2548
+ }
2549
+ const rawHeaders = {};
2550
+ for (let index = 0; index < response.rawHeaders.length; index += 2) {
2551
+ const name = response.rawHeaders[index].toLowerCase();
2552
+ const value = response.rawHeaders[index + 1];
2553
+ if (!Object.hasOwn(rawHeaders, name)) Object.defineProperty(rawHeaders, name, { value, enumerable: true, writable: true, configurable: true });
2554
+ else rawHeaders[name] = [...Array.isArray(rawHeaders[name]) ? rawHeaders[name] : [rawHeaders[name]], value];
2555
+ }
2556
+ const responseHeaders = new Headers();
2557
+ for (const [name, value] of Object.entries(rawHeaders)) {
2558
+ if (value == null) continue;
2559
+ for (const item of Array.isArray(value) ? name === "content-type" ? value.slice(0, 1) : value : [value]) responseHeaders.append(name, item);
2560
+ }
2561
+ const status = response.statusCode ?? 0;
2562
+ resolve({ status, ok: status >= 200 && status < 300, headers: responseHeaders, rawHeaders, body: Readable.toWeb(response) });
2563
+ });
2564
+ request.once("error", (error) => reject(signal.aborted ? signal.reason : error));
2565
+ request.on("information", (information) => {
2566
+ try {
2567
+ options.onInfo?.({ statusCode: information.statusCode, headers: information.headers });
2568
+ } catch (error) {
2569
+ informationalError = error;
2570
+ reject(error);
2571
+ request.destroy(error);
2572
+ }
2573
+ });
2574
+ request.once("socket", (socket) => {
2575
+ const transport = socket;
2576
+ try {
2577
+ if (transport.setTypeOfService && options.typeOfService != null) transport.setTypeOfService(options.typeOfService);
2578
+ } catch (error) {
2579
+ request.destroy(error);
2580
+ return;
2581
+ }
2582
+ if (socket.connecting) {
2583
+ const timer = setTimeout(() => request.destroy(Object.assign(new Error("Connect Timeout Error"), { name: "ConnectTimeoutError", code: "UND_ERR_CONNECT_TIMEOUT" })), 1e4);
2584
+ timer.unref();
2585
+ socket.once(url.protocol === "https:" ? "secureConnect" : "connect", () => clearTimeout(timer));
2586
+ request.once("close", () => clearTimeout(timer));
2587
+ }
2588
+ });
2589
+ if (payload instanceof Readable || payload && typeof payload === "object" && "getReader" in payload) {
2590
+ const source = payload instanceof Readable ? payload : Readable.fromWeb(payload);
2591
+ if (declaredLength != null) {
2592
+ let sent = 0;
2593
+ source.on("data", (chunk) => {
2594
+ sent += typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.byteLength;
2595
+ if (sent > declaredLength) {
2596
+ request.destroy(lengthError());
2597
+ source.destroy();
2598
+ }
2599
+ });
2600
+ source.once("end", () => {
2601
+ if (sent !== declaredLength) request.destroy(lengthError());
2602
+ });
2603
+ }
2604
+ source.once("error", (error) => request.destroy(error));
2605
+ request.once("close", () => {
2606
+ if (!source.destroyed) source.destroy();
2607
+ });
2608
+ source.pipe(request);
2609
+ } else request.end(payload);
2610
+ });
2611
+ }
2612
+ function stringStream(options, callback) {
2613
+ const complete = completion(callback);
2614
+ const opts = flattenOptions(options);
2615
+ const xml = !!opts._useHtmlParser2;
2616
+ const binding = requireNative();
2617
+ let native;
2618
+ let writeNative;
2619
+ let finishNative;
2620
+ let abortNative;
2621
+ let carry = "";
2622
+ if (opts._useHtmlParser2 && opts.Tokenizer) {
2623
+ const session = createTokenizerSession(opts);
2624
+ const chunks = [];
2625
+ writeNative = async (chunk) => {
2626
+ chunks.push(chunk);
2627
+ session.write(chunk);
2628
+ };
2629
+ finishNative = async () => {
2630
+ const document = new binding.NativeDocument(chunks.join(""), true, JSON.stringify(session.end()));
2631
+ chunks.length = 0;
2632
+ return createAPI(routeDocument(document, opts), opts);
2633
+ };
2634
+ abortNative = () => {
2635
+ chunks.length = 0;
2636
+ };
2637
+ } else if (!opts._useHtmlParser2 && opts.treeAdapter) {
2638
+ const session = createTreeAdapterSession(opts, true);
2639
+ writeNative = (chunk) => session.write(chunk);
2640
+ finishNative = async () => createAPI(await session.end(), opts);
2641
+ abortNative = () => session.abort();
2642
+ } else if (!opts._useHtmlParser2 && opts.onParseError) {
2643
+ const session = createDiagnosticSession(opts, true);
2644
+ writeNative = (chunk) => session.write(chunk);
2645
+ finishNative = async () => createAPI(await session.end(), opts);
2646
+ abortNative = () => session.abort();
2647
+ } else {
2648
+ if (!binding.NativeStream) throw new Error("This native build does not support incremental parsing");
2649
+ native = new binding.NativeStream(JSON.stringify(parserOptions("", opts)), true);
2650
+ writeNative = (chunk) => native.write(chunk);
2651
+ finishNative = async () => {
2652
+ const document = await native.finish();
2653
+ deliverParseErrors(document, opts);
2654
+ return createAPI(routeDocument(document, opts), opts);
2655
+ };
2656
+ abortNative = () => native.abort();
2657
+ }
2658
+ const stream = new Writable({
2659
+ decodeStrings: false,
2660
+ write(chunk, _encoding, done) {
2661
+ if (typeof chunk !== "string") throw new TypeError(xml ? "Expected a string" : "Parser can work only with string streams.");
2662
+ if (opts._useHtmlParser2 && opts.Tokenizer) {
2663
+ writeNative(chunk).then(() => done(), (error) => done(error));
2664
+ return;
2665
+ }
2666
+ let text = carry + chunk;
2667
+ carry = "";
2668
+ const last = text.charCodeAt(text.length - 1);
2669
+ if (last >= 55296 && last <= 56319) {
2670
+ carry = text.slice(-1);
2671
+ text = text.slice(0, -1);
2672
+ }
2673
+ if (!text) {
2674
+ done();
2675
+ return;
2676
+ }
2677
+ writeNative(text).then(() => done(), (error) => done(error));
2678
+ },
2679
+ final(done) {
2680
+ (async () => {
2681
+ if (carry) await writeNative(carry);
2682
+ return finishNative();
2683
+ })().then((document) => {
2684
+ complete(null, document);
2685
+ done();
2686
+ }, (error) => done(error));
2687
+ },
2688
+ destroy(error, done) {
2689
+ abortNative();
2690
+ done(error);
2691
+ }
2692
+ });
2693
+ stream.on("error", (error) => complete(error));
2694
+ return stream;
2695
+ }
2696
+ function decodeStream(options, callback) {
2697
+ const complete = completion(callback);
2698
+ const { encoding = {}, ...parserOptions2 } = options ?? {};
2699
+ const opts = flattenOptions(parserOptions2);
2700
+ const decoderOptions = { defaultEncoding: opts.xmlMode ? "utf-8" : "windows-1252", ...encoding };
2701
+ const maxBytes = decoderOptions.maxBytes ?? 1024;
2702
+ if (!Number.isSafeInteger(maxBytes) || maxBytes < 0) throw new RangeError("encoding.maxBytes must be a non-negative integer");
2703
+ const prefixLimit = Math.max(6, maxBytes);
2704
+ const prefix = [];
2705
+ let prefixLength = 0;
2706
+ let decoder;
2707
+ let userDefined = false;
2708
+ let started = false;
2709
+ const parser = stringStream(opts, (error, document) => complete(error, document));
2710
+ let downstreamError;
2711
+ parser.on("error", (error) => {
2712
+ downstreamError = error;
2713
+ stream.destroy(error);
2714
+ });
2715
+ const writeText = (text) => new Promise((resolve, reject) => {
2716
+ if (downstreamError) {
2717
+ reject(downstreamError);
2718
+ return;
2719
+ }
2720
+ if (!text) {
2721
+ resolve();
2722
+ return;
2723
+ }
2724
+ parser.write(text, (error) => error ? reject(error) : resolve());
2725
+ });
2726
+ const decode = (bytes, final = false) => {
2727
+ if (userDefined) {
2728
+ let text = "";
2729
+ for (const byte of bytes) text += String.fromCharCode(byte < 128 ? byte : 63232 + byte);
2730
+ return text;
2731
+ }
2732
+ return decoder.decode(bytes, { stream: !final });
2733
+ };
2734
+ const start = async () => {
2735
+ const bytes = Buffer.concat(prefix, prefixLength);
2736
+ const label = sniffEncoding(bytes, decoderOptions);
2737
+ userDefined = label === "x-user-defined";
2738
+ if (!userDefined) decoder = new TextDecoder(label);
2739
+ started = true;
2740
+ prefix.length = 0;
2741
+ await writeText(decode(bytes));
2742
+ };
2743
+ const accept = async (bytes) => {
2744
+ if (!started) {
2745
+ const count = Math.min(prefixLimit - prefixLength, bytes.length);
2746
+ if (count) {
2747
+ prefix.push(Buffer.from(bytes.subarray(0, count)));
2748
+ prefixLength += count;
2749
+ }
2750
+ bytes = bytes.subarray(count);
2751
+ const declaredEncoding = encodingLabel(decoderOptions.userEncoding) || encodingLabel(decoderOptions.transportLayerEncodingLabel);
2752
+ if (prefixLength >= prefixLimit || declaredEncoding && prefixLength >= 3) await start();
2753
+ }
2754
+ if (started && bytes.length) await writeText(decode(bytes));
2755
+ };
2756
+ const stream = new Writable({
2757
+ write(chunk, encoding2, done) {
2758
+ accept(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, encoding2)).then(() => done(), (error) => done(error));
2759
+ },
2760
+ final(done) {
2761
+ (async () => {
2762
+ if (!started) await start();
2763
+ await writeText(decode(new Uint8Array(), true));
2764
+ await new Promise((resolve, reject) => {
2765
+ parser.once("error", reject);
2766
+ parser.end(() => {
2767
+ parser.removeListener("error", reject);
2768
+ resolve();
2769
+ });
2770
+ });
2771
+ })().then(() => done(), (error) => done(error));
2772
+ },
2773
+ destroy(error, done) {
2774
+ parser.destroy(error ?? void 0);
2775
+ done(error);
2776
+ }
2777
+ });
2778
+ stream.on("error", (error) => complete(error));
2779
+ return stream;
2780
+ }
2781
+ async function fromURL(url, options = {}) {
2782
+ const signal = options.requestOptions?.signal;
2783
+ if (!signal) return loadURL(url, options);
2784
+ if (typeof signal !== "object" && typeof signal !== "function") throw new TypeError("signal must be an AbortSignal or EventEmitter");
2785
+ if ("addEventListener" in signal) return loadURL(url, options);
2786
+ if (!("once" in signal) || !("removeListener" in signal)) throw new TypeError("signal must be an AbortSignal or EventEmitter");
2787
+ const emitter = signal;
2788
+ const controller = new AbortController();
2789
+ const abort = () => controller.abort();
2790
+ emitter.once("abort", abort);
2791
+ try {
2792
+ return await loadURL(url, { ...options, requestOptions: { ...options.requestOptions, signal: controller.signal } });
2793
+ } finally {
2794
+ emitter.removeListener("abort", abort);
2795
+ }
2796
+ }
2797
+ async function loadURL(url, options) {
2798
+ const { requestOptions = {}, encoding, ...parserOptions2 } = options;
2799
+ const maxRedirects = requestOptions.maxRedirections ?? 5;
2800
+ if (!Number.isInteger(maxRedirects) || maxRedirects < 0) throw new RangeError("maxRedirections must be a non-negative integer");
2801
+ const headers = requestHeaders(requestOptions.headers);
2802
+ if (!Object.hasOwn(requestOptions, "headers")) headers.set("accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
2803
+ let current = new URL(url);
2804
+ if (requestOptions.query) {
2805
+ if (current.search || current.hash) throw new TypeError("URL must not contain a query or fragment when requestOptions.query is supplied");
2806
+ current.search = stringifyQuery(requestOptions.query);
2807
+ }
2808
+ let method = requestOptions.method ?? "GET";
2809
+ let body = requestOptions.body;
2810
+ let response;
2811
+ const controller = new AbortController();
2812
+ const signal = requestOptions.signal ? AbortSignal.any([requestOptions.signal, controller.signal]) : controller.signal;
2813
+ const timeoutError = (kind) => Object.assign(new Error(`${kind} Timeout Error`), {
2814
+ name: `${kind}TimeoutError`,
2815
+ code: kind === "Headers" ? "UND_ERR_HEADERS_TIMEOUT" : "UND_ERR_BODY_TIMEOUT"
2816
+ });
2817
+ for (const timeout of [requestOptions.headersTimeout, requestOptions.bodyTimeout]) {
2818
+ if (timeout != null && (!Number.isFinite(timeout) || timeout < 0)) throw new RangeError("HTTP timeouts must be non-negative finite numbers");
2819
+ }
2820
+ const suppliedDispatcher = requestOptions.dispatcher;
2821
+ if (suppliedDispatcher && typeof suppliedDispatcher.dispatch !== "function") throw new TypeError("requestOptions.dispatcher must implement dispatch");
2822
+ const dispatcher = suppliedDispatcher && {
2823
+ dispatch(dispatchOptions, handler) {
2824
+ const { dispatcher: _dispatcher, throwOnError: _throwOnError, maxRedirections: _maxRedirections, query: _query, ...transport } = requestOptions;
2825
+ return suppliedDispatcher.dispatch({ ...transport, ...dispatchOptions }, handler);
2826
+ }
2827
+ };
2828
+ for (let redirects = 0; ; redirects += 1) {
2829
+ let timer;
2830
+ const headersTimeout = requestOptions.headersTimeout ?? 3e5;
2831
+ if (headersTimeout) {
2832
+ timer = setTimeout(() => controller.abort(timeoutError("Headers")), headersTimeout);
2833
+ timer.unref();
2834
+ }
2835
+ try {
2836
+ if (dispatcher) {
2837
+ const init = { method, headers, body, redirect: "manual", signal, dispatcher };
2838
+ if (body != null && typeof body !== "string") init.duplex = "half";
2839
+ response = await fetch(current, init);
2840
+ } else response = await requestDocument(current, method, headers, body, requestOptions, signal);
2841
+ } catch (error) {
2842
+ throw signal.aborted ? signal.reason : error;
2843
+ } finally {
2844
+ if (timer) clearTimeout(timer);
2845
+ }
2846
+ const location = response.headers.get("location");
2847
+ if (![300, 301, 302, 303, 307, 308].includes(response.status) || !location) break;
2848
+ const rewriteToGet = response.status === 303 && method.toUpperCase() !== "HEAD" || (response.status === 301 || response.status === 302) && method.toUpperCase() === "POST";
2849
+ if (body instanceof Readable && body.readableDidRead && !rewriteToGet) break;
2850
+ await response.body?.cancel();
2851
+ if (redirects >= maxRedirects) throw new Error("max redirects reached");
2852
+ const next = new URL(location, current);
2853
+ headers.delete("host");
2854
+ if (response.status === 303) {
2855
+ for (const name of [...headers.keys()]) if (name.startsWith("content-")) headers.delete(name);
2856
+ }
2857
+ if (next.origin !== current.origin) {
2858
+ headers.delete("authorization");
2859
+ headers.delete("cookie");
2860
+ headers.delete("proxy-authorization");
2861
+ }
2862
+ if (rewriteToGet) {
2863
+ method = "GET";
2864
+ body = void 0;
2865
+ headers.delete("content-length");
2866
+ headers.delete("content-type");
2867
+ }
2868
+ current = next;
2869
+ }
2870
+ if (!response.ok) {
2871
+ await response.body?.cancel();
2872
+ const error = new Error("Response Error");
2873
+ error.name = "ResponseError";
2874
+ error.statusCode = response.status;
2875
+ error.code = "UND_ERR_RESPONSE";
2876
+ error.headers = response.rawHeaders ?? Object.fromEntries(response.headers);
2877
+ throw error;
2878
+ }
2879
+ const contentType = response.headers.get("content-type") ?? "text/html";
2880
+ let parsedType;
2881
+ try {
2882
+ parsedType = new MIMEType(contentType);
2883
+ } catch {
2884
+ await response.body?.cancel();
2885
+ throw new Error(`Could not parse MIME type string "${contentType}"`);
2886
+ }
2887
+ const mime = parsedType.essence;
2888
+ const xml = (parsedType.type === "application" || parsedType.type === "text") && parsedType.subtype === "xml" || parsedType.subtype.endsWith("+xml");
2889
+ if (mime !== "text/html" && !xml) {
2890
+ await response.body?.cancel();
2891
+ throw new RangeError(`The content-type "${mime}" is neither HTML nor XML.`);
2892
+ }
2893
+ const charset = parsedType.params.get("charset") ?? void 0;
2894
+ if (encoding) encoding.transportLayerEncodingLabel = charset;
2895
+ const streamOptions = {
2896
+ xmlMode: xml,
2897
+ baseURI: current,
2898
+ ...parserOptions2,
2899
+ encoding: { ...encoding, transportLayerEncodingLabel: charset }
2900
+ };
2901
+ return new Promise((resolve, reject) => {
2902
+ const parser = decodeStream(streamOptions, (error, document) => error ? reject(error) : resolve(document));
2903
+ const reader = response.body?.getReader();
2904
+ parser.once("error", (error) => {
2905
+ controller.abort(error);
2906
+ void reader?.cancel(error).catch(() => {
2907
+ });
2908
+ });
2909
+ (async () => {
2910
+ let received = 0;
2911
+ const maxResponseSize = requestOptions.maxResponseSize;
2912
+ if (maxResponseSize != null && (typeof maxResponseSize !== "number" || !Number.isSafeInteger(maxResponseSize) || maxResponseSize < -1)) throw new RangeError("maxResponseSize must be -1 or a non-negative integer");
2913
+ while (reader) {
2914
+ let timer;
2915
+ const bodyTimeout = requestOptions.bodyTimeout ?? 3e5;
2916
+ if (bodyTimeout) {
2917
+ timer = setTimeout(() => controller.abort(timeoutError("Body")), bodyTimeout);
2918
+ timer.unref();
2919
+ }
2920
+ let chunk;
2921
+ try {
2922
+ chunk = await reader.read();
2923
+ } catch (error) {
2924
+ throw controller.signal.aborted ? controller.signal.reason : error;
2925
+ } finally {
2926
+ if (timer) clearTimeout(timer);
2927
+ }
2928
+ if (chunk.done) break;
2929
+ received += chunk.value.byteLength;
2930
+ if (typeof maxResponseSize === "number" && maxResponseSize >= 0 && received > maxResponseSize) {
2931
+ throw Object.assign(new Error("Response content exceeded maxResponseSize"), { name: "ResponseExceededMaxSizeError", code: "UND_ERR_RES_EXCEEDED_MAX_SIZE" });
2932
+ }
2933
+ await new Promise((resolve2, reject2) => parser.write(Buffer.from(chunk.value.buffer, chunk.value.byteOffset, chunk.value.byteLength), (error) => error ? reject2(error) : resolve2()));
2934
+ }
2935
+ parser.end();
2936
+ })().catch((error) => {
2937
+ parser.destroy(error);
2938
+ reject(error);
2939
+ });
2940
+ });
2941
+ }
2942
+
2943
+ // src/index.ts
2944
+ var dom = {
2945
+ Node,
2946
+ DataNode,
2947
+ NodeWithChildren,
2948
+ Document,
2949
+ Element,
2950
+ Text,
2951
+ Comment,
2952
+ ProcessingInstruction,
2953
+ CDATA,
2954
+ ElementType,
2955
+ isTag,
2956
+ isText,
2957
+ isComment,
2958
+ isDirective,
2959
+ isDocument,
2960
+ isCDATA,
2961
+ hasChildren
2962
+ };
2963
+ function flattenOptions(options, base) {
2964
+ const result = { _useHtmlParser2: false, ...base, ...options };
2965
+ if (options?.xml) {
2966
+ result._useHtmlParser2 = true;
2967
+ result.xmlMode = true;
2968
+ if (options.xml !== true) Object.assign(result, options.xml);
2969
+ } else if (options?.xmlMode) result._useHtmlParser2 = true;
2970
+ return result;
2971
+ }
2972
+ function createAPI(document, options, initialRoot = document.rootId()) {
2973
+ const internal = flattenOptions(options);
2974
+ class LoadedCheerio extends Cheerio {
2975
+ }
2976
+ let api;
2977
+ const initialize2 = function(selector, context, root, override) {
2978
+ if (selector?.cheerio) return selector;
2979
+ const opts = flattenOptions(override, internal);
2980
+ const rootIds = root === void 0 ? [initialRoot] : typeof root === "string" ? [makeRoot(document, operation(document, "create", { html: root, options: opts }))] : root?.cheerio ? importNodes(document, root.toArray()) : importNodes(document, root);
2981
+ const rootInstance = new LoadedCheerio(api, document, rootIds, null, opts);
2982
+ rootInstance._root = rootInstance;
2983
+ if (!selector) return new LoadedCheerio(api, document, [], rootInstance, opts);
2984
+ if (typeof selector === "string" && isHtml(selector)) return new LoadedCheerio(api, document, operation(document, "create", { html: selector, options: opts }), rootInstance, opts);
2985
+ if (typeof selector === "object") {
2986
+ const values = "length" in selector && !selector.type ? Array.from(selector) : [selector];
2987
+ const allNodes = values.every((value) => value && typeof value === "object" && typeof value.type === "string");
2988
+ return new LoadedCheerio(api, document, allNodes ? importNodes(document, values) : [], rootInstance, opts, allNodes ? void 0 : values);
2989
+ }
2990
+ if (typeof selector !== "string") throw new TypeError("Unexpected type of selector");
2991
+ let search = selector;
2992
+ let searchContext = rootInstance;
2993
+ if (context) {
2994
+ if (typeof context === "string") {
2995
+ if (isHtml(context)) searchContext = new LoadedCheerio(api, document, [makeRoot(document, operation(document, "create", { html: context, options: opts }))], rootInstance, opts);
2996
+ else search = `${context} ${search}`;
2997
+ } else if (context.cheerio) searchContext = context;
2998
+ else searchContext = new LoadedCheerio(api, document, importNodes(document, context), rootInstance, opts);
2999
+ }
3000
+ return searchContext.find(search);
3001
+ };
3002
+ api = Object.assign(initialize2, {
3003
+ load,
3004
+ _root: getNode(document, initialRoot),
3005
+ _options: internal,
3006
+ fn: LoadedCheerio.prototype,
3007
+ prototype: LoadedCheerio.prototype,
3008
+ root() {
3009
+ return this(this._root);
3010
+ },
3011
+ html(dom2, renderOptions) {
3012
+ if (!this) return "";
3013
+ if (dom2 && typeof dom2 === "object" && !("length" in dom2) && !("type" in dom2)) {
3014
+ renderOptions = dom2;
3015
+ dom2 = void 0;
3016
+ }
3017
+ const nodes = dom2 === void 0 ? [this._root] : this(dom2).toArray();
3018
+ const binding = nodeBinding(this._root);
3019
+ return operation(binding.document, "render", { ids: importNodes(binding.document, nodes), options: flattenOptions(renderOptions, this._options) });
3020
+ },
3021
+ xml(dom2) {
3022
+ const binding = nodeBinding(this._root);
3023
+ return operation(binding.document, "render", { ids: importNodes(binding.document, dom2 === void 0 ? [this._root] : this(dom2).toArray()), options: { ...this._options, xmlMode: true, _useHtmlParser2: true } });
3024
+ },
3025
+ text(elements) {
3026
+ if (!elements && !this) return "";
3027
+ const nodes = elements ?? [this._root];
3028
+ const binding = this ? nodeBinding(this._root) : nodeBinding(nodes[0]);
3029
+ if (binding) return binding.document.text(importNodes(binding.document, nodes));
3030
+ const doc = routeDocument(new (requireNative()).NativeDocument("", false));
3031
+ return doc.text(importNodes(doc, nodes));
3032
+ },
3033
+ parseHTML(data2, context, keepScripts = typeof context === "boolean" ? context : false) {
3034
+ if (!data2 || typeof data2 !== "string") return null;
3035
+ if (typeof context === "boolean") keepScripts = context;
3036
+ const parsed = this.load(data2, this._options, false);
3037
+ if (!keepScripts) parsed("script").remove();
3038
+ return parsed._root.children.slice();
3039
+ },
3040
+ extract(map) {
3041
+ return this.root().extract(map);
3042
+ },
3043
+ contains,
3044
+ merge
3045
+ });
3046
+ return api;
3047
+ }
3048
+ function makeRoot(document, children2) {
3049
+ const id = operation(document, "createNode", { type: "root" });
3050
+ operation(document, "setNode", { id, field: "children", value: children2 });
3051
+ return id;
3052
+ }
3053
+ function load(content, options, isDocument2 = true) {
3054
+ if (content == null) throw new Error("cheerio.load() expects a string");
3055
+ const opts = flattenOptions(options);
3056
+ const binding = requireNative();
3057
+ const string = Buffer.isBuffer(content) ? content.toString() : typeof content === "string" ? content : void 0;
3058
+ const document = string === void 0 ? routeDocument(new binding.NativeDocument("", false, JSON.stringify(cleanParserOptions(opts))), opts) : parseNativeDocument(string, opts, isDocument2);
3059
+ if (string !== void 0) return createAPI(document, opts);
3060
+ const nodes = importNodes(document, content);
3061
+ if (!Array.isArray(content) && content.type === "root") return createAPI(document, opts, nodes[0]);
3062
+ operation(document, "setNode", { id: document.rootId(), field: "children", value: nodes });
3063
+ return createAPI(routeDocument(document, opts), opts);
3064
+ }
3065
+ async function loadAsync(content, options, isDocument2 = true) {
3066
+ if (content == null) throw new Error("cheerio.load() expects a string");
3067
+ if (typeof content !== "string" && !Buffer.isBuffer(content)) return load(content, options, isDocument2);
3068
+ const binding = requireNative();
3069
+ const opts = flattenOptions(options);
3070
+ const html = String(content);
3071
+ if (!opts._useHtmlParser2 && opts.treeAdapter) {
3072
+ const session = createTreeAdapterSession(opts, isDocument2);
3073
+ try {
3074
+ await session.write(html);
3075
+ return createAPI(await session.end(), opts);
3076
+ } catch (error) {
3077
+ session.abort();
3078
+ throw error;
3079
+ }
3080
+ }
3081
+ if (opts._useHtmlParser2 && opts.Tokenizer) return createAPI(parseNativeDocument(html, opts, isDocument2), opts);
3082
+ const document = binding.parseAsync ? await binding.parseAsync(html, isDocument2, JSON.stringify(parserOptions(html, opts))) : new binding.NativeDocument(html, isDocument2, JSON.stringify(parserOptions(html, opts)));
3083
+ deliverParseErrors(document, opts);
3084
+ return createAPI(routeDocument(document, opts), opts);
3085
+ }
3086
+ function contains(container, contained) {
3087
+ if (!container || !contained || container === contained) return false;
3088
+ let parent = nodeBinding(container);
3089
+ if (!parent) {
3090
+ const document = routeDocument(new (requireNative()).NativeDocument("", false));
3091
+ importNodes(document, [container]);
3092
+ parent = nodeBinding(container);
3093
+ }
3094
+ const child = nodeBinding(contained);
3095
+ return !!parent && !!child && sameNodeSpace(child.document, parent.document) && operation(parent.document, "contains", { container: parent.id, contained: child.id });
3096
+ }
3097
+ function merge(first, second) {
3098
+ const arrayLike = (value) => Array.isArray(value) || value && typeof value === "object" && typeof value.length === "number" && value.length >= 0 && Array.from({ length: value.length }, (_unused, i) => i in value).every(Boolean);
3099
+ if (!arrayLike(first) || !arrayLike(second)) return void 0;
3100
+ const writable = first;
3101
+ let length = first.length;
3102
+ for (let i = 0, count = +second.length; i < count; i++) writable[length++] = second[i];
3103
+ writable.length = length;
3104
+ return writable;
3105
+ }
3106
+ function parallelOptions(options) {
3107
+ const { threads = Math.min(availableParallelism(), 256), ...opts } = options ?? {};
3108
+ if (!Number.isSafeInteger(threads) || threads < 1 || threads > 256) throw new RangeError("threads must be an integer from 1 to 256");
3109
+ return { options: flattenOptions(opts), threads };
3110
+ }
3111
+ async function loadAll(content, options, isDocument2 = true) {
3112
+ const { options: opts, threads } = parallelOptions(options);
3113
+ if (!Array.isArray(content) || content.some((item) => typeof item !== "string")) throw new TypeError("loadAll expects an array of HTML strings");
3114
+ if (!content.length) return [];
3115
+ const binding = requireNative();
3116
+ if (!binding.parseManyAsync || hasParserHooks(opts)) return Promise.all(content.map((html) => loadAsync(html, opts, isDocument2)));
3117
+ const documents = await binding.parseManyAsync([...content], isDocument2, threads, JSON.stringify(opts));
3118
+ return documents.map((document) => createAPI(routeDocument(document, opts), opts));
3119
+ }
3120
+ function nativeQueries(map, options) {
3121
+ const queries = [];
3122
+ const plainProperties = /^(?:id|class|title|href|src|alt|name|data-.+|aria-.+)$/;
3123
+ for (const key in map) {
3124
+ const entry = map[key];
3125
+ const all = Array.isArray(entry);
3126
+ const descriptor = all ? entry[0] : entry;
3127
+ const selector = typeof descriptor === "string" ? descriptor : descriptor.selector;
3128
+ const value = typeof descriptor === "string" ? "textContent" : descriptor.value ?? "textContent";
3129
+ if (typeof value !== "string" || value !== "textContent" && !plainProperties.test(value) || options.baseURI && (value === "href" || value === "src") || options.pseudos) return void 0;
3130
+ queries.push({ key, selector, all, ...value === "textContent" ? {} : { attr: value } });
3131
+ }
3132
+ return queries;
3133
+ }
3134
+ async function extractAll(content, map, options) {
3135
+ const { options: opts, threads } = parallelOptions(options);
3136
+ if (!Array.isArray(content) || content.some((item) => typeof item !== "string")) throw new TypeError("extractAll expects an array of HTML strings");
3137
+ if (!content.length) return [];
3138
+ const binding = requireNative();
3139
+ const plan = hasParserHooks(opts) ? void 0 : compileExtractPlan(map, opts);
3140
+ if (binding.extractPlanManyAsync && plan) {
3141
+ const results2 = JSON.parse(await binding.extractPlanManyAsync([...content], JSON.stringify(plan), threads, JSON.stringify(opts)));
3142
+ for (const result of results2) hydrateExtractResult(result, plan.entries);
3143
+ return results2;
3144
+ }
3145
+ const queries = binding.extractPlanManyAsync || hasParserHooks(opts) ? void 0 : nativeQueries(map, opts);
3146
+ if (binding.extractManyAsync && queries) {
3147
+ const results2 = JSON.parse(await binding.extractManyAsync([...content], queries, threads, true, JSON.stringify(opts)));
3148
+ for (const result of results2) for (const query of queries) {
3149
+ if (!Object.hasOwn(result, query.key)) Object.defineProperty(result, query.key, { value: query.all ? [] : void 0, configurable: true, writable: true, enumerable: true });
3150
+ if (query.all && Array.isArray(result[query.key])) result[query.key] = result[query.key].filter((value) => value != null);
3151
+ }
3152
+ return results2;
3153
+ }
3154
+ const documents = await loadAll(content, { ...opts, threads });
3155
+ const results = [];
3156
+ let yieldedAt = performance.now();
3157
+ for (const document of documents) {
3158
+ results.push((await extractCooperatively(document.root(), map)).value);
3159
+ if (performance.now() - yieldedAt >= 4) {
3160
+ await yieldToEventLoop();
3161
+ yieldedAt = performance.now();
3162
+ }
3163
+ }
3164
+ return results;
3165
+ }
3166
+
3167
+ export {
3168
+ nativeStatus,
3169
+ configureWorkers,
3170
+ workerPoolInfo,
3171
+ loadBuffer,
3172
+ stringStream,
3173
+ decodeStream,
3174
+ fromURL,
3175
+ dom,
3176
+ flattenOptions,
3177
+ createAPI,
3178
+ load,
3179
+ loadAsync,
3180
+ contains,
3181
+ merge,
3182
+ loadAll,
3183
+ extractAll
3184
+ };
3185
+ //# sourceMappingURL=chunk-DKULX6VO.mjs.map