@agentsean/crawler 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/LICENSE +661 -0
  2. package/dist/adaptive.d.ts +9 -0
  3. package/dist/adaptive.d.ts.map +1 -0
  4. package/dist/adaptive.js +43 -0
  5. package/dist/adaptive.js.map +1 -0
  6. package/dist/crawl.d.ts +4 -0
  7. package/dist/crawl.d.ts.map +1 -0
  8. package/dist/crawl.js +348 -0
  9. package/dist/crawl.js.map +1 -0
  10. package/dist/decode.d.ts +7 -0
  11. package/dist/decode.d.ts.map +1 -0
  12. package/dist/decode.js +53 -0
  13. package/dist/decode.js.map +1 -0
  14. package/dist/extract.d.ts +4 -0
  15. package/dist/extract.d.ts.map +1 -0
  16. package/dist/extract.js +268 -0
  17. package/dist/extract.js.map +1 -0
  18. package/dist/hash.d.ts +4 -0
  19. package/dist/hash.d.ts.map +1 -0
  20. package/dist/hash.js +11 -0
  21. package/dist/hash.js.map +1 -0
  22. package/dist/http.d.ts +38 -0
  23. package/dist/http.d.ts.map +1 -0
  24. package/dist/http.js +207 -0
  25. package/dist/http.js.map +1 -0
  26. package/dist/index.d.ts +14 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +13 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/persist.d.ts +20 -0
  31. package/dist/persist.d.ts.map +1 -0
  32. package/dist/persist.js +186 -0
  33. package/dist/persist.js.map +1 -0
  34. package/dist/probe.d.ts +4 -0
  35. package/dist/probe.d.ts.map +1 -0
  36. package/dist/probe.js +132 -0
  37. package/dist/probe.js.map +1 -0
  38. package/dist/readability.d.ts +9 -0
  39. package/dist/readability.d.ts.map +1 -0
  40. package/dist/readability.js +60 -0
  41. package/dist/readability.js.map +1 -0
  42. package/dist/render.d.ts +15 -0
  43. package/dist/render.d.ts.map +1 -0
  44. package/dist/render.js +87 -0
  45. package/dist/render.js.map +1 -0
  46. package/dist/robots.d.ts +13 -0
  47. package/dist/robots.d.ts.map +1 -0
  48. package/dist/robots.js +187 -0
  49. package/dist/robots.js.map +1 -0
  50. package/dist/simhash.d.ts +9 -0
  51. package/dist/simhash.d.ts.map +1 -0
  52. package/dist/simhash.js +58 -0
  53. package/dist/simhash.js.map +1 -0
  54. package/dist/sitemap.d.ts +3 -0
  55. package/dist/sitemap.d.ts.map +1 -0
  56. package/dist/sitemap.js +165 -0
  57. package/dist/sitemap.js.map +1 -0
  58. package/dist/types.d.ts +251 -0
  59. package/dist/types.d.ts.map +1 -0
  60. package/dist/types.js +2 -0
  61. package/dist/types.js.map +1 -0
  62. package/dist/ua.d.ts +3 -0
  63. package/dist/ua.d.ts.map +1 -0
  64. package/dist/ua.js +3 -0
  65. package/dist/ua.js.map +1 -0
  66. package/dist/url.d.ts +11 -0
  67. package/dist/url.d.ts.map +1 -0
  68. package/dist/url.js +114 -0
  69. package/dist/url.js.map +1 -0
  70. package/package.json +60 -0
