polite-crawler 0.1.1 → 0.1.2

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 (48) hide show
  1. package/README.md +557 -10
  2. package/build/browser-CKRNbIDT.mjs +62 -0
  3. package/build/browser-CKRNbIDT.mjs.map +1 -0
  4. package/build/cli.mjs +795 -121
  5. package/build/cli.mjs.map +1 -1
  6. package/build/diff-Dk2eSvi-.mjs +648 -0
  7. package/build/diff-Dk2eSvi-.mjs.map +1 -0
  8. package/build/duration-iIuMMofi.mjs +38 -0
  9. package/build/duration-iIuMMofi.mjs.map +1 -0
  10. package/build/extract-DcwNrTK7.mjs +1793 -0
  11. package/build/extract-DcwNrTK7.mjs.map +1 -0
  12. package/build/{html-nWYFVsRU.d.mts → html-BACljlkf.d.mts} +8 -9
  13. package/build/{html-oNpGAHwi.mjs → html-DkQUAE_d.mjs} +18 -39
  14. package/build/html-DkQUAE_d.mjs.map +1 -0
  15. package/build/html.d.mts +2 -1
  16. package/build/html.mjs +3 -1
  17. package/build/index.d.mts +94 -4
  18. package/build/index.mjs +13 -5
  19. package/build/log-Dx-wXjJl.mjs +342 -0
  20. package/build/log-Dx-wXjJl.mjs.map +1 -0
  21. package/build/mcp.d.mts +7 -4
  22. package/build/mcp.mjs +556 -32
  23. package/build/mcp.mjs.map +1 -1
  24. package/build/open-Ca1lcWR3.d.mts +2875 -0
  25. package/build/open-DnrWgkC0.mjs +3161 -0
  26. package/build/open-DnrWgkC0.mjs.map +1 -0
  27. package/build/{browser-gJ_h4AhB.mjs → render-C1CUraWF.mjs} +31 -74
  28. package/build/render-C1CUraWF.mjs.map +1 -0
  29. package/build/rolldown-runtime-D7D4PA-g.mjs +13 -0
  30. package/build/{open-DYZ7KL2A.mjs → runtime-k8mo1_7U.mjs} +986 -1657
  31. package/build/runtime-k8mo1_7U.mjs.map +1 -0
  32. package/build/urls-BHFeSyEK.mjs +62 -0
  33. package/build/urls-BHFeSyEK.mjs.map +1 -0
  34. package/build/urls-BTDSgDLC.d.mts +16 -0
  35. package/build/wacz-sfOLT8e9.mjs +275 -0
  36. package/build/wacz-sfOLT8e9.mjs.map +1 -0
  37. package/build/warc-VIPscWxY.mjs +728 -0
  38. package/build/warc-VIPscWxY.mjs.map +1 -0
  39. package/build/webbotauth-CjJdTAfE.mjs +568 -0
  40. package/build/webbotauth-CjJdTAfE.mjs.map +1 -0
  41. package/package.json +1 -1
  42. package/record.schema.json +15 -1
  43. package/build/browser-gJ_h4AhB.mjs.map +0 -1
  44. package/build/html-oNpGAHwi.mjs.map +0 -1
  45. package/build/open-DYZ7KL2A.mjs.map +0 -1
  46. package/build/open-eHcriTds.d.mts +0 -1499
  47. package/build/version-no12qgos.mjs +0 -11
  48. package/build/version-no12qgos.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warc-VIPscWxY.mjs","names":[],"sources":["../src/zip.ts","../src/warc.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { createReadStream, createWriteStream } from \"node:fs\";\nimport type { FileHandle } from \"node:fs/promises\";\nimport { open, stat } from \"node:fs/promises\";\nimport { pipeline } from \"node:stream/promises\";\nimport * as zlib from \"node:zlib\";\n\n/*\n * This module writes a ZIP file with node:zlib only. The WACZ export uses it. It is not part of the\n * API of the package.\n *\n * - A member is stored (method 0) or deflated (method 8).\n * - The writer knows the CRC-32 and the sizes of each member before it writes the member. Thus the\n * local headers hold the true values, and the file has no data descriptors.\n * - The writer adds the Zip64 records only when a size, an offset or the count of members is too\n * large for the fields of 32 bits. The option `zip64: \"always\"` adds them in each case, for a test.\n */\n\nconst TABLE: Uint32Array = (() => {\n const table = new Uint32Array(256);\n for (let n = 0; n < 256; n += 1) {\n let c = n;\n for (let k = 0; k < 8; k += 1) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;\n table[n] = c >>> 0;\n }\n return table;\n})();\n\n/** This function calculates the CRC-32 of ISO 3309 with a table. It is the fallback of `crc32`. */\nexport const tableCrc32 = (bytes: Uint8Array, value = 0): number => {\n let crc = ~value >>> 0;\n for (const byte of bytes) crc = TABLE[(crc ^ byte) & 0xff]! ^ (crc >>> 8);\n return ~crc >>> 0;\n};\n\nconst native = (zlib as { readonly crc32?: (data: Uint8Array, value?: number) => number }).crc32;\n\n/** This function calculates the CRC-32 of the bytes. It continues from `value`. It uses `zlib.crc32` when Node.js has it. */\nexport const crc32 = (bytes: Uint8Array, value = 0): number =>\n native === undefined ? tableCrc32(bytes, value) : native(bytes, value);\n\n/** These are the facts of a file that a tally gives at its close. */\nexport interface Tallied {\n readonly path: string;\n readonly size: number;\n readonly crc: number;\n /** This value is the SHA-256 of the bytes, as hexadecimal digits. */\n readonly sha256: string;\n}\n\n/** This function writes the whole buffer. A write can write less than the buffer, and the loop writes the rest. */\nexport const writeAll = async (handle: FileHandle, bytes: Uint8Array): Promise<void> => {\n let at = 0;\n while (at < bytes.length) {\n const { bytesWritten } = await handle.write(bytes, at, bytes.length - at);\n at += bytesWritten;\n }\n};\n\n/** A tally writes a new file in sequence. It counts the bytes and calculates their CRC-32 and SHA-256. */\nexport class TalliedFile {\n private readonly hash = createHash(\"sha256\");\n private crcValue = 0;\n private count = 0;\n\n private constructor(\n readonly path: string,\n private readonly handle: FileHandle,\n ) {}\n\n /** This method makes a new file. It fails when the file exists. */\n static async create(path: string): Promise<TalliedFile> {\n return new TalliedFile(path, await open(path, \"wx\", 0o600));\n }\n\n /** This value is the count of bytes that the tally wrote. It is the offset of the next write. */\n get size(): number {\n return this.count;\n }\n\n async write(bytes: Uint8Array): Promise<void> {\n await writeAll(this.handle, bytes);\n this.hash.update(bytes);\n this.crcValue = crc32(bytes, this.crcValue);\n this.count += bytes.length;\n }\n\n /** This method closes the file and gives its facts. */\n async close(): Promise<Tallied> {\n await this.handle.close();\n return {\n path: this.path,\n size: this.count,\n crc: this.crcValue,\n sha256: this.hash.digest(\"hex\"),\n };\n }\n\n /** This method closes the file after an error. It gives no facts. */\n async abandon(): Promise<void> {\n await this.handle.close().catch(() => undefined);\n }\n}\n\n/** This function deflates a file into a new file (raw deflate, as ZIP needs it). It gives the size of the new file. */\nexport const deflateFile = async (from: string, to: string): Promise<number> => {\n await pipeline(\n createReadStream(from),\n zlib.createDeflateRaw(),\n createWriteStream(to, { flags: \"wx\", mode: 0o600 }),\n );\n return (await stat(to)).size;\n};\n\n/** A member of a ZIP file. Its bytes are in a file or in memory, as the ZIP stores them. */\nexport interface ZipMember {\n /** This value is the path of the member in the ZIP file. */\n readonly name: string;\n /** The value 0 stores the bytes. The value 8 holds deflated bytes. */\n readonly method: 0 | 8;\n /** This value is the CRC-32 of the bytes before compression. */\n readonly crc: number;\n /** This value is the count of bytes before compression. */\n readonly size: number;\n /** This value is the count of bytes in the ZIP file. */\n readonly compressedSize: number;\n /** This file holds the bytes as the ZIP stores them. */\n readonly file?: string | undefined;\n /** These bytes are the member as the ZIP stores them, when `file` is not given. */\n readonly data?: Uint8Array | undefined;\n}\n\n/** This function makes a member from bytes in memory. A member of method 8 holds the bytes deflated. */\nexport const memberOf = (name: string, bytes: Uint8Array, method: 0 | 8 = 8): ZipMember => {\n const data = method === 8 ? zlib.deflateRawSync(bytes) : bytes;\n return {\n name,\n method,\n crc: crc32(bytes),\n size: bytes.length,\n compressedSize: data.length,\n data,\n };\n};\n\n/** These options change a ZIP file. */\nexport interface ZipOptions {\n /** This time goes into each member, in the MS-DOS format of ZIP (UTC, to 2 seconds). */\n readonly date: Date;\n /** The value `auto` (the default) adds the Zip64 records only when they are necessary. */\n readonly zip64?: \"auto\" | \"always\" | undefined;\n}\n\nconst MAX32 = 0xffffffff;\nconst MAX16 = 0xffff;\nconst VERSION_ZIP = 20;\nconst VERSION_ZIP64 = 45;\n/** The member was made on Unix (3), with version 4.5 of the specification. */\nconst MADE_BY = (3 << 8) | VERSION_ZIP64;\n/** A plain file that its owner can read and write, and the others can read (`0o100644`). */\nconst FILE_MODE = (0o100644 << 16) >>> 0;\n/** Bit 11 of the flags tells that the name is UTF-8. */\nconst UTF8_NAMES = 0x0800;\n\nconst dosTime = (date: Date): { readonly time: number; readonly day: number } => {\n const year = Math.min(Math.max(date.getUTCFullYear(), 1980), 2107);\n return {\n time: (date.getUTCHours() << 11) | (date.getUTCMinutes() << 5) | (date.getUTCSeconds() >> 1),\n day: ((year - 1980) << 9) | ((date.getUTCMonth() + 1) << 5) | date.getUTCDate(),\n };\n};\n\n/** This function makes the Zip64 extra field (id 0x0001) with these values of 64 bits. */\nconst zip64Extra = (values: readonly number[]): Buffer => {\n const extra = Buffer.alloc(4 + 8 * values.length);\n extra.writeUInt16LE(0x0001, 0);\n extra.writeUInt16LE(8 * values.length, 2);\n values.forEach((value, at) => extra.writeBigUInt64LE(BigInt(value), 4 + 8 * at));\n return extra;\n};\n\n/**\n * This function writes a ZIP file with these members, in this sequence. It writes a new file and\n * fails when the file exists. It gives the size of the ZIP file.\n */\nexport const writeZip = async (\n target: string,\n members: readonly ZipMember[],\n options: ZipOptions,\n): Promise<number> => {\n const always = options.zip64 === \"always\";\n const { time, day } = dosTime(options.date);\n const handle = await open(target, \"wx\", 0o600);\n let offset = 0;\n const put = async (bytes: Uint8Array): Promise<void> => {\n await writeAll(handle, bytes);\n offset += bytes.length;\n };\n try {\n const central: Buffer[] = [];\n for (const member of members) {\n const name = Buffer.from(member.name, \"utf8\");\n const start = offset;\n const bigSizes = always || member.size >= MAX32 || member.compressedSize >= MAX32;\n const localExtra = bigSizes\n ? zip64Extra([member.size, member.compressedSize])\n : Buffer.alloc(0);\n const local = Buffer.alloc(30);\n local.writeUInt32LE(0x04034b50, 0);\n local.writeUInt16LE(bigSizes ? VERSION_ZIP64 : VERSION_ZIP, 4);\n local.writeUInt16LE(UTF8_NAMES, 6);\n local.writeUInt16LE(member.method, 8);\n local.writeUInt16LE(time, 10);\n local.writeUInt16LE(day, 12);\n local.writeUInt32LE(member.crc >>> 0, 14);\n local.writeUInt32LE(bigSizes ? MAX32 : member.compressedSize, 18);\n local.writeUInt32LE(bigSizes ? MAX32 : member.size, 22);\n local.writeUInt16LE(name.length, 26);\n local.writeUInt16LE(localExtra.length, 28);\n await put(local);\n await put(name);\n await put(localExtra);\n const before = offset;\n if (member.file !== undefined) {\n for await (const chunk of createReadStream(member.file) as AsyncIterable<Buffer>)\n await put(chunk);\n } else await put(member.data ?? new Uint8Array());\n if (offset - before !== member.compressedSize)\n throw new Error(\n `the member ${member.name} has ${String(offset - before)} bytes, not ${String(member.compressedSize)}`,\n );\n\n // the central header names only the values that are too large, in this sequence\n const bigSize = always || member.size >= MAX32;\n const bigCompressed = always || member.compressedSize >= MAX32;\n const bigOffset = always || start >= MAX32;\n const values = [\n ...(bigSize ? [member.size] : []),\n ...(bigCompressed ? [member.compressedSize] : []),\n ...(bigOffset ? [start] : []),\n ];\n const extra = values.length > 0 ? zip64Extra(values) : Buffer.alloc(0);\n const header = Buffer.alloc(46);\n header.writeUInt32LE(0x02014b50, 0);\n header.writeUInt16LE(MADE_BY, 4);\n header.writeUInt16LE(values.length > 0 ? VERSION_ZIP64 : VERSION_ZIP, 6);\n header.writeUInt16LE(UTF8_NAMES, 8);\n header.writeUInt16LE(member.method, 10);\n header.writeUInt16LE(time, 12);\n header.writeUInt16LE(day, 14);\n header.writeUInt32LE(member.crc >>> 0, 16);\n header.writeUInt32LE(bigCompressed ? MAX32 : member.compressedSize, 20);\n header.writeUInt32LE(bigSize ? MAX32 : member.size, 24);\n header.writeUInt16LE(name.length, 28);\n header.writeUInt16LE(extra.length, 30);\n header.writeUInt16LE(0, 32);\n header.writeUInt16LE(0, 34);\n header.writeUInt16LE(0, 36);\n header.writeUInt32LE(FILE_MODE, 38);\n header.writeUInt32LE(bigOffset ? MAX32 : start, 42);\n central.push(header, name, extra);\n }\n\n const centralStart = offset;\n for (const part of central) await put(part);\n const centralSize = offset - centralStart;\n const count = members.length;\n const zip64End = always || count >= MAX16 || centralStart >= MAX32 || centralSize >= MAX32;\n if (zip64End) {\n const recordAt = offset;\n const record = Buffer.alloc(56);\n record.writeUInt32LE(0x06064b50, 0);\n record.writeBigUInt64LE(44n, 4);\n record.writeUInt16LE(MADE_BY, 12);\n record.writeUInt16LE(VERSION_ZIP64, 14);\n record.writeUInt32LE(0, 16);\n record.writeUInt32LE(0, 20);\n record.writeBigUInt64LE(BigInt(count), 24);\n record.writeBigUInt64LE(BigInt(count), 32);\n record.writeBigUInt64LE(BigInt(centralSize), 40);\n record.writeBigUInt64LE(BigInt(centralStart), 48);\n await put(record);\n const locator = Buffer.alloc(20);\n locator.writeUInt32LE(0x07064b50, 0);\n locator.writeUInt32LE(0, 4);\n locator.writeBigUInt64LE(BigInt(recordAt), 8);\n locator.writeUInt32LE(1, 16);\n await put(locator);\n }\n const end = Buffer.alloc(22);\n end.writeUInt32LE(0x06054b50, 0);\n end.writeUInt16LE(0, 4);\n end.writeUInt16LE(0, 6);\n end.writeUInt16LE(zip64End ? MAX16 : count, 8);\n end.writeUInt16LE(zip64End ? MAX16 : count, 10);\n end.writeUInt32LE(zip64End ? MAX32 : centralSize, 12);\n end.writeUInt32LE(zip64End ? MAX32 : centralStart, 16);\n end.writeUInt16LE(0, 20);\n await put(end);\n } finally {\n await handle.close();\n }\n return offset;\n};\n","import { createHash, randomUUID } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { rename, rm } from \"node:fs/promises\";\nimport { STATUS_CODES } from \"node:http\";\nimport { basename, join, resolve } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { gzip } from \"node:zlib\";\nimport type { BlobStore } from \"./blobs.ts\";\nimport { FileBlobStore } from \"./blobs.ts\";\nimport type { CaptureReader } from \"./log.ts\";\nimport { CaptureLog } from \"./log.ts\";\nimport type { CaptureRecord } from \"./record.ts\";\nimport { BOT_PAGE, VERSION } from \"./version.ts\";\nimport { TalliedFile } from \"./zip.ts\";\n\n/*\n * This module writes the capture log as WARC/1.1 (ISO 28500:2017). The README tells what goes into\n * the archive and why. These are the records:\n *\n * - One `warcinfo` record names the software and the filters of the export.\n * - A capture with a body gives a `response` record. Its HTTP header block is rebuilt from the\n * headers that the capture kept, and its payload is the stored body.\n * - A 304 gives a `revisit` record with the profile `server-not-modified`.\n * - A page that the headless browser rendered gives a `conversion` record: the page after\n * JavaScript, not the body that the server sent.\n * - Each of them has a `metadata` record (`WARC-Concurrent-To`) with the JSON of the capture.\n *\n * Each record is one gzip member. The export reads the log as a stream and holds one body at a time.\n */\n\nconst gzipAsync = promisify(gzip);\n\nconst HOME = new URL(\"../\", BOT_PAGE).href;\nconst CRLF = \"\\r\\n\";\nconst END = Buffer.from(\"\\r\\n\\r\\n\", \"latin1\");\nconst KINDS: ReadonlySet<string> = new Set([\"capture\", \"revisit\", \"skipped\"]);\nconst HASH = /^[0-9a-f]{64}$/;\n/** The revisit records name their original from this count of recent responses. */\nconst ORIGINALS = 65_536;\nconst SERVER_NOT_MODIFIED = \"http://netpreserve.org/warc/1.1/revisit/server-not-modified\";\nconst HTTP_RESPONSE = \"application/http; msgtype=response\";\n\n/** The source of an export: the folder of a store, or the capture log and the blob store of a runtime. */\nexport type ArchiveSource =\n string | { readonly captures: CaptureReader; readonly blobs: BlobStore };\n\n/** These filters select the captures of an export. Each filter that you give makes the selection smaller. */\nexport interface ArchiveFilter {\n /** The export holds the captures received at this time or later. */\n readonly since?: string | Date | undefined;\n /** The export holds the captures received before this time. */\n readonly until?: string | Date | undefined;\n /** The export holds the captures of this host and of its subdomains, for example `example.com`. */\n readonly host?: string | undefined;\n /** The export holds the captures whose URL starts with this text. */\n readonly urlPrefix?: string | undefined;\n /** The export holds only the captures with these ids. */\n readonly ids?: readonly string[] | undefined;\n}\n\n/** These options control an export. Only `out` is necessary. */\nexport interface ArchiveOptions extends ArchiveFilter {\n /** This file gets the archive. The export writes a temporary file and gives it this name at the end. */\n readonly out: string;\n /**\n * When this value is true, each capture with no body (a refusal, a skip of robots.txt, an error, a\n * redirect) gets a `metadata` record. The default is false: the export leaves them out.\n */\n readonly includeRefusals?: boolean | undefined;\n /** When this value is true, the export replaces a file that exists. The default is false: the export fails. */\n readonly overwrite?: boolean | undefined;\n}\n\n/** These counts tell what an export wrote. */\nexport interface ArchiveCounts {\n /** This value is the count of capture records that the filters selected. */\n readonly captures: number;\n readonly responses: number;\n readonly revisits: number;\n /** This value is the count of rendered pages (`conversion` records). */\n readonly conversions: number;\n readonly metadata: number;\n /** This value is the count of captures with no body: refusals, skips, errors and redirects. */\n readonly bodiless: number;\n /** This value is the count of captures whose body is not in the blob store, or does not agree with its hash. */\n readonly missing: number;\n /** This value is the count of damaged lines of the capture log. */\n readonly damaged: number;\n}\n\n/** This is the result of `exportWarc`. */\nexport interface WarcResult extends ArchiveCounts {\n readonly format: \"warc\";\n /** This value is the absolute path of the archive. */\n readonly out: string;\n readonly bytes: number;\n}\n\n/** These are the facts of a `response` or `revisit` record that the index of a WACZ file needs. */\nexport interface ArchivedRecord {\n readonly type: \"response\" | \"revisit\";\n readonly url: string;\n readonly date: string;\n readonly status: number;\n readonly mime: string;\n readonly digest: string;\n readonly offset: number;\n readonly length: number;\n readonly capture: string;\n /** This value is true for a page of the page list: a 200 response that is not a robots.txt file. */\n readonly page: boolean;\n}\n\n/** A plan is a valid filter and an open source. An export makes it before it writes a file. */\nexport interface ArchivePlan {\n readonly captures: CaptureReader;\n readonly blobs: BlobStore;\n readonly filter: ArchiveSelection;\n readonly includeRefusals: boolean;\n}\n\n/** This is a filter after the checks: times in ISO 8601, a lowercase host and a set of ids. */\nexport interface ArchiveSelection {\n readonly since?: string | undefined;\n readonly until?: string | undefined;\n readonly host?: string | undefined;\n readonly urlPrefix?: string | undefined;\n readonly ids?: ReadonlySet<string> | undefined;\n}\n\nconst RFC4648 = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567\";\n\n/** This function writes bytes in base 32 (RFC 4648), with capitals and padding. WARC tools write SHA-256 digests in this form. */\nexport const base32 = (bytes: Uint8Array): string => {\n let out = \"\";\n let value = 0;\n let bits = 0;\n for (const byte of bytes) {\n value = ((value << 8) | byte) & 0xffff;\n bits += 8;\n while (bits >= 5) {\n out += RFC4648[(value >>> (bits - 5)) & 31]!;\n bits -= 5;\n }\n }\n if (bits > 0) out += RFC4648[(value << (5 - bits)) & 31]!;\n while (out.length % 8 !== 0) out += \"=\";\n return out;\n};\n\nconst digestOf = (bytes: Uint8Array): string => `sha256:${base32(bytes)}`;\n\nconst sha256Of = (...parts: readonly Uint8Array[]): Buffer => {\n const hash = createHash(\"sha256\");\n for (const part of parts) hash.update(part);\n return hash.digest();\n};\n\n/** This function gives a version 5 UUID (RFC 9562): the SHA-1 of a namespace and a name. */\nconst uuidV5 = (namespace: string, name: string): string => {\n const hash = createHash(\"sha1\")\n .update(Buffer.from(namespace.replace(/-/g, \"\"), \"hex\"))\n .update(name, \"utf8\")\n .digest();\n hash[6] = (hash[6]! & 0x0f) | 0x50;\n hash[8] = (hash[8]! & 0x3f) | 0x80;\n const hex = hash.subarray(0, 16).toString(\"hex\");\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n};\n\n/** The namespace of the record ids: a UUID of the URL of the site, in the URL namespace of RFC 9562. */\nconst NAMESPACE = uuidV5(\"6ba7b811-9dad-11d1-80b4-00c04fd430c8\", HOME);\n\n/** The id of a record of a capture is the same at each export: it comes from the hash of the capture. */\nconst recordId = (record: CaptureRecord, type: string): string =>\n `<urn:uuid:${uuidV5(NAMESPACE, `${record.content_hash || `${record.id}@${record.received_at}`}/${type}`)}>`;\n\n/** A field of a header holds no line break. */\nconst clean = (value: string): string => value.replace(/[\\r\\n]+/g, \" \").trim();\n\n/** This function gives one record: the WARC header, the block and the two line breaks at the end. */\nconst recordBytes = (\n fields: ReadonlyArray<readonly [string, string]>,\n block: readonly Uint8Array[],\n): Buffer => {\n const length = block.reduce((sum, part) => sum + part.length, 0);\n const head = [\n \"WARC/1.1\",\n ...fields.map(([name, value]) => `${name}: ${clean(value)}`),\n `Content-Length: ${String(length)}`,\n \"\",\n \"\",\n ].join(CRLF);\n return Buffer.concat([Buffer.from(head, \"utf8\"), ...block, END]);\n};\n\n/**\n * This function gives an HTTP status line and header block. HTTP headers are Latin-1 bytes, and\n * undici gives each byte as one character. Thus the block gives back the bytes that the server sent.\n */\nconst httpHead = (status: number, headers: ReadonlyArray<readonly [string, string]>): Buffer =>\n Buffer.from(\n [\n `HTTP/1.1 ${String(status)} ${STATUS_CODES[status] ?? \"Unknown\"}`,\n ...headers.map(([name, value]) => `${name}: ${clean(value)}`),\n \"\",\n \"\",\n ].join(CRLF),\n \"latin1\",\n );\n\n/** These fields of a capture keep a header of the response. */\nconst KEPT_HEADERS: ReadonlyArray<readonly [string, string]> = [\n [\"etag\", \"ETag\"],\n [\"last_modified\", \"Last-Modified\"],\n [\"cache_control\", \"Cache-Control\"],\n [\"expires\", \"Expires\"],\n [\"age\", \"Age\"],\n [\"date\", \"Date\"],\n [\"vary\", \"Vary\"],\n];\n\n/** These are the facts of a fetch record that the export reads. */\ninterface Facts {\n readonly url: string;\n readonly date: string;\n readonly status: number | undefined;\n readonly blob: string | undefined;\n readonly contentType: string | undefined;\n readonly rendered: boolean;\n readonly truncated: boolean;\n readonly cut: boolean;\n readonly revisitOf: string | undefined;\n readonly recipe: string | undefined;\n readonly headers: ReadonlyArray<readonly [string, string]>;\n}\n\nconst text = (value: unknown): string | undefined =>\n typeof value === \"string\" && value.length > 0 ? value : undefined;\n\n/** This function gives the time of a capture in ISO 8601, with milliseconds. WARC/1.1 permits them. */\nconst isoOf = (value: unknown, fallback: string): string => {\n const ms = typeof value === \"string\" ? Date.parse(value) : Number.NaN;\n if (Number.isFinite(ms)) return new Date(ms).toISOString();\n const other = Date.parse(fallback);\n return Number.isFinite(other) ? new Date(other).toISOString() : fallback;\n};\n\nconst factsOf = (record: CaptureRecord): Facts | undefined => {\n const payload = record.payload;\n if (typeof payload !== \"object\" || payload === null) return undefined;\n const fields = payload as Readonly<Record<string, unknown>>;\n const url = text(fields[\"url\"]) ?? text(record.external_id);\n if (url === undefined) return undefined;\n const blob = text(fields[\"blob\"]);\n const status = fields[\"status\"];\n return {\n url,\n date: isoOf(fields[\"fetched_at\"], record.received_at),\n status: typeof status === \"number\" && Number.isInteger(status) ? status : undefined,\n blob: blob !== undefined && HASH.test(blob) ? blob : undefined,\n contentType: text(fields[\"content_type\"]),\n rendered: fields[\"rendered\"] === true,\n truncated: fields[\"truncated\"] === true,\n cut: fields[\"cut\"] === true,\n revisitOf: text(fields[\"revisit_of\"]),\n recipe: text(fields[\"recipe\"]),\n headers: KEPT_HEADERS.flatMap(([field, name]) => {\n const value = text(fields[field]);\n return value === undefined ? [] : [[name, value] as const];\n }),\n };\n};\n\nconst timeOf = (name: string, value: string | Date | undefined): string | undefined => {\n if (value === undefined) return undefined;\n const ms = value instanceof Date ? value.getTime() : Date.parse(value);\n if (!Number.isFinite(ms)) throw new RangeError(`${name} is not a time: \"${String(value)}\"`);\n return new Date(ms).toISOString();\n};\n\nconst hostName = (value: string): string | undefined => {\n try {\n return new URL(value).hostname.toLowerCase().replace(/\\.$/, \"\");\n } catch {\n return undefined;\n }\n};\n\nconst filterOf = (options: ArchiveFilter): ArchiveSelection => {\n const since = timeOf(\"since\", options.since);\n const until = timeOf(\"until\", options.until);\n let host: string | undefined;\n if (options.host !== undefined) {\n host = options.host.trim().toLowerCase().replace(/^\\*\\./, \"\").replace(/\\.$/, \"\");\n if (host === \"\" || /[/:@\\s]/.test(host))\n throw new RangeError(`host is a host name, for example example.com, not \"${options.host}\"`);\n }\n return {\n since,\n until,\n host,\n urlPrefix: options.urlPrefix === \"\" ? undefined : options.urlPrefix,\n ids: options.ids === undefined ? undefined : new Set(options.ids),\n };\n};\n\nconst selected = (record: CaptureRecord, facts: Facts, filter: ArchiveSelection): boolean => {\n if (filter.since !== undefined && record.received_at < filter.since) return false;\n if (filter.until !== undefined && record.received_at >= filter.until) return false;\n if (filter.urlPrefix !== undefined && !facts.url.startsWith(filter.urlPrefix)) return false;\n if (filter.ids !== undefined && !filter.ids.has(record.id)) return false;\n if (filter.host !== undefined) {\n const host = hostName(facts.url);\n if (host === undefined || (host !== filter.host && !host.endsWith(`.${filter.host}`)))\n return false;\n }\n return true;\n};\n\n/**\n * This function checks the filters and opens the source. It writes nothing. A folder must hold a\n * capture log, and the export does not make a store.\n */\nexport const planArchive = (source: ArchiveSource, options: ArchiveOptions): ArchivePlan => {\n const filter = filterOf(options);\n const includeRefusals = options.includeRefusals === true;\n if (typeof source !== \"string\") {\n return { captures: source.captures, blobs: source.blobs, filter, includeRefusals };\n }\n const dir = resolve(source);\n if (!existsSync(join(dir, \"captures\")))\n throw new Error(`the store ${dir} has no capture log (captures/)`);\n return {\n captures: new CaptureLog(join(dir, \"captures\"), { sync: false }),\n blobs: new FileBlobStore(join(dir, \"blobs\"), { sync: false }),\n filter,\n includeRefusals,\n };\n};\n\n/** This function gives the path of the archive and of its temporary file. It fails when the archive exists, unless `overwrite` is true. */\nexport const outputOf = (\n options: ArchiveOptions,\n): { readonly target: string; readonly temporary: string } => {\n if (typeof options.out !== \"string\" || options.out.trim() === \"\")\n throw new Error(\"an export needs out: the file of the archive\");\n const target = resolve(options.out);\n if (options.overwrite !== true && existsSync(target))\n throw new Error(`${target} exists: give a different file, or set overwrite`);\n return { target, temporary: `${target}.${randomUUID()}.tmp` };\n};\n\n/** This function reads a body from the blob store. It gives no body when the bytes do not agree with the hash. */\nconst bodyOf = async (\n blobs: BlobStore,\n hash: string,\n): Promise<{ readonly bytes: Uint8Array; readonly digest: Buffer } | undefined> => {\n let bytes: Uint8Array | undefined;\n try {\n bytes = await blobs.get(hash);\n } catch {\n return undefined;\n }\n if (bytes === undefined) return undefined;\n const digest = sha256Of(bytes);\n return digest.toString(\"hex\") === hash ? { bytes, digest } : undefined;\n};\n\nconst mimeOf = (contentType: string | undefined): string =>\n contentType?.split(\";\")[0]?.trim().toLowerCase() || \"-\";\n\n/** This function gives the JSON of the metadata record of a capture. The labels and the scope of the application stay out. */\nconst metadataOf = (record: CaptureRecord, written: Readonly<Record<string, string>>): Buffer =>\n Buffer.from(\n `${JSON.stringify({\n capture: {\n id: record.id,\n source: record.source,\n kind: record.kind,\n ...(record.external_id !== undefined ? { external_id: record.external_id } : {}),\n ...(record.occurred_at !== undefined ? { occurred_at: record.occurred_at } : {}),\n received_at: record.received_at,\n content_hash: record.content_hash,\n payload: record.payload,\n },\n export: written,\n })}\\n`,\n \"utf8\",\n );\n\n/**\n * This function writes the records of an archive into a file: the `warcinfo` record, then the\n * records of each capture that the plan selects. It gives the facts of each `response` and\n * `revisit` record to `onRecord`, for the index of a WACZ file.\n */\nexport const writeArchive = async (\n plan: ArchivePlan,\n file: TalliedFile,\n filename: string,\n onRecord?: (record: ArchivedRecord) => Promise<void>,\n): Promise<ArchiveCounts> => {\n const counts = {\n captures: 0,\n responses: 0,\n revisits: 0,\n conversions: 0,\n metadata: 0,\n bodiless: 0,\n missing: 0,\n damaged: 0,\n };\n const { filter } = plan;\n const put = async (\n bytes: Buffer,\n ): Promise<{ readonly offset: number; readonly length: number }> => {\n const member = await gzipAsync(bytes);\n const offset = file.size;\n await file.write(member);\n return { offset, length: member.length };\n };\n\n const info = `<urn:uuid:${randomUUID()}>`;\n const shown = Object.fromEntries(\n Object.entries({\n since: filter.since,\n until: filter.until,\n host: filter.host,\n url_prefix: filter.urlPrefix,\n ids: filter.ids === undefined ? undefined : filter.ids.size,\n include_refusals: plan.includeRefusals,\n }).filter(([, value]) => value !== undefined),\n );\n const fields = [\n `software: polite-crawler/${VERSION} (+${HOME})`,\n \"format: WARC File Format 1.1\",\n \"conformsTo: https://iipc.github.io/warc-specifications/specifications/warc-format/warc-1.1/\",\n \"robots: obey\",\n \"description: An export of the capture log of polite-crawler. The HTTP headers of each response are rebuilt from the headers that the capture kept.\",\n `polite-crawler-filter: ${JSON.stringify(shown)}`,\n ];\n await put(\n recordBytes(\n [\n [\"WARC-Type\", \"warcinfo\"],\n [\"WARC-Record-ID\", info],\n [\"WARC-Date\", new Date().toISOString()],\n [\"WARC-Filename\", filename],\n [\"Content-Type\", \"application/warc-fields\"],\n ],\n [Buffer.from(`${fields.join(CRLF)}${CRLF}`, \"utf8\")],\n ),\n );\n\n // a revisit names its original when the original is one of the recent responses of the export\n const originals = new Map<\n string,\n { readonly id: string; readonly date: string; readonly url: string }\n >();\n const remember = (\n capture: string,\n original: { readonly id: string; readonly date: string; readonly url: string },\n ): void => {\n originals.delete(capture);\n originals.set(capture, original);\n if (originals.size > ORIGINALS) originals.delete(originals.keys().next().value!);\n };\n\n const scan = plan.captures.scan(\n { source: \"fetch\", since: filter.since },\n { onDamaged: () => void (counts.damaged += 1) },\n );\n for await (const record of scan) {\n if (record.source !== \"fetch\" || !KINDS.has(record.kind)) continue;\n const facts = factsOf(record);\n if (facts === undefined || !selected(record, facts, filter)) continue;\n counts.captures += 1;\n const common: Array<readonly [string, string]> = [\n [\"WARC-Date\", facts.date],\n [\"WARC-Target-URI\", facts.url],\n [\"WARC-Warcinfo-ID\", info],\n ];\n const vendor: Array<readonly [string, string]> = [[\"WARC-Polite-Crawler-Capture\", record.id]];\n let main: string | undefined;\n let written: Record<string, string> = { record: \"none\", reason: \"no body\" };\n\n if (record.kind === \"revisit\" && facts.blob !== undefined) {\n // the 304 confirmed the stored body, so the payload digest is the digest of that body\n const original = facts.revisitOf === undefined ? undefined : originals.get(facts.revisitOf);\n const head = httpHead(304, [\n ...(facts.contentType !== undefined ? [[\"Content-Type\", facts.contentType] as const] : []),\n ...facts.headers,\n ]);\n const digest = digestOf(Buffer.from(facts.blob, \"hex\"));\n main = recordId(record, \"revisit\");\n const at = await put(\n recordBytes(\n [\n [\"WARC-Type\", \"revisit\"],\n [\"WARC-Record-ID\", main],\n ...common,\n [\"WARC-Profile\", SERVER_NOT_MODIFIED],\n ...(original !== undefined ? [[\"WARC-Refers-To\", original.id] as const] : []),\n [\"WARC-Refers-To-Target-URI\", original?.url ?? facts.url],\n ...(original !== undefined ? [[\"WARC-Refers-To-Date\", original.date] as const] : []),\n [\"WARC-Payload-Digest\", digest],\n [\"WARC-Block-Digest\", digestOf(sha256Of(head))],\n ...vendor,\n [\"WARC-Polite-Crawler-Headers\", \"rebuilt\"],\n [\"Content-Type\", HTTP_RESPONSE],\n ],\n [head],\n ),\n );\n counts.revisits += 1;\n written = { record: \"revisit\", http_headers: \"rebuilt\" };\n await onRecord?.({\n type: \"revisit\",\n url: facts.url,\n date: facts.date,\n status: 304,\n mime: \"warc/revisit\",\n digest,\n ...at,\n capture: record.id,\n page: false,\n });\n } else if (record.kind === \"capture\" && facts.blob !== undefined) {\n const body = await bodyOf(plan.blobs, facts.blob);\n if (body === undefined) {\n counts.missing += 1;\n written = { record: \"none\", reason: \"body missing\" };\n } else if (facts.rendered) {\n // the page after JavaScript is a conversion of the page, not the body that the server sent\n const digest = digestOf(body.digest);\n main = recordId(record, \"conversion\");\n await put(\n recordBytes(\n [\n [\"WARC-Type\", \"conversion\"],\n [\"WARC-Record-ID\", main],\n ...common,\n [\"WARC-Payload-Digest\", digest],\n [\"WARC-Block-Digest\", digest],\n ...vendor,\n [\"Content-Type\", facts.contentType ?? \"text/html; charset=utf-8\"],\n ],\n [body.bytes],\n ),\n );\n counts.conversions += 1;\n written = { record: \"conversion\", body: \"rendered\" };\n } else if (facts.status !== undefined && facts.status >= 100 && facts.status <= 999) {\n const head = httpHead(facts.status, [\n ...(facts.contentType !== undefined\n ? [[\"Content-Type\", facts.contentType] as const]\n : []),\n [\"Content-Length\", String(body.bytes.length)],\n ...facts.headers,\n ]);\n const digest = digestOf(body.digest);\n main = recordId(record, \"response\");\n // a body that the crawler cut at its limit, or that ended early, says so\n const truncated = facts.cut ? \"disconnect\" : facts.truncated ? \"length\" : undefined;\n const at = await put(\n recordBytes(\n [\n [\"WARC-Type\", \"response\"],\n [\"WARC-Record-ID\", main],\n ...common,\n [\"WARC-Payload-Digest\", digest],\n [\"WARC-Block-Digest\", digestOf(sha256Of(head, body.bytes))],\n ...(truncated !== undefined ? [[\"WARC-Truncated\", truncated] as const] : []),\n ...vendor,\n [\"WARC-Polite-Crawler-Headers\", \"rebuilt\"],\n [\"Content-Type\", HTTP_RESPONSE],\n ],\n [head, body.bytes],\n ),\n );\n counts.responses += 1;\n written = { record: \"response\", http_headers: \"rebuilt\", body: \"decoded\" };\n remember(record.id, { id: main, date: facts.date, url: facts.url });\n await onRecord?.({\n type: \"response\",\n url: facts.url,\n date: facts.date,\n status: facts.status,\n mime: mimeOf(facts.contentType),\n digest,\n ...at,\n capture: record.id,\n page: facts.status === 200 && facts.recipe !== \"robots.txt\",\n });\n }\n }\n\n if (main === undefined) {\n if (written[\"reason\"] === \"no body\") counts.bodiless += 1;\n if (!plan.includeRefusals) continue;\n }\n const block = metadataOf(record, written);\n await put(\n recordBytes(\n [\n [\"WARC-Type\", \"metadata\"],\n [\"WARC-Record-ID\", recordId(record, \"metadata\")],\n ...common,\n ...(main !== undefined ? [[\"WARC-Concurrent-To\", main] as const] : []),\n [\"WARC-Block-Digest\", digestOf(sha256Of(block))],\n ...vendor,\n [\"Content-Type\", \"application/json\"],\n ],\n [block],\n ),\n );\n counts.metadata += 1;\n }\n return counts;\n};\n\n/**\n * This function gives the SURT key of a URL, as `pywb` and the `surt` library make it with their\n * defaults. The host is reversed with commas and has no `www.` and no default port. The path\n * and the query are lowercase, the path has no slash at the end, and the parts of the query are\n * sorted.\n */\nexport const surt = (value: string): string => {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n return value.toLowerCase();\n }\n const host = url.hostname\n .toLowerCase()\n .replace(/\\.$/, \"\")\n .replace(/^www\\d*\\./, \"\");\n const key = host.startsWith(\"[\") ? host : host.split(\".\").reverse().join(\",\");\n let path = url.pathname.toLowerCase();\n if (path.length > 1 && path.endsWith(\"/\")) path = path.slice(0, -1);\n const query = url.search.slice(1).toLowerCase().split(\"&\").filter(Boolean).sort().join(\"&\");\n return `${key}${url.port === \"\" ? \"\" : `:${url.port}`})${path}${query === \"\" ? \"\" : `?${query}`}`;\n};\n\n/** This function gives the line of a record in a CDXJ index: the SURT key, the time to the second, and JSON. */\nexport const cdxjLine = (record: ArchivedRecord, filename: string): string =>\n `${surt(record.url)} ${record.date.slice(0, 19).replace(/\\D/g, \"\")} ${JSON.stringify({\n url: record.url,\n mime: record.mime,\n status: String(record.status),\n digest: record.digest,\n length: String(record.length),\n offset: String(record.offset),\n filename,\n })}`;\n\n/**\n * This function writes the captures of a store as a WARC/1.1 file, with one gzip member for each\n * record (`.warc.gz`). It reads the capture log as a stream, so its memory does not grow with the\n * store. It writes a temporary file and gives it the name `out` at the end, so a failed export\n * leaves no part of a file.\n *\n * The source is the folder of a store, or the capture log and the blob store of a runtime\n * (`crawler.runtime`). The export only reads the store.\n */\nexport const exportWarc = async (\n source: ArchiveSource,\n options: ArchiveOptions,\n): Promise<WarcResult> => {\n const plan = planArchive(source, options);\n const { target, temporary } = outputOf(options);\n const file = await TalliedFile.create(temporary);\n try {\n const counts = await writeArchive(plan, file, basename(target));\n const done = await file.close();\n await rename(temporary, target);\n return { format: \"warc\", out: target, bytes: done.size, ...counts };\n } catch (error) {\n await file.abandon();\n await rm(temporary, { force: true }).catch(() => undefined);\n throw error;\n }\n};\n"],"mappings":";;;;;;;;;;;;;AAkBA,MAAM,eAA4B;CAChC,MAAM,wBAAQ,IAAI,YAAY,GAAG;CACjC,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,KAAK,GAAG;EAC/B,IAAI,IAAI;EACR,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,IAAI,IAAI,aAAc,MAAM,IAAK,MAAM;EAC1E,MAAM,KAAK,MAAM;CACnB;CACA,OAAO;AACT,EAAA,CAAG;;AAGH,MAAa,cAAc,OAAmB,QAAQ,MAAc;CAClE,IAAI,MAAM,CAAC,UAAU;CACrB,KAAK,MAAM,QAAQ,OAAO,MAAM,OAAO,MAAM,QAAQ,OAAU,QAAQ;CACvE,OAAO,CAAC,QAAQ;AAClB;AAEA,MAAM,SAAU,KAA2E;;AAG3F,MAAa,SAAS,OAAmB,QAAQ,MAC/C,WAAW,KAAA,IAAY,WAAW,OAAO,KAAK,IAAI,OAAO,OAAO,KAAK;;AAYvE,MAAa,WAAW,OAAO,QAAoB,UAAqC;CACtF,IAAI,KAAK;CACT,OAAO,KAAK,MAAM,QAAQ;EACxB,MAAM,EAAE,iBAAiB,MAAM,OAAO,MAAM,OAAO,IAAI,MAAM,SAAS,EAAE;EACxE,MAAM;CACR;AACF;;AAGA,IAAa,cAAb,MAAa,YAAY;CAMZ;CACQ;CANnB,OAAwB,WAAW,QAAQ;CAC3C,WAAmB;CACnB,QAAgB;CAEhB,YACE,MACA,QACA;EAFS,KAAA,OAAA;EACQ,KAAA,SAAA;CAChB;;CAGH,aAAa,OAAO,MAAoC;EACtD,OAAO,IAAI,YAAY,MAAM,MAAM,KAAK,MAAM,MAAM,GAAK,CAAC;CAC5D;;CAGA,IAAI,OAAe;EACjB,OAAO,KAAK;CACd;CAEA,MAAM,MAAM,OAAkC;EAC5C,MAAM,SAAS,KAAK,QAAQ,KAAK;EACjC,KAAK,KAAK,OAAO,KAAK;EACtB,KAAK,WAAW,MAAM,OAAO,KAAK,QAAQ;EAC1C,KAAK,SAAS,MAAM;CACtB;;CAGA,MAAM,QAA0B;EAC9B,MAAM,KAAK,OAAO,MAAM;EACxB,OAAO;GACL,MAAM,KAAK;GACX,MAAM,KAAK;GACX,KAAK,KAAK;GACV,QAAQ,KAAK,KAAK,OAAO,KAAK;EAChC;CACF;;CAGA,MAAM,UAAyB;EAC7B,MAAM,KAAK,OAAO,MAAM,CAAC,CAAC,YAAY,KAAA,CAAS;CACjD;AACF;;AAGA,MAAa,cAAc,OAAO,MAAc,OAAgC;CAC9E,MAAM,SACJ,iBAAiB,IAAI,GACrB,KAAK,iBAAiB,GACtB,kBAAkB,IAAI;EAAE,OAAO;EAAM,MAAM;CAAM,CAAC,CACpD;CACA,QAAQ,MAAM,KAAK,EAAE,EAAA,CAAG;AAC1B;;AAqBA,MAAa,YAAY,MAAc,OAAmB,SAAgB,MAAiB;CACzF,MAAM,OAAO,WAAW,IAAI,KAAK,eAAe,KAAK,IAAI;CACzD,OAAO;EACL;EACA;EACA,KAAK,MAAM,KAAK;EAChB,MAAM,MAAM;EACZ,gBAAgB,KAAK;EACrB;CACF;AACF;AAUA,MAAM,QAAQ;AACd,MAAM,QAAQ;AACd,MAAM,cAAc;AACpB,MAAM,gBAAgB;;AAEtB,MAAM,UAAU;;AAEhB,MAAM,YAAa,SAAY,OAAQ;;AAEvC,MAAM,aAAa;AAEnB,MAAM,WAAW,SAAgE;CAC/E,MAAM,OAAO,KAAK,IAAI,KAAK,IAAI,KAAK,eAAe,GAAG,IAAI,GAAG,IAAI;CACjE,OAAO;EACL,MAAO,KAAK,YAAY,KAAK,KAAO,KAAK,cAAc,KAAK,IAAM,KAAK,cAAc,KAAK;EAC1F,KAAO,OAAO,QAAS,IAAO,KAAK,YAAY,IAAI,KAAM,IAAK,KAAK,WAAW;CAChF;AACF;;AAGA,MAAM,cAAc,WAAsC;CACxD,MAAM,QAAQ,OAAO,MAAM,IAAI,IAAI,OAAO,MAAM;CAChD,MAAM,cAAc,GAAQ,CAAC;CAC7B,MAAM,cAAc,IAAI,OAAO,QAAQ,CAAC;CACxC,OAAO,SAAS,OAAO,OAAO,MAAM,iBAAiB,OAAO,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC;CAC/E,OAAO;AACT;;;;;AAMA,MAAa,WAAW,OACtB,QACA,SACA,YACoB;CACpB,MAAM,SAAS,QAAQ,UAAU;CACjC,MAAM,EAAE,MAAM,QAAQ,QAAQ,QAAQ,IAAI;CAC1C,MAAM,SAAS,MAAM,KAAK,QAAQ,MAAM,GAAK;CAC7C,IAAI,SAAS;CACb,MAAM,MAAM,OAAO,UAAqC;EACtD,MAAM,SAAS,QAAQ,KAAK;EAC5B,UAAU,MAAM;CAClB;CACA,IAAI;EACF,MAAM,UAAoB,CAAC;EAC3B,KAAK,MAAM,UAAU,SAAS;GAC5B,MAAM,OAAO,OAAO,KAAK,OAAO,MAAM,MAAM;GAC5C,MAAM,QAAQ;GACd,MAAM,WAAW,UAAU,OAAO,QAAQ,SAAS,OAAO,kBAAkB;GAC5E,MAAM,aAAa,WACf,WAAW,CAAC,OAAO,MAAM,OAAO,cAAc,CAAC,IAC/C,OAAO,MAAM,CAAC;GAClB,MAAM,QAAQ,OAAO,MAAM,EAAE;GAC7B,MAAM,cAAc,UAAY,CAAC;GACjC,MAAM,cAAc,WAAW,gBAAgB,aAAa,CAAC;GAC7D,MAAM,cAAc,YAAY,CAAC;GACjC,MAAM,cAAc,OAAO,QAAQ,CAAC;GACpC,MAAM,cAAc,MAAM,EAAE;GAC5B,MAAM,cAAc,KAAK,EAAE;GAC3B,MAAM,cAAc,OAAO,QAAQ,GAAG,EAAE;GACxC,MAAM,cAAc,WAAW,QAAQ,OAAO,gBAAgB,EAAE;GAChE,MAAM,cAAc,WAAW,QAAQ,OAAO,MAAM,EAAE;GACtD,MAAM,cAAc,KAAK,QAAQ,EAAE;GACnC,MAAM,cAAc,WAAW,QAAQ,EAAE;GACzC,MAAM,IAAI,KAAK;GACf,MAAM,IAAI,IAAI;GACd,MAAM,IAAI,UAAU;GACpB,MAAM,SAAS;GACf,IAAI,OAAO,SAAS,KAAA,GAClB,WAAW,MAAM,SAAS,iBAAiB,OAAO,IAAI,GACpD,MAAM,IAAI,KAAK;QACZ,MAAM,IAAI,OAAO,wBAAQ,IAAI,WAAW,CAAC;GAChD,IAAI,SAAS,WAAW,OAAO,gBAC7B,MAAM,IAAI,MACR,cAAc,OAAO,KAAK,OAAO,OAAO,SAAS,MAAM,EAAE,cAAc,OAAO,OAAO,cAAc,GACrG;GAGF,MAAM,UAAU,UAAU,OAAO,QAAQ;GACzC,MAAM,gBAAgB,UAAU,OAAO,kBAAkB;GACzD,MAAM,YAAY,UAAU,SAAS;GACrC,MAAM,SAAS;IACb,GAAI,UAAU,CAAC,OAAO,IAAI,IAAI,CAAC;IAC/B,GAAI,gBAAgB,CAAC,OAAO,cAAc,IAAI,CAAC;IAC/C,GAAI,YAAY,CAAC,KAAK,IAAI,CAAC;GAC7B;GACA,MAAM,QAAQ,OAAO,SAAS,IAAI,WAAW,MAAM,IAAI,OAAO,MAAM,CAAC;GACrE,MAAM,SAAS,OAAO,MAAM,EAAE;GAC9B,OAAO,cAAc,UAAY,CAAC;GAClC,OAAO,cAAc,SAAS,CAAC;GAC/B,OAAO,cAAc,OAAO,SAAS,IAAI,gBAAgB,aAAa,CAAC;GACvE,OAAO,cAAc,YAAY,CAAC;GAClC,OAAO,cAAc,OAAO,QAAQ,EAAE;GACtC,OAAO,cAAc,MAAM,EAAE;GAC7B,OAAO,cAAc,KAAK,EAAE;GAC5B,OAAO,cAAc,OAAO,QAAQ,GAAG,EAAE;GACzC,OAAO,cAAc,gBAAgB,QAAQ,OAAO,gBAAgB,EAAE;GACtE,OAAO,cAAc,UAAU,QAAQ,OAAO,MAAM,EAAE;GACtD,OAAO,cAAc,KAAK,QAAQ,EAAE;GACpC,OAAO,cAAc,MAAM,QAAQ,EAAE;GACrC,OAAO,cAAc,GAAG,EAAE;GAC1B,OAAO,cAAc,GAAG,EAAE;GAC1B,OAAO,cAAc,GAAG,EAAE;GAC1B,OAAO,cAAc,WAAW,EAAE;GAClC,OAAO,cAAc,YAAY,QAAQ,OAAO,EAAE;GAClD,QAAQ,KAAK,QAAQ,MAAM,KAAK;EAClC;EAEA,MAAM,eAAe;EACrB,KAAK,MAAM,QAAQ,SAAS,MAAM,IAAI,IAAI;EAC1C,MAAM,cAAc,SAAS;EAC7B,MAAM,QAAQ,QAAQ;EACtB,MAAM,WAAW,UAAU,SAAS,SAAS,gBAAgB,SAAS,eAAe;EACrF,IAAI,UAAU;GACZ,MAAM,WAAW;GACjB,MAAM,SAAS,OAAO,MAAM,EAAE;GAC9B,OAAO,cAAc,WAAY,CAAC;GAClC,OAAO,iBAAiB,KAAK,CAAC;GAC9B,OAAO,cAAc,SAAS,EAAE;GAChC,OAAO,cAAc,eAAe,EAAE;GACtC,OAAO,cAAc,GAAG,EAAE;GAC1B,OAAO,cAAc,GAAG,EAAE;GAC1B,OAAO,iBAAiB,OAAO,KAAK,GAAG,EAAE;GACzC,OAAO,iBAAiB,OAAO,KAAK,GAAG,EAAE;GACzC,OAAO,iBAAiB,OAAO,WAAW,GAAG,EAAE;GAC/C,OAAO,iBAAiB,OAAO,YAAY,GAAG,EAAE;GAChD,MAAM,IAAI,MAAM;GAChB,MAAM,UAAU,OAAO,MAAM,EAAE;GAC/B,QAAQ,cAAc,WAAY,CAAC;GACnC,QAAQ,cAAc,GAAG,CAAC;GAC1B,QAAQ,iBAAiB,OAAO,QAAQ,GAAG,CAAC;GAC5C,QAAQ,cAAc,GAAG,EAAE;GAC3B,MAAM,IAAI,OAAO;EACnB;EACA,MAAM,MAAM,OAAO,MAAM,EAAE;EAC3B,IAAI,cAAc,WAAY,CAAC;EAC/B,IAAI,cAAc,GAAG,CAAC;EACtB,IAAI,cAAc,GAAG,CAAC;EACtB,IAAI,cAAc,WAAW,QAAQ,OAAO,CAAC;EAC7C,IAAI,cAAc,WAAW,QAAQ,OAAO,EAAE;EAC9C,IAAI,cAAc,WAAW,QAAQ,aAAa,EAAE;EACpD,IAAI,cAAc,WAAW,QAAQ,cAAc,EAAE;EACrD,IAAI,cAAc,GAAG,EAAE;EACvB,MAAM,IAAI,GAAG;CACf,UAAU;EACR,MAAM,OAAO,MAAM;CACrB;CACA,OAAO;AACT;;;;;;;;;;;;ACjRA,MAAM,YAAY,UAAU,IAAI;AAEhC,MAAM,OAAO,IAAI,IAAI,OAAO,QAAQ,CAAC,CAAC;AACtC,MAAM,OAAO;AACb,MAAM,MAAM,OAAO,KAAK,YAAY,QAAQ;AAC5C,MAAM,wBAA6B,IAAI,IAAI;CAAC;CAAW;CAAW;AAAS,CAAC;AAC5E,MAAM,OAAO;;AAEb,MAAM,YAAY;AAClB,MAAM,sBAAsB;AAC5B,MAAM,gBAAgB;AA0FtB,MAAM,UAAU;;AAGhB,MAAa,UAAU,UAA8B;CACnD,IAAI,MAAM;CACV,IAAI,QAAQ;CACZ,IAAI,OAAO;CACX,KAAK,MAAM,QAAQ,OAAO;EACxB,SAAU,SAAS,IAAK,QAAQ;EAChC,QAAQ;EACR,OAAO,QAAQ,GAAG;GAChB,OAAO,QAAS,UAAW,OAAO,IAAM;GACxC,QAAQ;EACV;CACF;CACA,IAAI,OAAO,GAAG,OAAO,QAAS,SAAU,IAAI,OAAS;CACrD,OAAO,IAAI,SAAS,MAAM,GAAG,OAAO;CACpC,OAAO;AACT;AAEA,MAAM,YAAY,UAA8B,UAAU,OAAO,KAAK;AAEtE,MAAM,YAAY,GAAG,UAAyC;CAC5D,MAAM,OAAO,WAAW,QAAQ;CAChC,KAAK,MAAM,QAAQ,OAAO,KAAK,OAAO,IAAI;CAC1C,OAAO,KAAK,OAAO;AACrB;;AAGA,MAAM,UAAU,WAAmB,SAAyB;CAC1D,MAAM,OAAO,WAAW,MAAM,CAAC,CAC5B,OAAO,OAAO,KAAK,UAAU,QAAQ,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CACvD,OAAO,MAAM,MAAM,CAAC,CACpB,OAAO;CACV,KAAK,KAAM,KAAK,KAAM,KAAQ;CAC9B,KAAK,KAAM,KAAK,KAAM,KAAQ;CAC9B,MAAM,MAAM,KAAK,SAAS,GAAG,EAAE,CAAC,CAAC,SAAS,KAAK;CAC/C,OAAO,GAAG,IAAI,MAAM,GAAG,CAAC,EAAE,GAAG,IAAI,MAAM,GAAG,EAAE,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,EAAE,GAAG,IAAI,MAAM,IAAI,EAAE,EAAE,GAAG,IAAI,MAAM,EAAE;AACzG;;AAGA,MAAM,YAAY,OAAO,wCAAwC,IAAI;;AAGrE,MAAM,YAAY,QAAuB,SACvC,aAAa,OAAO,WAAW,GAAG,OAAO,gBAAgB,GAAG,OAAO,GAAG,GAAG,OAAO,cAAc,GAAG,MAAM,EAAE;;AAG3G,MAAM,SAAS,UAA0B,MAAM,QAAQ,YAAY,GAAG,CAAC,CAAC,KAAK;;AAG7E,MAAM,eACJ,QACA,UACW;CACX,MAAM,SAAS,MAAM,QAAQ,KAAK,SAAS,MAAM,KAAK,QAAQ,CAAC;CAC/D,MAAM,OAAO;EACX;EACA,GAAG,OAAO,KAAK,CAAC,MAAM,WAAW,GAAG,KAAK,IAAI,MAAM,KAAK,GAAG;EAC3D,mBAAmB,OAAO,MAAM;EAChC;EACA;CACF,CAAC,CAAC,KAAK,IAAI;CACX,OAAO,OAAO,OAAO;EAAC,OAAO,KAAK,MAAM,MAAM;EAAG,GAAG;EAAO;CAAG,CAAC;AACjE;;;;;AAMA,MAAM,YAAY,QAAgB,YAChC,OAAO,KACL;CACE,YAAY,OAAO,MAAM,EAAE,GAAG,aAAa,WAAW;CACtD,GAAG,QAAQ,KAAK,CAAC,MAAM,WAAW,GAAG,KAAK,IAAI,MAAM,KAAK,GAAG;CAC5D;CACA;AACF,CAAC,CAAC,KAAK,IAAI,GACX,QACF;;AAGF,MAAM,eAAyD;CAC7D,CAAC,QAAQ,MAAM;CACf,CAAC,iBAAiB,eAAe;CACjC,CAAC,iBAAiB,eAAe;CACjC,CAAC,WAAW,SAAS;CACrB,CAAC,OAAO,KAAK;CACb,CAAC,QAAQ,MAAM;CACf,CAAC,QAAQ,MAAM;AACjB;AAiBA,MAAM,QAAQ,UACZ,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ,KAAA;;AAG1D,MAAM,SAAS,OAAgB,aAA6B;CAC1D,MAAM,KAAK,OAAO,UAAU,WAAW,KAAK,MAAM,KAAK,IAAI;CAC3D,IAAI,OAAO,SAAS,EAAE,GAAG,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC,YAAY;CACzD,MAAM,QAAQ,KAAK,MAAM,QAAQ;CACjC,OAAO,OAAO,SAAS,KAAK,IAAI,IAAI,KAAK,KAAK,CAAC,CAAC,YAAY,IAAI;AAClE;AAEA,MAAM,WAAW,WAA6C;CAC5D,MAAM,UAAU,OAAO;CACvB,IAAI,OAAO,YAAY,YAAY,YAAY,MAAM,OAAO,KAAA;CAC5D,MAAM,SAAS;CACf,MAAM,MAAM,KAAK,OAAO,MAAM,KAAK,KAAK,OAAO,WAAW;CAC1D,IAAI,QAAQ,KAAA,GAAW,OAAO,KAAA;CAC9B,MAAM,OAAO,KAAK,OAAO,OAAO;CAChC,MAAM,SAAS,OAAO;CACtB,OAAO;EACL;EACA,MAAM,MAAM,OAAO,eAAe,OAAO,WAAW;EACpD,QAAQ,OAAO,WAAW,YAAY,OAAO,UAAU,MAAM,IAAI,SAAS,KAAA;EAC1E,MAAM,SAAS,KAAA,KAAa,KAAK,KAAK,IAAI,IAAI,OAAO,KAAA;EACrD,aAAa,KAAK,OAAO,eAAe;EACxC,UAAU,OAAO,gBAAgB;EACjC,WAAW,OAAO,iBAAiB;EACnC,KAAK,OAAO,WAAW;EACvB,WAAW,KAAK,OAAO,aAAa;EACpC,QAAQ,KAAK,OAAO,SAAS;EAC7B,SAAS,aAAa,SAAS,CAAC,OAAO,UAAU;GAC/C,MAAM,QAAQ,KAAK,OAAO,MAAM;GAChC,OAAO,UAAU,KAAA,IAAY,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAU;EAC3D,CAAC;CACH;AACF;AAEA,MAAM,UAAU,MAAc,UAAyD;CACrF,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;CAChC,MAAM,KAAK,iBAAiB,OAAO,MAAM,QAAQ,IAAI,KAAK,MAAM,KAAK;CACrE,IAAI,CAAC,OAAO,SAAS,EAAE,GAAG,MAAM,IAAI,WAAW,GAAG,KAAK,mBAAmB,OAAO,KAAK,EAAE,EAAE;CAC1F,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC,YAAY;AAClC;AAEA,MAAM,YAAY,UAAsC;CACtD,IAAI;EACF,OAAO,IAAI,IAAI,KAAK,CAAC,CAAC,SAAS,YAAY,CAAC,CAAC,QAAQ,OAAO,EAAE;CAChE,QAAQ;EACN;CACF;AACF;AAEA,MAAM,YAAY,YAA6C;CAC7D,MAAM,QAAQ,OAAO,SAAS,QAAQ,KAAK;CAC3C,MAAM,QAAQ,OAAO,SAAS,QAAQ,KAAK;CAC3C,IAAI;CACJ,IAAI,QAAQ,SAAS,KAAA,GAAW;EAC9B,OAAO,QAAQ,KAAK,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,QAAQ,SAAS,EAAE,CAAC,CAAC,QAAQ,OAAO,EAAE;EAC/E,IAAI,SAAS,MAAM,UAAU,KAAK,IAAI,GACpC,MAAM,IAAI,WAAW,sDAAsD,QAAQ,KAAK,EAAE;CAC9F;CACA,OAAO;EACL;EACA;EACA;EACA,WAAW,QAAQ,cAAc,KAAK,KAAA,IAAY,QAAQ;EAC1D,KAAK,QAAQ,QAAQ,KAAA,IAAY,KAAA,IAAY,IAAI,IAAI,QAAQ,GAAG;CAClE;AACF;AAEA,MAAM,YAAY,QAAuB,OAAc,WAAsC;CAC3F,IAAI,OAAO,UAAU,KAAA,KAAa,OAAO,cAAc,OAAO,OAAO,OAAO;CAC5E,IAAI,OAAO,UAAU,KAAA,KAAa,OAAO,eAAe,OAAO,OAAO,OAAO;CAC7E,IAAI,OAAO,cAAc,KAAA,KAAa,CAAC,MAAM,IAAI,WAAW,OAAO,SAAS,GAAG,OAAO;CACtF,IAAI,OAAO,QAAQ,KAAA,KAAa,CAAC,OAAO,IAAI,IAAI,OAAO,EAAE,GAAG,OAAO;CACnE,IAAI,OAAO,SAAS,KAAA,GAAW;EAC7B,MAAM,OAAO,SAAS,MAAM,GAAG;EAC/B,IAAI,SAAS,KAAA,KAAc,SAAS,OAAO,QAAQ,CAAC,KAAK,SAAS,IAAI,OAAO,MAAM,GACjF,OAAO;CACX;CACA,OAAO;AACT;;;;;AAMA,MAAa,eAAe,QAAuB,YAAyC;CAC1F,MAAM,SAAS,SAAS,OAAO;CAC/B,MAAM,kBAAkB,QAAQ,oBAAoB;CACpD,IAAI,OAAO,WAAW,UACpB,OAAO;EAAE,UAAU,OAAO;EAAU,OAAO,OAAO;EAAO;EAAQ;CAAgB;CAEnF,MAAM,MAAM,QAAQ,MAAM;CAC1B,IAAI,CAAC,WAAW,KAAK,KAAK,UAAU,CAAC,GACnC,MAAM,IAAI,MAAM,aAAa,IAAI,gCAAgC;CACnE,OAAO;EACL,UAAU,IAAI,WAAW,KAAK,KAAK,UAAU,GAAG,EAAE,MAAM,MAAM,CAAC;EAC/D,OAAO,IAAI,cAAc,KAAK,KAAK,OAAO,GAAG,EAAE,MAAM,MAAM,CAAC;EAC5D;EACA;CACF;AACF;;AAGA,MAAa,YACX,YAC4D;CAC5D,IAAI,OAAO,QAAQ,QAAQ,YAAY,QAAQ,IAAI,KAAK,MAAM,IAC5D,MAAM,IAAI,MAAM,8CAA8C;CAChE,MAAM,SAAS,QAAQ,QAAQ,GAAG;CAClC,IAAI,QAAQ,cAAc,QAAQ,WAAW,MAAM,GACjD,MAAM,IAAI,MAAM,GAAG,OAAO,iDAAiD;CAC7E,OAAO;EAAE;EAAQ,WAAW,GAAG,OAAO,GAAG,WAAW,EAAE;CAAM;AAC9D;;AAGA,MAAM,SAAS,OACb,OACA,SACiF;CACjF,IAAI;CACJ,IAAI;EACF,QAAQ,MAAM,MAAM,IAAI,IAAI;CAC9B,QAAQ;EACN;CACF;CACA,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;CAChC,MAAM,SAAS,SAAS,KAAK;CAC7B,OAAO,OAAO,SAAS,KAAK,MAAM,OAAO;EAAE;EAAO;CAAO,IAAI,KAAA;AAC/D;AAEA,MAAM,UAAU,gBACd,aAAa,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,YAAY,KAAK;;AAGtD,MAAM,cAAc,QAAuB,YACzC,OAAO,KACL,GAAG,KAAK,UAAU;CAChB,SAAS;EACP,IAAI,OAAO;EACX,QAAQ,OAAO;EACf,MAAM,OAAO;EACb,GAAI,OAAO,gBAAgB,KAAA,IAAY,EAAE,aAAa,OAAO,YAAY,IAAI,CAAC;EAC9E,GAAI,OAAO,gBAAgB,KAAA,IAAY,EAAE,aAAa,OAAO,YAAY,IAAI,CAAC;EAC9E,aAAa,OAAO;EACpB,cAAc,OAAO;EACrB,SAAS,OAAO;CAClB;CACA,QAAQ;AACV,CAAC,EAAE,KACH,MACF;;;;;;AAOF,MAAa,eAAe,OAC1B,MACA,MACA,UACA,aAC2B;CAC3B,MAAM,SAAS;EACb,UAAU;EACV,WAAW;EACX,UAAU;EACV,aAAa;EACb,UAAU;EACV,UAAU;EACV,SAAS;EACT,SAAS;CACX;CACA,MAAM,EAAE,WAAW;CACnB,MAAM,MAAM,OACV,UACkE;EAClE,MAAM,SAAS,MAAM,UAAU,KAAK;EACpC,MAAM,SAAS,KAAK;EACpB,MAAM,KAAK,MAAM,MAAM;EACvB,OAAO;GAAE;GAAQ,QAAQ,OAAO;EAAO;CACzC;CAEA,MAAM,OAAO,aAAa,WAAW,EAAE;CACvC,MAAM,QAAQ,OAAO,YACnB,OAAO,QAAQ;EACb,OAAO,OAAO;EACd,OAAO,OAAO;EACd,MAAM,OAAO;EACb,YAAY,OAAO;EACnB,KAAK,OAAO,QAAQ,KAAA,IAAY,KAAA,IAAY,OAAO,IAAI;EACvD,kBAAkB,KAAK;CACzB,CAAC,CAAC,CAAC,QAAQ,GAAG,WAAW,UAAU,KAAA,CAAS,CAC9C;CACA,MAAM,SAAS;EACb,4BAA4B,QAAQ,KAAK,KAAK;EAC9C;EACA;EACA;EACA;EACA,0BAA0B,KAAK,UAAU,KAAK;CAChD;CACA,MAAM,IACJ,YACE;EACE,CAAC,aAAa,UAAU;EACxB,CAAC,kBAAkB,IAAI;EACvB,CAAC,8BAAa,IAAI,KAAK,EAAA,CAAE,YAAY,CAAC;EACtC,CAAC,iBAAiB,QAAQ;EAC1B,CAAC,gBAAgB,yBAAyB;CAC5C,GACA,CAAC,OAAO,KAAK,GAAG,OAAO,KAAK,IAAI,IAAI,QAAQ,MAAM,CAAC,CACrD,CACF;CAGA,MAAM,4BAAY,IAAI,IAGpB;CACF,MAAM,YACJ,SACA,aACS;EACT,UAAU,OAAO,OAAO;EACxB,UAAU,IAAI,SAAS,QAAQ;EAC/B,IAAI,UAAU,OAAO,WAAW,UAAU,OAAO,UAAU,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,KAAM;CACjF;CAEA,MAAM,OAAO,KAAK,SAAS,KACzB;EAAE,QAAQ;EAAS,OAAO,OAAO;CAAM,GACvC,EAAE,iBAAiB,MAAM,OAAO,WAAW,GAAG,CAChD;CACA,WAAW,MAAM,UAAU,MAAM;EAC/B,IAAI,OAAO,WAAW,WAAW,CAAC,MAAM,IAAI,OAAO,IAAI,GAAG;EAC1D,MAAM,QAAQ,QAAQ,MAAM;EAC5B,IAAI,UAAU,KAAA,KAAa,CAAC,SAAS,QAAQ,OAAO,MAAM,GAAG;EAC7D,OAAO,YAAY;EACnB,MAAM,SAA2C;GAC/C,CAAC,aAAa,MAAM,IAAI;GACxB,CAAC,mBAAmB,MAAM,GAAG;GAC7B,CAAC,oBAAoB,IAAI;EAC3B;EACA,MAAM,SAA2C,CAAC,CAAC,+BAA+B,OAAO,EAAE,CAAC;EAC5F,IAAI;EACJ,IAAI,UAAkC;GAAE,QAAQ;GAAQ,QAAQ;EAAU;EAE1E,IAAI,OAAO,SAAS,aAAa,MAAM,SAAS,KAAA,GAAW;GAEzD,MAAM,WAAW,MAAM,cAAc,KAAA,IAAY,KAAA,IAAY,UAAU,IAAI,MAAM,SAAS;GAC1F,MAAM,OAAO,SAAS,KAAK,CACzB,GAAI,MAAM,gBAAgB,KAAA,IAAY,CAAC,CAAC,gBAAgB,MAAM,WAAW,CAAU,IAAI,CAAC,GACxF,GAAG,MAAM,OACX,CAAC;GACD,MAAM,SAAS,SAAS,OAAO,KAAK,MAAM,MAAM,KAAK,CAAC;GACtD,OAAO,SAAS,QAAQ,SAAS;GACjC,MAAM,KAAK,MAAM,IACf,YACE;IACE,CAAC,aAAa,SAAS;IACvB,CAAC,kBAAkB,IAAI;IACvB,GAAG;IACH,CAAC,gBAAgB,mBAAmB;IACpC,GAAI,aAAa,KAAA,IAAY,CAAC,CAAC,kBAAkB,SAAS,EAAE,CAAU,IAAI,CAAC;IAC3E,CAAC,6BAA6B,UAAU,OAAO,MAAM,GAAG;IACxD,GAAI,aAAa,KAAA,IAAY,CAAC,CAAC,uBAAuB,SAAS,IAAI,CAAU,IAAI,CAAC;IAClF,CAAC,uBAAuB,MAAM;IAC9B,CAAC,qBAAqB,SAAS,SAAS,IAAI,CAAC,CAAC;IAC9C,GAAG;IACH,CAAC,+BAA+B,SAAS;IACzC,CAAC,gBAAgB,aAAa;GAChC,GACA,CAAC,IAAI,CACP,CACF;GACA,OAAO,YAAY;GACnB,UAAU;IAAE,QAAQ;IAAW,cAAc;GAAU;GACvD,MAAM,WAAW;IACf,MAAM;IACN,KAAK,MAAM;IACX,MAAM,MAAM;IACZ,QAAQ;IACR,MAAM;IACN;IACA,GAAG;IACH,SAAS,OAAO;IAChB,MAAM;GACR,CAAC;EACH,OAAO,IAAI,OAAO,SAAS,aAAa,MAAM,SAAS,KAAA,GAAW;GAChE,MAAM,OAAO,MAAM,OAAO,KAAK,OAAO,MAAM,IAAI;GAChD,IAAI,SAAS,KAAA,GAAW;IACtB,OAAO,WAAW;IAClB,UAAU;KAAE,QAAQ;KAAQ,QAAQ;IAAe;GACrD,OAAO,IAAI,MAAM,UAAU;IAEzB,MAAM,SAAS,SAAS,KAAK,MAAM;IACnC,OAAO,SAAS,QAAQ,YAAY;IACpC,MAAM,IACJ,YACE;KACE,CAAC,aAAa,YAAY;KAC1B,CAAC,kBAAkB,IAAI;KACvB,GAAG;KACH,CAAC,uBAAuB,MAAM;KAC9B,CAAC,qBAAqB,MAAM;KAC5B,GAAG;KACH,CAAC,gBAAgB,MAAM,eAAe,0BAA0B;IAClE,GACA,CAAC,KAAK,KAAK,CACb,CACF;IACA,OAAO,eAAe;IACtB,UAAU;KAAE,QAAQ;KAAc,MAAM;IAAW;GACrD,OAAO,IAAI,MAAM,WAAW,KAAA,KAAa,MAAM,UAAU,OAAO,MAAM,UAAU,KAAK;IACnF,MAAM,OAAO,SAAS,MAAM,QAAQ;KAClC,GAAI,MAAM,gBAAgB,KAAA,IACtB,CAAC,CAAC,gBAAgB,MAAM,WAAW,CAAU,IAC7C,CAAC;KACL,CAAC,kBAAkB,OAAO,KAAK,MAAM,MAAM,CAAC;KAC5C,GAAG,MAAM;IACX,CAAC;IACD,MAAM,SAAS,SAAS,KAAK,MAAM;IACnC,OAAO,SAAS,QAAQ,UAAU;IAElC,MAAM,YAAY,MAAM,MAAM,eAAe,MAAM,YAAY,WAAW,KAAA;IAC1E,MAAM,KAAK,MAAM,IACf,YACE;KACE,CAAC,aAAa,UAAU;KACxB,CAAC,kBAAkB,IAAI;KACvB,GAAG;KACH,CAAC,uBAAuB,MAAM;KAC9B,CAAC,qBAAqB,SAAS,SAAS,MAAM,KAAK,KAAK,CAAC,CAAC;KAC1D,GAAI,cAAc,KAAA,IAAY,CAAC,CAAC,kBAAkB,SAAS,CAAU,IAAI,CAAC;KAC1E,GAAG;KACH,CAAC,+BAA+B,SAAS;KACzC,CAAC,gBAAgB,aAAa;IAChC,GACA,CAAC,MAAM,KAAK,KAAK,CACnB,CACF;IACA,OAAO,aAAa;IACpB,UAAU;KAAE,QAAQ;KAAY,cAAc;KAAW,MAAM;IAAU;IACzE,SAAS,OAAO,IAAI;KAAE,IAAI;KAAM,MAAM,MAAM;KAAM,KAAK,MAAM;IAAI,CAAC;IAClE,MAAM,WAAW;KACf,MAAM;KACN,KAAK,MAAM;KACX,MAAM,MAAM;KACZ,QAAQ,MAAM;KACd,MAAM,OAAO,MAAM,WAAW;KAC9B;KACA,GAAG;KACH,SAAS,OAAO;KAChB,MAAM,MAAM,WAAW,OAAO,MAAM,WAAW;IACjD,CAAC;GACH;EACF;EAEA,IAAI,SAAS,KAAA,GAAW;GACtB,IAAI,QAAQ,cAAc,WAAW,OAAO,YAAY;GACxD,IAAI,CAAC,KAAK,iBAAiB;EAC7B;EACA,MAAM,QAAQ,WAAW,QAAQ,OAAO;EACxC,MAAM,IACJ,YACE;GACE,CAAC,aAAa,UAAU;GACxB,CAAC,kBAAkB,SAAS,QAAQ,UAAU,CAAC;GAC/C,GAAG;GACH,GAAI,SAAS,KAAA,IAAY,CAAC,CAAC,sBAAsB,IAAI,CAAU,IAAI,CAAC;GACpE,CAAC,qBAAqB,SAAS,SAAS,KAAK,CAAC,CAAC;GAC/C,GAAG;GACH,CAAC,gBAAgB,kBAAkB;EACrC,GACA,CAAC,KAAK,CACR,CACF;EACA,OAAO,YAAY;CACrB;CACA,OAAO;AACT;;;;;;;AAQA,MAAa,QAAQ,UAA0B;CAC7C,IAAI;CACJ,IAAI;EACF,MAAM,IAAI,IAAI,KAAK;CACrB,QAAQ;EACN,OAAO,MAAM,YAAY;CAC3B;CACA,MAAM,OAAO,IAAI,SACd,YAAY,CAAC,CACb,QAAQ,OAAO,EAAE,CAAC,CAClB,QAAQ,aAAa,EAAE;CAC1B,MAAM,MAAM,KAAK,WAAW,GAAG,IAAI,OAAO,KAAK,MAAM,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,GAAG;CAC5E,IAAI,OAAO,IAAI,SAAS,YAAY;CACpC,IAAI,KAAK,SAAS,KAAK,KAAK,SAAS,GAAG,GAAG,OAAO,KAAK,MAAM,GAAG,EAAE;CAClE,MAAM,QAAQ,IAAI,OAAO,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG;CAC1F,OAAO,GAAG,MAAM,IAAI,SAAS,KAAK,KAAK,IAAI,IAAI,OAAO,GAAG,OAAO,UAAU,KAAK,KAAK,IAAI;AAC1F;;AAGA,MAAa,YAAY,QAAwB,aAC/C,GAAG,KAAK,OAAO,GAAG,EAAE,GAAG,OAAO,KAAK,MAAM,GAAG,EAAE,CAAC,CAAC,QAAQ,OAAO,EAAE,EAAE,GAAG,KAAK,UAAU;CACnF,KAAK,OAAO;CACZ,MAAM,OAAO;CACb,QAAQ,OAAO,OAAO,MAAM;CAC5B,QAAQ,OAAO;CACf,QAAQ,OAAO,OAAO,MAAM;CAC5B,QAAQ,OAAO,OAAO,MAAM;CAC5B;AACF,CAAC;;;;;;;;;;AAWH,MAAa,aAAa,OACxB,QACA,YACwB;CACxB,MAAM,OAAO,YAAY,QAAQ,OAAO;CACxC,MAAM,EAAE,QAAQ,cAAc,SAAS,OAAO;CAC9C,MAAM,OAAO,MAAM,YAAY,OAAO,SAAS;CAC/C,IAAI;EACF,MAAM,SAAS,MAAM,aAAa,MAAM,MAAM,SAAS,MAAM,CAAC;EAC9D,MAAM,OAAO,MAAM,KAAK,MAAM;EAC9B,MAAM,OAAO,WAAW,MAAM;EAC9B,OAAO;GAAE,QAAQ;GAAQ,KAAK;GAAQ,OAAO,KAAK;GAAM,GAAG;EAAO;CACpE,SAAS,OAAO;EACd,MAAM,KAAK,QAAQ;EACnB,MAAM,GAAG,WAAW,EAAE,OAAO,KAAK,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;EAC1D,MAAM;CACR;AACF"}