@artinstack/migrator 0.1.21 → 0.1.23

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sinks/types.ts","../src/sinks/run-migration.ts","../src/sinks/conflicts.ts","../src/parsers/squarespace/parse-export.ts","../src/parsers/squarespace/collect.ts","../src/parsers/wordpress/builders/shortcode-conflicts.ts","../src/sinks/filesystem.ts","../src/sinks/filesystem-sink.ts","../src/sinks/migration-report.ts","../src/sinks/storage-estimate.ts","../src/sinks/dry-run.ts"],"sourcesContent":["import type { Readable } from \"node:stream\";\n\nimport type {\n EntityKey,\n NormalizedAsset,\n NormalizedCategory,\n NormalizedPage,\n NormalizedPortfolio,\n NormalizedPost,\n NormalizedTag,\n PortfolioMediaLink,\n} from \"../normalizer/types.js\";\nimport type { RewriteInlineImagesOptions } from \"../transformers/rewrite-inline-images.js\";\n\nexport interface CreatePostResult {\n targetId: string;\n publicPath: string;\n}\n\nexport interface CreatePageResult {\n targetId: string;\n publicPath: string;\n}\n\nexport interface UploadAssetInput {\n asset: NormalizedAsset;\n /** Byte stream from source URL or local file. Optional for metadata-only sinks. */\n body?: Readable | ReadableStream<Uint8Array>;\n contentLength?: number;\n}\n\nexport interface UploadAssetResult {\n targetId: string;\n publicUrl?: string;\n}\n\nexport interface MigrationRedirect {\n fromPath: string;\n toPath: string;\n statusCode: number;\n}\n\nexport interface MigrationProgress {\n stage: string;\n progress: number;\n message?: string;\n}\n\n/**\n * Host-implemented write surface (e.g. ArtInStack PlatformMigrationSink).\n * This package defines the interface only — no Directus or platform imports.\n */\nexport interface MigrationSink {\n createCategory?(category: NormalizedCategory): Promise<{ targetId: string }>;\n createTag?(tag: NormalizedTag): Promise<{ targetId: string }>;\n uploadAsset(input: UploadAssetInput): Promise<UploadAssetResult>;\n createPortfolio?(portfolio: NormalizedPortfolio): Promise<{ targetId: string }>;\n createPost(post: NormalizedPost): Promise<CreatePostResult>;\n createPage(page: NormalizedPage): Promise<CreatePageResult>;\n linkPortfolioMedia?(link: PortfolioMediaLink): Promise<void>;\n writeRedirect?(redirect: MigrationRedirect): Promise<void>;\n reportProgress?(progress: MigrationProgress): Promise<void>;\n /** Optional lookup for idempotent re-runs. */\n findExisting?(key: EntityKey): Promise<string | undefined>;\n}\n\nexport interface ResolvedAssetStream {\n body: Readable | ReadableStream<Uint8Array>;\n contentLength?: number;\n}\n\nexport interface MigrationRunOptions {\n sink: MigrationSink;\n entities: AsyncIterable<import(\"../normalizer/types.js\").NormalizedEntity>;\n platform: import(\"../normalizer/types.js\").MigrationPlatform;\n /** Fetch source bytes before uploadAsset; omit for metadata-only sinks. */\n resolveAssetStream?: (asset: NormalizedAsset) => Promise<ResolvedAssetStream | null>;\n /** Rewrite post/page HTML after assets are uploaded. */\n rewriteInlineImages?: RewriteInlineImagesOptions;\n onEntityProcessed?: (key: EntityKey, result: \"done\" | \"failed\" | \"skipped\", error?: string) => void;\n}\n\nexport interface MigrationRunResult {\n processed: number;\n failed: number;\n skipped: number;\n}\n\nexport const MIGRATION_WRITE_STAGES = [\n \"taxonomy\",\n \"assets\",\n \"portfolios\",\n \"content\",\n \"bindings\",\n \"redirects\",\n] as const;\n\nexport type MigrationWriteStage = (typeof MIGRATION_WRITE_STAGES)[number];\n","import { Readable } from \"node:stream\";\n\nimport { collectEntities, type EntityBundle } from \"../normalizer/bundle.js\";\nimport { buildPortfolioMediaLinks } from \"../normalizer/portfolio-media.js\";\nimport { shouldProcessEntity } from \"../normalizer/idempotency.js\";\nimport { entityKey } from \"../normalizer/types.js\";\nimport type {\n EntityKey,\n NormalizedPage,\n NormalizedPost,\n} from \"../normalizer/types.js\";\nimport { createMigrationMediaRefReplaceWith, normalizeAssetUrl } from \"../lib/media-urls.js\";\nimport {\n rewriteInlineImages,\n type RewriteInlineImagesOptions,\n} from \"../transformers/rewrite-inline-images.js\";\nimport { buildRedirectMap } from \"./conflicts.js\";\nimport type {\n MigrationRunOptions,\n MigrationRunResult,\n MigrationWriteStage,\n UploadAssetResult,\n} from \"./types.js\";\n\nexport async function runMigration(options: MigrationRunOptions): Promise<MigrationRunResult> {\n const bundle = await collectEntities(options.entities);\n return runMigrationFromBundle(bundle, options);\n}\n\nexport async function runMigrationFromBundle(\n bundle: EntityBundle,\n options: MigrationRunOptions,\n): Promise<MigrationRunResult> {\n const { sink, platform, onEntityProcessed } = options;\n const checkpointEntities: import(\"../normalizer/idempotency.js\").TrackedEntity[] = [];\n const uploadedAssets = new Map<string, UploadAssetResult>();\n\n let processed = 0;\n let failed = 0;\n let skipped = 0;\n\n const track = async (\n stage: MigrationWriteStage,\n key: EntityKey,\n action: () => Promise<void>,\n ): Promise<void> => {\n if (!shouldProcessEntity(key, checkpointEntities)) {\n skipped += 1;\n onEntityProcessed?.(key, \"skipped\");\n return;\n }\n\n const existingTargetId = await sink.findExisting?.(key);\n if (existingTargetId) {\n if (stage === \"assets\" && key.entityType === \"asset\") {\n uploadedAssets.set(key.sourceId, { targetId: existingTargetId });\n }\n skipped += 1;\n onEntityProcessed?.(key, \"skipped\");\n return;\n }\n\n try {\n await sink.reportProgress?.({\n stage,\n progress: processed + failed + skipped,\n message: `${stage}:${key.entityType}:${key.sourceId}`,\n });\n await action();\n processed += 1;\n onEntityProcessed?.(key, \"done\");\n } catch (error) {\n failed += 1;\n const message = error instanceof Error ? error.message : String(error);\n onEntityProcessed?.(key, \"failed\", message);\n }\n };\n\n for (const category of bundle.categories) {\n const key = entityKey(category, platform);\n await track(\"taxonomy\", key, async () => {\n if (!sink.createCategory) return;\n await sink.createCategory(category);\n });\n }\n\n for (const tag of bundle.tags) {\n const key = entityKey(tag, platform);\n await track(\"taxonomy\", key, async () => {\n if (!sink.createTag) return;\n await sink.createTag(tag);\n });\n }\n\n for (const asset of bundle.media) {\n const key = entityKey(asset, platform);\n await track(\"assets\", key, async () => {\n const stream = options.resolveAssetStream ? await options.resolveAssetStream(asset) : null;\n const result = await sink.uploadAsset({\n asset,\n body: stream?.body ?? emptyBody(),\n contentLength: stream?.contentLength,\n });\n uploadedAssets.set(asset.sourceId, result);\n });\n }\n\n for (const portfolio of bundle.portfolios) {\n const key = entityKey(portfolio, platform);\n await track(\"portfolios\", key, async () => {\n if (!sink.createPortfolio) {\n throw new Error(\"Sink does not support portfolios\");\n }\n await sink.createPortfolio(portfolio);\n });\n }\n\n for (const post of bundle.posts) {\n const key = entityKey(post, platform);\n await track(\"content\", key, async () => {\n await sink.createPost(\n prepareContentEntity(post, options, uploadedAssets, bundle),\n );\n });\n }\n\n for (const page of bundle.pages) {\n const key = entityKey(page, platform);\n await track(\"content\", key, async () => {\n await sink.createPage(\n prepareContentEntity(page, options, uploadedAssets, bundle),\n );\n });\n }\n\n const portfolioLinks = buildPortfolioMediaLinks(bundle);\n for (const link of portfolioLinks) {\n const key: EntityKey = {\n platform,\n entityType: \"asset\",\n sourceId: `${link.portfolioSourceId}:${link.assetSourceId}`,\n };\n await track(\"bindings\", key, async () => {\n if (!sink.linkPortfolioMedia) return;\n await sink.linkPortfolioMedia(link);\n });\n }\n\n const redirects = buildRedirectMap(bundle);\n for (const redirect of redirects) {\n const key: EntityKey = {\n platform,\n entityType: \"page\",\n sourceId: `redirect:${redirect.fromPath}`,\n };\n await track(\"redirects\", key, async () => {\n if (!sink.writeRedirect) return;\n await sink.writeRedirect(redirect);\n });\n }\n\n return { processed, failed, skipped };\n}\n\nfunction prepareContentEntity<T extends NormalizedPost | NormalizedPage>(\n entity: T,\n options: MigrationRunOptions,\n uploadedAssets: Map<string, UploadAssetResult>,\n bundle: EntityBundle,\n): T {\n if (!options.rewriteInlineImages) return entity;\n\n const rewriteOptions = mergeRewriteOptions(bundle, options.rewriteInlineImages);\n const rewritten = rewriteInlineImages(entity.contentHtml, rewriteOptions, uploadedAssets);\n\n return {\n ...entity,\n contentHtml: rewritten.html,\n };\n}\n\nfunction mergeRewriteOptions(\n bundle: EntityBundle,\n options: RewriteInlineImagesOptions,\n): RewriteInlineImagesOptions {\n const urlToSourceId = new Map<string, string>();\n for (const asset of bundle.media) {\n urlToSourceId.set(asset.sourceUrl, asset.sourceId);\n const normalized = normalizeAssetUrl(asset.sourceUrl);\n if (normalized) urlToSourceId.set(normalized, asset.sourceId);\n }\n\n const replaceWith = options.replaceWith ?? createMigrationMediaRefReplaceWith();\n const requireUploaded = options.requireUploaded ?? Boolean(options.replaceWith);\n\n return {\n resolveAsset: (src) => {\n const resolved = options.resolveAsset(src);\n if (resolved) return resolved;\n const normalized = normalizeAssetUrl(src);\n const sourceAssetId =\n (normalized ? urlToSourceId.get(normalized) : undefined) ?? urlToSourceId.get(src);\n if (!sourceAssetId) return undefined;\n return { originalSrc: src, sourceAssetId };\n },\n replaceWith,\n requireUploaded,\n };\n}\n\nfunction emptyBody(): Readable {\n return Readable.from([]);\n}\n\nexport type { EntityKey };\n","import * as cheerio from \"cheerio\";\n\nimport type { EntityBundle } from \"../normalizer/bundle.js\";\nimport type { WxrImportSummary } from \"../normalizer/types.js\";\nimport {\n discoverContentAssets,\n discoverRawImgSrcs,\n isMigrationMediaRef,\n normalizeAssetUrl,\n} from \"../lib/media-urls.js\";\nimport { findUnsupportedBlockMarkers } from \"../parsers/squarespace/parse-export.js\";\nimport { findWordPressShortcodeMarkers } from \"../parsers/wordpress/builders/shortcode-conflicts.js\";\nexport interface DuplicateSlugConflict {\n entityType: \"post\" | \"page\";\n slug: string;\n sourceIds: string[];\n}\n\nexport interface MissingFeaturedImageConflict {\n postSourceId: string;\n featuredMediaSourceId: string;\n reason: string;\n}\n\nexport interface StaleAssetUrlConflict {\n sourceId: string;\n url: string;\n reason: string;\n}\n\nexport interface InvalidHtmlConflict {\n entityType: \"post\" | \"page\";\n sourceId: string;\n issues: string[];\n}\n\nexport interface UnresolvedInlineImageConflict {\n postOrPageSourceId: string;\n src: string;\n}\n\nexport interface UnsupportedBlockConflict {\n entityType: \"post\" | \"page\";\n sourceId: string;\n blockType: string;\n blockId?: string;\n}\n\nexport interface RedirectLoopConflict {\n fromPath: string;\n toPath: string;\n blocked: boolean;\n}\n\nexport interface AssetDiscoverySummary {\n /** Unique resolvable image URLs found in post/page HTML. */\n urlsDiscovered: number;\n /** Unique WordPress attachment ids referenced in content (`data-wp-attachment-id`, gallery `ids=`). */\n attachmentRefs: number;\n /** Attachment ids that resolved to a `media.json` row in this job. */\n attachmentRefsResolved: number;\n /** Attachment ids still lacking a URL in this export context. */\n attachmentRefsUnresolved: number;\n /** Sorted unresolved ids (for scan UI / follow-up REST export). */\n unresolvedAttachmentIds: string[];\n}\n\nexport interface ConflictReport {\n duplicatePostSlugs: DuplicateSlugConflict[];\n duplicatePageSlugs: DuplicateSlugConflict[];\n missingFeaturedImages: MissingFeaturedImageConflict[];\n staleAssetUrls: StaleAssetUrlConflict[];\n invalidHtml: InvalidHtmlConflict[];\n unresolvedInlineImages: UnresolvedInlineImageConflict[];\n unsupportedBlocks: UnsupportedBlockConflict[];\n redirectLoops: RedirectLoopConflict[];\n assetDiscovery: AssetDiscoverySummary;\n /** OSS-19 — unsupported WXR `post_type` counts (commerce, builder globals, …). */\n skippedPostTypes: Record<string, number>;\n importableItemCount: number;\n unsupportedOnly: boolean;\n skippedWooCommerceStubPages?: number;\n}\n\nexport function emptyAssetDiscoverySummary(): AssetDiscoverySummary {\n return {\n urlsDiscovered: 0,\n attachmentRefs: 0,\n attachmentRefsResolved: 0,\n attachmentRefsUnresolved: 0,\n unresolvedAttachmentIds: [],\n };\n}\n\nexport function summarizeAssetDiscovery(bundle: EntityBundle): AssetDiscoverySummary {\n const urlSet = new Set<string>();\n const attachmentIdSet = new Set<string>();\n\n for (const entity of [...bundle.posts, ...bundle.pages]) {\n const discovery = discoverContentAssets(entity.contentHtml ?? \"\");\n for (const url of discovery.urls) urlSet.add(url);\n for (const id of discovery.unresolvedAttachmentIds) attachmentIdSet.add(id);\n }\n\n const mediaSourceIds = new Set(bundle.media.map((asset) => asset.sourceId));\n const unresolvedAttachmentIds = [...attachmentIdSet]\n .filter((id) => !mediaSourceIds.has(id))\n .sort((left, right) => Number(left) - Number(right));\n\n return {\n urlsDiscovered: urlSet.size,\n attachmentRefs: attachmentIdSet.size,\n attachmentRefsResolved: attachmentIdSet.size - unresolvedAttachmentIds.length,\n attachmentRefsUnresolved: unresolvedAttachmentIds.length,\n unresolvedAttachmentIds,\n };\n}\n\nexport function emptyConflictReport(): ConflictReport {\n return {\n duplicatePostSlugs: [],\n duplicatePageSlugs: [],\n missingFeaturedImages: [],\n staleAssetUrls: [],\n invalidHtml: [],\n unresolvedInlineImages: [],\n unsupportedBlocks: [],\n redirectLoops: [],\n assetDiscovery: emptyAssetDiscoverySummary(),\n skippedPostTypes: {},\n importableItemCount: 0,\n unsupportedOnly: false,\n };\n}\n\nexport function applyWxrImportSummary(\n report: ConflictReport,\n summary: WxrImportSummary | undefined,\n): ConflictReport {\n if (!summary) return report;\n report.skippedPostTypes = summary.skippedPostTypes;\n report.importableItemCount = summary.importableItemCount;\n report.unsupportedOnly = summary.unsupportedOnly;\n if (summary.skippedWooCommerceStubPages !== undefined) {\n report.skippedWooCommerceStubPages = summary.skippedWooCommerceStubPages;\n }\n return report;\n}\n\nfunction findDuplicateSlugs(\n items: { sourceId: string; slug: string }[],\n entityType: \"post\" | \"page\",\n): DuplicateSlugConflict[] {\n const bySlug = new Map<string, string[]>();\n for (const item of items) {\n const list = bySlug.get(item.slug) ?? [];\n list.push(item.sourceId);\n bySlug.set(item.slug, list);\n }\n\n const conflicts: DuplicateSlugConflict[] = [];\n for (const [slug, sourceIds] of bySlug) {\n if (sourceIds.length > 1) {\n conflicts.push({ entityType, slug, sourceIds });\n }\n }\n return conflicts;\n}\n\nfunction analyzeHtml(html: string): string[] {\n const issues: string[] = [];\n if (/<script\\b/i.test(html)) {\n issues.push(\"script_tag_present\");\n }\n\n try {\n const $ = cheerio.load(html, { xml: false });\n $(\"p\").each((_, el) => {\n const inner = $(el).html() ?? \"\";\n if (inner.includes(\"<p\")) {\n issues.push(\"nested_paragraph\");\n }\n });\n } catch {\n issues.push(\"html_parse_error\");\n }\n\n return [...new Set(issues)];\n}\n\nfunction mediaUrlSet(bundle: EntityBundle): Set<string> {\n const urls = new Set<string>();\n for (const asset of bundle.media) {\n const normalized = normalizeAssetUrl(asset.sourceUrl);\n if (normalized) urls.add(normalized);\n urls.add(asset.sourceUrl);\n }\n return urls;\n}\n\nfunction findUnresolvedInlineImages(\n sourceId: string,\n contentHtml: string,\n mediaUrls: Set<string>,\n): UnresolvedInlineImageConflict[] {\n const conflicts: UnresolvedInlineImageConflict[] = [];\n for (const raw of discoverRawImgSrcs(contentHtml)) {\n if (isMigrationMediaRef(raw)) continue;\n const normalized = normalizeAssetUrl(raw);\n if (!normalized) continue;\n if (!mediaUrls.has(normalized) && !mediaUrls.has(raw)) {\n conflicts.push({ postOrPageSourceId: sourceId, src: raw });\n }\n }\n return conflicts;\n}\n\nfunction findUnsupportedBlocks(\n entityType: \"post\" | \"page\",\n sourceId: string,\n contentHtml: string,\n): UnsupportedBlockConflict[] {\n const conflicts: UnsupportedBlockConflict[] = [];\n\n for (const marker of findUnsupportedBlockMarkers(contentHtml)) {\n conflicts.push({\n entityType,\n sourceId,\n blockType: marker.blockType,\n blockId: marker.blockId,\n });\n }\n\n for (const marker of findWordPressShortcodeMarkers(contentHtml)) {\n conflicts.push({\n entityType,\n sourceId,\n blockType: marker.unresolvable\n ? `wordpress:unresolvable:${marker.shortcode}`\n : `wordpress:shortcode:${marker.shortcode}`,\n });\n }\n\n return conflicts;\n}\n\nexport function analyzeConflicts(\n bundle: EntityBundle,\n options?: {\n staleAssetUrls?: StaleAssetUrlConflict[];\n redirectLoops?: RedirectLoopConflict[];\n wxrImportSummary?: WxrImportSummary;\n },\n): ConflictReport {\n const report = emptyConflictReport();\n const mediaUrls = mediaUrlSet(bundle);\n\n report.duplicatePostSlugs = findDuplicateSlugs(bundle.posts, \"post\");\n report.duplicatePageSlugs = findDuplicateSlugs(bundle.pages, \"page\");\n\n for (const post of bundle.posts) {\n if (post.sourceFeaturedMediaId && !post.featuredAssetSourceId) {\n report.missingFeaturedImages.push({\n postSourceId: post.sourceId,\n featuredMediaSourceId: post.sourceFeaturedMediaId,\n reason: \"attachment_not_in_export\",\n });\n }\n\n const htmlIssues = analyzeHtml(post.contentHtml);\n if (htmlIssues.length) {\n report.invalidHtml.push({\n entityType: \"post\",\n sourceId: post.sourceId,\n issues: htmlIssues,\n });\n }\n\n report.unresolvedInlineImages.push(\n ...findUnresolvedInlineImages(post.sourceId, post.contentHtml, mediaUrls),\n );\n report.unsupportedBlocks.push(\n ...findUnsupportedBlocks(\"post\", post.sourceId, post.contentHtml),\n );\n }\n\n for (const page of bundle.pages) {\n const htmlIssues = analyzeHtml(page.contentHtml);\n if (htmlIssues.length) {\n report.invalidHtml.push({\n entityType: \"page\",\n sourceId: page.sourceId,\n issues: htmlIssues,\n });\n }\n\n report.unresolvedInlineImages.push(\n ...findUnresolvedInlineImages(page.sourceId, page.contentHtml, mediaUrls),\n );\n report.unsupportedBlocks.push(\n ...findUnsupportedBlocks(\"page\", page.sourceId, page.contentHtml),\n );\n }\n\n if (options?.staleAssetUrls) {\n report.staleAssetUrls = options.staleAssetUrls;\n }\n if (options?.redirectLoops) {\n report.redirectLoops = options.redirectLoops;\n }\n\n report.assetDiscovery = summarizeAssetDiscovery(bundle);\n applyWxrImportSummary(report, options?.wxrImportSummary);\n\n return report;\n}\n\nexport function hasBlockingConflicts(report: ConflictReport): boolean {\n return report.duplicatePageSlugs.length > 0 || report.redirectLoops.some((r) => r.blocked);\n}\n\nexport function hasWarnings(report: ConflictReport): boolean {\n return (\n report.duplicatePostSlugs.length > 0 ||\n report.missingFeaturedImages.length > 0 ||\n report.staleAssetUrls.length > 0 ||\n report.invalidHtml.length > 0 ||\n report.unresolvedInlineImages.length > 0 ||\n report.unsupportedBlocks.length > 0 ||\n report.assetDiscovery.attachmentRefsUnresolved > 0 ||\n report.unsupportedOnly\n );\n}\n\nexport function buildRedirectMap(bundle: EntityBundle): {\n fromPath: string;\n toPath: string;\n statusCode: number;\n}[] {\n const redirects: { fromPath: string; toPath: string; statusCode: number }[] = [];\n\n for (const post of bundle.posts) {\n const from = post.source.path;\n if (!from) continue;\n const to = `/blog/${post.slug}`;\n if (from.replace(/\\/$/, \"\") === to.replace(/\\/$/, \"\")) continue;\n redirects.push({ fromPath: from, toPath: to, statusCode: 301 });\n }\n\n for (const page of bundle.pages) {\n const from = page.source.path;\n if (!from) continue;\n const to = `/${page.slug}`;\n if (from.replace(/\\/$/, \"\") === to.replace(/\\/$/, \"\")) continue;\n redirects.push({ fromPath: from, toPath: to, statusCode: 301 });\n }\n\n return redirects;\n}\n\nexport function detectRedirectLoops(\n redirects: { fromPath: string; toPath: string }[],\n): RedirectLoopConflict[] {\n const loops: RedirectLoopConflict[] = [];\n for (const row of redirects) {\n if (row.fromPath.replace(/\\/$/, \"\") === row.toPath.replace(/\\/$/, \"\")) {\n loops.push({ fromPath: row.fromPath, toPath: row.toPath, blocked: true });\n }\n }\n return loops;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { basename } from \"node:path\";\n\nimport { discoverContentAssetUrls } from \"../../lib/media-urls.js\";\nimport { linkToPath, sanitizeSlug } from \"../../lib/utility.js\";\nimport type {\n NormalizedAsset,\n NormalizedCategory,\n NormalizedEntity,\n NormalizedPage,\n NormalizedPortfolio,\n NormalizedPost,\n NormalizedTag,\n PublishStatus,\n SourceMetadata,\n} from \"../../normalizer/types.js\";\nimport {\n SquarespaceCollectionClient,\n type SquarespaceClientOptions,\n type SquarespaceCollectTarget,\n} from \"./collect.js\";\nimport type {\n SquarespaceBlock,\n SquarespaceExport,\n SquarespaceGalleryCollection,\n SquarespaceGalleryItem,\n SquarespacePage,\n SquarespacePost,\n} from \"./types.js\";\n\nconst PLATFORM = \"squarespace\" as const;\nconst UNSUPPORTED_ATTR = \"data-artinstack-unsupported-block\";\nconst BLOCK_ID_ATTR = \"data-artinstack-block-id\";\n\n/** Block types flattened to HTML without a conflict flag. */\nconst SUPPORTED_BLOCK_TYPES = new Set([\n \"html\",\n \"text\",\n \"markdown\",\n \"image\",\n \"gallery\",\n \"quote\",\n \"button\",\n \"video\",\n \"code\",\n \"spacer\",\n \"line\",\n \"horizontalrule\",\n \"hr\",\n]);\n\n/** Known Squarespace block types that cannot be migrated as static HTML snapshots. */\nconst UNSUPPORTED_BLOCK_TYPES = new Set([\n \"product\",\n \"products\",\n \"form\",\n \"newsletter\",\n \"donation\",\n \"calendar\",\n \"chart\",\n \"map\",\n \"music\",\n \"social\",\n \"summary\",\n \"archive\",\n \"acuity\",\n \"member-area\",\n \"digital-product\",\n \"folder\",\n \"index\",\n \"tock\",\n \"opentable\",\n \"soundcloud\",\n \"foursquare\",\n]);\n\nexport interface SquarespaceParseOptions {\n filePath?: string;\n data?: SquarespaceExport;\n /** Pre-constructed json-pretty collector (live crawl). */\n client?: SquarespaceCollectionClient;\n /** Shorthand targets when constructing a client inline. */\n collectTargets?: SquarespaceCollectTarget[];\n clientOptions?: SquarespaceClientOptions;\n}\n\nexport interface FlattenBlocksResult {\n contentHtml: string;\n assetUrls: string[];\n}\n\nfunction sourceMeta(id: string, url?: string, exportedAt?: string): SourceMetadata {\n return {\n platform: PLATFORM,\n id,\n url,\n path: linkToPath(url),\n exportedAt,\n };\n}\n\nfunction mapPublishStatus(status: string | undefined): PublishStatus {\n switch ((status ?? \"published\").toLowerCase()) {\n case \"published\":\n return \"published\";\n case \"draft\":\n case \"scheduled\":\n return \"draft\";\n default:\n return \"archived\";\n }\n}\n\nfunction escapeHtml(text: string): string {\n return text\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\");\n}\n\nfunction blockShell(type: string, inner: string, blockId?: string): string {\n const idAttr = blockId ? ` id=\"sqs-block-${blockId}\"` : \"\";\n return `<div class=\"sqs-block sqs-block-${type}\"${idAttr}>${inner}</div>`;\n}\n\nfunction unsupportedPlaceholder(type: string, blockId?: string): string {\n const idPart = blockId ? ` ${BLOCK_ID_ATTR}=\"${escapeHtml(blockId)}\"` : \"\";\n return `<div class=\"sqs-block sqs-block-unsupported\" ${UNSUPPORTED_ATTR}=\"${escapeHtml(type)}\"${idPart} aria-hidden=\"true\"></div>`;\n}\n\nfunction flattenGalleryItem(item: SquarespaceGalleryItem): string {\n const alt = item.altText ? ` alt=\"${escapeHtml(item.altText)}\"` : \"\";\n const caption = item.caption ? `<figcaption>${item.caption}</figcaption>` : \"\";\n return `<figure><img src=\"${escapeHtml(item.imageUrl)}\"${alt} />${caption}</figure>`;\n}\n\nexport function flattenSquarespaceBlock(block: SquarespaceBlock): FlattenBlocksResult {\n const type = block.type.toLowerCase();\n const blockId = block.id;\n const assetUrls: string[] = [];\n\n if (UNSUPPORTED_BLOCK_TYPES.has(type)) {\n return {\n contentHtml: unsupportedPlaceholder(type, blockId),\n assetUrls,\n };\n }\n\n if (!SUPPORTED_BLOCK_TYPES.has(type)) {\n return {\n contentHtml: unsupportedPlaceholder(type || \"unknown\", blockId),\n assetUrls,\n };\n }\n\n switch (type) {\n case \"html\":\n case \"text\":\n return {\n contentHtml: blockShell(type, block.html ?? block.value ?? \"\", blockId),\n assetUrls,\n };\n\n case \"markdown\":\n return {\n contentHtml: blockShell(\n type,\n block.html ?? `<div class=\"sqs-markdown\">${escapeHtml(block.value ?? \"\")}</div>`,\n blockId,\n ),\n assetUrls,\n };\n\n case \"image\": {\n const url = block.imageUrl ?? \"\";\n if (url) assetUrls.push(url);\n const alt = block.altText ? ` alt=\"${escapeHtml(block.altText)}\"` : \"\";\n const caption = block.caption ? `<figcaption>${block.caption}</figcaption>` : \"\";\n const inner = url\n ? `<figure><img src=\"${escapeHtml(url)}\"${alt} />${caption}</figure>`\n : \"\";\n return { contentHtml: blockShell(type, inner, blockId), assetUrls };\n }\n\n case \"gallery\": {\n const figures = (block.items ?? [])\n .map((item) => {\n assetUrls.push(item.imageUrl);\n return flattenGalleryItem(item);\n })\n .join(\"\");\n return {\n contentHtml: blockShell(type, `<div class=\"sqs-gallery\">${figures}</div>`, blockId),\n assetUrls,\n };\n }\n\n case \"quote\": {\n const inner = block.html ?? `<blockquote>${escapeHtml(block.value ?? \"\")}</blockquote>`;\n return { contentHtml: blockShell(type, inner, blockId), assetUrls };\n }\n\n case \"button\": {\n const href = block.url ?? \"#\";\n const label = escapeHtml(block.label ?? block.value ?? \"Learn more\");\n return {\n contentHtml: blockShell(\n type,\n `<p><a class=\"sqs-block-button\" href=\"${escapeHtml(href)}\">${label}</a></p>`,\n blockId,\n ),\n assetUrls,\n };\n }\n\n case \"video\": {\n const inner =\n block.embedHtml ??\n block.html ??\n (block.url ? `<p><a href=\"${escapeHtml(block.url)}\">Video</a></p>` : \"\");\n return { contentHtml: blockShell(type, inner, blockId), assetUrls };\n }\n\n case \"code\": {\n const inner =\n block.html ??\n `<pre><code>${escapeHtml(block.value ?? \"\")}</code></pre>`;\n return { contentHtml: blockShell(type, inner, blockId), assetUrls };\n }\n\n case \"spacer\":\n return {\n contentHtml: blockShell(type, `<div class=\"sqs-spacer\" aria-hidden=\"true\"></div>`, blockId),\n assetUrls,\n };\n\n case \"line\":\n case \"horizontalrule\":\n case \"hr\":\n return { contentHtml: blockShell(\"line\", \"<hr />\", blockId), assetUrls };\n\n default:\n return {\n contentHtml: unsupportedPlaceholder(type, blockId),\n assetUrls,\n };\n }\n}\n\nexport function flattenSquarespaceBlocks(blocks: SquarespaceBlock[]): FlattenBlocksResult {\n const parts: string[] = [];\n const assetUrls: string[] = [];\n for (const block of blocks) {\n const flattened = flattenSquarespaceBlock(block);\n parts.push(flattened.contentHtml);\n assetUrls.push(...flattened.assetUrls);\n }\n return {\n contentHtml: parts.join(\"\\n\"),\n assetUrls,\n };\n}\n\nfunction resolveContentHtml(\n entity: SquarespacePage | SquarespacePost,\n): FlattenBlocksResult {\n if (entity.blocks?.length) {\n return flattenSquarespaceBlocks(entity.blocks);\n }\n const html = entity.contentHtml ?? \"\";\n return {\n contentHtml: html,\n assetUrls: [...discoverContentAssetUrls(html)],\n };\n}\n\nfunction guessMime(filename: string): string | undefined {\n const ext = filename.split(\".\").pop()?.toLowerCase();\n const map: Record<string, string> = {\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n png: \"image/png\",\n gif: \"image/gif\",\n webp: \"image/webp\",\n svg: \"image/svg+xml\",\n };\n return ext ? map[ext] : undefined;\n}\n\nfunction filenameFromUrl(url: string, fallback: string): string {\n try {\n return basename(new URL(url).pathname) || fallback;\n } catch {\n return basename(url.split(\"?\")[0] ?? \"\") || fallback;\n }\n}\n\nfunction assetFromUrl(\n url: string,\n exportedAt: string | undefined,\n index: number,\n): NormalizedAsset {\n const filename = filenameFromUrl(url, `asset-${index}.jpg`);\n const sourceId = `asset-${sanitizeSlug(filename)}-${index}`;\n return {\n type: \"asset\",\n source: sourceMeta(sourceId, url, exportedAt),\n sourceId,\n sourceUrl: url,\n filename,\n mimeType: guessMime(filename),\n };\n}\n\n/** Stable portfolio id for a Squarespace gallery block (host idempotency key). */\nexport function galleryPortfolioSourceId(\n parentSourceId: string,\n block: SquarespaceBlock,\n galleryIndex: number,\n): string {\n const blockId = block.id?.trim();\n if (blockId) return `gallery:${blockId}`;\n return `gallery:${parentSourceId}:${galleryIndex}`;\n}\n\nfunction countGalleryPortfolios(blocks: SquarespaceBlock[] | undefined): number {\n if (!blocks?.length) return 0;\n return blocks.filter(\n (block) => block.type.toLowerCase() === \"gallery\" && (block.items?.length ?? 0) > 0,\n ).length;\n}\n\nfunction collectGalleryImageUrls(blocks: SquarespaceBlock[] | undefined): Set<string> {\n const urls = new Set<string>();\n if (!blocks?.length) return urls;\n for (const block of blocks) {\n if (block.type.toLowerCase() !== \"gallery\") continue;\n for (const item of block.items ?? []) {\n if (item.imageUrl) urls.add(item.imageUrl);\n }\n }\n return urls;\n}\n\nfunction galleryAssetSourceId(\n portfolioSourceId: string,\n item: SquarespaceGalleryItem,\n sort: number,\n): string {\n const itemId = item.id?.trim();\n if (itemId) return itemId;\n return `${portfolioSourceId}:${sort}`;\n}\n\n/**\n * Emit one `NormalizedPortfolio` per non-empty gallery block, plus linked assets\n * with `portfolioSourceId` + `sort` for `buildPortfolioMediaLinks()`.\n */\nexport function* emitGalleriesFromBlocks(\n blocks: SquarespaceBlock[] | undefined,\n parent: { sourceId: string; title: string; url?: string },\n exportedAt?: string,\n): Generator<NormalizedEntity> {\n if (!blocks?.length) return;\n\n const nonEmptyGalleries = blocks.filter(\n (block) => block.type.toLowerCase() === \"gallery\" && (block.items?.length ?? 0) > 0,\n );\n if (nonEmptyGalleries.length === 0) return;\n\n let galleryIndex = 0;\n for (const block of blocks) {\n if (block.type.toLowerCase() !== \"gallery\") continue;\n const items = (block.items ?? []).filter((item) => Boolean(item.imageUrl?.trim()));\n if (items.length === 0) continue;\n\n const sourceId = galleryPortfolioSourceId(parent.sourceId, block, galleryIndex);\n const slugBase = block.id?.trim()\n ? sanitizeSlug(block.id)\n : sanitizeSlug(`gallery-${galleryIndex + 1}`);\n const title =\n nonEmptyGalleries.length === 1\n ? parent.title\n : `${parent.title} — Gallery ${galleryIndex + 1}`;\n\n yield {\n type: \"portfolio\",\n source: sourceMeta(sourceId, parent.url, exportedAt),\n sourceId,\n title,\n slug: slugBase.startsWith(\"gallery\") ? slugBase : `gallery-${slugBase}`,\n } satisfies NormalizedPortfolio;\n\n yield* emitGalleryAssets(sourceId, items, exportedAt);\n\n galleryIndex += 1;\n }\n}\n\n/** Stable portfolio id for a standalone gallery collection page. */\nexport function galleryCollectionPortfolioSourceId(collectionId: string): string {\n return `gallery-collection:${collectionId}`;\n}\n\nfunction* emitGalleryAssets(\n portfolioSourceId: string,\n items: SquarespaceGalleryItem[],\n exportedAt?: string,\n): Generator<NormalizedAsset> {\n for (let sort = 0; sort < items.length; sort++) {\n const item = items[sort]!;\n const assetSourceId = galleryAssetSourceId(portfolioSourceId, item, sort);\n const filename = filenameFromUrl(item.imageUrl, `${assetSourceId}.jpg`);\n yield {\n type: \"asset\",\n source: sourceMeta(assetSourceId, item.imageUrl, exportedAt),\n sourceId: assetSourceId,\n sourceUrl: item.imageUrl,\n filename,\n mimeType: guessMime(filename),\n caption: item.caption,\n altText: item.altText,\n portfolioSourceId,\n sort,\n } satisfies NormalizedAsset;\n }\n}\n\n/**\n * Emit one `NormalizedPortfolio` per non-empty top-level gallery collection\n * (json-pretty gallery pages), plus linked ordered assets.\n */\nexport function* emitGalleryCollections(\n galleries: SquarespaceGalleryCollection[] | undefined,\n exportedAt?: string,\n): Generator<NormalizedEntity> {\n if (!galleries?.length) return;\n\n for (const gallery of galleries) {\n const items = gallery.items.filter((item) => Boolean(item.imageUrl?.trim()));\n if (items.length === 0) continue;\n\n const sourceId = galleryCollectionPortfolioSourceId(gallery.id);\n const slugBase = sanitizeSlug(gallery.slug || gallery.id);\n yield {\n type: \"portfolio\",\n source: sourceMeta(sourceId, gallery.url, exportedAt),\n sourceId,\n title: gallery.title,\n slug: slugBase.startsWith(\"gallery\") ? slugBase : `gallery-${slugBase}`,\n description: gallery.description,\n } satisfies NormalizedPortfolio;\n\n yield* emitGalleryAssets(sourceId, items, exportedAt);\n }\n}\n\nexport function isSquarespaceExport(value: unknown): value is SquarespaceExport {\n if (!value || typeof value !== \"object\") return false;\n const record = value as SquarespaceExport;\n const version = record.exportVersion;\n return (version === 1 || version === \"1\") && Array.isArray(record.pages);\n}\n\nexport async function loadSquarespaceExport(\n options: SquarespaceParseOptions,\n): Promise<SquarespaceExport> {\n if (options.data) return options.data;\n if (options.client) {\n if (!options.collectTargets?.length) {\n throw new Error(\"Squarespace client.collectExport requires collectTargets\");\n }\n return options.client.collectExport(options.collectTargets);\n }\n if (options.collectTargets?.length) {\n const client = new SquarespaceCollectionClient(options.clientOptions);\n return client.collectExport(options.collectTargets);\n }\n if (!options.filePath) {\n throw new Error(\"Squarespace parser requires filePath, data, client, or collectTargets\");\n }\n const raw: unknown = JSON.parse(await readFile(options.filePath, \"utf8\"));\n if (isSquarespaceExport(raw)) return raw;\n throw new Error(\"Invalid Squarespace export: expected exportVersion 1 with pages[]\");\n}\n\nfunction* emitAssetsFromContent(\n contentHtml: string,\n explicitUrls: string[],\n exportedAt?: string,\n excludeUrls?: Set<string>,\n): Generator<NormalizedAsset> {\n const seen = new Set<string>(excludeUrls ?? []);\n const urls = [...explicitUrls, ...discoverContentAssetUrls(contentHtml)];\n let index = 0;\n for (const url of urls) {\n if (seen.has(url)) continue;\n seen.add(url);\n yield assetFromUrl(url, exportedAt, index);\n index += 1;\n }\n}\n\nasync function* emitPage(page: SquarespacePage, exportedAt?: string): AsyncGenerator<NormalizedEntity> {\n const { contentHtml, assetUrls } = resolveContentHtml(page);\n yield {\n type: \"page\",\n source: sourceMeta(page.id, page.url, exportedAt),\n sourceId: page.id,\n title: page.title,\n slug: sanitizeSlug(page.slug),\n contentHtml,\n contentCss: page.contentCss,\n isHomePage: page.isHomePage,\n status: mapPublishStatus(page.status),\n seoTitle: page.seoTitle,\n seoDescription: page.seoDescription,\n } satisfies NormalizedPage;\n\n yield* emitGalleriesFromBlocks(\n page.blocks,\n { sourceId: page.id, title: page.title, url: page.url },\n exportedAt,\n );\n\n const galleryUrls = collectGalleryImageUrls(page.blocks);\n yield* emitAssetsFromContent(contentHtml, assetUrls, exportedAt, galleryUrls);\n}\n\nasync function* emitPost(post: SquarespacePost, exportedAt?: string): AsyncGenerator<NormalizedEntity> {\n const { contentHtml, assetUrls } = resolveContentHtml(post);\n\n let featuredAssetSourceId: string | undefined;\n if (post.featuredImageUrl) {\n featuredAssetSourceId = `featured-${post.id}`;\n }\n\n yield {\n type: \"post\",\n source: sourceMeta(post.id, post.url, exportedAt),\n sourceId: post.id,\n title: post.title,\n slug: sanitizeSlug(post.slug),\n excerpt: post.excerpt,\n contentHtml,\n publishedAt: post.publishedAt,\n status: mapPublishStatus(post.status),\n categorySlugs: post.categorySlugs,\n tagSlugs: post.tagSlugs,\n featuredAssetSourceId,\n seoTitle: post.seoTitle,\n seoDescription: post.seoDescription,\n } satisfies NormalizedPost;\n\n if (post.featuredImageUrl) {\n const filename = filenameFromUrl(post.featuredImageUrl, `${post.id}-featured.jpg`);\n yield {\n type: \"asset\",\n source: sourceMeta(featuredAssetSourceId!, post.featuredImageUrl, exportedAt),\n sourceId: featuredAssetSourceId!,\n sourceUrl: post.featuredImageUrl,\n filename,\n mimeType: guessMime(filename),\n } satisfies NormalizedAsset;\n }\n\n yield* emitGalleriesFromBlocks(\n post.blocks,\n { sourceId: post.id, title: post.title, url: post.url },\n exportedAt,\n );\n\n const galleryUrls = collectGalleryImageUrls(post.blocks);\n yield* emitAssetsFromContent(contentHtml, assetUrls, exportedAt, galleryUrls);\n}\n\n/** Parse Squarespace JSON export → normalizer DTOs (static HTML snapshots). */\nexport async function* enumerateSquarespaceEntities(\n options: SquarespaceParseOptions,\n): AsyncGenerator<NormalizedEntity> {\n const doc = await loadSquarespaceExport(options);\n const exportedAt = doc.exportedAt;\n\n for (const category of doc.categories ?? []) {\n yield {\n type: \"category\",\n source: sourceMeta(category.id, undefined, exportedAt),\n sourceId: category.id,\n name: category.name,\n slug: sanitizeSlug(category.slug),\n } satisfies NormalizedCategory;\n }\n\n for (const tag of doc.tags ?? []) {\n yield {\n type: \"tag\",\n source: sourceMeta(tag.id, undefined, exportedAt),\n sourceId: tag.id,\n name: tag.name,\n slug: sanitizeSlug(tag.slug),\n } satisfies NormalizedTag;\n }\n\n for (const page of doc.pages) {\n yield* emitPage(page, exportedAt);\n }\n\n for (const post of doc.posts ?? []) {\n yield* emitPost(post, exportedAt);\n }\n\n yield* emitGalleryCollections(doc.galleries, exportedAt);\n}\n\nfunction countCollectionPortfolios(galleries: SquarespaceGalleryCollection[] | undefined): number {\n if (!galleries?.length) return 0;\n return galleries.filter((gallery) =>\n gallery.items.some((item) => Boolean(item.imageUrl?.trim())),\n ).length;\n}\n\nexport function summarizeSquarespaceExport(doc: SquarespaceExport): {\n pages: number;\n posts: number;\n categories: number;\n tags: number;\n portfolios: number;\n} {\n let portfolios = 0;\n for (const page of doc.pages) {\n portfolios += countGalleryPortfolios(page.blocks);\n }\n for (const post of doc.posts ?? []) {\n portfolios += countGalleryPortfolios(post.blocks);\n }\n portfolios += countCollectionPortfolios(doc.galleries);\n return {\n pages: doc.pages.length,\n posts: doc.posts?.length ?? 0,\n categories: doc.categories?.length ?? 0,\n tags: doc.tags?.length ?? 0,\n portfolios,\n };\n}\n\nexport async function validateSquarespaceExportFile(filePath: string): Promise<{\n ok: boolean;\n issues: { code: string; message: string }[];\n summary: Record<string, number>;\n}> {\n const issues: { code: string; message: string }[] = [];\n let doc: SquarespaceExport;\n try {\n doc = await loadSquarespaceExport({ filePath });\n } catch (error) {\n return {\n ok: false,\n issues: [\n {\n code: \"invalid_export\",\n message: error instanceof Error ? error.message : String(error),\n },\n ],\n summary: {},\n };\n }\n\n if (doc.pages.length === 0 && (doc.posts?.length ?? 0) === 0) {\n issues.push({ code: \"empty_export\", message: \"No pages or posts in export\" });\n }\n\n const summary = summarizeSquarespaceExport(doc);\n return {\n ok: issues.length === 0,\n issues,\n summary: {\n pages: summary.pages,\n posts: summary.posts,\n categories: summary.categories,\n tags: summary.tags,\n portfolios: summary.portfolios,\n assets: 0,\n },\n };\n}\n\n/** @internal Scan flattened HTML for unsupported block markers (used by conflict analysis). */\nexport function findUnsupportedBlockMarkers(html: string): { blockType: string; blockId?: string }[] {\n const markers: { blockType: string; blockId?: string }[] = [];\n const pattern =\n /data-artinstack-unsupported-block=\"([^\"]+)\"(?:\\s+data-artinstack-block-id=\"([^\"]*)\")?/g;\n for (const match of html.matchAll(pattern)) {\n markers.push({\n blockType: match[1] ?? \"unknown\",\n blockId: match[2] || undefined,\n });\n }\n return markers;\n}\n\nexport { SUPPORTED_BLOCK_TYPES, UNSUPPORTED_BLOCK_TYPES, UNSUPPORTED_ATTR, BLOCK_ID_ATTR };\n","import * as cheerio from \"cheerio\";\nimport { z } from \"zod\";\n\nimport { sanitizeSlug } from \"../../lib/utility.js\";\nimport type {\n SquarespaceBlock,\n SquarespaceCategory,\n SquarespaceExport,\n SquarespaceGalleryCollection,\n SquarespaceGalleryItem,\n SquarespacePage,\n SquarespacePost,\n SquarespaceTag,\n} from \"./types.js\";\n\nexport const SQUARESPACE_JSON_FORMAT = \"json-pretty\" as const;\nexport const SQUARESPACE_JSON_FORMAT_COMPACT = \"json\" as const;\n\nexport type SquarespaceJsonFormat =\n | typeof SQUARESPACE_JSON_FORMAT\n | typeof SQUARESPACE_JSON_FORMAT_COMPACT;\n\nexport const squarespaceClientOptionsSchema = z.object({\n format: z.enum([\"json\", \"json-pretty\"]).default(\"json-pretty\"),\n maxRetries: z.number().int().min(0).max(10).default(3),\n retryBaseDelayMs: z.number().int().min(0).default(500),\n maxRetryDelayMs: z.number().int().min(0).default(8000),\n requestIntervalMs: z.number().int().min(0).default(200),\n /**\n * When json-pretty yields an empty classic layout (common on 7.1 section pages),\n * fetch the rendered HTML once and parse `.sqs-block` content from `#sections`.\n */\n htmlFallback: z.boolean().default(true),\n fetchImpl: z.custom<typeof fetch>().optional(),\n});\n\nexport type SquarespaceClientOptions = z.input<typeof squarespaceClientOptionsSchema>;\n\nexport interface SquarespaceCollectTarget {\n /** Page or collection URL on the live Squarespace site (without format query). */\n url: string;\n /** `collection` paginates `items[]`; `page` fetches a single static page/item. */\n kind?: \"auto\" | \"page\" | \"collection\";\n isHomePage?: boolean;\n}\n\ninterface WireRecord {\n [key: string]: unknown;\n}\n\ninterface WirePagination {\n nextPage?: boolean;\n nextPageUrl?: string;\n}\n\nfunction isRecord(value: unknown): value is WireRecord {\n return !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction asRecord(value: unknown): WireRecord | undefined {\n return isRecord(value) ? value : undefined;\n}\n\nfunction asStringArray(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.filter((entry): entry is string => typeof entry === \"string\");\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** Append Squarespace `?format=json-pretty` (or `json`) to a site URL. */\nexport function buildJsonPrettyUrl(\n pageUrl: string,\n format: SquarespaceJsonFormat = SQUARESPACE_JSON_FORMAT,\n): string {\n const url = new URL(pageUrl);\n url.searchParams.set(\"format\", format);\n return url.toString();\n}\n\nfunction mapWorkflowState(state: unknown): SquarespacePage[\"status\"] {\n if (state === 1 || state === \"1\") return \"published\";\n if (state === 2 || state === \"2\") return \"draft\";\n return \"published\";\n}\n\nfunction mapPublishOn(value: unknown): string | undefined {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return undefined;\n return new Date(value).toISOString();\n}\n\nfunction readSeo(seoData: unknown, field: \"title\" | \"description\"): string | undefined {\n const record = asRecord(seoData);\n if (!record) return undefined;\n const value = record[field];\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\n/** Infer block type from Squarespace LayoutEngine / Fluid Engine class names. */\nexport function inferBlockTypeFromClassName(className: string): string {\n const match = className.match(/\\bsqs-block-([a-z0-9-]+)\\b/i);\n if (!match?.[1]) return \"html\";\n const raw = match[1].toLowerCase();\n if (raw === \"horizontalrule\") return \"line\";\n return raw.replace(/-block$/g, \"\");\n}\n\n/** True when json-pretty `mainContent` is an empty classic LayoutEngine shell. */\nexport function isEmptyClassicMainContent(html: string | undefined): boolean {\n if (!html?.trim()) return true;\n const $ = cheerio.load(html, { xml: false });\n if ($(\".sqs-block\").length > 0) return false;\n if ($(\".sqs-layout.empty\").length > 0) return true;\n // Tiny shells with no blocks are not usable page bodies.\n return html.replace(/\\s+/g, \" \").trim().length < 280;\n}\n\n/** True when an export page has no blocks and no usable contentHtml. */\nexport function pageContentIsEmpty(page: Pick<SquarespacePage, \"blocks\" | \"contentHtml\">): boolean {\n if ((page.blocks?.length ?? 0) > 0) return false;\n return isEmptyClassicMainContent(page.contentHtml);\n}\n\n/**\n * Pull the primary page body from a rendered Squarespace HTML document.\n * Prefers 7.1 `#sections` / `article.sections`, then `main`.\n */\nexport function extractPageBodyHtml(html: string): string {\n if (!html.trim()) return \"\";\n const $ = cheerio.load(html, { xml: false });\n const sections = $(\"#sections\").first();\n if (sections.length) return sections.html() ?? \"\";\n const article = $(\"article.sections\").first();\n if (article.length) return article.html() ?? \"\";\n const main = $(\"main#page, main[role='main'], main\").first();\n if (main.length) return main.html() ?? \"\";\n return \"\";\n}\n\n/** Map rendered page HTML into export `blocks` / `contentHtml`. */\nexport function extractPageContentFromHtml(\n html: string,\n): Pick<SquarespacePage, \"blocks\" | \"contentHtml\"> {\n const body = extractPageBodyHtml(html);\n if (!body.trim()) return { contentHtml: \"\" };\n\n const parsedBlocks = extractBlocksFromBodyHtml(body);\n if (parsedBlocks.length > 0) {\n return { blocks: parsedBlocks };\n }\n return { contentHtml: body };\n}\n\n/** Parse rendered `body` HTML into block entries when wire JSON has no structured blocks. */\nexport function extractBlocksFromBodyHtml(html: string): SquarespaceBlock[] {\n if (!html.trim()) return [];\n const $ = cheerio.load(html, { xml: false });\n const blocks: SquarespaceBlock[] = [];\n\n $(\".sqs-block\").each((_, element) => {\n const el = $(element);\n const className = el.attr(\"class\") ?? \"\";\n const type = inferBlockTypeFromClassName(className);\n const id = el.attr(\"id\")?.replace(/^block-/, \"\");\n const content = el.find(\".sqs-block-content\").first();\n const innerHtml = (content.length ? content.html() : el.html()) ?? \"\";\n\n if (type === \"image\") {\n const img = content.find(\"img\").first();\n const imageUrl = img.attr(\"data-src\") ?? img.attr(\"src\") ?? undefined;\n blocks.push({\n id,\n type,\n imageUrl,\n altText: img.attr(\"alt\") ?? undefined,\n caption: content.find(\"figcaption\").text() || undefined,\n html: innerHtml || undefined,\n });\n return;\n }\n\n if (type === \"gallery\") {\n const items: SquarespaceGalleryItem[] = [];\n content.find(\"img\").each((idx, imgEl) => {\n const img = $(imgEl);\n const imageUrl = img.attr(\"data-src\") ?? img.attr(\"src\");\n if (!imageUrl) return;\n items.push({\n id: img.attr(\"data-image-id\") ?? `gallery-${idx}`,\n imageUrl,\n altText: img.attr(\"alt\") ?? undefined,\n });\n });\n blocks.push({ id, type, items, html: innerHtml || undefined });\n return;\n }\n\n if (type === \"button\") {\n const anchor = content.find(\"a\").first();\n blocks.push({\n id,\n type,\n url: anchor.attr(\"href\") ?? undefined,\n label: anchor.text() || undefined,\n html: innerHtml || undefined,\n });\n return;\n }\n\n if (type === \"video\" || type === \"embed\") {\n const iframe = content.find(\"iframe\").first();\n blocks.push({\n id,\n type: type === \"embed\" ? \"embed\" : \"video\",\n embedHtml: iframe.length ? $.html(iframe) : innerHtml || undefined,\n html: innerHtml || undefined,\n });\n return;\n }\n\n blocks.push({\n id,\n type,\n html: innerHtml || undefined,\n value: type === \"markdown\" || type === \"quote\" ? content.text() : undefined,\n });\n });\n\n return blocks;\n}\n\nfunction mapWireBlocks(value: unknown): SquarespaceBlock[] | undefined {\n if (!Array.isArray(value)) return undefined;\n const blocks: SquarespaceBlock[] = [];\n for (const entry of value) {\n const record = asRecord(entry);\n if (!record) continue;\n const type = String(record.type ?? record.blockType ?? \"html\");\n blocks.push({\n id: record.id ? String(record.id) : undefined,\n type,\n html: typeof record.html === \"string\" ? record.html : undefined,\n value: typeof record.value === \"string\" ? record.value : undefined,\n imageUrl:\n typeof record.imageUrl === \"string\"\n ? record.imageUrl\n : typeof record.assetUrl === \"string\"\n ? record.assetUrl\n : undefined,\n altText: typeof record.altText === \"string\" ? record.altText : undefined,\n caption: typeof record.caption === \"string\" ? record.caption : undefined,\n url: typeof record.url === \"string\" ? record.url : undefined,\n label: typeof record.label === \"string\" ? record.label : undefined,\n embedHtml: typeof record.embedHtml === \"string\" ? record.embedHtml : undefined,\n items: Array.isArray(record.items)\n ? record.items\n .map((item) => asRecord(item))\n .filter((item): item is WireRecord => !!item)\n .map((item) => ({\n id: item.id ? String(item.id) : undefined,\n imageUrl: String(item.imageUrl ?? item.assetUrl ?? \"\"),\n altText: typeof item.altText === \"string\" ? item.altText : undefined,\n caption: typeof item.caption === \"string\" ? item.caption : undefined,\n }))\n .filter((item) => item.imageUrl.length > 0)\n : undefined,\n });\n }\n return blocks.length > 0 ? blocks : undefined;\n}\n\nfunction mapStructuredBlocksFromItem(item: WireRecord): SquarespaceBlock[] | undefined {\n const direct = mapWireBlocks(item.blocks);\n if (direct?.length) return direct;\n\n const sections = item.sections;\n if (!Array.isArray(sections)) return undefined;\n\n const flattened: SquarespaceBlock[] = [];\n for (const section of sections) {\n const sectionRecord = asRecord(section);\n if (!sectionRecord) continue;\n const rows = sectionRecord.rows;\n if (!Array.isArray(rows)) continue;\n for (const row of rows) {\n const rowRecord = asRecord(row);\n if (!rowRecord) continue;\n const columns = rowRecord.columns;\n if (!Array.isArray(columns)) continue;\n for (const column of columns) {\n const columnRecord = asRecord(column);\n if (!columnRecord) continue;\n const blocks = mapWireBlocks(columnRecord.blocks);\n if (blocks) flattened.push(...blocks);\n }\n }\n }\n return flattened.length > 0 ? flattened : undefined;\n}\n\nfunction mapWireItemContent(item: WireRecord): Pick<SquarespacePage, \"blocks\" | \"contentHtml\"> {\n const structured = mapStructuredBlocksFromItem(item);\n if (structured?.length) {\n return { blocks: structured };\n }\n\n const body = typeof item.body === \"string\" ? item.body : undefined;\n if (!body) return { contentHtml: \"\" };\n\n const parsedBlocks = extractBlocksFromBodyHtml(body);\n if (parsedBlocks.length > 0) {\n return { blocks: parsedBlocks };\n }\n return { contentHtml: body };\n}\n\nfunction isBlogCollection(collection: WireRecord | undefined): boolean {\n if (!collection) return false;\n const ordering = String(collection.ordering ?? \"\").toLowerCase();\n if (ordering === \"chronological\" || ordering === \"calendar\") return true;\n const typeName = String(collection.typeName ?? collection.typeLabel ?? \"\").toLowerCase();\n return typeName.includes(\"blog\");\n}\n\n/** Gallery / portfolio collection pages — items are media, not blog posts. */\nexport function isGalleryCollection(collection: WireRecord | undefined): boolean {\n if (!collection) return false;\n if (isBlogCollection(collection)) return false;\n const typeName = String(collection.typeName ?? \"\").toLowerCase();\n const typeLabel = String(collection.typeLabel ?? \"\").toLowerCase();\n return (\n typeName.includes(\"gallery\") ||\n typeLabel.includes(\"gallery\") ||\n typeName === \"portfolio\" ||\n typeLabel === \"portfolio\"\n );\n}\n\nfunction isStaticPageItem(item: WireRecord, collection: WireRecord | undefined): boolean {\n const recordTypeLabel = String(item.recordTypeLabel ?? \"\").toLowerCase();\n if (recordTypeLabel.includes(\"page\")) return true;\n const collectionType = String(collection?.typeName ?? collection?.typeLabel ?? \"\").toLowerCase();\n return collectionType === \"page\" || collectionType.includes(\"page-collection\");\n}\n\nfunction stripSimpleHtml(value: string): string {\n return value.replace(/<[^>]+>/g, \" \").replace(/\\s+/g, \" \").trim();\n}\n\n/** Map one json-pretty gallery-collection item → export gallery item. */\nexport function mapWireGalleryItem(item: WireRecord): SquarespaceGalleryItem | undefined {\n const resolved =\n typeof item.assetUrl === \"string\" && item.assetUrl.trim()\n ? item.assetUrl.trim()\n : typeof item.imageUrl === \"string\" && item.imageUrl.trim()\n ? item.imageUrl.trim()\n : \"\";\n if (!resolved.startsWith(\"http\")) return undefined;\n\n const rawCaption =\n typeof item.body === \"string\"\n ? stripSimpleHtml(item.body)\n : typeof item.excerpt === \"string\"\n ? item.excerpt.trim()\n : typeof item.caption === \"string\"\n ? item.caption.trim()\n : undefined;\n\n return {\n id: String(item.id ?? item.systemDataId ?? item.urlId ?? \"\"),\n imageUrl: resolved,\n altText:\n typeof item.altText === \"string\"\n ? item.altText\n : typeof item.title === \"string\"\n ? item.title\n : undefined,\n caption: rawCaption || undefined,\n };\n}\n\nfunction mapWireGalleryCollection(\n collection: WireRecord,\n items: WireRecord[],\n context?: { fetchedUrl?: string },\n): SquarespaceGalleryCollection {\n const id = String(collection.id ?? collection.urlId ?? collection.fullUrl ?? \"gallery\");\n const title = String(collection.title ?? collection.navigationTitle ?? \"Gallery\");\n const slug = sanitizeSlug(String(collection.urlId ?? collection.title ?? id));\n const galleryItems = items\n .map((item) => mapWireGalleryItem(item))\n .filter((item): item is SquarespaceGalleryItem => !!item);\n\n return {\n id,\n title,\n slug,\n url: resolveAbsoluteUrl(\n typeof collection.fullUrl === \"string\" ? collection.fullUrl : undefined,\n context?.fetchedUrl,\n ),\n description:\n typeof collection.description === \"string\"\n ? stripSimpleHtml(collection.description)\n : undefined,\n items: galleryItems,\n };\n}\n\nfunction mapWireItemToPost(item: WireRecord, options?: { fallbackUrl?: string }): SquarespacePost {\n const content = mapWireItemContent(item);\n return {\n id: String(item.id ?? item.systemDataId ?? item.urlId ?? \"\"),\n title: String(item.title ?? \"Untitled\"),\n slug: sanitizeSlug(String(item.urlId ?? item.title ?? item.id ?? \"post\")),\n url: resolveAbsoluteUrl(\n typeof item.fullUrl === \"string\" ? item.fullUrl : undefined,\n options?.fallbackUrl,\n ),\n excerpt: typeof item.excerpt === \"string\" ? item.excerpt : undefined,\n publishedAt: mapPublishOn(item.publishOn ?? item.addedOn),\n status: mapWorkflowState(item.workflowState),\n categorySlugs: asStringArray(item.categories).map((slug) => sanitizeSlug(slug)),\n tagSlugs: asStringArray(item.tags).map((slug) => sanitizeSlug(slug)),\n featuredImageUrl: typeof item.assetUrl === \"string\" ? item.assetUrl : undefined,\n seoTitle: readSeo(item.seoData, \"title\"),\n seoDescription: readSeo(item.seoData, \"description\"),\n ...content,\n };\n}\n\nfunction resolveAbsoluteUrl(\n raw: string | undefined,\n fallback?: string,\n): string | undefined {\n const candidate = raw?.trim() || fallback?.trim();\n if (!candidate) return undefined;\n try {\n if (fallback) return new URL(candidate, fallback).toString();\n return new URL(candidate).toString();\n } catch {\n return candidate.startsWith(\"http\") ? candidate : undefined;\n }\n}\n\nfunction mapWireItemToPage(\n item: WireRecord,\n options?: { isHomePage?: boolean; fallbackUrl?: string },\n): SquarespacePage {\n const content = mapWireItemContent(item);\n return {\n id: String(item.id ?? item.urlId ?? \"\"),\n title: String(item.title ?? \"Untitled\"),\n slug: sanitizeSlug(String(item.urlId ?? item.title ?? item.id ?? \"page\")),\n url: resolveAbsoluteUrl(\n typeof item.fullUrl === \"string\" ? item.fullUrl : undefined,\n options?.fallbackUrl,\n ),\n status: mapWorkflowState(item.workflowState),\n isHomePage: options?.isHomePage,\n seoTitle: readSeo(item.seoData, \"title\"),\n seoDescription: readSeo(item.seoData, \"description\"),\n ...content,\n };\n}\n\nfunction mapWireCategories(collection: WireRecord | undefined): SquarespaceCategory[] {\n if (!collection) return [];\n return asStringArray(collection.categories).map((name) => ({\n id: `cat-${sanitizeSlug(name)}`,\n name,\n slug: sanitizeSlug(name),\n }));\n}\n\nfunction mapWireTags(items: WireRecord[]): SquarespaceTag[] {\n const seen = new Map<string, SquarespaceTag>();\n for (const item of items) {\n for (const tag of asStringArray(item.tags)) {\n const slug = sanitizeSlug(tag);\n if (!seen.has(slug)) {\n seen.set(slug, { id: `tag-${slug}`, name: tag, slug });\n }\n }\n }\n return [...seen.values()];\n}\n\nfunction siteFromWire(wire: WireRecord): SquarespaceExport[\"site\"] {\n const website = asRecord(wire.website);\n if (!website) return undefined;\n const url =\n typeof website.authenticUrl === \"string\"\n ? website.authenticUrl\n : typeof website.baseUrl === \"string\"\n ? website.baseUrl\n : undefined;\n const title = typeof website.siteTitle === \"string\" ? website.siteTitle : undefined;\n if (!url && !title) return undefined;\n return { url, title };\n}\n\n/** Map one Squarespace `?format=json-pretty` response into export partials. */\nexport function mapJsonPrettyWire(\n wire: unknown,\n context?: { fetchedUrl?: string; isHomePage?: boolean },\n): Partial<SquarespaceExport> {\n if (!isRecord(wire)) {\n throw new Error(\"Invalid Squarespace json-pretty response\");\n }\n\n const collection = asRecord(wire.collection);\n const partial: Partial<SquarespaceExport> = {\n site: siteFromWire(wire),\n pages: [],\n posts: [],\n galleries: [],\n categories: mapWireCategories(collection),\n tags: [],\n };\n\n if (Array.isArray(wire.items)) {\n const itemRecords = wire.items\n .map((entry) => asRecord(entry))\n .filter((entry): entry is WireRecord => !!entry);\n\n if (collection && isGalleryCollection(collection)) {\n partial.galleries = [mapWireGalleryCollection(collection, itemRecords, context)];\n return partial;\n }\n\n partial.tags = mapWireTags(itemRecords);\n\n for (const item of itemRecords) {\n if (isStaticPageItem(item, collection)) {\n partial.pages!.push(\n mapWireItemToPage(item, { fallbackUrl: context?.fetchedUrl, isHomePage: context?.isHomePage }),\n );\n } else {\n partial.posts!.push(mapWireItemToPost(item, { fallbackUrl: context?.fetchedUrl }));\n }\n }\n return partial;\n }\n\n const item = asRecord(wire.item);\n if (item) {\n if (isStaticPageItem(item, collection)) {\n partial.pages!.push(\n mapWireItemToPage(item, { fallbackUrl: context?.fetchedUrl, isHomePage: context?.isHomePage }),\n );\n } else {\n partial.posts!.push(mapWireItemToPost(item, { fallbackUrl: context?.fetchedUrl }));\n partial.tags = mapWireTags([item]);\n }\n return partial;\n }\n\n if (collection && isGalleryCollection(collection)) {\n partial.galleries = [mapWireGalleryCollection(collection, [], context)];\n return partial;\n }\n\n if (collection && isBlogCollection(collection) === false) {\n const mainContent =\n typeof wire.mainContent === \"string\" ? wire.mainContent : undefined;\n const body =\n mainContent && !isEmptyClassicMainContent(mainContent)\n ? mainContent\n : typeof collection.description === \"string\"\n ? collection.description\n : undefined;\n partial.pages!.push(\n mapWireItemToPage(\n {\n id: collection.id ?? collection.urlId ?? collection.fullUrl,\n title: collection.title ?? collection.navigationTitle,\n urlId: collection.urlId,\n fullUrl: resolveAbsoluteUrl(\n typeof collection.fullUrl === \"string\" ? collection.fullUrl : undefined,\n context?.fetchedUrl,\n ),\n body,\n workflowState: collection.draft ? 2 : 1,\n seoData: collection.seoData,\n },\n { fallbackUrl: context?.fetchedUrl, isHomePage: context?.isHomePage },\n ),\n );\n }\n\n return partial;\n}\n\nfunction dedupeById<T extends { id: string }>(items: T[]): T[] {\n const seen = new Map<string, T>();\n for (const item of items) {\n seen.set(item.id, item);\n }\n return [...seen.values()];\n}\n\nfunction dedupeBySlug<T extends { slug: string }>(items: T[]): T[] {\n const seen = new Map<string, T>();\n for (const item of items) {\n seen.set(item.slug, item);\n }\n return [...seen.values()];\n}\n\n/** Merge multiple mapped partial exports into one canonical `SquarespaceExport`. */\nexport function mergeSquarespaceExportPartials(\n partials: Partial<SquarespaceExport>[],\n): SquarespaceExport {\n const merged: SquarespaceExport = {\n exportVersion: 1,\n exportedAt: new Date().toISOString(),\n pages: [],\n posts: [],\n galleries: [],\n categories: [],\n tags: [],\n };\n\n for (const partial of partials) {\n if (partial.site) merged.site = { ...merged.site, ...partial.site };\n merged.pages.push(...(partial.pages ?? []));\n merged.posts!.push(...(partial.posts ?? []));\n merged.galleries!.push(...(partial.galleries ?? []));\n merged.categories!.push(...(partial.categories ?? []));\n merged.tags!.push(...(partial.tags ?? []));\n }\n\n merged.pages = dedupeById(merged.pages);\n merged.posts = dedupeById(merged.posts ?? []);\n merged.galleries = dedupeById(merged.galleries ?? []);\n merged.categories = dedupeBySlug(merged.categories ?? []);\n merged.tags = dedupeBySlug(merged.tags ?? []);\n return merged;\n}\n\nfunction paginationFromWire(wire: unknown): WirePagination | undefined {\n return asRecord(wire)?.pagination as WirePagination | undefined;\n}\n\nfunction inferTargetKind(target: SquarespaceCollectTarget): \"page\" | \"collection\" {\n if (target.kind && target.kind !== \"auto\") return target.kind;\n try {\n const pathname = new URL(target.url).pathname;\n if (pathname === \"/\" || pathname.endsWith(\"/\")) return \"collection\";\n } catch {\n return \"page\";\n }\n return \"page\";\n}\n\n/** Fetch json-pretty pages/collections and assemble a canonical export document. */\nexport class SquarespaceCollectionClient {\n readonly format: SquarespaceJsonFormat;\n readonly maxRetries: number;\n readonly retryBaseDelayMs: number;\n readonly maxRetryDelayMs: number;\n readonly requestIntervalMs: number;\n readonly htmlFallback: boolean;\n readonly fetchImpl: typeof fetch;\n\n private lastRequestAt = 0;\n\n constructor(options: SquarespaceClientOptions = {}) {\n const parsed = squarespaceClientOptionsSchema.parse(options);\n this.format = parsed.format;\n this.maxRetries = parsed.maxRetries;\n this.retryBaseDelayMs = parsed.retryBaseDelayMs;\n this.maxRetryDelayMs = parsed.maxRetryDelayMs;\n this.requestIntervalMs = parsed.requestIntervalMs;\n this.htmlFallback = parsed.htmlFallback;\n this.fetchImpl = parsed.fetchImpl ?? fetch;\n }\n\n buildJsonPrettyUrl(pageUrl: string): string {\n return buildJsonPrettyUrl(pageUrl, this.format);\n }\n\n async fetchWire(url: string): Promise<unknown> {\n const response = await this.requestWithRetry(this.buildJsonPrettyUrl(url), {\n accept: \"application/json, text/html, */*\",\n });\n return response.json() as Promise<unknown>;\n }\n\n async fetchHtml(url: string): Promise<string> {\n const response = await this.requestWithRetry(url, {\n accept: \"text/html,application/xhtml+xml\",\n });\n return response.text();\n }\n\n async collectExport(targets: SquarespaceCollectTarget[]): Promise<SquarespaceExport> {\n if (targets.length === 0) {\n throw new Error(\"Squarespace collector requires at least one target URL\");\n }\n\n const partials: Partial<SquarespaceExport>[] = [];\n for (const target of targets) {\n const kind = inferTargetKind(target);\n if (kind === \"collection\") {\n partials.push(...(await this.collectCollectionPages(target)));\n } else {\n const wire = await this.fetchWire(target.url);\n partials.push(\n mapJsonPrettyWire(wire, { fetchedUrl: target.url, isHomePage: target.isHomePage }),\n );\n }\n }\n\n const merged = mergeSquarespaceExportPartials(partials);\n if (this.htmlFallback) {\n await this.enrichEmptyPagesFromHtml(merged);\n }\n return merged;\n }\n\n private async enrichEmptyPagesFromHtml(doc: SquarespaceExport): Promise<void> {\n for (const page of doc.pages) {\n if (!pageContentIsEmpty(page)) continue;\n const pageUrl = page.url?.trim();\n if (!pageUrl) continue;\n try {\n const html = await this.fetchHtml(pageUrl);\n const content = extractPageContentFromHtml(html);\n if (content.blocks?.length) {\n page.blocks = content.blocks;\n delete page.contentHtml;\n } else if (content.contentHtml?.trim()) {\n page.contentHtml = content.contentHtml;\n delete page.blocks;\n }\n } catch {\n // Leave empty page; host scan can surface the gap.\n }\n }\n }\n\n private async collectCollectionPages(\n target: SquarespaceCollectTarget,\n ): Promise<Partial<SquarespaceExport>[]> {\n const partials: Partial<SquarespaceExport>[] = [];\n let nextUrl: string | undefined = target.url;\n\n while (nextUrl) {\n const wire = await this.fetchWire(nextUrl);\n partials.push(\n mapJsonPrettyWire(wire, { fetchedUrl: nextUrl, isHomePage: target.isHomePage }),\n );\n\n const pagination = paginationFromWire(wire);\n if (!pagination?.nextPage || !pagination.nextPageUrl) break;\n const base = new URL(target.url);\n nextUrl = new URL(pagination.nextPageUrl, `${base.origin}/`).toString();\n }\n\n return partials;\n }\n\n private async requestWithRetry(\n url: string,\n options?: { accept?: string },\n ): Promise<Response> {\n let attempt = 0;\n const accept = options?.accept ?? \"application/json, text/html, */*\";\n while (true) {\n await this.throttle();\n const response = await this.fetchImpl(url, {\n method: \"GET\",\n headers: { Accept: accept },\n });\n\n if (response.ok) {\n return response;\n }\n\n const retryable = response.status === 429 || response.status >= 500;\n if (!retryable || attempt >= this.maxRetries) {\n const detail = await response.text().catch(() => \"\");\n throw new Error(\n `Squarespace HTTP ${response.status}${detail ? `: ${detail.slice(0, 200)}` : \"\"}`,\n );\n }\n\n const retryAfter = Number.parseInt(response.headers.get(\"retry-after\") ?? \"\", 10);\n const delay = Number.isFinite(retryAfter)\n ? retryAfter * 1000\n : Math.min(this.maxRetryDelayMs, this.retryBaseDelayMs * 2 ** attempt);\n await sleep(delay);\n attempt += 1;\n }\n }\n\n private async throttle(): Promise<void> {\n if (this.requestIntervalMs <= 0) return;\n const elapsed = Date.now() - this.lastRequestAt;\n if (elapsed < this.requestIntervalMs) {\n await sleep(this.requestIntervalMs - elapsed);\n }\n this.lastRequestAt = Date.now();\n }\n}\n","import {\n UNRESOLVABLE_SHORTCODE_PREFIXES,\n} from \"./registry.js\";\n\nexport interface WordPressShortcodeMarker {\n shortcode: string;\n unresolvable: boolean;\n}\n\nconst SHORTCODE_PATTERN = /\\[(\\/?)([a-z][a-z0-9_-]*)\\b[^\\]]*\\]/gi;\n\nfunction isUnresolvable(name: string): boolean {\n const lower = name.toLowerCase();\n if (UNRESOLVABLE_SHORTCODE_PREFIXES.includes(lower as (typeof UNRESOLVABLE_SHORTCODE_PREFIXES)[number])) {\n return true;\n }\n return lower.startsWith(\"woocommerce_\");\n}\n\n/** Collect remaining WordPress shortcode tokens after builder flattening. */\nexport function findWordPressShortcodeMarkers(contentHtml: string): WordPressShortcodeMarker[] {\n if (!contentHtml.trim()) return [];\n\n const seen = new Set<string>();\n const markers: WordPressShortcodeMarker[] = [];\n\n for (const match of contentHtml.matchAll(SHORTCODE_PATTERN)) {\n const closing = match[1] === \"/\";\n const name = (match[2] ?? \"\").toLowerCase();\n if (!name || closing) continue;\n\n const key = name;\n if (seen.has(key)) continue;\n seen.add(key);\n\n markers.push({\n shortcode: name,\n unresolvable: isUnresolvable(name),\n });\n }\n\n return markers.sort((a, b) => a.shortcode.localeCompare(b.shortcode));\n}\n\nexport function hasUnresolvableShortcodes(contentHtml: string): boolean {\n return findWordPressShortcodeMarkers(contentHtml).some((m) => m.unresolvable);\n}\n\nexport { UNRESOLVABLE_SHORTCODE_PREFIXES };\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport type { EntityBundle } from \"../normalizer/bundle.js\";\nimport { buildPortfolioMediaLinks } from \"../normalizer/portfolio-media.js\";\nimport type { ConflictReport } from \"./conflicts.js\";\nimport type { MigrationReport } from \"./migration-report.js\";\n\nexport interface WriteFilesystemOptions {\n outDir: string;\n bundle: EntityBundle;\n conflicts?: ConflictReport;\n report?: MigrationReport;\n}\n\nasync function writeJson(path: string, data: unknown): Promise<void> {\n await writeFile(path, `${JSON.stringify(data, null, 2)}\\n`, \"utf8\");\n}\n\nexport async function writeFilesystemExport(options: WriteFilesystemOptions): Promise<void> {\n await mkdir(options.outDir, { recursive: true });\n\n await writeJson(join(options.outDir, \"posts.json\"), options.bundle.posts);\n await writeJson(join(options.outDir, \"pages.json\"), options.bundle.pages);\n await writeJson(join(options.outDir, \"media.json\"), options.bundle.media);\n await writeJson(join(options.outDir, \"portfolios.json\"), options.bundle.portfolios);\n await writeJson(\n join(options.outDir, \"portfolio-media.json\"),\n buildPortfolioMediaLinks(options.bundle),\n );\n await writeJson(join(options.outDir, \"categories.json\"), options.bundle.categories);\n await writeJson(join(options.outDir, \"tags.json\"), options.bundle.tags);\n\n if (options.conflicts) {\n await writeJson(join(options.outDir, \"conflicts.json\"), options.conflicts);\n }\n if (options.report) {\n await writeJson(join(options.outDir, \"migration-report.json\"), options.report);\n }\n}\n\nexport function bundleToCombinedJson(bundle: EntityBundle): Record<string, unknown> {\n return {\n posts: bundle.posts,\n pages: bundle.pages,\n media: bundle.media,\n portfolios: bundle.portfolios,\n portfolioMedia: buildPortfolioMediaLinks(bundle),\n categories: bundle.categories,\n tags: bundle.tags,\n };\n}\n","import type { EntityBundle } from \"../normalizer/bundle.js\";\nimport { emptyBundle } from \"../normalizer/bundle.js\";\nimport { buildPortfolioMediaLinks } from \"../normalizer/portfolio-media.js\";\nimport type {\n NormalizedAsset,\n NormalizedCategory,\n NormalizedPage,\n NormalizedPortfolio,\n NormalizedPost,\n NormalizedTag,\n PortfolioMediaLink,\n} from \"../normalizer/types.js\";\nimport type {\n CreatePageResult,\n CreatePostResult,\n MigrationRedirect,\n MigrationSink,\n UploadAssetInput,\n UploadAssetResult,\n} from \"./types.js\";\nimport { writeFilesystemExport, type WriteFilesystemOptions } from \"./filesystem.js\";\n\n/** Reference MigrationSink that accumulates entities and writes M0 JSON bundles. */\nexport class FilesystemMigrationSink implements MigrationSink {\n readonly bundle: EntityBundle = emptyBundle();\n readonly portfolioMediaLinks: PortfolioMediaLink[] = [];\n readonly redirects: MigrationRedirect[] = [];\n\n async createCategory(category: NormalizedCategory): Promise<{ targetId: string }> {\n this.bundle.categories.push(category);\n return { targetId: category.sourceId };\n }\n\n async createTag(tag: NormalizedTag): Promise<{ targetId: string }> {\n this.bundle.tags.push(tag);\n return { targetId: tag.sourceId };\n }\n\n async uploadAsset(input: UploadAssetInput): Promise<UploadAssetResult> {\n this.bundle.media.push(input.asset);\n return {\n targetId: input.asset.sourceId,\n publicUrl: input.asset.sourceUrl,\n };\n }\n\n async createPortfolio(portfolio: NormalizedPortfolio): Promise<{ targetId: string }> {\n this.bundle.portfolios.push(portfolio);\n return { targetId: portfolio.sourceId };\n }\n\n async createPost(post: NormalizedPost): Promise<CreatePostResult> {\n this.bundle.posts.push(post);\n return {\n targetId: post.sourceId,\n publicPath: post.source.path ?? `/${post.slug}`,\n };\n }\n\n async createPage(page: NormalizedPage): Promise<CreatePageResult> {\n this.bundle.pages.push(page);\n return {\n targetId: page.sourceId,\n publicPath: page.source.path ?? `/${page.slug}`,\n };\n }\n\n async linkPortfolioMedia(link: PortfolioMediaLink): Promise<void> {\n this.portfolioMediaLinks.push(link);\n }\n\n async writeRedirect(redirect: MigrationRedirect): Promise<void> {\n this.redirects.push(redirect);\n }\n\n async flush(options: WriteFilesystemOptions): Promise<void> {\n await writeFilesystemExport({\n ...options,\n bundle: this.bundle,\n });\n }\n}\n\nexport function createFilesystemMigrationSink(): FilesystemMigrationSink {\n return new FilesystemMigrationSink();\n}\n\n/** Verify sink-produced M2M links match bundle-derived index. */\nexport function portfolioMediaMatchesBundle(\n sink: FilesystemMigrationSink,\n): boolean {\n const expected = buildPortfolioMediaLinks(sink.bundle);\n if (expected.length !== sink.portfolioMediaLinks.length) return false;\n return expected.every((link, index) => {\n const actual = sink.portfolioMediaLinks[index];\n return (\n actual?.portfolioSourceId === link.portfolioSourceId &&\n actual?.assetSourceId === link.assetSourceId &&\n actual?.sort === link.sort\n );\n });\n}\n","import { randomUUID } from \"node:crypto\";\n\nimport type { EntityBundle } from \"../normalizer/bundle.js\";\nimport { bundleCounts } from \"../normalizer/bundle.js\";\nimport type { MigrationPlatform } from \"../normalizer/types.js\";\nimport type { AssetDiscoverySummary, ConflictReport } from \"./conflicts.js\";\nimport type { WxrImportSummary } from \"../normalizer/types.js\";\n\nexport type MigrationRunMode = \"dry-run\" | \"export\" | \"sink\" | \"worker\";\n\nexport interface MigrationReport {\n runId: string;\n platform: MigrationPlatform;\n mode: MigrationRunMode;\n startedAt: string;\n finishedAt: string;\n summary: {\n posts: number;\n pages: number;\n assets: number;\n portfolios: number;\n categories: number;\n tags: number;\n storageBytesEstimated?: number;\n assetDiscovery?: AssetDiscoverySummary;\n importableItemCount?: number;\n unsupportedOnly?: boolean;\n skippedPostTypes?: Record<string, number>;\n };\n warnings: string[];\n errors: string[];\n conflicts: ConflictReport;\n redirectMap: { fromPath: string; toPath: string; statusCode: number }[];\n}\n\nexport function buildMigrationReport(input: {\n platform: MigrationPlatform;\n mode: MigrationRunMode;\n bundle: EntityBundle;\n conflicts: ConflictReport;\n redirectMap: { fromPath: string; toPath: string; statusCode: number }[];\n startedAt: Date;\n finishedAt?: Date;\n storageBytesEstimated?: number;\n warnings?: string[];\n errors?: string[];\n runId?: string;\n}): MigrationReport {\n const counts = bundleCounts(input.bundle);\n return {\n runId: input.runId ?? randomUUID(),\n platform: input.platform,\n mode: input.mode,\n startedAt: input.startedAt.toISOString(),\n finishedAt: (input.finishedAt ?? new Date()).toISOString(),\n summary: {\n ...counts,\n storageBytesEstimated: input.storageBytesEstimated,\n assetDiscovery: input.conflicts.assetDiscovery,\n importableItemCount: input.conflicts.importableItemCount,\n unsupportedOnly: input.conflicts.unsupportedOnly,\n skippedPostTypes: input.conflicts.skippedPostTypes,\n },\n warnings: input.warnings ?? [],\n errors: input.errors ?? [],\n conflicts: input.conflicts,\n redirectMap: input.redirectMap,\n };\n}\n","import type { NormalizedAsset } from \"../normalizer/types.js\";\n\nexport const FALLBACK_ASSET_BYTES = 4 * 1024 * 1024; // 4 MB\n\nexport interface AssetSizeResult {\n sourceId: string;\n url: string;\n bytes: number;\n source: \"head\" | \"fallback\";\n error?: string;\n}\n\nexport interface StorageEstimate {\n totalBytes: number;\n assets: AssetSizeResult[];\n}\n\nexport interface EstimateStorageOptions {\n assets: NormalizedAsset[];\n /** When true, skip network and use fallback for all assets. */\n offline?: boolean;\n fetchFn?: typeof fetch;\n}\n\nexport async function estimateStorage(\n options: EstimateStorageOptions,\n): Promise<StorageEstimate> {\n const fetchFn = options.fetchFn ?? fetch;\n const results: AssetSizeResult[] = [];\n\n for (const asset of options.assets) {\n if (options.offline) {\n results.push({\n sourceId: asset.sourceId,\n url: asset.sourceUrl,\n bytes: FALLBACK_ASSET_BYTES,\n source: \"fallback\",\n error: \"offline_mode\",\n });\n continue;\n }\n\n try {\n const response = await fetchFn(asset.sourceUrl, {\n method: \"HEAD\",\n signal: AbortSignal.timeout(8000),\n });\n\n if (response.ok) {\n const length = response.headers.get(\"content-length\");\n const bytes = length ? Number.parseInt(length, 10) : FALLBACK_ASSET_BYTES;\n results.push({\n sourceId: asset.sourceId,\n url: asset.sourceUrl,\n bytes: Number.isFinite(bytes) ? bytes : FALLBACK_ASSET_BYTES,\n source: \"head\",\n });\n } else {\n results.push({\n sourceId: asset.sourceId,\n url: asset.sourceUrl,\n bytes: FALLBACK_ASSET_BYTES,\n source: \"fallback\",\n error: `http_${response.status}`,\n });\n }\n } catch (error) {\n results.push({\n sourceId: asset.sourceId,\n url: asset.sourceUrl,\n bytes: FALLBACK_ASSET_BYTES,\n source: \"fallback\",\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n const totalBytes = results.reduce((sum, r) => sum + r.bytes, 0);\n return { totalBytes, assets: results };\n}\n\nexport function staleUrlsFromEstimate(estimate: StorageEstimate) {\n return estimate.assets\n .filter((a) => a.source === \"fallback\" && a.error && a.error !== \"offline_mode\")\n .map((a) => ({\n sourceId: a.sourceId,\n url: a.url,\n reason: a.error ?? \"unknown\",\n }));\n}\n","import { collectEntities, type EntityBundle } from \"../normalizer/bundle.js\";\nimport type { MigrationAdapter, MigrationPlatform, WxrImportSummary } from \"../normalizer/types.js\";\nimport {\n analyzeConflicts,\n buildRedirectMap,\n detectRedirectLoops,\n hasBlockingConflicts,\n hasWarnings,\n type ConflictReport,\n} from \"./conflicts.js\";\nimport { buildMigrationReport, type MigrationReport } from \"./migration-report.js\";\nimport { estimateStorage, staleUrlsFromEstimate } from \"./storage-estimate.js\";\n\nexport interface DryRunOptions {\n adapter: MigrationAdapter;\n input: unknown;\n platform: MigrationPlatform;\n offlineStorageEstimate?: boolean;\n fetchFn?: typeof fetch;\n}\n\nexport interface DryRunResult {\n bundle: EntityBundle;\n conflicts: ConflictReport;\n report: MigrationReport;\n exitCode: 0 | 1 | 2;\n}\n\nexport async function resolveAdapterImportSummary(\n adapter: MigrationAdapter,\n input: unknown,\n): Promise<WxrImportSummary | undefined> {\n if (!adapter.getImportSummary) return undefined;\n return adapter.getImportSummary(input);\n}\n\nexport async function runDryRun(options: DryRunOptions): Promise<DryRunResult> {\n const startedAt = new Date();\n const wxrImportSummary = await resolveAdapterImportSummary(options.adapter, options.input);\n const bundle = await collectEntities(\n options.adapter.enumerateEntities({ input: options.input }),\n );\n\n const estimate = await estimateStorage({\n assets: bundle.media,\n offline: options.offlineStorageEstimate,\n fetchFn: options.fetchFn,\n });\n\n const redirectMap = buildRedirectMap(bundle);\n const redirectLoops = detectRedirectLoops(redirectMap);\n const staleAssetUrls = staleUrlsFromEstimate(estimate);\n\n const conflicts = analyzeConflicts(bundle, {\n staleAssetUrls,\n redirectLoops,\n wxrImportSummary,\n });\n\n const warnings: string[] = [];\n if (staleAssetUrls.length > 0) {\n warnings.push(`${staleAssetUrls.length} asset URL(s) unreachable; used 4 MB fallback each`);\n }\n if (wxrImportSummary?.unsupportedOnly) {\n warnings.push(\n \"Export contains no importable content; see conflicts.skippedPostTypes for omitted post_type counts\",\n );\n }\n const { assetDiscovery } = conflicts;\n if (assetDiscovery.attachmentRefsUnresolved > 0) {\n warnings.push(\n `${assetDiscovery.attachmentRefsUnresolved} attachment ref(s) lack URLs in this export ` +\n `(${assetDiscovery.attachmentRefsResolved}/${assetDiscovery.attachmentRefs} resolved; ` +\n \"include attachment rows, a media export, or REST resolution)\",\n );\n }\n if (conflicts.duplicatePostSlugs.length > 0) {\n warnings.push(\n `${conflicts.duplicatePostSlugs.length} duplicate post slug group(s); host may auto-suffix`,\n );\n }\n\n const report = buildMigrationReport({\n platform: options.platform,\n mode: \"dry-run\",\n bundle,\n conflicts,\n redirectMap,\n startedAt,\n storageBytesEstimated: estimate.totalBytes,\n warnings,\n });\n\n let exitCode: 0 | 1 | 2 = 0;\n if (hasBlockingConflicts(conflicts)) exitCode = 1;\n else if (hasWarnings(conflicts) || warnings.length > 0) exitCode = 2;\n\n return { bundle, conflicts, report, exitCode };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAwFO,IAAM,yBAAyB;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;AC/FA,SAAS,gBAAgB;;;ACAzB,YAAYA,cAAa;;;ACAzB,SAAS,gBAAgB;AACzB,SAAS,gBAAgB;;;ACDzB,YAAY,aAAa;AACzB,SAAS,SAAS;AAcX,IAAM,0BAA0B;AAOhC,IAAM,iCAAiC,EAAE,OAAO;AAAA,EACrD,QAAQ,EAAE,KAAK,CAAC,QAAQ,aAAa,CAAC,EAAE,QAAQ,aAAa;AAAA,EAC7D,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC;AAAA,EACrD,kBAAkB,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,QAAQ,GAAG;AAAA,EACrD,iBAAiB,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,QAAQ,GAAI;AAAA,EACrD,mBAAmB,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,QAAQ,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA,EAKtD,cAAc,EAAE,QAAQ,EAAE,QAAQ,IAAI;AAAA,EACtC,WAAW,EAAE,OAAqB,EAAE,SAAS;AAC/C,CAAC;AAqBD,SAAS,SAAS,OAAqC;AACrD,SAAO,CAAC,CAAC,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AACrE;AAEA,SAAS,SAAS,OAAwC;AACxD,SAAO,SAAS,KAAK,IAAI,QAAQ;AACnC;AAEA,SAAS,cAAc,OAA0B;AAC/C,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO,CAAC;AACnC,SAAO,MAAM,OAAO,CAAC,UAA2B,OAAO,UAAU,QAAQ;AAC3E;AAEA,SAAS,MAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD;AAGO,SAAS,mBACd,SACA,SAAgC,yBACxB;AACR,QAAM,MAAM,IAAI,IAAI,OAAO;AAC3B,MAAI,aAAa,IAAI,UAAU,MAAM;AACrC,SAAO,IAAI,SAAS;AACtB;AAEA,SAAS,iBAAiB,OAA2C;AACnE,MAAI,UAAU,KAAK,UAAU,IAAK,QAAO;AACzC,MAAI,UAAU,KAAK,UAAU,IAAK,QAAO;AACzC,SAAO;AACT;AAEA,SAAS,aAAa,OAAoC;AACxD,MAAI,OAAO,UAAU,YAAY,CAAC,OAAO,SAAS,KAAK,EAAG,QAAO;AACjE,SAAO,IAAI,KAAK,KAAK,EAAE,YAAY;AACrC;AAEA,SAAS,QAAQ,SAAkB,OAAoD;AACrF,QAAM,SAAS,SAAS,OAAO;AAC/B,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,QAAQ,OAAO,KAAK;AAC1B,SAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ;AACjE;AAGO,SAAS,4BAA4B,WAA2B;AACrE,QAAM,QAAQ,UAAU,MAAM,6BAA6B;AAC3D,MAAI,CAAC,QAAQ,CAAC,EAAG,QAAO;AACxB,QAAM,MAAM,MAAM,CAAC,EAAE,YAAY;AACjC,MAAI,QAAQ,iBAAkB,QAAO;AACrC,SAAO,IAAI,QAAQ,YAAY,EAAE;AACnC;AAGO,SAAS,0BAA0B,MAAmC;AAC3E,MAAI,CAAC,MAAM,KAAK,EAAG,QAAO;AAC1B,QAAM,IAAY,aAAK,MAAM,EAAE,KAAK,MAAM,CAAC;AAC3C,MAAI,EAAE,YAAY,EAAE,SAAS,EAAG,QAAO;AACvC,MAAI,EAAE,mBAAmB,EAAE,SAAS,EAAG,QAAO;AAE9C,SAAO,KAAK,QAAQ,QAAQ,GAAG,EAAE,KAAK,EAAE,SAAS;AACnD;AAGO,SAAS,mBAAmB,MAAgE;AACjG,OAAK,KAAK,QAAQ,UAAU,KAAK,EAAG,QAAO;AAC3C,SAAO,0BAA0B,KAAK,WAAW;AACnD;AAMO,SAAS,oBAAoB,MAAsB;AACxD,MAAI,CAAC,KAAK,KAAK,EAAG,QAAO;AACzB,QAAM,IAAY,aAAK,MAAM,EAAE,KAAK,MAAM,CAAC;AAC3C,QAAM,WAAW,EAAE,WAAW,EAAE,MAAM;AACtC,MAAI,SAAS,OAAQ,QAAO,SAAS,KAAK,KAAK;AAC/C,QAAM,UAAU,EAAE,kBAAkB,EAAE,MAAM;AAC5C,MAAI,QAAQ,OAAQ,QAAO,QAAQ,KAAK,KAAK;AAC7C,QAAM,OAAO,EAAE,oCAAoC,EAAE,MAAM;AAC3D,MAAI,KAAK,OAAQ,QAAO,KAAK,KAAK,KAAK;AACvC,SAAO;AACT;AAGO,SAAS,2BACd,MACiD;AACjD,QAAM,OAAO,oBAAoB,IAAI;AACrC,MAAI,CAAC,KAAK,KAAK,EAAG,QAAO,EAAE,aAAa,GAAG;AAE3C,QAAM,eAAe,0BAA0B,IAAI;AACnD,MAAI,aAAa,SAAS,GAAG;AAC3B,WAAO,EAAE,QAAQ,aAAa;AAAA,EAChC;AACA,SAAO,EAAE,aAAa,KAAK;AAC7B;AAGO,SAAS,0BAA0B,MAAkC;AAC1E,MAAI,CAAC,KAAK,KAAK,EAAG,QAAO,CAAC;AAC1B,QAAM,IAAY,aAAK,MAAM,EAAE,KAAK,MAAM,CAAC;AAC3C,QAAM,SAA6B,CAAC;AAEpC,IAAE,YAAY,EAAE,KAAK,CAAC,GAAG,YAAY;AACnC,UAAM,KAAK,EAAE,OAAO;AACpB,UAAM,YAAY,GAAG,KAAK,OAAO,KAAK;AACtC,UAAM,OAAO,4BAA4B,SAAS;AAClD,UAAM,KAAK,GAAG,KAAK,IAAI,GAAG,QAAQ,WAAW,EAAE;AAC/C,UAAM,UAAU,GAAG,KAAK,oBAAoB,EAAE,MAAM;AACpD,UAAM,aAAa,QAAQ,SAAS,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAM;AAEnE,QAAI,SAAS,SAAS;AACpB,YAAM,MAAM,QAAQ,KAAK,KAAK,EAAE,MAAM;AACtC,YAAM,WAAW,IAAI,KAAK,UAAU,KAAK,IAAI,KAAK,KAAK,KAAK;AAC5D,aAAO,KAAK;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS,IAAI,KAAK,KAAK,KAAK;AAAA,QAC5B,SAAS,QAAQ,KAAK,YAAY,EAAE,KAAK,KAAK;AAAA,QAC9C,MAAM,aAAa;AAAA,MACrB,CAAC;AACD;AAAA,IACF;AAEA,QAAI,SAAS,WAAW;AACtB,YAAM,QAAkC,CAAC;AACzC,cAAQ,KAAK,KAAK,EAAE,KAAK,CAAC,KAAK,UAAU;AACvC,cAAM,MAAM,EAAE,KAAK;AACnB,cAAM,WAAW,IAAI,KAAK,UAAU,KAAK,IAAI,KAAK,KAAK;AACvD,YAAI,CAAC,SAAU;AACf,cAAM,KAAK;AAAA,UACT,IAAI,IAAI,KAAK,eAAe,KAAK,WAAW,GAAG;AAAA,UAC/C;AAAA,UACA,SAAS,IAAI,KAAK,KAAK,KAAK;AAAA,QAC9B,CAAC;AAAA,MACH,CAAC;AACD,aAAO,KAAK,EAAE,IAAI,MAAM,OAAO,MAAM,aAAa,OAAU,CAAC;AAC7D;AAAA,IACF;AAEA,QAAI,SAAS,UAAU;AACrB,YAAM,SAAS,QAAQ,KAAK,GAAG,EAAE,MAAM;AACvC,aAAO,KAAK;AAAA,QACV;AAAA,QACA;AAAA,QACA,KAAK,OAAO,KAAK,MAAM,KAAK;AAAA,QAC5B,OAAO,OAAO,KAAK,KAAK;AAAA,QACxB,MAAM,aAAa;AAAA,MACrB,CAAC;AACD;AAAA,IACF;AAEA,QAAI,SAAS,WAAW,SAAS,SAAS;AACxC,YAAM,SAAS,QAAQ,KAAK,QAAQ,EAAE,MAAM;AAC5C,aAAO,KAAK;AAAA,QACV;AAAA,QACA,MAAM,SAAS,UAAU,UAAU;AAAA,QACnC,WAAW,OAAO,SAAS,EAAE,KAAK,MAAM,IAAI,aAAa;AAAA,QACzD,MAAM,aAAa;AAAA,MACrB,CAAC;AACD;AAAA,IACF;AAEA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA,MAAM,aAAa;AAAA,MACnB,OAAO,SAAS,cAAc,SAAS,UAAU,QAAQ,KAAK,IAAI;AAAA,IACpE,CAAC;AAAA,EACH,CAAC;AAED,SAAO;AACT;AAEA,SAAS,cAAc,OAAgD;AACrE,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO;AAClC,QAAM,SAA6B,CAAC;AACpC,aAAW,SAAS,OAAO;AACzB,UAAM,SAAS,SAAS,KAAK;AAC7B,QAAI,CAAC,OAAQ;AACb,UAAM,OAAO,OAAO,OAAO,QAAQ,OAAO,aAAa,MAAM;AAC7D,WAAO,KAAK;AAAA,MACV,IAAI,OAAO,KAAK,OAAO,OAAO,EAAE,IAAI;AAAA,MACpC;AAAA,MACA,MAAM,OAAO,OAAO,SAAS,WAAW,OAAO,OAAO;AAAA,MACtD,OAAO,OAAO,OAAO,UAAU,WAAW,OAAO,QAAQ;AAAA,MACzD,UACE,OAAO,OAAO,aAAa,WACvB,OAAO,WACP,OAAO,OAAO,aAAa,WACzB,OAAO,WACP;AAAA,MACR,SAAS,OAAO,OAAO,YAAY,WAAW,OAAO,UAAU;AAAA,MAC/D,SAAS,OAAO,OAAO,YAAY,WAAW,OAAO,UAAU;AAAA,MAC/D,KAAK,OAAO,OAAO,QAAQ,WAAW,OAAO,MAAM;AAAA,MACnD,OAAO,OAAO,OAAO,UAAU,WAAW,OAAO,QAAQ;AAAA,MACzD,WAAW,OAAO,OAAO,cAAc,WAAW,OAAO,YAAY;AAAA,MACrE,OAAO,MAAM,QAAQ,OAAO,KAAK,IAC7B,OAAO,MACJ,IAAI,CAAC,SAAS,SAAS,IAAI,CAAC,EAC5B,OAAO,CAAC,SAA6B,CAAC,CAAC,IAAI,EAC3C,IAAI,CAAC,UAAU;AAAA,QACd,IAAI,KAAK,KAAK,OAAO,KAAK,EAAE,IAAI;AAAA,QAChC,UAAU,OAAO,KAAK,YAAY,KAAK,YAAY,EAAE;AAAA,QACrD,SAAS,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU;AAAA,QAC3D,SAAS,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU;AAAA,MAC7D,EAAE,EACD,OAAO,CAAC,SAAS,KAAK,SAAS,SAAS,CAAC,IAC5C;AAAA,IACN,CAAC;AAAA,EACH;AACA,SAAO,OAAO,SAAS,IAAI,SAAS;AACtC;AAEA,SAAS,4BAA4B,MAAkD;AACrF,QAAM,SAAS,cAAc,KAAK,MAAM;AACxC,MAAI,QAAQ,OAAQ,QAAO;AAE3B,QAAM,WAAW,KAAK;AACtB,MAAI,CAAC,MAAM,QAAQ,QAAQ,EAAG,QAAO;AAErC,QAAM,YAAgC,CAAC;AACvC,aAAW,WAAW,UAAU;AAC9B,UAAM,gBAAgB,SAAS,OAAO;AACtC,QAAI,CAAC,cAAe;AACpB,UAAM,OAAO,cAAc;AAC3B,QAAI,CAAC,MAAM,QAAQ,IAAI,EAAG;AAC1B,eAAW,OAAO,MAAM;AACtB,YAAM,YAAY,SAAS,GAAG;AAC9B,UAAI,CAAC,UAAW;AAChB,YAAM,UAAU,UAAU;AAC1B,UAAI,CAAC,MAAM,QAAQ,OAAO,EAAG;AAC7B,iBAAW,UAAU,SAAS;AAC5B,cAAM,eAAe,SAAS,MAAM;AACpC,YAAI,CAAC,aAAc;AACnB,cAAM,SAAS,cAAc,aAAa,MAAM;AAChD,YAAI,OAAQ,WAAU,KAAK,GAAG,MAAM;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AACA,SAAO,UAAU,SAAS,IAAI,YAAY;AAC5C;AAEA,SAAS,mBAAmB,MAAmE;AAC7F,QAAM,aAAa,4BAA4B,IAAI;AACnD,MAAI,YAAY,QAAQ;AACtB,WAAO,EAAE,QAAQ,WAAW;AAAA,EAC9B;AAEA,QAAM,OAAO,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO;AACzD,MAAI,CAAC,KAAM,QAAO,EAAE,aAAa,GAAG;AAEpC,QAAM,eAAe,0BAA0B,IAAI;AACnD,MAAI,aAAa,SAAS,GAAG;AAC3B,WAAO,EAAE,QAAQ,aAAa;AAAA,EAChC;AACA,SAAO,EAAE,aAAa,KAAK;AAC7B;AAEA,SAAS,iBAAiB,YAA6C;AACrE,MAAI,CAAC,WAAY,QAAO;AACxB,QAAM,WAAW,OAAO,WAAW,YAAY,EAAE,EAAE,YAAY;AAC/D,MAAI,aAAa,mBAAmB,aAAa,WAAY,QAAO;AACpE,QAAM,WAAW,OAAO,WAAW,YAAY,WAAW,aAAa,EAAE,EAAE,YAAY;AACvF,SAAO,SAAS,SAAS,MAAM;AACjC;AAGO,SAAS,oBAAoB,YAA6C;AAC/E,MAAI,CAAC,WAAY,QAAO;AACxB,MAAI,iBAAiB,UAAU,EAAG,QAAO;AACzC,QAAM,WAAW,OAAO,WAAW,YAAY,EAAE,EAAE,YAAY;AAC/D,QAAM,YAAY,OAAO,WAAW,aAAa,EAAE,EAAE,YAAY;AACjE,SACE,SAAS,SAAS,SAAS,KAC3B,UAAU,SAAS,SAAS,KAC5B,aAAa,eACb,cAAc;AAElB;AAEA,SAAS,iBAAiB,MAAkB,YAA6C;AACvF,QAAM,kBAAkB,OAAO,KAAK,mBAAmB,EAAE,EAAE,YAAY;AACvE,MAAI,gBAAgB,SAAS,MAAM,EAAG,QAAO;AAC7C,QAAM,iBAAiB,OAAO,YAAY,YAAY,YAAY,aAAa,EAAE,EAAE,YAAY;AAC/F,SAAO,mBAAmB,UAAU,eAAe,SAAS,iBAAiB;AAC/E;AAEA,SAAS,gBAAgB,OAAuB;AAC9C,SAAO,MAAM,QAAQ,YAAY,GAAG,EAAE,QAAQ,QAAQ,GAAG,EAAE,KAAK;AAClE;AAGO,SAAS,mBAAmB,MAAsD;AACvF,QAAM,WACJ,OAAO,KAAK,aAAa,YAAY,KAAK,SAAS,KAAK,IACpD,KAAK,SAAS,KAAK,IACnB,OAAO,KAAK,aAAa,YAAY,KAAK,SAAS,KAAK,IACtD,KAAK,SAAS,KAAK,IACnB;AACR,MAAI,CAAC,SAAS,WAAW,MAAM,EAAG,QAAO;AAEzC,QAAM,aACJ,OAAO,KAAK,SAAS,WACjB,gBAAgB,KAAK,IAAI,IACzB,OAAO,KAAK,YAAY,WACtB,KAAK,QAAQ,KAAK,IAClB,OAAO,KAAK,YAAY,WACtB,KAAK,QAAQ,KAAK,IAClB;AAEV,SAAO;AAAA,IACL,IAAI,OAAO,KAAK,MAAM,KAAK,gBAAgB,KAAK,SAAS,EAAE;AAAA,IAC3D,UAAU;AAAA,IACV,SACE,OAAO,KAAK,YAAY,WACpB,KAAK,UACL,OAAO,KAAK,UAAU,WACpB,KAAK,QACL;AAAA,IACR,SAAS,cAAc;AAAA,EACzB;AACF;AAEA,SAAS,yBACP,YACA,OACA,SAC8B;AAC9B,QAAM,KAAK,OAAO,WAAW,MAAM,WAAW,SAAS,WAAW,WAAW,SAAS;AACtF,QAAM,QAAQ,OAAO,WAAW,SAAS,WAAW,mBAAmB,SAAS;AAChF,QAAM,OAAO,aAAa,OAAO,WAAW,SAAS,WAAW,SAAS,EAAE,CAAC;AAC5E,QAAM,eAAe,MAClB,IAAI,CAAC,SAAS,mBAAmB,IAAI,CAAC,EACtC,OAAO,CAAC,SAAyC,CAAC,CAAC,IAAI;AAE1D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,KAAK;AAAA,MACH,OAAO,WAAW,YAAY,WAAW,WAAW,UAAU;AAAA,MAC9D,SAAS;AAAA,IACX;AAAA,IACA,aACE,OAAO,WAAW,gBAAgB,WAC9B,gBAAgB,WAAW,WAAW,IACtC;AAAA,IACN,OAAO;AAAA,EACT;AACF;AAEA,SAAS,kBAAkB,MAAkB,SAAqD;AAChG,QAAM,UAAU,mBAAmB,IAAI;AACvC,SAAO;AAAA,IACL,IAAI,OAAO,KAAK,MAAM,KAAK,gBAAgB,KAAK,SAAS,EAAE;AAAA,IAC3D,OAAO,OAAO,KAAK,SAAS,UAAU;AAAA,IACtC,MAAM,aAAa,OAAO,KAAK,SAAS,KAAK,SAAS,KAAK,MAAM,MAAM,CAAC;AAAA,IACxE,KAAK;AAAA,MACH,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU;AAAA,MAClD,SAAS;AAAA,IACX;AAAA,IACA,SAAS,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU;AAAA,IAC3D,aAAa,aAAa,KAAK,aAAa,KAAK,OAAO;AAAA,IACxD,QAAQ,iBAAiB,KAAK,aAAa;AAAA,IAC3C,eAAe,cAAc,KAAK,UAAU,EAAE,IAAI,CAAC,SAAS,aAAa,IAAI,CAAC;AAAA,IAC9E,UAAU,cAAc,KAAK,IAAI,EAAE,IAAI,CAAC,SAAS,aAAa,IAAI,CAAC;AAAA,IACnE,kBAAkB,OAAO,KAAK,aAAa,WAAW,KAAK,WAAW;AAAA,IACtE,UAAU,QAAQ,KAAK,SAAS,OAAO;AAAA,IACvC,gBAAgB,QAAQ,KAAK,SAAS,aAAa;AAAA,IACnD,GAAG;AAAA,EACL;AACF;AAEA,SAAS,mBACP,KACA,UACoB;AACpB,QAAM,YAAY,KAAK,KAAK,KAAK,UAAU,KAAK;AAChD,MAAI,CAAC,UAAW,QAAO;AACvB,MAAI;AACF,QAAI,SAAU,QAAO,IAAI,IAAI,WAAW,QAAQ,EAAE,SAAS;AAC3D,WAAO,IAAI,IAAI,SAAS,EAAE,SAAS;AAAA,EACrC,QAAQ;AACN,WAAO,UAAU,WAAW,MAAM,IAAI,YAAY;AAAA,EACpD;AACF;AAEA,SAAS,kBACP,MACA,SACiB;AACjB,QAAM,UAAU,mBAAmB,IAAI;AACvC,SAAO;AAAA,IACL,IAAI,OAAO,KAAK,MAAM,KAAK,SAAS,EAAE;AAAA,IACtC,OAAO,OAAO,KAAK,SAAS,UAAU;AAAA,IACtC,MAAM,aAAa,OAAO,KAAK,SAAS,KAAK,SAAS,KAAK,MAAM,MAAM,CAAC;AAAA,IACxE,KAAK;AAAA,MACH,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU;AAAA,MAClD,SAAS;AAAA,IACX;AAAA,IACA,QAAQ,iBAAiB,KAAK,aAAa;AAAA,IAC3C,YAAY,SAAS;AAAA,IACrB,UAAU,QAAQ,KAAK,SAAS,OAAO;AAAA,IACvC,gBAAgB,QAAQ,KAAK,SAAS,aAAa;AAAA,IACnD,GAAG;AAAA,EACL;AACF;AAEA,SAAS,kBAAkB,YAA2D;AACpF,MAAI,CAAC,WAAY,QAAO,CAAC;AACzB,SAAO,cAAc,WAAW,UAAU,EAAE,IAAI,CAAC,UAAU;AAAA,IACzD,IAAI,OAAO,aAAa,IAAI,CAAC;AAAA,IAC7B;AAAA,IACA,MAAM,aAAa,IAAI;AAAA,EACzB,EAAE;AACJ;AAEA,SAAS,YAAY,OAAuC;AAC1D,QAAM,OAAO,oBAAI,IAA4B;AAC7C,aAAW,QAAQ,OAAO;AACxB,eAAW,OAAO,cAAc,KAAK,IAAI,GAAG;AAC1C,YAAM,OAAO,aAAa,GAAG;AAC7B,UAAI,CAAC,KAAK,IAAI,IAAI,GAAG;AACnB,aAAK,IAAI,MAAM,EAAE,IAAI,OAAO,IAAI,IAAI,MAAM,KAAK,KAAK,CAAC;AAAA,MACvD;AAAA,IACF;AAAA,EACF;AACA,SAAO,CAAC,GAAG,KAAK,OAAO,CAAC;AAC1B;AAEA,SAAS,aAAa,MAA6C;AACjE,QAAM,UAAU,SAAS,KAAK,OAAO;AACrC,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,MACJ,OAAO,QAAQ,iBAAiB,WAC5B,QAAQ,eACR,OAAO,QAAQ,YAAY,WACzB,QAAQ,UACR;AACR,QAAM,QAAQ,OAAO,QAAQ,cAAc,WAAW,QAAQ,YAAY;AAC1E,MAAI,CAAC,OAAO,CAAC,MAAO,QAAO;AAC3B,SAAO,EAAE,KAAK,MAAM;AACtB;AAGO,SAAS,kBACd,MACA,SAC4B;AAC5B,MAAI,CAAC,SAAS,IAAI,GAAG;AACnB,UAAM,IAAI,MAAM,0CAA0C;AAAA,EAC5D;AAEA,QAAM,aAAa,SAAS,KAAK,UAAU;AAC3C,QAAM,UAAsC;AAAA,IAC1C,MAAM,aAAa,IAAI;AAAA,IACvB,OAAO,CAAC;AAAA,IACR,OAAO,CAAC;AAAA,IACR,WAAW,CAAC;AAAA,IACZ,YAAY,kBAAkB,UAAU;AAAA,IACxC,MAAM,CAAC;AAAA,EACT;AAEA,MAAI,MAAM,QAAQ,KAAK,KAAK,GAAG;AAC7B,UAAM,cAAc,KAAK,MACtB,IAAI,CAAC,UAAU,SAAS,KAAK,CAAC,EAC9B,OAAO,CAAC,UAA+B,CAAC,CAAC,KAAK;AAEjD,QAAI,cAAc,oBAAoB,UAAU,GAAG;AACjD,cAAQ,YAAY,CAAC,yBAAyB,YAAY,aAAa,OAAO,CAAC;AAC/E,aAAO;AAAA,IACT;AAEA,YAAQ,OAAO,YAAY,WAAW;AAEtC,eAAWC,SAAQ,aAAa;AAC9B,UAAI,iBAAiBA,OAAM,UAAU,GAAG;AACtC,gBAAQ,MAAO;AAAA,UACb,kBAAkBA,OAAM,EAAE,aAAa,SAAS,YAAY,YAAY,SAAS,WAAW,CAAC;AAAA,QAC/F;AAAA,MACF,OAAO;AACL,gBAAQ,MAAO,KAAK,kBAAkBA,OAAM,EAAE,aAAa,SAAS,WAAW,CAAC,CAAC;AAAA,MACnF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,SAAS,KAAK,IAAI;AAC/B,MAAI,MAAM;AACR,QAAI,iBAAiB,MAAM,UAAU,GAAG;AACtC,cAAQ,MAAO;AAAA,QACb,kBAAkB,MAAM,EAAE,aAAa,SAAS,YAAY,YAAY,SAAS,WAAW,CAAC;AAAA,MAC/F;AAAA,IACF,OAAO;AACL,cAAQ,MAAO,KAAK,kBAAkB,MAAM,EAAE,aAAa,SAAS,WAAW,CAAC,CAAC;AACjF,cAAQ,OAAO,YAAY,CAAC,IAAI,CAAC;AAAA,IACnC;AACA,WAAO;AAAA,EACT;AAEA,MAAI,cAAc,oBAAoB,UAAU,GAAG;AACjD,YAAQ,YAAY,CAAC,yBAAyB,YAAY,CAAC,GAAG,OAAO,CAAC;AACtE,WAAO;AAAA,EACT;AAEA,MAAI,cAAc,iBAAiB,UAAU,MAAM,OAAO;AACxD,UAAM,cACJ,OAAO,KAAK,gBAAgB,WAAW,KAAK,cAAc;AAC5D,UAAM,OACJ,eAAe,CAAC,0BAA0B,WAAW,IACjD,cACA,OAAO,WAAW,gBAAgB,WAChC,WAAW,cACX;AACR,YAAQ,MAAO;AAAA,MACb;AAAA,QACE;AAAA,UACE,IAAI,WAAW,MAAM,WAAW,SAAS,WAAW;AAAA,UACpD,OAAO,WAAW,SAAS,WAAW;AAAA,UACtC,OAAO,WAAW;AAAA,UAClB,SAAS;AAAA,YACP,OAAO,WAAW,YAAY,WAAW,WAAW,UAAU;AAAA,YAC9D,SAAS;AAAA,UACX;AAAA,UACA;AAAA,UACA,eAAe,WAAW,QAAQ,IAAI;AAAA,UACtC,SAAS,WAAW;AAAA,QACtB;AAAA,QACA,EAAE,aAAa,SAAS,YAAY,YAAY,SAAS,WAAW;AAAA,MACtE;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,WAAqC,OAAiB;AAC7D,QAAM,OAAO,oBAAI,IAAe;AAChC,aAAW,QAAQ,OAAO;AACxB,SAAK,IAAI,KAAK,IAAI,IAAI;AAAA,EACxB;AACA,SAAO,CAAC,GAAG,KAAK,OAAO,CAAC;AAC1B;AAEA,SAAS,aAAyC,OAAiB;AACjE,QAAM,OAAO,oBAAI,IAAe;AAChC,aAAW,QAAQ,OAAO;AACxB,SAAK,IAAI,KAAK,MAAM,IAAI;AAAA,EAC1B;AACA,SAAO,CAAC,GAAG,KAAK,OAAO,CAAC;AAC1B;AAGO,SAAS,+BACd,UACmB;AACnB,QAAM,SAA4B;AAAA,IAChC,eAAe;AAAA,IACf,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,IACnC,OAAO,CAAC;AAAA,IACR,OAAO,CAAC;AAAA,IACR,WAAW,CAAC;AAAA,IACZ,YAAY,CAAC;AAAA,IACb,MAAM,CAAC;AAAA,EACT;AAEA,aAAW,WAAW,UAAU;AAC9B,QAAI,QAAQ,KAAM,QAAO,OAAO,EAAE,GAAG,OAAO,MAAM,GAAG,QAAQ,KAAK;AAClE,WAAO,MAAM,KAAK,GAAI,QAAQ,SAAS,CAAC,CAAE;AAC1C,WAAO,MAAO,KAAK,GAAI,QAAQ,SAAS,CAAC,CAAE;AAC3C,WAAO,UAAW,KAAK,GAAI,QAAQ,aAAa,CAAC,CAAE;AACnD,WAAO,WAAY,KAAK,GAAI,QAAQ,cAAc,CAAC,CAAE;AACrD,WAAO,KAAM,KAAK,GAAI,QAAQ,QAAQ,CAAC,CAAE;AAAA,EAC3C;AAEA,SAAO,QAAQ,WAAW,OAAO,KAAK;AACtC,SAAO,QAAQ,WAAW,OAAO,SAAS,CAAC,CAAC;AAC5C,SAAO,YAAY,WAAW,OAAO,aAAa,CAAC,CAAC;AACpD,SAAO,aAAa,aAAa,OAAO,cAAc,CAAC,CAAC;AACxD,SAAO,OAAO,aAAa,OAAO,QAAQ,CAAC,CAAC;AAC5C,SAAO;AACT;AAEA,SAAS,mBAAmB,MAA2C;AACrE,SAAO,SAAS,IAAI,GAAG;AACzB;AAEA,SAAS,gBAAgB,QAAyD;AAChF,MAAI,OAAO,QAAQ,OAAO,SAAS,OAAQ,QAAO,OAAO;AACzD,MAAI;AACF,UAAM,WAAW,IAAI,IAAI,OAAO,GAAG,EAAE;AACrC,QAAI,aAAa,OAAO,SAAS,SAAS,GAAG,EAAG,QAAO;AAAA,EACzD,QAAQ;AACN,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAGO,IAAM,8BAAN,MAAkC;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAED,gBAAgB;AAAA,EAExB,YAAY,UAAoC,CAAC,GAAG;AAClD,UAAM,SAAS,+BAA+B,MAAM,OAAO;AAC3D,SAAK,SAAS,OAAO;AACrB,SAAK,aAAa,OAAO;AACzB,SAAK,mBAAmB,OAAO;AAC/B,SAAK,kBAAkB,OAAO;AAC9B,SAAK,oBAAoB,OAAO;AAChC,SAAK,eAAe,OAAO;AAC3B,SAAK,YAAY,OAAO,aAAa;AAAA,EACvC;AAAA,EAEA,mBAAmB,SAAyB;AAC1C,WAAO,mBAAmB,SAAS,KAAK,MAAM;AAAA,EAChD;AAAA,EAEA,MAAM,UAAU,KAA+B;AAC7C,UAAM,WAAW,MAAM,KAAK,iBAAiB,KAAK,mBAAmB,GAAG,GAAG;AAAA,MACzE,QAAQ;AAAA,IACV,CAAC;AACD,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA,EAEA,MAAM,UAAU,KAA8B;AAC5C,UAAM,WAAW,MAAM,KAAK,iBAAiB,KAAK;AAAA,MAChD,QAAQ;AAAA,IACV,CAAC;AACD,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA,EAEA,MAAM,cAAc,SAAiE;AACnF,QAAI,QAAQ,WAAW,GAAG;AACxB,YAAM,IAAI,MAAM,wDAAwD;AAAA,IAC1E;AAEA,UAAM,WAAyC,CAAC;AAChD,eAAW,UAAU,SAAS;AAC5B,YAAM,OAAO,gBAAgB,MAAM;AACnC,UAAI,SAAS,cAAc;AACzB,iBAAS,KAAK,GAAI,MAAM,KAAK,uBAAuB,MAAM,CAAE;AAAA,MAC9D,OAAO;AACL,cAAM,OAAO,MAAM,KAAK,UAAU,OAAO,GAAG;AAC5C,iBAAS;AAAA,UACP,kBAAkB,MAAM,EAAE,YAAY,OAAO,KAAK,YAAY,OAAO,WAAW,CAAC;AAAA,QACnF;AAAA,MACF;AAAA,IACF;AAEA,UAAM,SAAS,+BAA+B,QAAQ;AACtD,QAAI,KAAK,cAAc;AACrB,YAAM,KAAK,yBAAyB,MAAM;AAAA,IAC5C;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,yBAAyB,KAAuC;AAC5E,eAAW,QAAQ,IAAI,OAAO;AAC5B,UAAI,CAAC,mBAAmB,IAAI,EAAG;AAC/B,YAAM,UAAU,KAAK,KAAK,KAAK;AAC/B,UAAI,CAAC,QAAS;AACd,UAAI;AACF,cAAM,OAAO,MAAM,KAAK,UAAU,OAAO;AACzC,cAAM,UAAU,2BAA2B,IAAI;AAC/C,YAAI,QAAQ,QAAQ,QAAQ;AAC1B,eAAK,SAAS,QAAQ;AACtB,iBAAO,KAAK;AAAA,QACd,WAAW,QAAQ,aAAa,KAAK,GAAG;AACtC,eAAK,cAAc,QAAQ;AAC3B,iBAAO,KAAK;AAAA,QACd;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,uBACZ,QACuC;AACvC,UAAM,WAAyC,CAAC;AAChD,QAAI,UAA8B,OAAO;AAEzC,WAAO,SAAS;AACd,YAAM,OAAO,MAAM,KAAK,UAAU,OAAO;AACzC,eAAS;AAAA,QACP,kBAAkB,MAAM,EAAE,YAAY,SAAS,YAAY,OAAO,WAAW,CAAC;AAAA,MAChF;AAEA,YAAM,aAAa,mBAAmB,IAAI;AAC1C,UAAI,CAAC,YAAY,YAAY,CAAC,WAAW,YAAa;AACtD,YAAM,OAAO,IAAI,IAAI,OAAO,GAAG;AAC/B,gBAAU,IAAI,IAAI,WAAW,aAAa,GAAG,KAAK,MAAM,GAAG,EAAE,SAAS;AAAA,IACxE;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,iBACZ,KACA,SACmB;AACnB,QAAI,UAAU;AACd,UAAM,SAAS,SAAS,UAAU;AAClC,WAAO,MAAM;AACX,YAAM,KAAK,SAAS;AACpB,YAAM,WAAW,MAAM,KAAK,UAAU,KAAK;AAAA,QACzC,QAAQ;AAAA,QACR,SAAS,EAAE,QAAQ,OAAO;AAAA,MAC5B,CAAC;AAED,UAAI,SAAS,IAAI;AACf,eAAO;AAAA,MACT;AAEA,YAAM,YAAY,SAAS,WAAW,OAAO,SAAS,UAAU;AAChE,UAAI,CAAC,aAAa,WAAW,KAAK,YAAY;AAC5C,cAAM,SAAS,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,EAAE;AACnD,cAAM,IAAI;AAAA,UACR,oBAAoB,SAAS,MAAM,GAAG,SAAS,KAAK,OAAO,MAAM,GAAG,GAAG,CAAC,KAAK,EAAE;AAAA,QACjF;AAAA,MACF;AAEA,YAAM,aAAa,OAAO,SAAS,SAAS,QAAQ,IAAI,aAAa,KAAK,IAAI,EAAE;AAChF,YAAM,QAAQ,OAAO,SAAS,UAAU,IACpC,aAAa,MACb,KAAK,IAAI,KAAK,iBAAiB,KAAK,mBAAmB,KAAK,OAAO;AACvE,YAAM,MAAM,KAAK;AACjB,iBAAW;AAAA,IACb;AAAA,EACF;AAAA,EAEA,MAAc,WAA0B;AACtC,QAAI,KAAK,qBAAqB,EAAG;AACjC,UAAM,UAAU,KAAK,IAAI,IAAI,KAAK;AAClC,QAAI,UAAU,KAAK,mBAAmB;AACpC,YAAM,MAAM,KAAK,oBAAoB,OAAO;AAAA,IAC9C;AACA,SAAK,gBAAgB,KAAK,IAAI;AAAA,EAChC;AACF;;;AD1wBA,IAAM,WAAW;AACjB,IAAM,mBAAmB;AACzB,IAAM,gBAAgB;AAGtB,IAAM,wBAAwB,oBAAI,IAAI;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGD,IAAM,0BAA0B,oBAAI,IAAI;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAiBD,SAAS,WAAW,IAAY,KAAc,YAAqC;AACjF,SAAO;AAAA,IACL,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,MAAM,WAAW,GAAG;AAAA,IACpB;AAAA,EACF;AACF;AAEA,SAAS,iBAAiB,QAA2C;AACnE,WAAS,UAAU,aAAa,YAAY,GAAG;AAAA,IAC7C,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,WAAW,MAAsB;AACxC,SAAO,KACJ,QAAQ,MAAM,OAAO,EACrB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,QAAQ;AAC3B;AAEA,SAAS,WAAW,MAAc,OAAe,SAA0B;AACzE,QAAM,SAAS,UAAU,kBAAkB,OAAO,MAAM;AACxD,SAAO,mCAAmC,IAAI,IAAI,MAAM,IAAI,KAAK;AACnE;AAEA,SAAS,uBAAuB,MAAc,SAA0B;AACtE,QAAM,SAAS,UAAU,IAAI,aAAa,KAAK,WAAW,OAAO,CAAC,MAAM;AACxE,SAAO,gDAAgD,gBAAgB,KAAK,WAAW,IAAI,CAAC,IAAI,MAAM;AACxG;AAEA,SAAS,mBAAmB,MAAsC;AAChE,QAAM,MAAM,KAAK,UAAU,SAAS,WAAW,KAAK,OAAO,CAAC,MAAM;AAClE,QAAM,UAAU,KAAK,UAAU,eAAe,KAAK,OAAO,kBAAkB;AAC5E,SAAO,qBAAqB,WAAW,KAAK,QAAQ,CAAC,IAAI,GAAG,MAAM,OAAO;AAC3E;AAEO,SAAS,wBAAwB,OAA8C;AACpF,QAAM,OAAO,MAAM,KAAK,YAAY;AACpC,QAAM,UAAU,MAAM;AACtB,QAAM,YAAsB,CAAC;AAE7B,MAAI,wBAAwB,IAAI,IAAI,GAAG;AACrC,WAAO;AAAA,MACL,aAAa,uBAAuB,MAAM,OAAO;AAAA,MACjD;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,sBAAsB,IAAI,IAAI,GAAG;AACpC,WAAO;AAAA,MACL,aAAa,uBAAuB,QAAQ,WAAW,OAAO;AAAA,MAC9D;AAAA,IACF;AAAA,EACF;AAEA,UAAQ,MAAM;AAAA,IACZ,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,QACL,aAAa,WAAW,MAAM,MAAM,QAAQ,MAAM,SAAS,IAAI,OAAO;AAAA,QACtE;AAAA,MACF;AAAA,IAEF,KAAK;AACH,aAAO;AAAA,QACL,aAAa;AAAA,UACX;AAAA,UACA,MAAM,QAAQ,6BAA6B,WAAW,MAAM,SAAS,EAAE,CAAC;AAAA,UACxE;AAAA,QACF;AAAA,QACA;AAAA,MACF;AAAA,IAEF,KAAK,SAAS;AACZ,YAAM,MAAM,MAAM,YAAY;AAC9B,UAAI,IAAK,WAAU,KAAK,GAAG;AAC3B,YAAM,MAAM,MAAM,UAAU,SAAS,WAAW,MAAM,OAAO,CAAC,MAAM;AACpE,YAAM,UAAU,MAAM,UAAU,eAAe,MAAM,OAAO,kBAAkB;AAC9E,YAAM,QAAQ,MACV,qBAAqB,WAAW,GAAG,CAAC,IAAI,GAAG,MAAM,OAAO,cACxD;AACJ,aAAO,EAAE,aAAa,WAAW,MAAM,OAAO,OAAO,GAAG,UAAU;AAAA,IACpE;AAAA,IAEA,KAAK,WAAW;AACd,YAAM,WAAW,MAAM,SAAS,CAAC,GAC9B,IAAI,CAAC,SAAS;AACb,kBAAU,KAAK,KAAK,QAAQ;AAC5B,eAAO,mBAAmB,IAAI;AAAA,MAChC,CAAC,EACA,KAAK,EAAE;AACV,aAAO;AAAA,QACL,aAAa,WAAW,MAAM,4BAA4B,OAAO,UAAU,OAAO;AAAA,QAClF;AAAA,MACF;AAAA,IACF;AAAA,IAEA,KAAK,SAAS;AACZ,YAAM,QAAQ,MAAM,QAAQ,eAAe,WAAW,MAAM,SAAS,EAAE,CAAC;AACxE,aAAO,EAAE,aAAa,WAAW,MAAM,OAAO,OAAO,GAAG,UAAU;AAAA,IACpE;AAAA,IAEA,KAAK,UAAU;AACb,YAAM,OAAO,MAAM,OAAO;AAC1B,YAAM,QAAQ,WAAW,MAAM,SAAS,MAAM,SAAS,YAAY;AACnE,aAAO;AAAA,QACL,aAAa;AAAA,UACX;AAAA,UACA,wCAAwC,WAAW,IAAI,CAAC,KAAK,KAAK;AAAA,UAClE;AAAA,QACF;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,IAEA,KAAK,SAAS;AACZ,YAAM,QACJ,MAAM,aACN,MAAM,SACL,MAAM,MAAM,eAAe,WAAW,MAAM,GAAG,CAAC,oBAAoB;AACvE,aAAO,EAAE,aAAa,WAAW,MAAM,OAAO,OAAO,GAAG,UAAU;AAAA,IACpE;AAAA,IAEA,KAAK,QAAQ;AACX,YAAM,QACJ,MAAM,QACN,cAAc,WAAW,MAAM,SAAS,EAAE,CAAC;AAC7C,aAAO,EAAE,aAAa,WAAW,MAAM,OAAO,OAAO,GAAG,UAAU;AAAA,IACpE;AAAA,IAEA,KAAK;AACH,aAAO;AAAA,QACL,aAAa,WAAW,MAAM,qDAAqD,OAAO;AAAA,QAC1F;AAAA,MACF;AAAA,IAEF,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO,EAAE,aAAa,WAAW,QAAQ,UAAU,OAAO,GAAG,UAAU;AAAA,IAEzE;AACE,aAAO;AAAA,QACL,aAAa,uBAAuB,MAAM,OAAO;AAAA,QACjD;AAAA,MACF;AAAA,EACJ;AACF;AAEO,SAAS,yBAAyB,QAAiD;AACxF,QAAM,QAAkB,CAAC;AACzB,QAAM,YAAsB,CAAC;AAC7B,aAAW,SAAS,QAAQ;AAC1B,UAAM,YAAY,wBAAwB,KAAK;AAC/C,UAAM,KAAK,UAAU,WAAW;AAChC,cAAU,KAAK,GAAG,UAAU,SAAS;AAAA,EACvC;AACA,SAAO;AAAA,IACL,aAAa,MAAM,KAAK,IAAI;AAAA,IAC5B;AAAA,EACF;AACF;AAEA,SAAS,mBACP,QACqB;AACrB,MAAI,OAAO,QAAQ,QAAQ;AACzB,WAAO,yBAAyB,OAAO,MAAM;AAAA,EAC/C;AACA,QAAM,OAAO,OAAO,eAAe;AACnC,SAAO;AAAA,IACL,aAAa;AAAA,IACb,WAAW,CAAC,GAAG,yBAAyB,IAAI,CAAC;AAAA,EAC/C;AACF;AAEA,SAAS,UAAU,UAAsC;AACvD,QAAM,MAAM,SAAS,MAAM,GAAG,EAAE,IAAI,GAAG,YAAY;AACnD,QAAM,MAA8B;AAAA,IAClC,KAAK;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,IACL,KAAK;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,EACP;AACA,SAAO,MAAM,IAAI,GAAG,IAAI;AAC1B;AAEA,SAAS,gBAAgB,KAAa,UAA0B;AAC9D,MAAI;AACF,WAAO,SAAS,IAAI,IAAI,GAAG,EAAE,QAAQ,KAAK;AAAA,EAC5C,QAAQ;AACN,WAAO,SAAS,IAAI,MAAM,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK;AAAA,EAC9C;AACF;AAEA,SAAS,aACP,KACA,YACA,OACiB;AACjB,QAAM,WAAW,gBAAgB,KAAK,SAAS,KAAK,MAAM;AAC1D,QAAM,WAAW,SAAS,aAAa,QAAQ,CAAC,IAAI,KAAK;AACzD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ,WAAW,UAAU,KAAK,UAAU;AAAA,IAC5C;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA,UAAU,UAAU,QAAQ;AAAA,EAC9B;AACF;AAGO,SAAS,yBACd,gBACA,OACA,cACQ;AACR,QAAM,UAAU,MAAM,IAAI,KAAK;AAC/B,MAAI,QAAS,QAAO,WAAW,OAAO;AACtC,SAAO,WAAW,cAAc,IAAI,YAAY;AAClD;AAEA,SAAS,uBAAuB,QAAgD;AAC9E,MAAI,CAAC,QAAQ,OAAQ,QAAO;AAC5B,SAAO,OAAO;AAAA,IACZ,CAAC,UAAU,MAAM,KAAK,YAAY,MAAM,cAAc,MAAM,OAAO,UAAU,KAAK;AAAA,EACpF,EAAE;AACJ;AAEA,SAAS,wBAAwB,QAAqD;AACpF,QAAM,OAAO,oBAAI,IAAY;AAC7B,MAAI,CAAC,QAAQ,OAAQ,QAAO;AAC5B,aAAW,SAAS,QAAQ;AAC1B,QAAI,MAAM,KAAK,YAAY,MAAM,UAAW;AAC5C,eAAW,QAAQ,MAAM,SAAS,CAAC,GAAG;AACpC,UAAI,KAAK,SAAU,MAAK,IAAI,KAAK,QAAQ;AAAA,IAC3C;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,qBACP,mBACA,MACA,MACQ;AACR,QAAM,SAAS,KAAK,IAAI,KAAK;AAC7B,MAAI,OAAQ,QAAO;AACnB,SAAO,GAAG,iBAAiB,IAAI,IAAI;AACrC;AAMO,UAAU,wBACf,QACA,QACA,YAC6B;AAC7B,MAAI,CAAC,QAAQ,OAAQ;AAErB,QAAM,oBAAoB,OAAO;AAAA,IAC/B,CAAC,UAAU,MAAM,KAAK,YAAY,MAAM,cAAc,MAAM,OAAO,UAAU,KAAK;AAAA,EACpF;AACA,MAAI,kBAAkB,WAAW,EAAG;AAEpC,MAAI,eAAe;AACnB,aAAW,SAAS,QAAQ;AAC1B,QAAI,MAAM,KAAK,YAAY,MAAM,UAAW;AAC5C,UAAM,SAAS,MAAM,SAAS,CAAC,GAAG,OAAO,CAAC,SAAS,QAAQ,KAAK,UAAU,KAAK,CAAC,CAAC;AACjF,QAAI,MAAM,WAAW,EAAG;AAExB,UAAM,WAAW,yBAAyB,OAAO,UAAU,OAAO,YAAY;AAC9E,UAAM,WAAW,MAAM,IAAI,KAAK,IAC5B,aAAa,MAAM,EAAE,IACrB,aAAa,WAAW,eAAe,CAAC,EAAE;AAC9C,UAAM,QACJ,kBAAkB,WAAW,IACzB,OAAO,QACP,GAAG,OAAO,KAAK,mBAAc,eAAe,CAAC;AAEnD,UAAM;AAAA,MACJ,MAAM;AAAA,MACN,QAAQ,WAAW,UAAU,OAAO,KAAK,UAAU;AAAA,MACnD;AAAA,MACA;AAAA,MACA,MAAM,SAAS,WAAW,SAAS,IAAI,WAAW,WAAW,QAAQ;AAAA,IACvE;AAEA,WAAO,kBAAkB,UAAU,OAAO,UAAU;AAEpD,oBAAgB;AAAA,EAClB;AACF;AAGO,SAAS,mCAAmC,cAA8B;AAC/E,SAAO,sBAAsB,YAAY;AAC3C;AAEA,UAAU,kBACR,mBACA,OACA,YAC4B;AAC5B,WAAS,OAAO,GAAG,OAAO,MAAM,QAAQ,QAAQ;AAC9C,UAAM,OAAO,MAAM,IAAI;AACvB,UAAM,gBAAgB,qBAAqB,mBAAmB,MAAM,IAAI;AACxE,UAAM,WAAW,gBAAgB,KAAK,UAAU,GAAG,aAAa,MAAM;AACtE,UAAM;AAAA,MACJ,MAAM;AAAA,MACN,QAAQ,WAAW,eAAe,KAAK,UAAU,UAAU;AAAA,MAC3D,UAAU;AAAA,MACV,WAAW,KAAK;AAAA,MAChB;AAAA,MACA,UAAU,UAAU,QAAQ;AAAA,MAC5B,SAAS,KAAK;AAAA,MACd,SAAS,KAAK;AAAA,MACd;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAMO,UAAU,uBACf,WACA,YAC6B;AAC7B,MAAI,CAAC,WAAW,OAAQ;AAExB,aAAW,WAAW,WAAW;AAC/B,UAAM,QAAQ,QAAQ,MAAM,OAAO,CAAC,SAAS,QAAQ,KAAK,UAAU,KAAK,CAAC,CAAC;AAC3E,QAAI,MAAM,WAAW,EAAG;AAExB,UAAM,WAAW,mCAAmC,QAAQ,EAAE;AAC9D,UAAM,WAAW,aAAa,QAAQ,QAAQ,QAAQ,EAAE;AACxD,UAAM;AAAA,MACJ,MAAM;AAAA,MACN,QAAQ,WAAW,UAAU,QAAQ,KAAK,UAAU;AAAA,MACpD;AAAA,MACA,OAAO,QAAQ;AAAA,MACf,MAAM,SAAS,WAAW,SAAS,IAAI,WAAW,WAAW,QAAQ;AAAA,MACrE,aAAa,QAAQ;AAAA,IACvB;AAEA,WAAO,kBAAkB,UAAU,OAAO,UAAU;AAAA,EACtD;AACF;AAEO,SAAS,oBAAoB,OAA4C;AAC9E,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,SAAS;AACf,QAAM,UAAU,OAAO;AACvB,UAAQ,YAAY,KAAK,YAAY,QAAQ,MAAM,QAAQ,OAAO,KAAK;AACzE;AAEA,eAAsB,sBACpB,SAC4B;AAC5B,MAAI,QAAQ,KAAM,QAAO,QAAQ;AACjC,MAAI,QAAQ,QAAQ;AAClB,QAAI,CAAC,QAAQ,gBAAgB,QAAQ;AACnC,YAAM,IAAI,MAAM,0DAA0D;AAAA,IAC5E;AACA,WAAO,QAAQ,OAAO,cAAc,QAAQ,cAAc;AAAA,EAC5D;AACA,MAAI,QAAQ,gBAAgB,QAAQ;AAClC,UAAM,SAAS,IAAI,4BAA4B,QAAQ,aAAa;AACpE,WAAO,OAAO,cAAc,QAAQ,cAAc;AAAA,EACpD;AACA,MAAI,CAAC,QAAQ,UAAU;AACrB,UAAM,IAAI,MAAM,uEAAuE;AAAA,EACzF;AACA,QAAM,MAAe,KAAK,MAAM,MAAM,SAAS,QAAQ,UAAU,MAAM,CAAC;AACxE,MAAI,oBAAoB,GAAG,EAAG,QAAO;AACrC,QAAM,IAAI,MAAM,mEAAmE;AACrF;AAEA,UAAU,sBACR,aACA,cACA,YACA,aAC4B;AAC5B,QAAM,OAAO,IAAI,IAAY,eAAe,CAAC,CAAC;AAC9C,QAAM,OAAO,CAAC,GAAG,cAAc,GAAG,yBAAyB,WAAW,CAAC;AACvE,MAAI,QAAQ;AACZ,aAAW,OAAO,MAAM;AACtB,QAAI,KAAK,IAAI,GAAG,EAAG;AACnB,SAAK,IAAI,GAAG;AACZ,UAAM,aAAa,KAAK,YAAY,KAAK;AACzC,aAAS;AAAA,EACX;AACF;AAEA,gBAAgB,SAAS,MAAuB,YAAuD;AACrG,QAAM,EAAE,aAAa,UAAU,IAAI,mBAAmB,IAAI;AAC1D,QAAM;AAAA,IACJ,MAAM;AAAA,IACN,QAAQ,WAAW,KAAK,IAAI,KAAK,KAAK,UAAU;AAAA,IAChD,UAAU,KAAK;AAAA,IACf,OAAO,KAAK;AAAA,IACZ,MAAM,aAAa,KAAK,IAAI;AAAA,IAC5B;AAAA,IACA,YAAY,KAAK;AAAA,IACjB,YAAY,KAAK;AAAA,IACjB,QAAQ,iBAAiB,KAAK,MAAM;AAAA,IACpC,UAAU,KAAK;AAAA,IACf,gBAAgB,KAAK;AAAA,EACvB;AAEA,SAAO;AAAA,IACL,KAAK;AAAA,IACL,EAAE,UAAU,KAAK,IAAI,OAAO,KAAK,OAAO,KAAK,KAAK,IAAI;AAAA,IACtD;AAAA,EACF;AAEA,QAAM,cAAc,wBAAwB,KAAK,MAAM;AACvD,SAAO,sBAAsB,aAAa,WAAW,YAAY,WAAW;AAC9E;AAEA,gBAAgB,SAAS,MAAuB,YAAuD;AACrG,QAAM,EAAE,aAAa,UAAU,IAAI,mBAAmB,IAAI;AAE1D,MAAI;AACJ,MAAI,KAAK,kBAAkB;AACzB,4BAAwB,YAAY,KAAK,EAAE;AAAA,EAC7C;AAEA,QAAM;AAAA,IACJ,MAAM;AAAA,IACN,QAAQ,WAAW,KAAK,IAAI,KAAK,KAAK,UAAU;AAAA,IAChD,UAAU,KAAK;AAAA,IACf,OAAO,KAAK;AAAA,IACZ,MAAM,aAAa,KAAK,IAAI;AAAA,IAC5B,SAAS,KAAK;AAAA,IACd;AAAA,IACA,aAAa,KAAK;AAAA,IAClB,QAAQ,iBAAiB,KAAK,MAAM;AAAA,IACpC,eAAe,KAAK;AAAA,IACpB,UAAU,KAAK;AAAA,IACf;AAAA,IACA,UAAU,KAAK;AAAA,IACf,gBAAgB,KAAK;AAAA,EACvB;AAEA,MAAI,KAAK,kBAAkB;AACzB,UAAM,WAAW,gBAAgB,KAAK,kBAAkB,GAAG,KAAK,EAAE,eAAe;AACjF,UAAM;AAAA,MACJ,MAAM;AAAA,MACN,QAAQ,WAAW,uBAAwB,KAAK,kBAAkB,UAAU;AAAA,MAC5E,UAAU;AAAA,MACV,WAAW,KAAK;AAAA,MAChB;AAAA,MACA,UAAU,UAAU,QAAQ;AAAA,IAC9B;AAAA,EACF;AAEA,SAAO;AAAA,IACL,KAAK;AAAA,IACL,EAAE,UAAU,KAAK,IAAI,OAAO,KAAK,OAAO,KAAK,KAAK,IAAI;AAAA,IACtD;AAAA,EACF;AAEA,QAAM,cAAc,wBAAwB,KAAK,MAAM;AACvD,SAAO,sBAAsB,aAAa,WAAW,YAAY,WAAW;AAC9E;AAGA,gBAAuB,6BACrB,SACkC;AAClC,QAAM,MAAM,MAAM,sBAAsB,OAAO;AAC/C,QAAM,aAAa,IAAI;AAEvB,aAAW,YAAY,IAAI,cAAc,CAAC,GAAG;AAC3C,UAAM;AAAA,MACJ,MAAM;AAAA,MACN,QAAQ,WAAW,SAAS,IAAI,QAAW,UAAU;AAAA,MACrD,UAAU,SAAS;AAAA,MACnB,MAAM,SAAS;AAAA,MACf,MAAM,aAAa,SAAS,IAAI;AAAA,IAClC;AAAA,EACF;AAEA,aAAW,OAAO,IAAI,QAAQ,CAAC,GAAG;AAChC,UAAM;AAAA,MACJ,MAAM;AAAA,MACN,QAAQ,WAAW,IAAI,IAAI,QAAW,UAAU;AAAA,MAChD,UAAU,IAAI;AAAA,MACd,MAAM,IAAI;AAAA,MACV,MAAM,aAAa,IAAI,IAAI;AAAA,IAC7B;AAAA,EACF;AAEA,aAAW,QAAQ,IAAI,OAAO;AAC5B,WAAO,SAAS,MAAM,UAAU;AAAA,EAClC;AAEA,aAAW,QAAQ,IAAI,SAAS,CAAC,GAAG;AAClC,WAAO,SAAS,MAAM,UAAU;AAAA,EAClC;AAEA,SAAO,uBAAuB,IAAI,WAAW,UAAU;AACzD;AAEA,SAAS,0BAA0B,WAA+D;AAChG,MAAI,CAAC,WAAW,OAAQ,QAAO;AAC/B,SAAO,UAAU;AAAA,IAAO,CAAC,YACvB,QAAQ,MAAM,KAAK,CAAC,SAAS,QAAQ,KAAK,UAAU,KAAK,CAAC,CAAC;AAAA,EAC7D,EAAE;AACJ;AAEO,SAAS,2BAA2B,KAMzC;AACA,MAAI,aAAa;AACjB,aAAW,QAAQ,IAAI,OAAO;AAC5B,kBAAc,uBAAuB,KAAK,MAAM;AAAA,EAClD;AACA,aAAW,QAAQ,IAAI,SAAS,CAAC,GAAG;AAClC,kBAAc,uBAAuB,KAAK,MAAM;AAAA,EAClD;AACA,gBAAc,0BAA0B,IAAI,SAAS;AACrD,SAAO;AAAA,IACL,OAAO,IAAI,MAAM;AAAA,IACjB,OAAO,IAAI,OAAO,UAAU;AAAA,IAC5B,YAAY,IAAI,YAAY,UAAU;AAAA,IACtC,MAAM,IAAI,MAAM,UAAU;AAAA,IAC1B;AAAA,EACF;AACF;AAEA,eAAsB,8BAA8B,UAIjD;AACD,QAAM,SAA8C,CAAC;AACrD,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,sBAAsB,EAAE,SAAS,CAAC;AAAA,EAChD,SAAS,OAAO;AACd,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,QAAQ;AAAA,QACN;AAAA,UACE,MAAM;AAAA,UACN,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QAChE;AAAA,MACF;AAAA,MACA,SAAS,CAAC;AAAA,IACZ;AAAA,EACF;AAEA,MAAI,IAAI,MAAM,WAAW,MAAM,IAAI,OAAO,UAAU,OAAO,GAAG;AAC5D,WAAO,KAAK,EAAE,MAAM,gBAAgB,SAAS,8BAA8B,CAAC;AAAA,EAC9E;AAEA,QAAM,UAAU,2BAA2B,GAAG;AAC9C,SAAO;AAAA,IACL,IAAI,OAAO,WAAW;AAAA,IACtB;AAAA,IACA,SAAS;AAAA,MACP,OAAO,QAAQ;AAAA,MACf,OAAO,QAAQ;AAAA,MACf,YAAY,QAAQ;AAAA,MACpB,MAAM,QAAQ;AAAA,MACd,YAAY,QAAQ;AAAA,MACpB,QAAQ;AAAA,IACV;AAAA,EACF;AACF;AAGO,SAAS,4BAA4B,MAAyD;AACnG,QAAM,UAAqD,CAAC;AAC5D,QAAM,UACJ;AACF,aAAW,SAAS,KAAK,SAAS,OAAO,GAAG;AAC1C,YAAQ,KAAK;AAAA,MACX,WAAW,MAAM,CAAC,KAAK;AAAA,MACvB,SAAS,MAAM,CAAC,KAAK;AAAA,IACvB,CAAC;AAAA,EACH;AACA,SAAO;AACT;;;AElrBA,IAAM,oBAAoB;AAE1B,SAAS,eAAe,MAAuB;AAC7C,QAAM,QAAQ,KAAK,YAAY;AAC/B,MAAI,gCAAgC,SAAS,KAAyD,GAAG;AACvG,WAAO;AAAA,EACT;AACA,SAAO,MAAM,WAAW,cAAc;AACxC;AAGO,SAAS,8BAA8B,aAAiD;AAC7F,MAAI,CAAC,YAAY,KAAK,EAAG,QAAO,CAAC;AAEjC,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,UAAsC,CAAC;AAE7C,aAAW,SAAS,YAAY,SAAS,iBAAiB,GAAG;AAC3D,UAAM,UAAU,MAAM,CAAC,MAAM;AAC7B,UAAM,QAAQ,MAAM,CAAC,KAAK,IAAI,YAAY;AAC1C,QAAI,CAAC,QAAQ,QAAS;AAEtB,UAAM,MAAM;AACZ,QAAI,KAAK,IAAI,GAAG,EAAG;AACnB,SAAK,IAAI,GAAG;AAEZ,YAAQ,KAAK;AAAA,MACX,WAAW;AAAA,MACX,cAAc,eAAe,IAAI;AAAA,IACnC,CAAC;AAAA,EACH;AAEA,SAAO,QAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,cAAc,EAAE,SAAS,CAAC;AACtE;;;AH0CO,SAAS,6BAAoD;AAClE,SAAO;AAAA,IACL,gBAAgB;AAAA,IAChB,gBAAgB;AAAA,IAChB,wBAAwB;AAAA,IACxB,0BAA0B;AAAA,IAC1B,yBAAyB,CAAC;AAAA,EAC5B;AACF;AAEO,SAAS,wBAAwB,QAA6C;AACnF,QAAM,SAAS,oBAAI,IAAY;AAC/B,QAAM,kBAAkB,oBAAI,IAAY;AAExC,aAAW,UAAU,CAAC,GAAG,OAAO,OAAO,GAAG,OAAO,KAAK,GAAG;AACvD,UAAM,YAAY,sBAAsB,OAAO,eAAe,EAAE;AAChE,eAAW,OAAO,UAAU,KAAM,QAAO,IAAI,GAAG;AAChD,eAAW,MAAM,UAAU,wBAAyB,iBAAgB,IAAI,EAAE;AAAA,EAC5E;AAEA,QAAM,iBAAiB,IAAI,IAAI,OAAO,MAAM,IAAI,CAAC,UAAU,MAAM,QAAQ,CAAC;AAC1E,QAAM,0BAA0B,CAAC,GAAG,eAAe,EAChD,OAAO,CAAC,OAAO,CAAC,eAAe,IAAI,EAAE,CAAC,EACtC,KAAK,CAAC,MAAM,UAAU,OAAO,IAAI,IAAI,OAAO,KAAK,CAAC;AAErD,SAAO;AAAA,IACL,gBAAgB,OAAO;AAAA,IACvB,gBAAgB,gBAAgB;AAAA,IAChC,wBAAwB,gBAAgB,OAAO,wBAAwB;AAAA,IACvE,0BAA0B,wBAAwB;AAAA,IAClD;AAAA,EACF;AACF;AAEO,SAAS,sBAAsC;AACpD,SAAO;AAAA,IACL,oBAAoB,CAAC;AAAA,IACrB,oBAAoB,CAAC;AAAA,IACrB,uBAAuB,CAAC;AAAA,IACxB,gBAAgB,CAAC;AAAA,IACjB,aAAa,CAAC;AAAA,IACd,wBAAwB,CAAC;AAAA,IACzB,mBAAmB,CAAC;AAAA,IACpB,eAAe,CAAC;AAAA,IAChB,gBAAgB,2BAA2B;AAAA,IAC3C,kBAAkB,CAAC;AAAA,IACnB,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,EACnB;AACF;AAEO,SAAS,sBACd,QACA,SACgB;AAChB,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO,mBAAmB,QAAQ;AAClC,SAAO,sBAAsB,QAAQ;AACrC,SAAO,kBAAkB,QAAQ;AACjC,MAAI,QAAQ,gCAAgC,QAAW;AACrD,WAAO,8BAA8B,QAAQ;AAAA,EAC/C;AACA,SAAO;AACT;AAEA,SAAS,mBACP,OACA,YACyB;AACzB,QAAM,SAAS,oBAAI,IAAsB;AACzC,aAAW,QAAQ,OAAO;AACxB,UAAM,OAAO,OAAO,IAAI,KAAK,IAAI,KAAK,CAAC;AACvC,SAAK,KAAK,KAAK,QAAQ;AACvB,WAAO,IAAI,KAAK,MAAM,IAAI;AAAA,EAC5B;AAEA,QAAM,YAAqC,CAAC;AAC5C,aAAW,CAAC,MAAM,SAAS,KAAK,QAAQ;AACtC,QAAI,UAAU,SAAS,GAAG;AACxB,gBAAU,KAAK,EAAE,YAAY,MAAM,UAAU,CAAC;AAAA,IAChD;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,YAAY,MAAwB;AAC3C,QAAM,SAAmB,CAAC;AAC1B,MAAI,aAAa,KAAK,IAAI,GAAG;AAC3B,WAAO,KAAK,oBAAoB;AAAA,EAClC;AAEA,MAAI;AACF,UAAM,IAAY,cAAK,MAAM,EAAE,KAAK,MAAM,CAAC;AAC3C,MAAE,GAAG,EAAE,KAAK,CAAC,GAAG,OAAO;AACrB,YAAM,QAAQ,EAAE,EAAE,EAAE,KAAK,KAAK;AAC9B,UAAI,MAAM,SAAS,IAAI,GAAG;AACxB,eAAO,KAAK,kBAAkB;AAAA,MAChC;AAAA,IACF,CAAC;AAAA,EACH,QAAQ;AACN,WAAO,KAAK,kBAAkB;AAAA,EAChC;AAEA,SAAO,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC;AAC5B;AAEA,SAAS,YAAY,QAAmC;AACtD,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,SAAS,OAAO,OAAO;AAChC,UAAM,aAAa,kBAAkB,MAAM,SAAS;AACpD,QAAI,WAAY,MAAK,IAAI,UAAU;AACnC,SAAK,IAAI,MAAM,SAAS;AAAA,EAC1B;AACA,SAAO;AACT;AAEA,SAAS,2BACP,UACA,aACA,WACiC;AACjC,QAAM,YAA6C,CAAC;AACpD,aAAW,OAAO,mBAAmB,WAAW,GAAG;AACjD,QAAI,oBAAoB,GAAG,EAAG;AAC9B,UAAM,aAAa,kBAAkB,GAAG;AACxC,QAAI,CAAC,WAAY;AACjB,QAAI,CAAC,UAAU,IAAI,UAAU,KAAK,CAAC,UAAU,IAAI,GAAG,GAAG;AACrD,gBAAU,KAAK,EAAE,oBAAoB,UAAU,KAAK,IAAI,CAAC;AAAA,IAC3D;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,sBACP,YACA,UACA,aAC4B;AAC5B,QAAM,YAAwC,CAAC;AAE/C,aAAW,UAAU,4BAA4B,WAAW,GAAG;AAC7D,cAAU,KAAK;AAAA,MACb;AAAA,MACA;AAAA,MACA,WAAW,OAAO;AAAA,MAClB,SAAS,OAAO;AAAA,IAClB,CAAC;AAAA,EACH;AAEA,aAAW,UAAU,8BAA8B,WAAW,GAAG;AAC/D,cAAU,KAAK;AAAA,MACb;AAAA,MACA;AAAA,MACA,WAAW,OAAO,eACd,0BAA0B,OAAO,SAAS,KAC1C,uBAAuB,OAAO,SAAS;AAAA,IAC7C,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEO,SAAS,iBACd,QACA,SAKgB;AAChB,QAAM,SAAS,oBAAoB;AACnC,QAAM,YAAY,YAAY,MAAM;AAEpC,SAAO,qBAAqB,mBAAmB,OAAO,OAAO,MAAM;AACnE,SAAO,qBAAqB,mBAAmB,OAAO,OAAO,MAAM;AAEnE,aAAW,QAAQ,OAAO,OAAO;AAC/B,QAAI,KAAK,yBAAyB,CAAC,KAAK,uBAAuB;AAC7D,aAAO,sBAAsB,KAAK;AAAA,QAChC,cAAc,KAAK;AAAA,QACnB,uBAAuB,KAAK;AAAA,QAC5B,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAEA,UAAM,aAAa,YAAY,KAAK,WAAW;AAC/C,QAAI,WAAW,QAAQ;AACrB,aAAO,YAAY,KAAK;AAAA,QACtB,YAAY;AAAA,QACZ,UAAU,KAAK;AAAA,QACf,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAEA,WAAO,uBAAuB;AAAA,MAC5B,GAAG,2BAA2B,KAAK,UAAU,KAAK,aAAa,SAAS;AAAA,IAC1E;AACA,WAAO,kBAAkB;AAAA,MACvB,GAAG,sBAAsB,QAAQ,KAAK,UAAU,KAAK,WAAW;AAAA,IAClE;AAAA,EACF;AAEA,aAAW,QAAQ,OAAO,OAAO;AAC/B,UAAM,aAAa,YAAY,KAAK,WAAW;AAC/C,QAAI,WAAW,QAAQ;AACrB,aAAO,YAAY,KAAK;AAAA,QACtB,YAAY;AAAA,QACZ,UAAU,KAAK;AAAA,QACf,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAEA,WAAO,uBAAuB;AAAA,MAC5B,GAAG,2BAA2B,KAAK,UAAU,KAAK,aAAa,SAAS;AAAA,IAC1E;AACA,WAAO,kBAAkB;AAAA,MACvB,GAAG,sBAAsB,QAAQ,KAAK,UAAU,KAAK,WAAW;AAAA,IAClE;AAAA,EACF;AAEA,MAAI,SAAS,gBAAgB;AAC3B,WAAO,iBAAiB,QAAQ;AAAA,EAClC;AACA,MAAI,SAAS,eAAe;AAC1B,WAAO,gBAAgB,QAAQ;AAAA,EACjC;AAEA,SAAO,iBAAiB,wBAAwB,MAAM;AACtD,wBAAsB,QAAQ,SAAS,gBAAgB;AAEvD,SAAO;AACT;AAEO,SAAS,qBAAqB,QAAiC;AACpE,SAAO,OAAO,mBAAmB,SAAS,KAAK,OAAO,cAAc,KAAK,CAAC,MAAM,EAAE,OAAO;AAC3F;AAEO,SAAS,YAAY,QAAiC;AAC3D,SACE,OAAO,mBAAmB,SAAS,KACnC,OAAO,sBAAsB,SAAS,KACtC,OAAO,eAAe,SAAS,KAC/B,OAAO,YAAY,SAAS,KAC5B,OAAO,uBAAuB,SAAS,KACvC,OAAO,kBAAkB,SAAS,KAClC,OAAO,eAAe,2BAA2B,KACjD,OAAO;AAEX;AAEO,SAAS,iBAAiB,QAI7B;AACF,QAAM,YAAwE,CAAC;AAE/E,aAAW,QAAQ,OAAO,OAAO;AAC/B,UAAM,OAAO,KAAK,OAAO;AACzB,QAAI,CAAC,KAAM;AACX,UAAM,KAAK,SAAS,KAAK,IAAI;AAC7B,QAAI,KAAK,QAAQ,OAAO,EAAE,MAAM,GAAG,QAAQ,OAAO,EAAE,EAAG;AACvD,cAAU,KAAK,EAAE,UAAU,MAAM,QAAQ,IAAI,YAAY,IAAI,CAAC;AAAA,EAChE;AAEA,aAAW,QAAQ,OAAO,OAAO;AAC/B,UAAM,OAAO,KAAK,OAAO;AACzB,QAAI,CAAC,KAAM;AACX,UAAM,KAAK,IAAI,KAAK,IAAI;AACxB,QAAI,KAAK,QAAQ,OAAO,EAAE,MAAM,GAAG,QAAQ,OAAO,EAAE,EAAG;AACvD,cAAU,KAAK,EAAE,UAAU,MAAM,QAAQ,IAAI,YAAY,IAAI,CAAC;AAAA,EAChE;AAEA,SAAO;AACT;AAEO,SAAS,oBACd,WACwB;AACxB,QAAM,QAAgC,CAAC;AACvC,aAAW,OAAO,WAAW;AAC3B,QAAI,IAAI,SAAS,QAAQ,OAAO,EAAE,MAAM,IAAI,OAAO,QAAQ,OAAO,EAAE,GAAG;AACrE,YAAM,KAAK,EAAE,UAAU,IAAI,UAAU,QAAQ,IAAI,QAAQ,SAAS,KAAK,CAAC;AAAA,IAC1E;AAAA,EACF;AACA,SAAO;AACT;;;AD1VA,eAAsB,aAAa,SAA2D;AAC5F,QAAM,SAAS,MAAM,gBAAgB,QAAQ,QAAQ;AACrD,SAAO,uBAAuB,QAAQ,OAAO;AAC/C;AAEA,eAAsB,uBACpB,QACA,SAC6B;AAC7B,QAAM,EAAE,MAAM,UAAU,kBAAkB,IAAI;AAC9C,QAAM,qBAA6E,CAAC;AACpF,QAAM,iBAAiB,oBAAI,IAA+B;AAE1D,MAAI,YAAY;AAChB,MAAI,SAAS;AACb,MAAI,UAAU;AAEd,QAAM,QAAQ,OACZ,OACA,KACA,WACkB;AAClB,QAAI,CAAC,oBAAoB,KAAK,kBAAkB,GAAG;AACjD,iBAAW;AACX,0BAAoB,KAAK,SAAS;AAClC;AAAA,IACF;AAEA,UAAM,mBAAmB,MAAM,KAAK,eAAe,GAAG;AACtD,QAAI,kBAAkB;AACpB,UAAI,UAAU,YAAY,IAAI,eAAe,SAAS;AACpD,uBAAe,IAAI,IAAI,UAAU,EAAE,UAAU,iBAAiB,CAAC;AAAA,MACjE;AACA,iBAAW;AACX,0BAAoB,KAAK,SAAS;AAClC;AAAA,IACF;AAEA,QAAI;AACF,YAAM,KAAK,iBAAiB;AAAA,QAC1B;AAAA,QACA,UAAU,YAAY,SAAS;AAAA,QAC/B,SAAS,GAAG,KAAK,IAAI,IAAI,UAAU,IAAI,IAAI,QAAQ;AAAA,MACrD,CAAC;AACD,YAAM,OAAO;AACb,mBAAa;AACb,0BAAoB,KAAK,MAAM;AAAA,IACjC,SAAS,OAAO;AACd,gBAAU;AACV,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,0BAAoB,KAAK,UAAU,OAAO;AAAA,IAC5C;AAAA,EACF;AAEA,aAAW,YAAY,OAAO,YAAY;AACxC,UAAM,MAAM,UAAU,UAAU,QAAQ;AACxC,UAAM,MAAM,YAAY,KAAK,YAAY;AACvC,UAAI,CAAC,KAAK,eAAgB;AAC1B,YAAM,KAAK,eAAe,QAAQ;AAAA,IACpC,CAAC;AAAA,EACH;AAEA,aAAW,OAAO,OAAO,MAAM;AAC7B,UAAM,MAAM,UAAU,KAAK,QAAQ;AACnC,UAAM,MAAM,YAAY,KAAK,YAAY;AACvC,UAAI,CAAC,KAAK,UAAW;AACrB,YAAM,KAAK,UAAU,GAAG;AAAA,IAC1B,CAAC;AAAA,EACH;AAEA,aAAW,SAAS,OAAO,OAAO;AAChC,UAAM,MAAM,UAAU,OAAO,QAAQ;AACrC,UAAM,MAAM,UAAU,KAAK,YAAY;AACrC,YAAM,SAAS,QAAQ,qBAAqB,MAAM,QAAQ,mBAAmB,KAAK,IAAI;AACtF,YAAM,SAAS,MAAM,KAAK,YAAY;AAAA,QACpC;AAAA,QACA,MAAM,QAAQ,QAAQ,UAAU;AAAA,QAChC,eAAe,QAAQ;AAAA,MACzB,CAAC;AACD,qBAAe,IAAI,MAAM,UAAU,MAAM;AAAA,IAC3C,CAAC;AAAA,EACH;AAEA,aAAW,aAAa,OAAO,YAAY;AACzC,UAAM,MAAM,UAAU,WAAW,QAAQ;AACzC,UAAM,MAAM,cAAc,KAAK,YAAY;AACzC,UAAI,CAAC,KAAK,iBAAiB;AACzB,cAAM,IAAI,MAAM,kCAAkC;AAAA,MACpD;AACA,YAAM,KAAK,gBAAgB,SAAS;AAAA,IACtC,CAAC;AAAA,EACH;AAEA,aAAW,QAAQ,OAAO,OAAO;AAC/B,UAAM,MAAM,UAAU,MAAM,QAAQ;AACpC,UAAM,MAAM,WAAW,KAAK,YAAY;AACtC,YAAM,KAAK;AAAA,QACT,qBAAqB,MAAM,SAAS,gBAAgB,MAAM;AAAA,MAC5D;AAAA,IACF,CAAC;AAAA,EACH;AAEA,aAAW,QAAQ,OAAO,OAAO;AAC/B,UAAM,MAAM,UAAU,MAAM,QAAQ;AACpC,UAAM,MAAM,WAAW,KAAK,YAAY;AACtC,YAAM,KAAK;AAAA,QACT,qBAAqB,MAAM,SAAS,gBAAgB,MAAM;AAAA,MAC5D;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,iBAAiB,yBAAyB,MAAM;AACtD,aAAW,QAAQ,gBAAgB;AACjC,UAAM,MAAiB;AAAA,MACrB;AAAA,MACA,YAAY;AAAA,MACZ,UAAU,GAAG,KAAK,iBAAiB,IAAI,KAAK,aAAa;AAAA,IAC3D;AACA,UAAM,MAAM,YAAY,KAAK,YAAY;AACvC,UAAI,CAAC,KAAK,mBAAoB;AAC9B,YAAM,KAAK,mBAAmB,IAAI;AAAA,IACpC,CAAC;AAAA,EACH;AAEA,QAAM,YAAY,iBAAiB,MAAM;AACzC,aAAW,YAAY,WAAW;AAChC,UAAM,MAAiB;AAAA,MACrB;AAAA,MACA,YAAY;AAAA,MACZ,UAAU,YAAY,SAAS,QAAQ;AAAA,IACzC;AACA,UAAM,MAAM,aAAa,KAAK,YAAY;AACxC,UAAI,CAAC,KAAK,cAAe;AACzB,YAAM,KAAK,cAAc,QAAQ;AAAA,IACnC,CAAC;AAAA,EACH;AAEA,SAAO,EAAE,WAAW,QAAQ,QAAQ;AACtC;AAEA,SAAS,qBACP,QACA,SACA,gBACA,QACG;AACH,MAAI,CAAC,QAAQ,oBAAqB,QAAO;AAEzC,QAAM,iBAAiB,oBAAoB,QAAQ,QAAQ,mBAAmB;AAC9E,QAAM,YAAY,oBAAoB,OAAO,aAAa,gBAAgB,cAAc;AAExF,SAAO;AAAA,IACL,GAAG;AAAA,IACH,aAAa,UAAU;AAAA,EACzB;AACF;AAEA,SAAS,oBACP,QACA,SAC4B;AAC5B,QAAM,gBAAgB,oBAAI,IAAoB;AAC9C,aAAW,SAAS,OAAO,OAAO;AAChC,kBAAc,IAAI,MAAM,WAAW,MAAM,QAAQ;AACjD,UAAM,aAAa,kBAAkB,MAAM,SAAS;AACpD,QAAI,WAAY,eAAc,IAAI,YAAY,MAAM,QAAQ;AAAA,EAC9D;AAEA,QAAM,cAAc,QAAQ,eAAe,mCAAmC;AAC9E,QAAM,kBAAkB,QAAQ,mBAAmB,QAAQ,QAAQ,WAAW;AAE9E,SAAO;AAAA,IACL,cAAc,CAAC,QAAQ;AACrB,YAAM,WAAW,QAAQ,aAAa,GAAG;AACzC,UAAI,SAAU,QAAO;AACrB,YAAM,aAAa,kBAAkB,GAAG;AACxC,YAAM,iBACH,aAAa,cAAc,IAAI,UAAU,IAAI,WAAc,cAAc,IAAI,GAAG;AACnF,UAAI,CAAC,cAAe,QAAO;AAC3B,aAAO,EAAE,aAAa,KAAK,cAAc;AAAA,IAC3C;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,YAAsB;AAC7B,SAAO,SAAS,KAAK,CAAC,CAAC;AACzB;;;AKpNA,SAAS,OAAO,iBAAiB;AACjC,SAAS,YAAY;AAcrB,eAAe,UAAU,MAAc,MAA8B;AACnE,QAAM,UAAU,MAAM,GAAG,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA,GAAM,MAAM;AACpE;AAEA,eAAsB,sBAAsB,SAAgD;AAC1F,QAAM,MAAM,QAAQ,QAAQ,EAAE,WAAW,KAAK,CAAC;AAE/C,QAAM,UAAU,KAAK,QAAQ,QAAQ,YAAY,GAAG,QAAQ,OAAO,KAAK;AACxE,QAAM,UAAU,KAAK,QAAQ,QAAQ,YAAY,GAAG,QAAQ,OAAO,KAAK;AACxE,QAAM,UAAU,KAAK,QAAQ,QAAQ,YAAY,GAAG,QAAQ,OAAO,KAAK;AACxE,QAAM,UAAU,KAAK,QAAQ,QAAQ,iBAAiB,GAAG,QAAQ,OAAO,UAAU;AAClF,QAAM;AAAA,IACJ,KAAK,QAAQ,QAAQ,sBAAsB;AAAA,IAC3C,yBAAyB,QAAQ,MAAM;AAAA,EACzC;AACA,QAAM,UAAU,KAAK,QAAQ,QAAQ,iBAAiB,GAAG,QAAQ,OAAO,UAAU;AAClF,QAAM,UAAU,KAAK,QAAQ,QAAQ,WAAW,GAAG,QAAQ,OAAO,IAAI;AAEtE,MAAI,QAAQ,WAAW;AACrB,UAAM,UAAU,KAAK,QAAQ,QAAQ,gBAAgB,GAAG,QAAQ,SAAS;AAAA,EAC3E;AACA,MAAI,QAAQ,QAAQ;AAClB,UAAM,UAAU,KAAK,QAAQ,QAAQ,uBAAuB,GAAG,QAAQ,MAAM;AAAA,EAC/E;AACF;AAEO,SAAS,qBAAqB,QAA+C;AAClF,SAAO;AAAA,IACL,OAAO,OAAO;AAAA,IACd,OAAO,OAAO;AAAA,IACd,OAAO,OAAO;AAAA,IACd,YAAY,OAAO;AAAA,IACnB,gBAAgB,yBAAyB,MAAM;AAAA,IAC/C,YAAY,OAAO;AAAA,IACnB,MAAM,OAAO;AAAA,EACf;AACF;;;AC5BO,IAAM,0BAAN,MAAuD;AAAA,EACnD,SAAuB,YAAY;AAAA,EACnC,sBAA4C,CAAC;AAAA,EAC7C,YAAiC,CAAC;AAAA,EAE3C,MAAM,eAAe,UAA6D;AAChF,SAAK,OAAO,WAAW,KAAK,QAAQ;AACpC,WAAO,EAAE,UAAU,SAAS,SAAS;AAAA,EACvC;AAAA,EAEA,MAAM,UAAU,KAAmD;AACjE,SAAK,OAAO,KAAK,KAAK,GAAG;AACzB,WAAO,EAAE,UAAU,IAAI,SAAS;AAAA,EAClC;AAAA,EAEA,MAAM,YAAY,OAAqD;AACrE,SAAK,OAAO,MAAM,KAAK,MAAM,KAAK;AAClC,WAAO;AAAA,MACL,UAAU,MAAM,MAAM;AAAA,MACtB,WAAW,MAAM,MAAM;AAAA,IACzB;AAAA,EACF;AAAA,EAEA,MAAM,gBAAgB,WAA+D;AACnF,SAAK,OAAO,WAAW,KAAK,SAAS;AACrC,WAAO,EAAE,UAAU,UAAU,SAAS;AAAA,EACxC;AAAA,EAEA,MAAM,WAAW,MAAiD;AAChE,SAAK,OAAO,MAAM,KAAK,IAAI;AAC3B,WAAO;AAAA,MACL,UAAU,KAAK;AAAA,MACf,YAAY,KAAK,OAAO,QAAQ,IAAI,KAAK,IAAI;AAAA,IAC/C;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,MAAiD;AAChE,SAAK,OAAO,MAAM,KAAK,IAAI;AAC3B,WAAO;AAAA,MACL,UAAU,KAAK;AAAA,MACf,YAAY,KAAK,OAAO,QAAQ,IAAI,KAAK,IAAI;AAAA,IAC/C;AAAA,EACF;AAAA,EAEA,MAAM,mBAAmB,MAAyC;AAChE,SAAK,oBAAoB,KAAK,IAAI;AAAA,EACpC;AAAA,EAEA,MAAM,cAAc,UAA4C;AAC9D,SAAK,UAAU,KAAK,QAAQ;AAAA,EAC9B;AAAA,EAEA,MAAM,MAAM,SAAgD;AAC1D,UAAM,sBAAsB;AAAA,MAC1B,GAAG;AAAA,MACH,QAAQ,KAAK;AAAA,IACf,CAAC;AAAA,EACH;AACF;AAEO,SAAS,gCAAyD;AACvE,SAAO,IAAI,wBAAwB;AACrC;AAGO,SAAS,4BACd,MACS;AACT,QAAM,WAAW,yBAAyB,KAAK,MAAM;AACrD,MAAI,SAAS,WAAW,KAAK,oBAAoB,OAAQ,QAAO;AAChE,SAAO,SAAS,MAAM,CAAC,MAAM,UAAU;AACrC,UAAM,SAAS,KAAK,oBAAoB,KAAK;AAC7C,WACE,QAAQ,sBAAsB,KAAK,qBACnC,QAAQ,kBAAkB,KAAK,iBAC/B,QAAQ,SAAS,KAAK;AAAA,EAE1B,CAAC;AACH;;;ACrGA,SAAS,kBAAkB;AAmCpB,SAAS,qBAAqB,OAYjB;AAClB,QAAM,SAAS,aAAa,MAAM,MAAM;AACxC,SAAO;AAAA,IACL,OAAO,MAAM,SAAS,WAAW;AAAA,IACjC,UAAU,MAAM;AAAA,IAChB,MAAM,MAAM;AAAA,IACZ,WAAW,MAAM,UAAU,YAAY;AAAA,IACvC,aAAa,MAAM,cAAc,oBAAI,KAAK,GAAG,YAAY;AAAA,IACzD,SAAS;AAAA,MACP,GAAG;AAAA,MACH,uBAAuB,MAAM;AAAA,MAC7B,gBAAgB,MAAM,UAAU;AAAA,MAChC,qBAAqB,MAAM,UAAU;AAAA,MACrC,iBAAiB,MAAM,UAAU;AAAA,MACjC,kBAAkB,MAAM,UAAU;AAAA,IACpC;AAAA,IACA,UAAU,MAAM,YAAY,CAAC;AAAA,IAC7B,QAAQ,MAAM,UAAU,CAAC;AAAA,IACzB,WAAW,MAAM;AAAA,IACjB,aAAa,MAAM;AAAA,EACrB;AACF;;;AClEO,IAAM,uBAAuB,IAAI,OAAO;AAsB/C,eAAsB,gBACpB,SAC0B;AAC1B,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,UAA6B,CAAC;AAEpC,aAAW,SAAS,QAAQ,QAAQ;AAClC,QAAI,QAAQ,SAAS;AACnB,cAAQ,KAAK;AAAA,QACX,UAAU,MAAM;AAAA,QAChB,KAAK,MAAM;AAAA,QACX,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,OAAO;AAAA,MACT,CAAC;AACD;AAAA,IACF;AAEA,QAAI;AACF,YAAM,WAAW,MAAM,QAAQ,MAAM,WAAW;AAAA,QAC9C,QAAQ;AAAA,QACR,QAAQ,YAAY,QAAQ,GAAI;AAAA,MAClC,CAAC;AAED,UAAI,SAAS,IAAI;AACf,cAAM,SAAS,SAAS,QAAQ,IAAI,gBAAgB;AACpD,cAAM,QAAQ,SAAS,OAAO,SAAS,QAAQ,EAAE,IAAI;AACrD,gBAAQ,KAAK;AAAA,UACX,UAAU,MAAM;AAAA,UAChB,KAAK,MAAM;AAAA,UACX,OAAO,OAAO,SAAS,KAAK,IAAI,QAAQ;AAAA,UACxC,QAAQ;AAAA,QACV,CAAC;AAAA,MACH,OAAO;AACL,gBAAQ,KAAK;AAAA,UACX,UAAU,MAAM;AAAA,UAChB,KAAK,MAAM;AAAA,UACX,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,OAAO,QAAQ,SAAS,MAAM;AAAA,QAChC,CAAC;AAAA,MACH;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,KAAK;AAAA,QACX,UAAU,MAAM;AAAA,QAChB,KAAK,MAAM;AAAA,QACX,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MAC9D,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,aAAa,QAAQ,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,OAAO,CAAC;AAC9D,SAAO,EAAE,YAAY,QAAQ,QAAQ;AACvC;AAEO,SAAS,sBAAsB,UAA2B;AAC/D,SAAO,SAAS,OACb,OAAO,CAAC,MAAM,EAAE,WAAW,cAAc,EAAE,SAAS,EAAE,UAAU,cAAc,EAC9E,IAAI,CAAC,OAAO;AAAA,IACX,UAAU,EAAE;AAAA,IACZ,KAAK,EAAE;AAAA,IACP,QAAQ,EAAE,SAAS;AAAA,EACrB,EAAE;AACN;;;AC7DA,eAAsB,4BACpB,SACA,OACuC;AACvC,MAAI,CAAC,QAAQ,iBAAkB,QAAO;AACtC,SAAO,QAAQ,iBAAiB,KAAK;AACvC;AAEA,eAAsB,UAAU,SAA+C;AAC7E,QAAM,YAAY,oBAAI,KAAK;AAC3B,QAAM,mBAAmB,MAAM,4BAA4B,QAAQ,SAAS,QAAQ,KAAK;AACzF,QAAM,SAAS,MAAM;AAAA,IACnB,QAAQ,QAAQ,kBAAkB,EAAE,OAAO,QAAQ,MAAM,CAAC;AAAA,EAC5D;AAEA,QAAM,WAAW,MAAM,gBAAgB;AAAA,IACrC,QAAQ,OAAO;AAAA,IACf,SAAS,QAAQ;AAAA,IACjB,SAAS,QAAQ;AAAA,EACnB,CAAC;AAED,QAAM,cAAc,iBAAiB,MAAM;AAC3C,QAAM,gBAAgB,oBAAoB,WAAW;AACrD,QAAM,iBAAiB,sBAAsB,QAAQ;AAErD,QAAM,YAAY,iBAAiB,QAAQ;AAAA,IACzC;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,WAAqB,CAAC;AAC5B,MAAI,eAAe,SAAS,GAAG;AAC7B,aAAS,KAAK,GAAG,eAAe,MAAM,oDAAoD;AAAA,EAC5F;AACA,MAAI,kBAAkB,iBAAiB;AACrC,aAAS;AAAA,MACP;AAAA,IACF;AAAA,EACF;AACA,QAAM,EAAE,eAAe,IAAI;AAC3B,MAAI,eAAe,2BAA2B,GAAG;AAC/C,aAAS;AAAA,MACP,GAAG,eAAe,wBAAwB,gDACpC,eAAe,sBAAsB,IAAI,eAAe,cAAc;AAAA,IAE9E;AAAA,EACF;AACA,MAAI,UAAU,mBAAmB,SAAS,GAAG;AAC3C,aAAS;AAAA,MACP,GAAG,UAAU,mBAAmB,MAAM;AAAA,IACxC;AAAA,EACF;AAEA,QAAM,SAAS,qBAAqB;AAAA,IAClC,UAAU,QAAQ;AAAA,IAClB,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,uBAAuB,SAAS;AAAA,IAChC;AAAA,EACF,CAAC;AAED,MAAI,WAAsB;AAC1B,MAAI,qBAAqB,SAAS,EAAG,YAAW;AAAA,WACvC,YAAY,SAAS,KAAK,SAAS,SAAS,EAAG,YAAW;AAEnE,SAAO,EAAE,QAAQ,WAAW,QAAQ,SAAS;AAC/C;","names":["cheerio","item"]}
package/dist/cli/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  getAdapter
4
- } from "../chunk-J3WX7IAS.js";
4
+ } from "../chunk-6UEPTHEU.js";
5
5
  import {
6
6
  analyzeConflicts,
7
7
  buildMigrationReport,
@@ -17,7 +17,7 @@ import {
17
17
  runMigration,
18
18
  staleUrlsFromEstimate,
19
19
  writeFilesystemExport
20
- } from "../chunk-H62Y7JAJ.js";
20
+ } from "../chunk-E2EUJY3C.js";
21
21
  import {
22
22
  collectEntities
23
23
  } from "../chunk-PD5AZX3B.js";