@@ -0,0 +1,43 @@
1
+ import { jsDependencyScore } from "./render.js";
2
+ const DETECTION_RATIO = 0.1;
3
+ const FINGERPRINT_N = 50;
4
+ export function decideRenderPolicy(pages, page, index) {
5
+ if (shouldAlwaysRender(page))
6
+ return "always";
7
+ if (index < FINGERPRINT_N)
8
+ return "sample";
9
+ const same = pages.filter((p) => p.templateKey === page.templateKey);
10
+ if (same.length < 3)
11
+ return "sample";
12
+ const scores = same.map((p) => p.jsDependencyScore).toSorted((a, b) => a - b);
13
+ const median = scores[Math.floor(scores.length / 2)] ?? 0;
14
+ const p95 = scores[Math.floor(scores.length * 0.95)] ?? median;
15
+ if (median > 0.35)
16
+ return "always";
17
+ if (p95 < 0.05)
18
+ return "never";
19
+ return Math.random() < DETECTION_RATIO ? "sample" : "never";
20
+ }
21
+ export function shouldAlwaysRender(page) {
22
+ try {
23
+ const u = new URL(page.url);
24
+ if (u.pathname === "/" || u.pathname === "")
25
+ return true;
26
+ }
27
+ catch {
28
+ /* ignore */
29
+ }
30
+ if (!page.extract)
31
+ return false;
32
+ if (page.extract.spaRootEmpty)
33
+ return true;
34
+ if (page.extract.hasNoscriptJsWarning)
35
+ return true;
36
+ if (page.extract.mainWordCount < 200 && page.extract.spaRootEmpty)
37
+ return true;
38
+ return false;
39
+ }
40
+ export function scoreFromHtml(html, extract) {
41
+ return jsDependencyScore(html, extract);
42
+ }
43
+ //# sourceMappingURL=adaptive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adaptive.js","sourceRoot":"","sources":["../src/adaptive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAKhD,MAAM,eAAe,GAAG,GAAG,CAAC;AAC5B,MAAM,aAAa,GAAG,EAAE,CAAC;AAEzB,MAAM,UAAU,kBAAkB,CAChC,KAAuE,EACvE,IAAgF,EAChF,KAAa;IAEb,IAAI,kBAAkB,CAAC,IAAI,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC9C,IAAI,KAAK,GAAG,aAAa;QAAE,OAAO,QAAQ,CAAC;IAC3C,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,IAAI,CAAC,WAAW,CAAC,CAAC;IACrE,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAC;IACrC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9E,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC1D,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC;IAC/D,IAAI,MAAM,GAAG,IAAI;QAAE,OAAO,QAAQ,CAAC;IACnC,IAAI,GAAG,GAAG,IAAI;QAAE,OAAO,OAAO,CAAC;IAC/B,OAAO,IAAI,CAAC,MAAM,EAAE,GAAG,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAGlC;IACC,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,CAAC,CAAC,QAAQ,KAAK,GAAG,IAAI,CAAC,CAAC,QAAQ,KAAK,EAAE;YAAE,OAAO,IAAI,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,YAAY;IACd,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAChC,IAAI,IAAI,CAAC,OAAO,CAAC,YAAY;QAAE,OAAO,IAAI,CAAC;IAC3C,IAAI,IAAI,CAAC,OAAO,CAAC,oBAAoB;QAAE,OAAO,IAAI,CAAC;IACnD,IAAI,IAAI,CAAC,OAAO,CAAC,aAAa,GAAG,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,YAAY;QAAE,OAAO,IAAI,CAAC;IAC/E,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,OAAoB;IAC9D,OAAO,iBAAiB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { CrawlOptions, CrawlResult } from "./types.js";
2
+ export declare function ramConcurrency(): number;
3
+ export declare function crawlSite(options: CrawlOptions): Promise<CrawlResult>;
4
+ //# sourceMappingURL=crawl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crawl.d.ts","sourceRoot":"","sources":["../src/crawl.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAGV,YAAY,EACZ,WAAW,EAGZ,MAAM,YAAY,CAAC;AAEpB,wBAAgB,cAAc,IAAI,MAAM,CAKvC;AAED,wBAAsB,SAAS,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAuK3E"}
package/dist/crawl.js ADDED
@@ -0,0 +1,348 @@
1
+ import os from "node:os";
2
+ import { createCrawlerAgent, fetchUrl, ROBOTS_MAX_REDIRECTS } from "./http.js";
3
+ import { extractPage, parseLinkHeaderCanonicals } from "./extract.js";
4
+ import { parseSitemapXml } from "./sitemap.js";
5
+ import { isAllowedByRobots, robotsFromFetch } from "./robots.js";
6
+ import { contentHash } from "./hash.js";
7
+ import { simhashHex } from "./simhash.js";
8
+ import { originOf, templateKey, isInternalUrl, normalizeUrl } from "./url.js";
9
+ import { decideRenderPolicy, scoreFromHtml } from "./adaptive.js";
10
+ import { renderPage } from "./render.js";
11
+ import { probeOrigin } from "./probe.js";
12
+ import { SEAN_UA } from "./ua.js";
13
+ export function ramConcurrency() {
14
+ const freeMb = os.freemem() / (1024 * 1024);
15
+ const cores = Math.max(1, os.cpus().length);
16
+ const fromRam = Math.floor((freeMb - 400) / 50);
17
+ return Math.max(2, Math.min(fromRam || cores, cores * 2, 16));
18
+ }
19
+ export async function crawlSite(options) {
20
+ const startUrl = normalizeUrl(options.startUrl);
21
+ const origin = originOf(startUrl);
22
+ const maxPages = options.maxPages ?? 5000;
23
+ const concurrency = options.concurrency ?? ramConcurrency();
24
+ const rps = options.rps ?? 4;
25
+ const render = options.render ?? true;
26
+ const userAgent = options.userAgent ?? SEAN_UA;
27
+ const startedAt = new Date().toISOString();
28
+ const agent = createCrawlerAgent(2);
29
+ const robots = await fetchRobots(origin, agent, userAgent);
30
+ const sitemaps = await fetchSitemaps(origin, robots, agent, userAgent);
31
+ const seen = new Set(options.resume?.seen ?? []);
32
+ const queue = options.resume?.queue
33
+ ? options.resume.queue.map((q) => ({ url: q.url, depth: q.depth }))
34
+ : [];
35
+ const enqueue = (url, depth) => {
36
+ let abs;
37
+ try {
38
+ abs = normalizeUrl(url);
39
+ }
40
+ catch {
41
+ return;
42
+ }
43
+ if (!isInternalUrl(abs, origin) && !options.followExternal)
44
+ return;
45
+ if (seen.has(abs))
46
+ return;
47
+ if (!isAllowedByRobots(robots, abs, userAgent)) {
48
+ seen.add(abs);
49
+ blocked.push(abs);
50
+ return;
51
+ }
52
+ seen.add(abs);
53
+ queue.push({ url: abs, depth });
54
+ };
55
+ const blocked = [];
56
+ if (!options.resume) {
57
+ enqueue(startUrl, 0);
58
+ for (const sm of sitemaps) {
59
+ for (const u of sm.urls)
60
+ enqueue(u.loc, 1);
61
+ }
62
+ }
63
+ const sitemapLocs = new Set(sitemaps.flatMap((s) => s.urls.map((u) => normalizeUrlSafe(u.loc))));
64
+ const pages = [];
65
+ const inlinks = new Map();
66
+ const followInlinks = new Map();
67
+ const minInterval = 1000 / Math.max(0.1, rps);
68
+ let lastFetch = 0;
69
+ let nextIndex = 0;
70
+ let active = 0;
71
+ const snapshot = () => ({
72
+ seen: [...seen],
73
+ queue: queue.map((q) => ({ url: q.url, depth: q.depth })),
74
+ pagesSeen: pages.length,
75
+ });
76
+ const emitCheckpoint = () => {
77
+ const every = options.checkpointEvery ?? 10;
78
+ if (pages.length % every !== 0)
79
+ return;
80
+ options.onCheckpoint?.(snapshot());
81
+ };
82
+ let aborted = false;
83
+ const workers = Array.from({ length: Math.min(concurrency, maxPages) }, async () => {
84
+ while (pages.length < maxPages) {
85
+ if (options.signal?.aborted) {
86
+ aborted = true;
87
+ return;
88
+ }
89
+ const item = queue.shift();
90
+ if (!item) {
91
+ if (active === 0)
92
+ return;
93
+ await sleep(20);
94
+ continue;
95
+ }
96
+ active++;
97
+ try {
98
+ const wait = lastFetch + minInterval - Date.now();
99
+ if (wait > 0)
100
+ await sleep(wait);
101
+ lastFetch = Date.now();
102
+ const page = await crawlOne({
103
+ url: item.url,
104
+ depth: item.depth,
105
+ origin,
106
+ agent,
107
+ userAgent,
108
+ timeoutMs: options.timeoutMs ?? 20_000,
109
+ robots,
110
+ sitemapLocs,
111
+ render,
112
+ index: nextIndex++,
113
+ prior: pages,
114
+ check304: options.check304 ?? true,
115
+ });
116
+ pages.push(page);
117
+ emitCheckpoint();
118
+ if (page.extract) {
119
+ for (const link of page.extract.links) {
120
+ if (!link.isInternal)
121
+ continue;
122
+ inlinks.set(link.absUrl, (inlinks.get(link.absUrl) ?? 0) + 1);
123
+ if (!link.isNofollow) {
124
+ followInlinks.set(link.absUrl, (followInlinks.get(link.absUrl) ?? 0) + 1);
125
+ }
126
+ if (pages.length + queue.length < maxPages * 2) {
127
+ enqueue(link.absUrl, item.depth + 1);
128
+ }
129
+ }
130
+ }
131
+ }
132
+ finally {
133
+ active--;
134
+ }
135
+ }
136
+ });
137
+ await Promise.all(workers);
138
+ for (const p of pages) {
139
+ p.inlinkCount = inlinks.get(p.url) ?? 0;
140
+ p.followInlinkCount = followInlinks.get(p.url) ?? 0;
141
+ }
142
+ let originProbe;
143
+ try {
144
+ originProbe = await probeOrigin(startUrl, agent);
145
+ }
146
+ catch {
147
+ originProbe = {
148
+ https: startUrl.startsWith("https:"),
149
+ httpRedirectsToHttps: null,
150
+ wwwSplit: null,
151
+ wwwPreferred: null,
152
+ trailingSlashSplit: null,
153
+ randomSoft404: false,
154
+ randomSoft404Url: null,
155
+ randomSoft404Hash: null,
156
+ certValidTo: null,
157
+ certDaysRemaining: null,
158
+ certError: null,
159
+ alpn: null,
160
+ hsts: null,
161
+ };
162
+ }
163
+ await agent.close();
164
+ const checkpoint = snapshot();
165
+ options.onCheckpoint?.(checkpoint);
166
+ return {
167
+ origin,
168
+ startUrl,
169
+ startedAt,
170
+ finishedAt: new Date().toISOString(),
171
+ pages,
172
+ robots,
173
+ sitemaps,
174
+ originProbe,
175
+ pagesSeen: pages.length,
176
+ pagesChanged: pages.filter((p) => !p.notModified).length,
177
+ maxPages,
178
+ truncated: queue.length > 0 || seen.size > pages.length,
179
+ aborted,
180
+ checkpoint,
181
+ };
182
+ }
183
+ async function crawlOne(opts) {
184
+ const fetched = await fetchUrl(opts.url, {
185
+ agent: opts.agent,
186
+ userAgent: opts.userAgent,
187
+ timeoutMs: opts.timeoutMs,
188
+ });
189
+ const isHtml = /html|xml|xhtml/i.test(fetched.contentType) || looksLikeHtml(fetched.decoded);
190
+ const html = isHtml ? fetched.decoded.toString("utf8") : null;
191
+ const headerCanonical = parseLinkHeaderCanonicals(fetched.headers.link);
192
+ const xRobots = fetched.headers["x-robots-tag"] ?? null;
193
+ const extract = html
194
+ ? extractPage(html, fetched.finalUrl, headerCanonical, xRobots)
195
+ : null;
196
+ const hash = fetched.decoded.length ? contentHash(fetched.decoded) : null;
197
+ const sh = extract ? simhashHex(extract.mainText || extract.allText) : null;
198
+ const jsScore = html && extract ? scoreFromHtml(html, extract) : 0;
199
+ const tmpl = templateKey(opts.url);
200
+ let supports304 = null;
201
+ if (opts.check304 &&
202
+ fetched.statusCode === 200 &&
203
+ (fetched.etag || fetched.lastModified)) {
204
+ const again = await fetchUrl(opts.url, {
205
+ agent: opts.agent,
206
+ userAgent: opts.userAgent,
207
+ timeoutMs: opts.timeoutMs,
208
+ etag: fetched.etag ?? undefined,
209
+ lastModified: fetched.lastModified ?? undefined,
210
+ maxRedirects: 0,
211
+ });
212
+ supports304 = again.statusCode === 304;
213
+ }
214
+ const draft = {
215
+ url: opts.url,
216
+ finalUrl: fetched.finalUrl,
217
+ statusCode: fetched.statusCode,
218
+ error: fetched.error,
219
+ contentType: fetched.contentType,
220
+ headers: fetched.headers,
221
+ ttfbMs: fetched.ttfbMs,
222
+ totalMs: fetched.totalMs,
223
+ wireBytes: fetched.wireBytes,
224
+ decodedBytes: fetched.decodedBytes,
225
+ httpVersion: null,
226
+ redirectChain: fetched.redirectChain,
227
+ redirectLoop: fetched.redirectLoop,
228
+ exceedsGoogleRedirectLimit: fetched.exceedsGoogleRedirectLimit,
229
+ html,
230
+ renderedHtml: null,
231
+ extract,
232
+ renderedExtract: null,
233
+ contentHash: hash,
234
+ simhash: sh,
235
+ etag: fetched.etag,
236
+ lastModified: fetched.lastModified,
237
+ notModified: fetched.notModified,
238
+ supports304,
239
+ inSitemap: opts.sitemapLocs.has(opts.url) || opts.sitemapLocs.has(fetched.finalUrl),
240
+ robotsAllowed: isAllowedByRobots(opts.robots, opts.url, opts.userAgent),
241
+ depth: opts.depth,
242
+ inlinkCount: 0,
243
+ outlinkCount: extract?.links.filter((l) => l.isInternal).length ?? 0,
244
+ followInlinkCount: 0,
245
+ isInternal: isInternalUrl(opts.url, opts.origin),
246
+ fetchedAt: new Date().toISOString(),
247
+ renderPolicy: "skipped",
248
+ rendered: false,
249
+ jsDependencyScore: jsScore,
250
+ templateKey: tmpl,
251
+ };
252
+ if (opts.render && html && extract && fetched.statusCode === 200) {
253
+ const policy = decideRenderPolicy(opts.prior, draft, opts.index);
254
+ draft.renderPolicy = policy === "never" ? "never" : policy;
255
+ if (policy === "always" || policy === "sample") {
256
+ const rendered = await renderPage(opts.url, html);
257
+ if (rendered && !rendered.errors.includes("playwright_unavailable")) {
258
+ draft.renderedHtml = rendered.html;
259
+ draft.renderedExtract = rendered.extract;
260
+ draft.rendered = true;
261
+ if (rendered.timedOut)
262
+ draft.error = draft.error ?? "render_timeout";
263
+ }
264
+ else {
265
+ draft.renderPolicy = "skipped";
266
+ }
267
+ }
268
+ }
269
+ return draft;
270
+ }
271
+ async function fetchRobots(origin, agent, userAgent) {
272
+ const url = `${origin}/robots.txt`;
273
+ const res = await fetchUrl(url, {
274
+ agent,
275
+ userAgent,
276
+ timeoutMs: 10_000,
277
+ maxRedirects: ROBOTS_MAX_REDIRECTS,
278
+ accept: "text/plain,*/*;q=0.1",
279
+ });
280
+ return robotsFromFetch({
281
+ statusCode: res.statusCode,
282
+ raw: res.decoded.toString("utf8"),
283
+ contentType: res.contentType,
284
+ bytes: res.decodedBytes,
285
+ redirectHops: Math.max(0, res.redirectChain.length - 1),
286
+ error: res.error,
287
+ });
288
+ }
289
+ async function fetchSitemaps(origin, robots, agent, userAgent) {
290
+ const candidates = [
291
+ ...robots.sitemaps,
292
+ `${origin}/sitemap.xml`,
293
+ `${origin}/sitemap_index.xml`,
294
+ ];
295
+ const seen = new Set();
296
+ const out = [];
297
+ for (const loc of candidates) {
298
+ let url;
299
+ try {
300
+ url = new URL(loc, origin).href;
301
+ }
302
+ catch {
303
+ continue;
304
+ }
305
+ if (seen.has(url))
306
+ continue;
307
+ seen.add(url);
308
+ const res = await fetchUrl(url, {
309
+ agent,
310
+ userAgent,
311
+ timeoutMs: 15_000,
312
+ accept: "application/xml,text/xml,*/*;q=0.1",
313
+ });
314
+ if (res.statusCode === 404 || res.statusCode === null) {
315
+ if (!robots.sitemaps.includes(loc) && !robots.sitemaps.includes(url))
316
+ continue;
317
+ }
318
+ const parsed = await parseSitemapXml(res.decoded, url, url.endsWith(".gz") || (res.headers["content-type"] ?? "").includes("gzip"));
319
+ const sm = {
320
+ ...parsed,
321
+ statusCode: res.statusCode,
322
+ contentType: res.contentType,
323
+ error: parsed.error ?? res.error,
324
+ };
325
+ out.push(sm);
326
+ for (const child of sm.childSitemaps) {
327
+ if (!seen.has(child) && out.length < 50)
328
+ candidates.push(child);
329
+ }
330
+ }
331
+ return out;
332
+ }
333
+ function looksLikeHtml(buf) {
334
+ const head = buf.slice(0, 256).toString("utf8").toLowerCase();
335
+ return (head.includes("<html") || head.includes("<!doctype html") || head.includes("<head"));
336
+ }
337
+ function normalizeUrlSafe(url) {
338
+ try {
339
+ return normalizeUrl(url);
340
+ }
341
+ catch {
342
+ return url;
343
+ }
344
+ }
345
+ function sleep(ms) {
346
+ return new Promise((r) => setTimeout(r, ms));
347
+ }
348
+ //# sourceMappingURL=crawl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crawl.js","sourceRoot":"","sources":["../src/crawl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAC/E,OAAO,EAAE,WAAW,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC9E,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAUlC,MAAM,UAAU,cAAc;IAC5B,MAAM,MAAM,GAAG,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;IAChD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,KAAK,EAAE,KAAK,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAqB;IACnD,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC;IAC1C,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,cAAc,EAAE,CAAC;IAC5D,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7B,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC;IACtC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC;IAC/C,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,MAAM,KAAK,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAC;IAEpC,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IAC3D,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IAEvE,MAAM,IAAI,GAAG,IAAI,GAAG,CAAS,OAAO,CAAC,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;IACzD,MAAM,KAAK,GAAqC,OAAO,CAAC,MAAM,EAAE,KAAK;QACnE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QACnE,CAAC,CAAC,EAAE,CAAC;IACP,MAAM,OAAO,GAAG,CAAC,GAAW,EAAE,KAAa,EAAE,EAAE;QAC7C,IAAI,GAAW,CAAC;QAChB,IAAI,CAAC;YACH,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;QACT,CAAC;QACD,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc;YAAE,OAAO;QACnE,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO;QAC1B,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,GAAG,EAAE,SAAS,CAAC,EAAE,CAAC;YAC/C,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACd,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAClB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;IAClC,CAAC,CAAC;IAEF,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACpB,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QACrB,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;YAC1B,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI;gBAAE,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,GAAG,CACzB,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CACpE,CAAC;IACF,MAAM,KAAK,GAAkB,EAAE,CAAC;IAChC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC1C,MAAM,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;IAChD,MAAM,WAAW,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC9C,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf,MAAM,QAAQ,GAAG,GAAoB,EAAE,CAAC,CAAC;QACvC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;QACf,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QACzD,SAAS,EAAE,KAAK,CAAC,MAAM;KACxB,CAAC,CAAC;IACH,MAAM,cAAc,GAAG,GAAG,EAAE;QAC1B,MAAM,KAAK,GAAG,OAAO,CAAC,eAAe,IAAI,EAAE,CAAC;QAC5C,IAAI,KAAK,CAAC,MAAM,GAAG,KAAK,KAAK,CAAC;YAAE,OAAO;QACvC,OAAO,CAAC,YAAY,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;IACrC,CAAC,CAAC;IACF,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,IAAI,EAAE;QACjF,OAAO,KAAK,CAAC,MAAM,GAAG,QAAQ,EAAE,CAAC;YAC/B,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;gBAC5B,OAAO,GAAG,IAAI,CAAC;gBACf,OAAO;YACT,CAAC;YACD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;YAC3B,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,IAAI,MAAM,KAAK,CAAC;oBAAE,OAAO;gBACzB,MAAM,KAAK,CAAC,EAAE,CAAC,CAAC;gBAChB,SAAS;YACX,CAAC;YACD,MAAM,EAAE,CAAC;YACT,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,SAAS,GAAG,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAClD,IAAI,IAAI,GAAG,CAAC;oBAAE,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;gBAChC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBACvB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC;oBAC1B,GAAG,EAAE,IAAI,CAAC,GAAG;oBACb,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,MAAM;oBACN,KAAK;oBACL,SAAS;oBACT,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,MAAM;oBACtC,MAAM;oBACN,WAAW;oBACX,MAAM;oBACN,KAAK,EAAE,SAAS,EAAE;oBAClB,KAAK,EAAE,KAAK;oBACZ,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,IAAI;iBACnC,CAAC,CAAC;gBACH,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACjB,cAAc,EAAE,CAAC;gBACjB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;oBACjB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;wBACtC,IAAI,CAAC,IAAI,CAAC,UAAU;4BAAE,SAAS;wBAC/B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;wBAC9D,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;4BACrB,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;wBAC5E,CAAC;wBACD,IAAI,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC;4BAC/C,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;wBACvC,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;oBAAS,CAAC;gBACT,MAAM,EAAE,CAAC;YACX,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAE3B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,CAAC,CAAC,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACxC,CAAC,CAAC,iBAAiB,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACtD,CAAC;IAED,IAAI,WAAW,CAAC;IAChB,IAAI,CAAC;QACH,WAAW,GAAG,MAAM,WAAW,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,WAAW,GAAG;YACZ,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC;YACpC,oBAAoB,EAAE,IAAI;YAC1B,QAAQ,EAAE,IAAI;YACd,YAAY,EAAE,IAAI;YAClB,kBAAkB,EAAE,IAAI;YACxB,aAAa,EAAE,KAAK;YACpB,gBAAgB,EAAE,IAAI;YACtB,iBAAiB,EAAE,IAAI;YACvB,WAAW,EAAE,IAAI;YACjB,iBAAiB,EAAE,IAAI;YACvB,SAAS,EAAE,IAAI;YACf,IAAI,EAAE,IAAI;YACV,IAAI,EAAE,IAAI;SACX,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC;IAEpB,MAAM,UAAU,GAAG,QAAQ,EAAE,CAAC;IAC9B,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,CAAC,CAAC;IAEnC,OAAO;QACL,MAAM;QACN,QAAQ;QACR,SAAS;QACT,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACpC,KAAK;QACL,MAAM;QACN,QAAQ;QACR,WAAW;QACX,SAAS,EAAE,KAAK,CAAC,MAAM;QACvB,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,MAAM;QACxD,QAAQ;QACR,SAAS,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,MAAM;QACvD,OAAO;QACP,UAAU;KACX,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,IAavB;IACC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE;QACvC,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,SAAS,EAAE,IAAI,CAAC,SAAS;KAC1B,CAAC,CAAC;IACH,MAAM,MAAM,GACV,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAChF,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9D,MAAM,eAAe,GAAG,yBAAyB,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,IAAI,CAAC;IACxD,MAAM,OAAO,GAAG,IAAI;QAClB,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,eAAe,EAAE,OAAO,CAAC;QAC/D,CAAC,CAAC,IAAI,CAAC;IACT,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1E,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5E,MAAM,OAAO,GAAG,IAAI,IAAI,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnE,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEnC,IAAI,WAAW,GAAmB,IAAI,CAAC;IACvC,IACE,IAAI,CAAC,QAAQ;QACb,OAAO,CAAC,UAAU,KAAK,GAAG;QAC1B,CAAC,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,YAAY,CAAC,EACtC,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE;YACrC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,SAAS;YAC/B,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,SAAS;YAC/C,YAAY,EAAE,CAAC;SAChB,CAAC,CAAC;QACH,WAAW,GAAG,KAAK,CAAC,UAAU,KAAK,GAAG,CAAC;IACzC,CAAC;IAED,MAAM,KAAK,GAAgB;QACzB,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,WAAW,EAAE,IAAI;QACjB,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,0BAA0B,EAAE,OAAO,CAAC,0BAA0B;QAC9D,IAAI;QACJ,YAAY,EAAE,IAAI;QAClB,OAAO;QACP,eAAe,EAAE,IAAI;QACrB,WAAW,EAAE,IAAI;QACjB,OAAO,EAAE,EAAE;QACX,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,WAAW;QACX,SAAS,EAAE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC;QACnF,aAAa,EAAE,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC;QACvE,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,WAAW,EAAE,CAAC;QACd,YAAY,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,MAAM,IAAI,CAAC;QACpE,iBAAiB,EAAE,CAAC;QACpB,UAAU,EAAE,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC;QAChD,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,YAAY,EAAE,SAAS;QACvB,QAAQ,EAAE,KAAK;QACf,iBAAiB,EAAE,OAAO;QAC1B,WAAW,EAAE,IAAI;KAClB,CAAC;IAEF,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,IAAI,OAAO,IAAI,OAAO,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;QACjE,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACjE,KAAK,CAAC,YAAY,GAAG,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;QAC3D,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC/C,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAClD,IAAI,QAAQ,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,CAAC;gBACpE,KAAK,CAAC,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC;gBACnC,KAAK,CAAC,eAAe,GAAG,QAAQ,CAAC,OAAO,CAAC;gBACzC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;gBACtB,IAAI,QAAQ,CAAC,QAAQ;oBAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,gBAAgB,CAAC;YACvE,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,YAAY,GAAG,SAAS,CAAC;YACjC,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,KAAK,UAAU,WAAW,CACxB,MAAc,EACd,KAAY,EACZ,SAAiB;IAEjB,MAAM,GAAG,GAAG,GAAG,MAAM,aAAa,CAAC;IACnC,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,GAAG,EAAE;QAC9B,KAAK;QACL,SAAS;QACT,SAAS,EAAE,MAAM;QACjB,YAAY,EAAE,oBAAoB;QAClC,MAAM,EAAE,sBAAsB;KAC/B,CAAC,CAAC;IACH,OAAO,eAAe,CAAC;QACrB,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;QACjC,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,KAAK,EAAE,GAAG,CAAC,YAAY;QACvB,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC;QACvD,KAAK,EAAE,GAAG,CAAC,KAAK;KACjB,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,aAAa,CAC1B,MAAc,EACd,MAAqB,EACrB,KAAY,EACZ,SAAiB;IAEjB,MAAM,UAAU,GAAG;QACjB,GAAG,MAAM,CAAC,QAAQ;QAClB,GAAG,MAAM,cAAc;QACvB,GAAG,MAAM,oBAAoB;KAC9B,CAAC;IACF,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAAoB,EAAE,CAAC;IAChC,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,IAAI,GAAW,CAAC;QAChB,IAAI,CAAC;YACH,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC;QAClC,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,GAAG,EAAE;YAC9B,KAAK;YACL,SAAS;YACT,SAAS,EAAE,MAAM;YACjB,MAAM,EAAE,oCAAoC;SAC7C,CAAC,CAAC;QACH,IAAI,GAAG,CAAC,UAAU,KAAK,GAAG,IAAI,GAAG,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;YACtD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,SAAS;QACjF,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,eAAe,CAClC,GAAG,CAAC,OAAO,EACX,GAAG,EACH,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAC5E,CAAC;QACF,MAAM,EAAE,GAAkB;YACxB,GAAG,MAAM;YACT,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,GAAG,CAAC,KAAK;SACjC,CAAC;QACF,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACb,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC,aAAa,EAAE,CAAC;YACrC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,EAAE;gBAAE,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,aAAa,CAAC,GAAW;IAChC,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;IAC9D,OAAO,CACL,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CACpF,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAW;IACnC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,CAAC;IACb,CAAC;AACH,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Decode Content-Encoding. undici.request() does not decompress; we must.
3
+ * Apply chained encodings right-to-left.
4
+ */
5
+ export declare function decodeBody(buf: Buffer, contentEncoding: string | undefined): Promise<Buffer>;
6
+ export declare function acceptEncodingHeader(): string;
7
+ //# sourceMappingURL=decode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode.d.ts","sourceRoot":"","sources":["../src/decode.ts"],"names":[],"mappings":"AAYA;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,MAAM,EACX,eAAe,EAAE,MAAM,GAAG,SAAS,GAClC,OAAO,CAAC,MAAM,CAAC,CA2BjB;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAI7C"}
package/dist/decode.js ADDED
@@ -0,0 +1,53 @@
1
+ import { promisify } from "node:util";
2
+ import zlib from "node:zlib";
3
+ const gunzip = promisify(zlib.gunzip);
4
+ const inflate = promisify(zlib.inflate);
5
+ const inflateRaw = promisify(zlib.inflateRaw);
6
+ const brotli = promisify(zlib.brotliDecompress);
7
+ const zstd = "zstdDecompress" in zlib && typeof zlib.zstdDecompress === "function"
8
+ ? promisify(zlib.zstdDecompress)
9
+ : null;
10
+ /**
11
+ * Decode Content-Encoding. undici.request() does not decompress; we must.
12
+ * Apply chained encodings right-to-left.
13
+ */
14
+ export async function decodeBody(buf, contentEncoding) {
15
+ if (!contentEncoding)
16
+ return buf;
17
+ const encodings = contentEncoding
18
+ .split(",")
19
+ .map((s) => s.trim().toLowerCase())
20
+ .filter((s) => s && s !== "identity");
21
+ let out = buf;
22
+ for (let i = encodings.length - 1; i >= 0; i--) {
23
+ const enc = encodings[i];
24
+ if (enc === "gzip" || enc === "x-gzip") {
25
+ out = Buffer.from(await gunzip(out));
26
+ }
27
+ else if (enc === "deflate") {
28
+ try {
29
+ out = Buffer.from(await inflate(out));
30
+ }
31
+ catch {
32
+ out = Buffer.from(await inflateRaw(out));
33
+ }
34
+ }
35
+ else if (enc === "br") {
36
+ out = Buffer.from(await brotli(out));
37
+ }
38
+ else if (enc === "zstd" || enc === "zst") {
39
+ if (!zstd) {
40
+ throw new Error("zstd Content-Encoding requires Node >= 22.15");
41
+ }
42
+ out = Buffer.from(await zstd(out));
43
+ }
44
+ }
45
+ return out;
46
+ }
47
+ export function acceptEncodingHeader() {
48
+ const parts = ["gzip", "deflate", "br"];
49
+ if (zstd)
50
+ parts.push("zstd");
51
+ return parts.join(", ");
52
+ }
53
+ //# sourceMappingURL=decode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode.js","sourceRoot":"","sources":["../src/decode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACtC,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACxC,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AAC9C,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;AAChD,MAAM,IAAI,GACR,gBAAgB,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,cAAc,KAAK,UAAU;IACnE,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,cAAc,CAAC;IAChC,CAAC,CAAC,IAAI,CAAC;AAEX;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,GAAW,EACX,eAAmC;IAEnC,IAAI,CAAC,eAAe;QAAE,OAAO,GAAG,CAAC;IACjC,MAAM,SAAS,GAAG,eAAe;SAC9B,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;SAClC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,CAAC;IACxC,IAAI,GAAG,GAAW,GAAG,CAAC;IACtB,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/C,MAAM,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;YACvC,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACvC,CAAC;aAAM,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACH,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;YACxC,CAAC;YAAC,MAAM,CAAC;gBACP,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;aAAM,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACxB,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACvC,CAAC;aAAM,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;YAC3C,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;YAClE,CAAC;YACD,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;IACxC,IAAI,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC7B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { PageExtract } from "./types.js";
2
+ export declare function extractPage(html: string, pageUrl: string, headerCanonical?: string[], xRobots?: string | null): PageExtract;
3
+ export declare function parseLinkHeaderCanonicals(header: string | undefined): string[];
4
+ //# sourceMappingURL=extract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAKV,WAAW,EACZ,MAAM,YAAY,CAAC;AAKpB,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,eAAe,GAAE,MAAM,EAAO,EAC9B,OAAO,GAAE,MAAM,GAAG,IAAW,GAC5B,WAAW,CA4Mb;AAiED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAQ9E"}