package/dist/index.d.ts CHANGED
@@ -350,6 +350,15 @@ interface SquarespaceTag {
350
350
  name: string;
351
351
  slug: string;
352
352
  }
353
+ /** Standalone gallery collection page (`?format=json-pretty` on a gallery URL). */
354
+ interface SquarespaceGalleryCollection {
355
+ id: string;
356
+ title: string;
357
+ slug: string;
358
+ url?: string;
359
+ description?: string;
360
+ items: SquarespaceGalleryItem[];
361
+ }
353
362
  interface SquarespaceExport {
354
363
  exportVersion: string | number;
355
364
  exportedAt?: string;
@@ -359,6 +368,8 @@ interface SquarespaceExport {
359
368
  };
360
369
  pages: SquarespacePage[];
361
370
  posts?: SquarespacePost[];
371
+ /** Top-level gallery collections (not embedded page/post blocks). */
372
+ galleries?: SquarespaceGalleryCollection[];
362
373
  categories?: SquarespaceCategory[];
363
374
  tags?: SquarespaceTag[];
364
375
  }
@@ -372,6 +383,11 @@ declare const squarespaceClientOptionsSchema: z.ZodObject<{
372
383
  retryBaseDelayMs: z.ZodDefault<z.ZodNumber>;
373
384
  maxRetryDelayMs: z.ZodDefault<z.ZodNumber>;
374
385
  requestIntervalMs: z.ZodDefault<z.ZodNumber>;
386
+ /**
387
+ * When json-pretty yields an empty classic layout (common on 7.1 section pages),
388
+ * fetch the rendered HTML once and parse `.sqs-block` content from `#sections`.
389
+ */
390
+ htmlFallback: z.ZodDefault<z.ZodBoolean>;
375
391
  fetchImpl: z.ZodOptional<z.ZodType<typeof fetch, z.ZodTypeDef, typeof fetch>>;
376
392
  }, "strip", z.ZodTypeAny, {
377
393
  format: "json-pretty" | "json";
@@ -379,6 +395,7 @@ declare const squarespaceClientOptionsSchema: z.ZodObject<{
379
395
  retryBaseDelayMs: number;
380
396
  maxRetryDelayMs: number;
381
397
  requestIntervalMs: number;
398
+ htmlFallback: boolean;
382
399
  fetchImpl?: typeof fetch | undefined;
383
400
  }, {
384
401
  format?: "json-pretty" | "json" | undefined;
@@ -386,6 +403,7 @@ declare const squarespaceClientOptionsSchema: z.ZodObject<{
386
403
  retryBaseDelayMs?: number | undefined;
387
404
  maxRetryDelayMs?: number | undefined;
388
405
  requestIntervalMs?: number | undefined;
406
+ htmlFallback?: boolean | undefined;
389
407
  fetchImpl?: typeof fetch | undefined;
390
408
  }>;
391
409
  type SquarespaceClientOptions = z.input<typeof squarespaceClientOptionsSchema>;
@@ -396,8 +414,26 @@ interface SquarespaceCollectTarget {
396
414
  kind?: "auto" | "page" | "collection";
397
415
  isHomePage?: boolean;
398
416
  }
417
+ interface WireRecord {
418
+ [key: string]: unknown;
419
+ }
399
420
  /** Append Squarespace `?format=json-pretty` (or `json`) to a site URL. */
400
421
  declare function buildJsonPrettyUrl(pageUrl: string, format?: SquarespaceJsonFormat): string;
422
+ /** True when json-pretty `mainContent` is an empty classic LayoutEngine shell. */
423
+ declare function isEmptyClassicMainContent(html: string | undefined): boolean;
424
+ /** True when an export page has no blocks and no usable contentHtml. */
425
+ declare function pageContentIsEmpty(page: Pick<SquarespacePage, "blocks" | "contentHtml">): boolean;
426
+ /**
427
+ * Pull the primary page body from a rendered Squarespace HTML document.
428
+ * Prefers 7.1 `#sections` / `article.sections`, then `main`.
429
+ */
430
+ declare function extractPageBodyHtml(html: string): string;
431
+ /** Map rendered page HTML into export `blocks` / `contentHtml`. */
432
+ declare function extractPageContentFromHtml(html: string): Pick<SquarespacePage, "blocks" | "contentHtml">;
433
+ /** Parse rendered `body` HTML into block entries when wire JSON has no structured blocks. */
434
+ declare function extractBlocksFromBodyHtml(html: string): SquarespaceBlock[];
435
+ /** Gallery / portfolio collection pages — items are media, not blog posts. */
436
+ declare function isGalleryCollection(collection: WireRecord | undefined): boolean;
401
437
  /** Map one Squarespace `?format=json-pretty` response into export partials. */
402
438
  declare function mapJsonPrettyWire(wire: unknown, context?: {
403
439
  fetchedUrl?: string;
@@ -410,12 +446,15 @@ declare class SquarespaceCollectionClient {
410
446
  readonly retryBaseDelayMs: number;
411
447
  readonly maxRetryDelayMs: number;
412
448
  readonly requestIntervalMs: number;
449
+ readonly htmlFallback: boolean;
413
450
  readonly fetchImpl: typeof fetch;
414
451
  private lastRequestAt;
415
452
  constructor(options?: SquarespaceClientOptions);
416
453
  buildJsonPrettyUrl(pageUrl: string): string;
417
454
  fetchWire(url: string): Promise<unknown>;
455
+ fetchHtml(url: string): Promise<string>;
418
456
  collectExport(targets: SquarespaceCollectTarget[]): Promise<SquarespaceExport>;
457
+ private enrichEmptyPagesFromHtml;
419
458
  private collectCollectionPages;
420
459
  private requestWithRetry;
421
460
  private throttle;
@@ -626,4 +665,4 @@ declare const wixAdapter: MigrationAdapter;
626
665
 
627
666
  declare function getAdapter(platform: MigrationPlatform): MigrationAdapter;
628
667
 
629
- export { MigrationAdapter, MigrationPlatform, SMUGMUG_API_BASE, SMUGMUG_OAUTH_ENDPOINTS, SQUARESPACE_JSON_FORMAT, type SmugMugAccessLevel, SmugMugApiClient, type SmugMugAuthorizeUrlOptions, type SmugMugClientOptions, type SmugMugConsumerCredentials, type SmugMugCredentials, type SmugMugOAuthSession, type SmugMugOAuthSigningMaterial, type SmugMugOAuthTokenPair, type SmugMugPermissionLevel, type SmugMugRequestTokenResult, type SquarespaceClientOptions, type SquarespaceCollectTarget, SquarespaceCollectionClient, WixCollectionClient, WixPageSnapshotCollector, asSmugMugList, buildJsonPrettyUrl, buildSmugMugAuthorizationHeader, buildSmugMugAuthorizeUrl, createSmugMugOAuthSession, getAdapter, getSmugMugAccessToken, getSmugMugRequestToken, mapJsonPrettyWire, parseSmugMugOAuthFormBody, readSmugMugCredentialsFromEnv, resolveSmugMugUriLink, signSmugMugOAuthRequest, smugMugConsumerCredentialsSchema, smugMugCredentialsSchema, smugmugAdapter, squarespaceAdapter, wixAdapter, wordpressAdapter };
668
+ export { MigrationAdapter, MigrationPlatform, SMUGMUG_API_BASE, SMUGMUG_OAUTH_ENDPOINTS, SQUARESPACE_JSON_FORMAT, type SmugMugAccessLevel, SmugMugApiClient, type SmugMugAuthorizeUrlOptions, type SmugMugClientOptions, type SmugMugConsumerCredentials, type SmugMugCredentials, type SmugMugOAuthSession, type SmugMugOAuthSigningMaterial, type SmugMugOAuthTokenPair, type SmugMugPermissionLevel, type SmugMugRequestTokenResult, type SquarespaceClientOptions, type SquarespaceCollectTarget, SquarespaceCollectionClient, WixCollectionClient, WixPageSnapshotCollector, asSmugMugList, buildJsonPrettyUrl, buildSmugMugAuthorizationHeader, buildSmugMugAuthorizeUrl, createSmugMugOAuthSession, extractBlocksFromBodyHtml, extractPageBodyHtml, extractPageContentFromHtml, getAdapter, getSmugMugAccessToken, getSmugMugRequestToken, isEmptyClassicMainContent, isGalleryCollection, mapJsonPrettyWire, pageContentIsEmpty, parseSmugMugOAuthFormBody, readSmugMugCredentialsFromEnv, resolveSmugMugUriLink, signSmugMugOAuthRequest, smugMugConsumerCredentialsSchema, smugMugCredentialsSchema, smugmugAdapter, squarespaceAdapter, wixAdapter, wordpressAdapter };
package/dist/index.js CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  squarespaceAdapter,
22
22
  wixAdapter,
23
23
  wordpressAdapter
24
- } from "./chunk-J3WX7IAS.js";
24
+ } from "./chunk-6UEPTHEU.js";
25
25
  import {
26
26
  normalizedAssetExifSchema,
27
27
  normalizedAssetSchema,
@@ -55,9 +55,15 @@ import {
55
55
  detectRedirectLoops,
56
56
  emptyConflictReport,
57
57
  estimateStorage,
58
+ extractBlocksFromBodyHtml,
59
+ extractPageBodyHtml,
60
+ extractPageContentFromHtml,
58
61
  hasBlockingConflicts,
59
62
  hasWarnings,
63
+ isEmptyClassicMainContent,
64
+ isGalleryCollection,
60
65
  mapJsonPrettyWire,
66
+ pageContentIsEmpty,
61
67
  portfolioMediaMatchesBundle,
62
68
  resolveAdapterImportSummary,
63
69
  runDryRun,
@@ -66,7 +72,7 @@ import {
66
72
  staleUrlsFromEstimate,
67
73
  summarizeAssetDiscovery,
68
74
  writeFilesystemExport
69
- } from "./chunk-H62Y7JAJ.js";
75
+ } from "./chunk-E2EUJY3C.js";
70
76
  import {
71
77
  buildPortfolioMediaLinks,
72
78
  bundleCounts,
@@ -164,7 +170,10 @@ export {
164
170
  entityKey,
165
171
  estimateStorage,
166
172
  expandMigrationMediaRefs,
173
+ extractBlocksFromBodyHtml,
167
174
  extractInlineImageSrcs,
175
+ extractPageBodyHtml,
176
+ extractPageContentFromHtml,
168
177
  formatMigrationMediaRef,
169
178
  getAdapter,
170
179
  getSmugMugAccessToken,
@@ -176,6 +185,8 @@ export {
176
185
  hasWarnings,
177
186
  htmlToGrapes,
178
187
  htmlToTiptap,
188
+ isEmptyClassicMainContent,
189
+ isGalleryCollection,
179
190
  isLikelyContentAssetUrl,
180
191
  isLikelyImageUrl,
181
192
  isLikelyVideoUrl,
@@ -192,6 +203,7 @@ export {
192
203
  normalizedPortfolioSchema,
193
204
  normalizedPostSchema,
194
205
  normalizedTagSchema,
206
+ pageContentIsEmpty,
195
207
  parseMigrationMediaRef,
196
208
  parseSmugMugOAuthFormBody,
197
209
  portfolioMediaMatchesBundle,
@@ -20,7 +20,7 @@ import {
20
20
  staleUrlsFromEstimate,
21
21
  summarizeAssetDiscovery,
22
22
  writeFilesystemExport
23
- } from "../chunk-H62Y7JAJ.js";
23
+ } from "../chunk-E2EUJY3C.js";
24
24
  import "../chunk-PD5AZX3B.js";
25
25
  import {
26
26
  rewriteInlineImages
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@artinstack/migrator",
3
- "version": "0.1.21",
3
+ "version": "0.1.23",
4
4
  "description": "MIT OSS migration framework — WordPress, SmugMug, Squarespace, Wix to portable DTOs. CLI + MigrationSink for any host; also powers import on artinstack.com",
5
5
  "license": "MIT",
6
6
  "author": "ArtInStack",