@x12i/editor 0.0.0-stage → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +361 -3
- package/dist/chunk-FYXMOAJT.js +1890 -0
- package/dist/chunk-FYXMOAJT.js.map +1 -0
- package/dist/index.d.ts +220 -0
- package/dist/index.js +1326 -0
- package/dist/index.js.map +1 -0
- package/dist/outline-Drc3E0C1.d.ts +339 -0
- package/dist/react.d.ts +546 -0
- package/dist/react.js +4439 -0
- package/dist/react.js.map +1 -0
- package/dist/styles.css +1219 -0
- package/package.json +88 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/schema.ts","../src/ids.ts","../src/url.ts","../src/tokens.ts","../src/tiptap-json.ts","../src/convert.ts","../src/emoji.ts","../src/text.ts","../src/outline.ts","../src/html.ts","../src/markdown.ts"],"sourcesContent":["/**\n * The stored document (spec section 11): versioned JSON owned by the kit, with\n * converters to and from the engine's format. That keeps the editor engine\n * (Tiptap by default) replaceable.\n *\n * This module is headless: no React, no DOM, no engine imports.\n */\nimport type { ChartSpec } from \"@x12i/charts\";\nimport type { SavedView } from \"@x12i/data\";\nimport type { DiagramDocument } from \"@x12i/diagrams\";\n\nexport const DOCUMENT_VERSION = 1;\n\n// ---------------------------------------------------------------------------\n// Inline content\n// ---------------------------------------------------------------------------\n\nexport type Mark =\n | { type: \"bold\" }\n | { type: \"italic\" }\n | { type: \"underline\" }\n | { type: \"strike\" }\n | { type: \"code\" }\n | { type: \"link\"; href: string }\n | { type: \"color\"; token: string }\n | { type: \"highlight\"; token: string };\n\nexport type InlineNode =\n | { type: \"text\"; text: string; marks?: Mark[] }\n | { type: \"mention\"; kind: \"person\" | \"page\" | \"date\"; id: string; label: string }\n | { type: \"emoji\"; shortcode: string };\n\nexport type Inline = InlineNode[];\n\n// ---------------------------------------------------------------------------\n// Blocks\n// ---------------------------------------------------------------------------\n\nexport interface BlockBase {\n id: string;\n}\n\nexport type CalloutVariant = \"info\" | \"success\" | \"warning\" | \"danger\" | \"neutral\";\n\nexport interface TaskItem {\n id: string;\n content: Inline;\n checked: boolean;\n children?: TaskItem[];\n}\n\nexport interface ListItem {\n id: string;\n content: Inline;\n children?: ListItem[];\n}\n\nexport interface TableCell {\n content: Inline;\n colSpan?: number;\n rowSpan?: number;\n header?: boolean;\n}\n\nexport type Block = BlockBase &\n (\n | { type: \"paragraph\"; content: Inline }\n | { type: \"heading\"; level: 1 | 2 | 3 | 4; content: Inline }\n | { type: \"quote\"; content: Inline }\n | { type: \"callout\"; variant: CalloutVariant; content: Inline }\n | { type: \"toggle\"; summary: Inline; children: Block[] }\n | { type: \"divider\" }\n | { type: \"bulleted-list\"; items: ListItem[] }\n | { type: \"numbered-list\"; items: ListItem[] }\n | { type: \"task-list\"; items: TaskItem[] }\n | { type: \"code\"; language?: string; code: string }\n | { type: \"equation\"; latex: string }\n | { type: \"table\"; headerRow?: boolean; headerColumn?: boolean; rows: TableCell[][] }\n | { type: \"image\"; src: string; alt: string; caption?: Inline; align?: \"start\" | \"center\" | \"end\"; width?: number }\n | { type: \"video\" | \"audio\"; src: string; caption?: Inline }\n | { type: \"file\"; src: string; name: string; size?: number }\n | { type: \"bookmark\"; url: string; title?: string; description?: string }\n | { type: \"columns\"; columns: Block[][] }\n | { type: \"page-break\" }\n | { type: \"table-of-contents\" }\n // Kit blocks\n | { type: \"chart\"; spec: ChartSpec }\n | { type: \"diagram\"; engine: \"mermaid\" | \"canvas\" | \"excalidraw\"; diagram?: DiagramDocument; source?: string }\n | { type: \"data-view\"; dataset: string; view: SavedView }\n | { type: \"ai\"; prompt: string; result?: Block[] }\n );\n\nexport type BlockType = Block[\"type\"];\n\nexport interface EditorDocument {\n version: typeof DOCUMENT_VERSION;\n title?: string;\n blocks: Block[];\n}\n\n/** An empty document with one empty paragraph. */\nexport function createEmptyDocument(id = \"root\"): EditorDocument {\n return {\n version: DOCUMENT_VERSION,\n blocks: [{ id, type: \"paragraph\", content: [] }],\n };\n}\n\n// ---------------------------------------------------------------------------\n// Optional packages: collaboration and AI assistance\n// ---------------------------------------------------------------------------\n\n/**\n * Shared document model behind a provider interface (Yjs and Hocuspocus\n * planned). This version ships the contract only: there is no presence or\n * cursor implementation.\n */\nexport interface CollaborationProvider {\n connect(documentId: string): Promise<void>;\n disconnect(): void;\n onPresence(listener: (users: Array<{ id: string; name: string; color: string }>) => void): () => void;\n}\n\nexport type AiCommand = \"continue\" | \"summarize\" | \"rewrite\" | \"fix-grammar\";\n\n/** Provider-agnostic hook. The kit calls no model by itself. */\nexport interface AiProvider {\n run(input: {\n command: AiCommand;\n selection: string;\n /** For `rewrite`, for example \"formal\". */\n tone?: string;\n signal?: AbortSignal;\n }): AsyncIterable<string>;\n}\n\n// ---------------------------------------------------------------------------\n// Additive helpers (1.1)\n// ---------------------------------------------------------------------------\n\n/** Every block type the schema knows, in the order the slash menu groups them. */\nexport const BLOCK_TYPES = [\n \"paragraph\",\n \"heading\",\n \"quote\",\n \"callout\",\n \"toggle\",\n \"divider\",\n \"bulleted-list\",\n \"numbered-list\",\n \"task-list\",\n \"code\",\n \"equation\",\n \"table\",\n \"image\",\n \"video\",\n \"audio\",\n \"file\",\n \"bookmark\",\n \"columns\",\n \"page-break\",\n \"table-of-contents\",\n \"chart\",\n \"diagram\",\n \"data-view\",\n \"ai\",\n] as const satisfies readonly BlockType[];\n\n/** Every mark type the schema knows, in canonical (nesting) order. */\nexport const MARK_TYPES = [\n \"bold\",\n \"italic\",\n \"underline\",\n \"strike\",\n \"code\",\n \"link\",\n \"color\",\n \"highlight\",\n] as const satisfies readonly Mark[\"type\"][];\n\nexport const CALLOUT_VARIANTS = [\n \"info\",\n \"success\",\n \"warning\",\n \"danger\",\n \"neutral\",\n] as const satisfies readonly CalloutVariant[];\n\nconst blockTypeSet: ReadonlySet<string> = new Set(BLOCK_TYPES);\n\n/** True when `type` names a block this version of the schema understands. */\nexport function isKnownBlockType(type: unknown): type is BlockType {\n return typeof type === \"string\" && blockTypeSet.has(type);\n}\n\n/** Creates an empty paragraph block. */\nexport function createParagraph(id: string, text = \"\"): Extract<Block, { type: \"paragraph\" }> {\n return {\n id,\n type: \"paragraph\",\n content: text === \"\" ? [] : [{ type: \"text\", text }],\n };\n}\n","/**\n * Block ids. Every block, list item and task item carries a stable id so a\n * diff, a comment anchor or a collaboration layer can refer to it.\n */\nimport type { Block, EditorDocument, ListItem, TaskItem } from \"./schema\";\n\nconst ALPHABET = \"0123456789abcdefghijklmnopqrstuvwxyz\";\nconst ID_LENGTH = 12;\n\n/**\n * A new random block id: 12 lowercase base-36 characters. Uses the Web Crypto\n * API when it exists (browsers, Node 20+, edge runtimes) and falls back to\n * `Math.random`, so it works on the server too.\n */\nexport function generateBlockId(): string {\n const bytes = new Uint8Array(ID_LENGTH);\n const webCrypto = (globalThis as { crypto?: Crypto }).crypto;\n if (webCrypto?.getRandomValues) {\n webCrypto.getRandomValues(bytes);\n } else {\n for (let index = 0; index < ID_LENGTH; index += 1) bytes[index] = Math.floor(Math.random() * 256);\n }\n let id = \"\";\n for (const byte of bytes) id += ALPHABET.charAt(byte % ALPHABET.length);\n return id;\n}\n\n/** A small seeded PRNG (mulberry32). Deterministic across platforms. */\nexport function createSeededRandom(seed: number): () => number {\n let state = seed >>> 0;\n return () => {\n state = (state + 0x6d2b79f5) >>> 0;\n let value = state;\n value = Math.imul(value ^ (value >>> 15), value | 1);\n value ^= value + Math.imul(value ^ (value >>> 7), value | 61);\n return ((value ^ (value >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n/**\n * A deterministic id generator for tests and fixtures: `b1`, `b2`, ... with\n * your own prefix. Never use it for real documents.\n */\nexport function createSequentialIdGenerator(prefix = \"b\", start = 1): () => string {\n let counter = start;\n return () => {\n const id = `${prefix}${counter}`;\n counter += 1;\n return id;\n };\n}\n\nfunction walkListItems(items: ReadonlyArray<ListItem | TaskItem>, visit: (id: string) => void): void {\n for (const item of items) {\n visit(item.id);\n if (item.children) walkListItems(item.children, visit);\n }\n}\n\n/** Calls `visit` for every block, including blocks nested in toggles, columns and AI results. */\nexport function walkBlocks(blocks: readonly Block[], visit: (block: Block, parent: Block | null) => void, parent: Block | null = null): void {\n for (const block of blocks) {\n visit(block, parent);\n switch (block.type) {\n case \"toggle\":\n walkBlocks(block.children ?? [], visit, block);\n break;\n case \"columns\":\n for (const column of block.columns ?? []) walkBlocks(column, visit, block);\n break;\n case \"ai\":\n if (block.result) walkBlocks(block.result, visit, block);\n break;\n default:\n break;\n }\n }\n}\n\n/** Every id in the document: blocks (nested too), list items and task items, in document order. */\nexport function collectIds(doc: EditorDocument): string[] {\n const ids: string[] = [];\n walkBlocks(doc.blocks, (block) => {\n ids.push(block.id);\n if (block.type === \"bulleted-list\" || block.type === \"numbered-list\" || block.type === \"task-list\") {\n walkListItems(block.items ?? [], (id) => ids.push(id));\n }\n });\n return ids;\n}\n\n/** Ids that occur more than once. A healthy document returns an empty array. */\nexport function findDuplicateIds(doc: EditorDocument): string[] {\n const seen = new Set<string>();\n const duplicates = new Set<string>();\n for (const id of collectIds(doc)) {\n if (seen.has(id)) duplicates.add(id);\n seen.add(id);\n }\n return [...duplicates];\n}\n","/**\n * URL safety. Links and media in a stored document come from users, so every\n * renderer runs them through here: http, https, mailto, tel and relative URLs\n * pass; `javascript:`, `vbscript:`, `file:` and `data:` do not, except\n * `data:image/*` for image sources.\n */\n\nexport interface SanitizeUrlOptions {\n /** Allow `data:image/*` URLs. Only set this for image sources, never for links. */\n allowDataImage?: boolean;\n /** Schemes (without the colon) that pass, in lower case. Defaults to http, https, mailto, tel. */\n allowedProtocols?: readonly string[];\n}\n\nconst DEFAULT_PROTOCOLS: readonly string[] = [\"http\", \"https\", \"mailto\", \"tel\"];\n\n// Browsers strip tabs, newlines and other control characters while parsing a\n// URL, so `java\\tscript:alert(1)` is a script URL. Compare on a compacted copy.\n// eslint-disable-next-line no-control-regex\nconst INVISIBLE = /[\\u0000-\\u0020\\u007f-\\u00a0\\u1680\\u180e\\u2000-\\u200f\\u2028-\\u202f\\u205f-\\u2064\\u3000\\ufeff]/g;\nconst SCHEME = /^([a-z][a-z0-9+.-]*):/i;\nconst DATA_IMAGE = /^data:image\\/[a-z0-9.+-]+(?:;[a-z0-9=.+-]+)*,/i;\n\n/**\n * Returns the trimmed URL when it is safe to render, or `null` when it is not.\n * Relative URLs (`/a`, `./a`, `../a`, `a/b`, `#id`, `?q=1`) are safe.\n */\nexport function sanitizeUrl(input: unknown, options: SanitizeUrlOptions = {}): string | null {\n if (typeof input !== \"string\") return null;\n const trimmed = input.trim();\n if (trimmed === \"\") return null;\n\n const compact = trimmed.replace(INVISIBLE, \"\");\n const scheme = SCHEME.exec(compact);\n if (scheme === null) {\n // Scheme-less. A colon inside the first path segment would be read as a\n // scheme by some parsers, but SCHEME already covers that: nothing matched.\n return trimmed;\n }\n\n const protocol = (scheme[1] ?? \"\").toLowerCase();\n if (protocol === \"data\") {\n return options.allowDataImage === true && DATA_IMAGE.test(compact) ? trimmed : null;\n }\n const allowed = options.allowedProtocols ?? DEFAULT_PROTOCOLS;\n return allowed.includes(protocol) ? trimmed : null;\n}\n\n/** True when `sanitizeUrl` accepts the value. */\nexport function isSafeUrl(input: unknown, options?: SanitizeUrlOptions): boolean {\n return sanitizeUrl(input, options) !== null;\n}\n\n/** Sanitizer for image, video and audio sources: also lets `data:image/*` through. */\nexport function sanitizeMediaUrl(input: unknown): string | null {\n return sanitizeUrl(input, { allowDataImage: true });\n}\n\nconst DOMAIN_LIKE = /^(?:[a-z0-9-]+\\.)+[a-z]{2,}(?::\\d+)?(?:[/?#]|$)/i;\nconst EMAIL_LIKE = /^[^\\s@/:]+@[^\\s@/:]+\\.[^\\s@/:]+$/;\n\n/**\n * Turns what a person typed in a link field into a URL: bare domains get\n * `https://`, bare email addresses get `mailto:`. Anything else is returned\n * trimmed. Run the result through `sanitizeUrl` before storing it.\n */\nexport function normalizeUrlInput(input: string): string {\n const trimmed = input.trim();\n if (trimmed === \"\") return \"\";\n if (EMAIL_LIKE.test(trimmed)) return `mailto:${trimmed}`;\n // Checked before the scheme test: `example.com:8080` looks like a scheme to a regular expression.\n if (DOMAIN_LIKE.test(trimmed)) return `https://${trimmed}`;\n return trimmed;\n}\n","/**\n * Color and highlight marks store a token path such as\n * `color.status.danger.foreground`, never a raw color. That keeps stored\n * documents theme-aware (light, dark and high contrast). Only tokens on the\n * allow-lists below render; anything else is ignored, so a stored document\n * cannot inject arbitrary CSS.\n */\nimport type { TokenPath } from \"@x12i/tokens\";\n\n/** Text colors. Foreground tokens are chosen to keep 4.5:1 on the surface in every theme. */\nexport const TEXT_COLOR_TOKENS = [\n \"color.text.secondary\",\n \"color.text.link\",\n \"color.accent.default\",\n \"color.status.success.foreground\",\n \"color.status.warning.foreground\",\n \"color.status.danger.foreground\",\n \"color.status.info.foreground\",\n \"color.chart.categorical.4\",\n] as const satisfies readonly TokenPath[];\n\n/** Highlight (background) colors. Text keeps the primary text color on top of them. */\nexport const HIGHLIGHT_TOKENS = [\n \"color.highlight\",\n \"color.accent.subtle\",\n \"color.status.success.background\",\n \"color.status.warning.background\",\n \"color.status.danger.background\",\n \"color.status.info.background\",\n] as const satisfies readonly TokenPath[];\n\nexport type TextColorToken = (typeof TEXT_COLOR_TOKENS)[number];\nexport type HighlightToken = (typeof HIGHLIGHT_TOKENS)[number];\n\nconst textColorSet: ReadonlySet<string> = new Set(TEXT_COLOR_TOKENS);\nconst highlightSet: ReadonlySet<string> = new Set(HIGHLIGHT_TOKENS);\n\nexport function isTextColorToken(token: unknown): token is TextColorToken {\n return typeof token === \"string\" && textColorSet.has(token);\n}\n\nexport function isHighlightToken(token: unknown): token is HighlightToken {\n return typeof token === \"string\" && highlightSet.has(token);\n}\n\nconst toKebab = (segment: string) => segment.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase();\n\n/** The CSS custom property for a token path, for example `--kit-color-text-link`. */\nexport function tokenToCssVarName(token: string): string {\n return `--kit-${token.split(\".\").map(toKebab).join(\"-\")}`;\n}\n\n/** `var(--kit-...)` for an allowed text color token, or `null` when the token is not on the list. */\nexport function textColorToCss(token: unknown): string | null {\n return isTextColorToken(token) ? `var(${tokenToCssVarName(token)})` : null;\n}\n\n/** `var(--kit-...)` for an allowed highlight token, or `null` when the token is not on the list. */\nexport function highlightToCss(token: unknown): string | null {\n return isHighlightToken(token) ? `var(${tokenToCssVarName(token)})` : null;\n}\n","/**\n * Plain Tiptap / ProseMirror JSON shapes. The converters work on these, so the\n * root entry needs no engine import and runs on the server.\n */\n\nexport interface TiptapMark {\n type: string;\n attrs?: Record<string, unknown>;\n}\n\nexport interface TiptapNode {\n type: string;\n attrs?: Record<string, unknown>;\n content?: TiptapNode[];\n marks?: TiptapMark[];\n text?: string;\n}\n\nexport interface TiptapDoc extends TiptapNode {\n type: \"doc\";\n content: TiptapNode[];\n}\n\n/**\n * Node and mark names of the editor schema. The React entry registers\n * extensions with exactly these names; the converters emit and read them.\n */\nexport const TIPTAP_NODES = {\n doc: \"doc\",\n text: \"text\",\n paragraph: \"paragraph\",\n heading: \"heading\",\n blockquote: \"blockquote\",\n callout: \"callout\",\n toggle: \"toggle\",\n toggleSummary: \"toggleSummary\",\n horizontalRule: \"horizontalRule\",\n bulletList: \"bulletList\",\n orderedList: \"orderedList\",\n listItem: \"listItem\",\n taskList: \"taskList\",\n taskItem: \"taskItem\",\n codeBlock: \"codeBlock\",\n equation: \"equation\",\n table: \"table\",\n tableRow: \"tableRow\",\n tableCell: \"tableCell\",\n tableHeader: \"tableHeader\",\n image: \"image\",\n media: \"media\",\n file: \"file\",\n bookmark: \"bookmark\",\n columns: \"columns\",\n column: \"column\",\n pageBreak: \"pageBreak\",\n tableOfContents: \"tableOfContents\",\n chart: \"chart\",\n diagram: \"diagram\",\n dataView: \"dataView\",\n aiBlock: \"aiBlock\",\n unknownBlock: \"unknownBlock\",\n hardBreak: \"hardBreak\",\n mention: \"mention\",\n emoji: \"emoji\",\n} as const;\n\nexport type TiptapNodeName = (typeof TIPTAP_NODES)[keyof typeof TIPTAP_NODES];\n\nexport const TIPTAP_MARKS = {\n bold: \"bold\",\n italic: \"italic\",\n underline: \"underline\",\n strike: \"strike\",\n code: \"code\",\n link: \"link\",\n color: \"color\",\n highlight: \"highlight\",\n} as const;\n\n/** Nodes that carry a block id attribute in the editor schema. */\nexport const BLOCK_ID_NODES: readonly string[] = [\n TIPTAP_NODES.paragraph,\n TIPTAP_NODES.heading,\n TIPTAP_NODES.blockquote,\n TIPTAP_NODES.callout,\n TIPTAP_NODES.toggle,\n TIPTAP_NODES.horizontalRule,\n TIPTAP_NODES.bulletList,\n TIPTAP_NODES.orderedList,\n TIPTAP_NODES.taskList,\n TIPTAP_NODES.codeBlock,\n TIPTAP_NODES.equation,\n TIPTAP_NODES.table,\n TIPTAP_NODES.image,\n TIPTAP_NODES.media,\n TIPTAP_NODES.file,\n TIPTAP_NODES.bookmark,\n TIPTAP_NODES.columns,\n TIPTAP_NODES.pageBreak,\n TIPTAP_NODES.tableOfContents,\n TIPTAP_NODES.chart,\n TIPTAP_NODES.diagram,\n TIPTAP_NODES.dataView,\n TIPTAP_NODES.aiBlock,\n TIPTAP_NODES.unknownBlock,\n TIPTAP_NODES.listItem,\n TIPTAP_NODES.taskItem,\n];\n","/**\n * Converters between the kit's `EditorDocument` and Tiptap / ProseMirror JSON.\n *\n * Both directions work on plain JSON, so they run anywhere. The mapping is\n * lossless for every block and mark in the schema, with these documented\n * canonical forms (a document that already uses them round-trips unchanged;\n * `normalizeDocument` rewrites any document into them):\n *\n * - Adjacent text with identical marks is merged; empty text is dropped.\n * - Marks are sorted into canonical order (see `MARK_TYPES`) and de-duplicated.\n * - A line break inside text is the character `\"\\n\"` (a `hardBreak` in Tiptap).\n * - Table spans of 1 are omitted; a table with no rows gets one empty cell.\n * - A full header row or column of explicit `header: true` cells folds into\n * `headerRow` / `headerColumn` when the flag was not set.\n * - Containers that the editor needs to be non-empty (a document, a list, a\n * column) get one empty paragraph or item when they are empty.\n * - Several paragraphs inside one quote, callout, list item or table cell are\n * joined with `\"\\n\"`, because the schema stores one inline run there.\n * - Nested lists take the type of their parent list.\n * - Blocks of an unknown type survive as opaque atoms and are flagged.\n */\nimport { generateBlockId } from \"./ids\";\nimport { sanitizeMediaUrl, sanitizeUrl } from \"./url\";\nimport {\n CALLOUT_VARIANTS,\n DOCUMENT_VERSION,\n MARK_TYPES,\n type Block,\n type CalloutVariant,\n type EditorDocument,\n type Inline,\n type InlineNode,\n type ListItem,\n type Mark,\n type TableCell,\n type TaskItem,\n} from \"./schema\";\nimport {\n TIPTAP_MARKS,\n TIPTAP_NODES,\n type TiptapDoc,\n type TiptapMark,\n type TiptapNode,\n} from \"./tiptap-json\";\n\n// ---------------------------------------------------------------------------\n// Options and warnings\n// ---------------------------------------------------------------------------\n\nexport type ConversionWarningCode =\n | \"unknown-block\"\n | \"unknown-node\"\n | \"unknown-mark\"\n | \"unknown-inline\"\n | \"invalid-mark\"\n | \"invalid-value\"\n | \"duplicate-id\"\n | \"lossy\";\n\nexport interface ConversionWarning {\n code: ConversionWarningCode;\n message: string;\n /** Id of the block the warning is about, when known. */\n blockId?: string;\n /** Block type or node name the warning is about. */\n nodeType?: string;\n}\n\nexport interface ConvertOptions {\n /** Receives warnings (unknown blocks and marks, lossy structures). */\n warnings?: ConversionWarning[];\n /** Creates ids for blocks that have none. Defaults to `generateBlockId`. */\n generateId?: () => string;\n}\n\ninterface Context {\n warnings: ConversionWarning[] | undefined;\n generateId: () => string;\n seenIds: Set<string>;\n}\n\nfunction createContext(options: ConvertOptions | undefined): Context {\n return {\n warnings: options?.warnings,\n generateId: options?.generateId ?? generateBlockId,\n seenIds: new Set(),\n };\n}\n\nfunction warn(\n ctx: Context,\n code: ConversionWarningCode,\n message: string,\n extra: { blockId?: string | undefined; nodeType?: string | undefined } = {},\n): void {\n if (!ctx.warnings) return;\n const warning: ConversionWarning = { code, message };\n if (extra.blockId !== undefined) warning.blockId = extra.blockId;\n if (extra.nodeType !== undefined) warning.nodeType = extra.nodeType;\n ctx.warnings.push(warning);\n}\n\n// ---------------------------------------------------------------------------\n// Small helpers\n// ---------------------------------------------------------------------------\n\ntype Json = Record<string, unknown>;\n\nfunction isRecord(value: unknown): value is Json {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction str(value: unknown, fallback = \"\"): string {\n return typeof value === \"string\" ? value : fallback;\n}\n\nfunction optionalString(value: unknown): string | undefined {\n return typeof value === \"string\" ? value : undefined;\n}\n\n/** A URL that is safe to store: unsafe values become an empty string and are reported. */\nfunction safeUrl(value: unknown, ctx: Context, media: boolean): string {\n const url = str(value);\n if (url === \"\") return \"\";\n const safe = media ? sanitizeMediaUrl(url) : sanitizeUrl(url);\n if (safe === null) {\n warn(ctx, \"invalid-value\", \"An unsafe URL was replaced by an empty value.\");\n return \"\";\n }\n return url;\n}\n\nfunction optionalNumber(value: unknown): number | undefined {\n return typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n}\n\n/** Deep copy through JSON. Also drops `undefined` properties, which the schema treats as absent. */\nfunction cloneJson<T>(value: T): T {\n return JSON.parse(JSON.stringify(value)) as T;\n}\n\nfunction nullable<T>(value: T | undefined): T | null {\n return value === undefined ? null : value;\n}\n\nfunction node(type: string, attrs?: Json, content?: TiptapNode[]): TiptapNode {\n const result: TiptapNode = { type };\n if (attrs !== undefined) result.attrs = attrs;\n if (content !== undefined && content.length > 0) result.content = content;\n return result;\n}\n\nconst markOrder = new Map<string, number>(MARK_TYPES.map((type, index) => [type, index]));\n\n// ---------------------------------------------------------------------------\n// Inline: document -> Tiptap\n// ---------------------------------------------------------------------------\n\nfunction markToTiptap(mark: Mark, ctx: Context): TiptapMark | null {\n switch (mark.type) {\n case \"bold\":\n case \"italic\":\n case \"underline\":\n case \"strike\":\n case \"code\":\n return { type: mark.type };\n case \"link\":\n if (typeof mark.href !== \"string\" || mark.href === \"\") {\n warn(ctx, \"invalid-mark\", \"A link mark without an href was dropped.\", { nodeType: \"link\" });\n return null;\n }\n if (sanitizeUrl(mark.href) === null) {\n warn(ctx, \"invalid-mark\", \"A link with an unsafe URL was dropped.\", { nodeType: \"link\" });\n return null;\n }\n return { type: TIPTAP_MARKS.link, attrs: { href: mark.href } };\n case \"color\":\n case \"highlight\":\n if (typeof mark.token !== \"string\" || mark.token === \"\") {\n warn(ctx, \"invalid-mark\", `A ${mark.type} mark without a token was dropped.`, { nodeType: mark.type });\n return null;\n }\n return { type: mark.type, attrs: { token: mark.token } };\n default: {\n const unknown = mark as { type?: unknown };\n warn(ctx, \"unknown-mark\", `The mark \"${String(unknown.type)}\" is not supported and was dropped.`, {\n nodeType: String(unknown.type),\n });\n return null;\n }\n }\n}\n\nfunction sortMarks(marks: TiptapMark[]): TiptapMark[] {\n const seen = new Set<string>();\n const unique = marks.filter((mark) => {\n if (seen.has(mark.type)) return false;\n seen.add(mark.type);\n return true;\n });\n return unique\n .map((mark, index) => ({ mark, index }))\n .sort((a, b) => (markOrder.get(a.mark.type) ?? 99) - (markOrder.get(b.mark.type) ?? 99) || a.index - b.index)\n .map((entry) => entry.mark);\n}\n\nfunction marksToTiptap(marks: readonly Mark[] | undefined, ctx: Context): TiptapMark[] | undefined {\n if (!marks || marks.length === 0) return undefined;\n const converted: TiptapMark[] = [];\n for (const mark of marks) {\n const result = markToTiptap(mark, ctx);\n if (result) converted.push(result);\n }\n const sorted = sortMarks(converted);\n return sorted.length > 0 ? sorted : undefined;\n}\n\nfunction withMarks(base: TiptapNode, marks: TiptapMark[] | undefined): TiptapNode {\n if (marks) base.marks = marks.map((mark) => ({ ...mark, ...(mark.attrs ? { attrs: { ...mark.attrs } } : {}) }));\n return base;\n}\n\nfunction inlineToTiptap(inline: Inline | undefined, ctx: Context): TiptapNode[] {\n const out: TiptapNode[] = [];\n for (const item of inline ?? []) {\n if (!isRecord(item)) continue;\n switch (item.type) {\n case \"text\": {\n const marks = marksToTiptap(item.marks, ctx);\n const parts = str(item.text).split(\"\\n\");\n parts.forEach((part, index) => {\n if (index > 0) out.push(withMarks({ type: TIPTAP_NODES.hardBreak }, marks));\n if (part !== \"\") out.push(withMarks({ type: TIPTAP_NODES.text, text: part }, marks));\n });\n break;\n }\n case \"mention\":\n out.push({\n type: TIPTAP_NODES.mention,\n attrs: { kind: str(item.kind, \"person\"), id: str(item.id), label: str(item.label) },\n });\n break;\n case \"emoji\":\n out.push({ type: TIPTAP_NODES.emoji, attrs: { shortcode: str(item.shortcode) } });\n break;\n default:\n warn(ctx, \"unknown-inline\", `The inline node \"${String((item as { type?: unknown }).type)}\" was dropped.`);\n }\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Inline: Tiptap -> document\n// ---------------------------------------------------------------------------\n\nfunction marksFromTiptap(marks: readonly TiptapMark[] | undefined, ctx: Context): Mark[] {\n if (!marks || marks.length === 0) return [];\n const converted: TiptapMark[] = [];\n for (const mark of marks) {\n if (!isRecord(mark)) continue;\n switch (mark.type) {\n case \"bold\":\n case \"italic\":\n case \"underline\":\n case \"strike\":\n case \"code\":\n converted.push({ type: mark.type });\n break;\n case \"link\": {\n const href = optionalString(mark.attrs?.href);\n if (href === undefined || href === \"\") {\n warn(ctx, \"invalid-mark\", \"A link mark without an href was dropped.\", { nodeType: \"link\" });\n } else if (sanitizeUrl(href) === null) {\n warn(ctx, \"invalid-mark\", \"A link with an unsafe URL was dropped.\", { nodeType: \"link\" });\n } else {\n converted.push({ type: \"link\", attrs: { href } });\n }\n break;\n }\n case \"color\":\n case \"highlight\": {\n const token = optionalString(mark.attrs?.token);\n if (token === undefined || token === \"\") {\n warn(ctx, \"invalid-mark\", `A ${mark.type} mark without a token path was dropped.`, { nodeType: mark.type });\n } else {\n converted.push({ type: mark.type, attrs: { token } });\n }\n break;\n }\n default:\n warn(ctx, \"unknown-mark\", `The mark \"${String(mark.type)}\" is not supported and was dropped.`, {\n nodeType: String(mark.type),\n });\n }\n }\n return sortMarks(converted).map((mark): Mark => {\n switch (mark.type) {\n case \"link\":\n return { type: \"link\", href: str(mark.attrs?.href) };\n case \"color\":\n return { type: \"color\", token: str(mark.attrs?.token) };\n case \"highlight\":\n return { type: \"highlight\", token: str(mark.attrs?.token) };\n default:\n return { type: mark.type } as Mark;\n }\n });\n}\n\nfunction marksEqual(a: readonly Mark[] | undefined, b: readonly Mark[]): boolean {\n const left = a ?? [];\n if (left.length !== b.length) return false;\n return left.every((mark, index) => JSON.stringify(mark) === JSON.stringify(b[index]));\n}\n\nconst MENTION_KINDS = [\"person\", \"page\", \"date\"] as const;\n\nfunction inlineFromTiptap(nodes: readonly TiptapNode[] | undefined, ctx: Context): Inline {\n const out: InlineNode[] = [];\n const pushText = (text: string, marks: Mark[]) => {\n if (text === \"\") return;\n const last = out[out.length - 1];\n if (last && last.type === \"text\" && marksEqual(last.marks, marks)) {\n last.text += text;\n } else {\n out.push(marks.length > 0 ? { type: \"text\", text, marks } : { type: \"text\", text });\n }\n };\n\n for (const item of nodes ?? []) {\n if (!isRecord(item)) continue;\n switch (item.type) {\n case TIPTAP_NODES.text:\n pushText(str(item.text), marksFromTiptap(item.marks, ctx));\n break;\n case TIPTAP_NODES.hardBreak:\n pushText(\"\\n\", marksFromTiptap(item.marks, ctx));\n break;\n case TIPTAP_NODES.mention: {\n const kind = MENTION_KINDS.find((candidate) => candidate === item.attrs?.kind) ?? \"person\";\n out.push({ type: \"mention\", kind, id: str(item.attrs?.id), label: str(item.attrs?.label) });\n break;\n }\n case TIPTAP_NODES.emoji:\n out.push({ type: \"emoji\", shortcode: str(item.attrs?.shortcode) });\n break;\n default:\n // An inline node we do not know (for example an inline image from\n // another schema): keep its text, flag the rest.\n warn(ctx, \"unknown-inline\", `The inline node \"${item.type}\" was dropped.`, { nodeType: item.type });\n if (typeof item.text === \"string\") pushText(item.text, marksFromTiptap(item.marks, ctx));\n }\n }\n return out;\n}\n\n/**\n * Rewrites inline content into canonical form: no empty text, adjacent text\n * with equal marks merged, marks sorted and de-duplicated.\n */\nexport function normalizeInline(inline: Inline | undefined): Inline {\n const ctx = createContext(undefined);\n return inlineFromTiptap(inlineToTiptap(inline, ctx), ctx);\n}\n\nfunction joinInlines(parts: Inline[]): Inline {\n const joined: Inline = [];\n parts.forEach((part, index) => {\n if (index > 0) joined.push({ type: \"text\", text: \"\\n\" });\n joined.push(...part);\n });\n return joined;\n}\n\nfunction plainTextOf(tiptapNode: TiptapNode): string {\n if (typeof tiptapNode.text === \"string\") return tiptapNode.text;\n if (tiptapNode.type === TIPTAP_NODES.hardBreak) return \"\\n\";\n const children = tiptapNode.content ?? [];\n const separator = children.some((child) => !(child.type === TIPTAP_NODES.text || child.type === TIPTAP_NODES.hardBreak))\n ? \"\\n\"\n : \"\";\n return children.map(plainTextOf).join(separator);\n}\n\n// ---------------------------------------------------------------------------\n// Blocks: document -> Tiptap\n// ---------------------------------------------------------------------------\n\nconst EMPTY_PARAGRAPH = (): TiptapNode => ({ type: TIPTAP_NODES.paragraph });\n\nfunction paragraphOf(inline: Inline | undefined, ctx: Context): TiptapNode {\n return node(TIPTAP_NODES.paragraph, undefined, inlineToTiptap(inline, ctx));\n}\n\nfunction listItemToTiptap(\n item: ListItem | TaskItem,\n listType: string,\n itemType: string,\n ctx: Context,\n): TiptapNode {\n const attrs: Json = { id: item.id };\n if (itemType === TIPTAP_NODES.taskItem) attrs.checked = (item as TaskItem).checked === true;\n const content: TiptapNode[] = [paragraphOf(item.content, ctx)];\n if (item.children && item.children.length > 0) {\n content.push(\n node(\n listType,\n undefined,\n item.children.map((child) => listItemToTiptap(child, listType, itemType, ctx)),\n ),\n );\n }\n return node(itemType, attrs, content);\n}\n\nfunction listToTiptap(\n block: { id: string; items: Array<ListItem | TaskItem> },\n listType: string,\n itemType: string,\n ctx: Context,\n): TiptapNode {\n const items = block.items && block.items.length > 0 ? block.items : [{ id: ctx.generateId(), content: [] }];\n return node(\n listType,\n { id: block.id },\n items.map((item) => listItemToTiptap(item, listType, itemType, ctx)),\n );\n}\n\nfunction blocksToTiptap(blocks: readonly Block[] | undefined, ctx: Context): TiptapNode[] {\n return (blocks ?? []).map((block) => blockToTiptap(block, ctx));\n}\n\nfunction blockToTiptap(block: Block, ctx: Context): TiptapNode {\n const id = block.id;\n switch (block.type) {\n case \"paragraph\":\n return node(TIPTAP_NODES.paragraph, { id }, inlineToTiptap(block.content, ctx));\n case \"heading\":\n return node(TIPTAP_NODES.heading, { id, level: block.level }, inlineToTiptap(block.content, ctx));\n case \"quote\":\n return node(TIPTAP_NODES.blockquote, { id }, [paragraphOf(block.content, ctx)]);\n case \"callout\":\n return node(TIPTAP_NODES.callout, { id, variant: block.variant }, inlineToTiptap(block.content, ctx));\n case \"toggle\":\n return node(TIPTAP_NODES.toggle, { id }, [\n node(TIPTAP_NODES.toggleSummary, undefined, inlineToTiptap(block.summary, ctx)),\n ...blocksToTiptap(block.children, ctx),\n ]);\n case \"divider\":\n return node(TIPTAP_NODES.horizontalRule, { id });\n case \"bulleted-list\":\n return listToTiptap(block, TIPTAP_NODES.bulletList, TIPTAP_NODES.listItem, ctx);\n case \"numbered-list\":\n return listToTiptap(block, TIPTAP_NODES.orderedList, TIPTAP_NODES.listItem, ctx);\n case \"task-list\":\n return listToTiptap(block, TIPTAP_NODES.taskList, TIPTAP_NODES.taskItem, ctx);\n case \"code\":\n return node(\n TIPTAP_NODES.codeBlock,\n { id, language: nullable(block.language) },\n block.code ? [{ type: TIPTAP_NODES.text, text: block.code }] : [],\n );\n case \"equation\":\n return node(\n TIPTAP_NODES.equation,\n { id },\n block.latex ? [{ type: TIPTAP_NODES.text, text: block.latex }] : [],\n );\n case \"table\":\n return tableToTiptap(block, ctx);\n case \"image\":\n return {\n type: TIPTAP_NODES.image,\n attrs: {\n id,\n src: block.src,\n alt: block.alt ?? \"\",\n caption: block.caption === undefined ? null : normalizeInline(block.caption),\n align: nullable(block.align),\n width: nullable(block.width),\n },\n };\n case \"video\":\n case \"audio\":\n return {\n type: TIPTAP_NODES.media,\n attrs: {\n id,\n kind: block.type,\n src: block.src,\n caption: block.caption === undefined ? null : normalizeInline(block.caption),\n },\n };\n case \"file\":\n return { type: TIPTAP_NODES.file, attrs: { id, src: block.src, name: block.name, size: nullable(block.size) } };\n case \"bookmark\":\n return {\n type: TIPTAP_NODES.bookmark,\n attrs: { id, url: block.url, title: nullable(block.title), description: nullable(block.description) },\n };\n case \"columns\": {\n const columns = block.columns && block.columns.length > 0 ? block.columns : [[]];\n return node(\n TIPTAP_NODES.columns,\n { id },\n columns.map((column) => {\n const content = blocksToTiptap(column, ctx);\n return node(TIPTAP_NODES.column, undefined, content.length > 0 ? content : [EMPTY_PARAGRAPH()]);\n }),\n );\n }\n case \"page-break\":\n return { type: TIPTAP_NODES.pageBreak, attrs: { id } };\n case \"table-of-contents\":\n return { type: TIPTAP_NODES.tableOfContents, attrs: { id } };\n case \"chart\":\n return { type: TIPTAP_NODES.chart, attrs: { id, spec: cloneJson(block.spec) } };\n case \"diagram\":\n return {\n type: TIPTAP_NODES.diagram,\n attrs: {\n id,\n engine: block.engine,\n diagram: block.diagram === undefined ? null : cloneJson(block.diagram),\n source: nullable(block.source),\n },\n };\n case \"data-view\":\n return { type: TIPTAP_NODES.dataView, attrs: { id, dataset: block.dataset, view: cloneJson(block.view) } };\n case \"ai\":\n return {\n type: TIPTAP_NODES.aiBlock,\n attrs: { id, prompt: block.prompt, result: block.result === undefined ? null : cloneJson(block.result) },\n };\n default: {\n const unknown = block as unknown as Json;\n const blockType = String(unknown.type);\n const blockId = optionalString(unknown.id);\n warn(ctx, \"unknown-block\", `The block type \"${blockType}\" is not supported; it is kept as an opaque block.`, {\n blockId,\n nodeType: blockType,\n });\n return {\n type: TIPTAP_NODES.unknownBlock,\n attrs: { id: nullable(blockId), blockType, payload: cloneJson(unknown) },\n };\n }\n }\n}\n\nfunction tableToTiptap(block: Extract<Block, { type: \"table\" }>, ctx: Context): TiptapNode {\n const rows: TableCell[][] = block.rows && block.rows.length > 0 ? block.rows : [[{ content: [] }]];\n const headerRow = block.headerRow;\n const headerColumn = block.headerColumn;\n return node(\n TIPTAP_NODES.table,\n { id: block.id, headerRow: nullable(headerRow), headerColumn: nullable(headerColumn) },\n rows.map((row, rowIndex) =>\n node(\n TIPTAP_NODES.tableRow,\n undefined,\n row.map((cell, columnIndex) => {\n const isHeader =\n cell.header === true ||\n (headerRow === true && rowIndex === 0) ||\n (headerColumn === true && columnIndex === 0);\n return node(\n isHeader ? TIPTAP_NODES.tableHeader : TIPTAP_NODES.tableCell,\n { colspan: cell.colSpan ?? 1, rowspan: cell.rowSpan ?? 1, colwidth: null },\n [paragraphOf(cell.content, ctx)],\n );\n }),\n ),\n ),\n );\n}\n\n// ---------------------------------------------------------------------------\n// Blocks: Tiptap -> document\n// ---------------------------------------------------------------------------\n\nfunction readId(source: TiptapNode, ctx: Context): string {\n const candidate = source.attrs?.id;\n let id = typeof candidate === \"string\" && candidate !== \"\" ? candidate : \"\";\n if (id !== \"\" && ctx.seenIds.has(id)) {\n warn(ctx, \"duplicate-id\", `The id \"${id}\" was used twice; the second block got a new id.`, {\n blockId: id,\n nodeType: source.type,\n });\n id = \"\";\n }\n if (id === \"\") {\n do {\n id = ctx.generateId();\n } while (ctx.seenIds.has(id));\n }\n ctx.seenIds.add(id);\n return id;\n}\n\n/** The inline run of a text container (paragraph, heading, callout, ...). */\nfunction inlineOfTextblock(textblock: TiptapNode, ctx: Context): Inline {\n return inlineFromTiptap(textblock.content, ctx);\n}\n\n/** Joins the text of several paragraph-like children into one inline run. */\nfunction inlineOfContainer(container: TiptapNode, ctx: Context, extraBlocks?: Block[]): Inline {\n const runs: Inline[] = [];\n for (const child of container.content ?? []) {\n if (child.type === TIPTAP_NODES.paragraph || child.type === TIPTAP_NODES.heading) {\n runs.push(inlineOfTextblock(child, ctx));\n } else if (extraBlocks) {\n blockFromTiptap(child, ctx, extraBlocks);\n } else {\n const text = plainTextOf(child);\n warn(ctx, \"lossy\", `A \"${child.type}\" inside a ${container.type} was reduced to plain text.`, {\n nodeType: child.type,\n });\n if (text !== \"\") runs.push([{ type: \"text\", text }]);\n }\n }\n return normalizeInline(joinInlines(runs));\n}\n\ntype ListLike = ListItem | TaskItem;\n\nfunction listItemFromTiptap(\n source: TiptapNode,\n parentListType: string,\n isTask: boolean,\n ctx: Context,\n): ListLike {\n const id = readId(source, ctx);\n const runs: Inline[] = [];\n const children: ListLike[] = [];\n\n for (const child of source.content ?? []) {\n if (child.type === TIPTAP_NODES.paragraph) {\n runs.push(inlineOfTextblock(child, ctx));\n } else if (\n child.type === TIPTAP_NODES.bulletList ||\n child.type === TIPTAP_NODES.orderedList ||\n child.type === TIPTAP_NODES.taskList\n ) {\n if (child.type !== parentListType) {\n warn(ctx, \"lossy\", `A nested ${child.type} inside a ${parentListType} took the type of its parent list.`, {\n nodeType: child.type,\n });\n }\n for (const nested of child.content ?? []) {\n if (nested.type === TIPTAP_NODES.listItem || nested.type === TIPTAP_NODES.taskItem) {\n children.push(listItemFromTiptap(nested, parentListType, isTask, ctx));\n }\n }\n } else {\n const text = plainTextOf(child);\n warn(ctx, \"lossy\", `A \"${child.type}\" inside a list item was reduced to plain text.`, { nodeType: child.type });\n if (text !== \"\") runs.push([{ type: \"text\", text }]);\n }\n }\n\n const content = normalizeInline(joinInlines(runs));\n const result: ListLike = isTask\n ? { id, content, checked: source.attrs?.checked === true }\n : { id, content };\n if (children.length > 0) result.children = children as never;\n return result;\n}\n\nfunction listFromTiptap(\n source: TiptapNode,\n type: \"bulleted-list\" | \"numbered-list\" | \"task-list\",\n ctx: Context,\n): Block {\n const id = readId(source, ctx);\n const isTask = type === \"task-list\";\n const items: ListLike[] = [];\n for (const child of source.content ?? []) {\n if (child.type === TIPTAP_NODES.listItem || child.type === TIPTAP_NODES.taskItem) {\n items.push(listItemFromTiptap(child, source.type, isTask, ctx));\n }\n }\n return { id, type, items } as Block;\n}\n\nconst HEADER_ATTR_VALUES = [true, false] as const;\n\nfunction readHint(value: unknown): boolean | null {\n return HEADER_ATTR_VALUES.find((candidate) => candidate === value) ?? null;\n}\n\nfunction resolveHeaderFlag(hint: boolean | null, allHeader: boolean, ambiguous: boolean): boolean | undefined {\n if (hint === true) return allHeader;\n if (hint === false) return false;\n return allHeader && !ambiguous ? true : undefined;\n}\n\nfunction tableFromTiptap(source: TiptapNode, ctx: Context): Block {\n const id = readId(source, ctx);\n const rowNodes = (source.content ?? []).filter((row) => row.type === TIPTAP_NODES.tableRow);\n const grid = rowNodes.map((row) =>\n (row.content ?? []).filter(\n (cell) => cell.type === TIPTAP_NODES.tableCell || cell.type === TIPTAP_NODES.tableHeader,\n ),\n );\n\n const isHeader = (cell: TiptapNode) => cell.type === TIPTAP_NODES.tableHeader;\n const firstRow = grid[0] ?? [];\n const rowAll = firstRow.length > 0 && firstRow.every(isHeader);\n const columnAll = grid.length > 0 && grid.every((row) => row.length > 0 && isHeader(row[0] as TiptapNode));\n\n const headerRow = resolveHeaderFlag(\n readHint(source.attrs?.headerRow),\n rowAll,\n firstRow.length === 1 && columnAll,\n );\n const headerColumn = resolveHeaderFlag(\n readHint(source.attrs?.headerColumn),\n columnAll,\n grid.length === 1 && rowAll,\n );\n\n const rows: TableCell[][] = grid.map((row, rowIndex) =>\n row.map((cellNode, columnIndex) => {\n const cell: TableCell = { content: inlineOfContainer(cellNode, ctx) };\n const colSpan = optionalNumber(cellNode.attrs?.colspan);\n const rowSpan = optionalNumber(cellNode.attrs?.rowspan);\n if (colSpan !== undefined && colSpan > 1) cell.colSpan = colSpan;\n if (rowSpan !== undefined && rowSpan > 1) cell.rowSpan = rowSpan;\n const coveredByRow = headerRow === true && rowIndex === 0;\n const coveredByColumn = headerColumn === true && columnIndex === 0;\n if (isHeader(cellNode) && !coveredByRow && !coveredByColumn) cell.header = true;\n return cell;\n }),\n );\n if (rows.length === 0) rows.push([{ content: [] }]);\n\n const block: Extract<Block, { type: \"table\" }> = { id, type: \"table\", rows };\n if (headerRow !== undefined) block.headerRow = headerRow;\n if (headerColumn !== undefined) block.headerColumn = headerColumn;\n return block;\n}\n\nfunction codeTextOf(source: TiptapNode): string {\n return (source.content ?? []).map((child) => (child.type === TIPTAP_NODES.hardBreak ? \"\\n\" : str(child.text))).join(\"\");\n}\n\nfunction captionOf(value: unknown, ctx: Context): Inline | undefined {\n if (!Array.isArray(value)) return undefined;\n const inline = inlineFromTiptap(inlineToTiptap(value as Inline, ctx), ctx);\n return inline;\n}\n\nconst ALIGNMENTS = [\"start\", \"center\", \"end\"] as const;\nconst DIAGRAM_ENGINES = [\"mermaid\", \"canvas\", \"excalidraw\"] as const;\n\nfunction blockFromTiptap(source: TiptapNode, ctx: Context, out: Block[]): void {\n if (!isRecord(source)) return;\n switch (source.type) {\n case TIPTAP_NODES.paragraph:\n out.push({ id: readId(source, ctx), type: \"paragraph\", content: inlineOfTextblock(source, ctx) });\n return;\n case TIPTAP_NODES.heading: {\n const id = readId(source, ctx);\n const raw = optionalNumber(source.attrs?.level) ?? 1;\n const level = Math.min(4, Math.max(1, Math.round(raw))) as 1 | 2 | 3 | 4;\n if (level !== raw) {\n warn(ctx, \"invalid-value\", `Heading level ${raw} was clamped to ${level}.`, { blockId: id, nodeType: \"heading\" });\n }\n out.push({ id, type: \"heading\", level, content: inlineOfTextblock(source, ctx) });\n return;\n }\n case TIPTAP_NODES.blockquote: {\n const id = readId(source, ctx);\n const trailing: Block[] = [];\n const content = inlineOfContainer(source, ctx, trailing);\n const hasText = (source.content ?? []).some(\n (child) => child.type === TIPTAP_NODES.paragraph || child.type === TIPTAP_NODES.heading,\n );\n if (hasText || trailing.length === 0) out.push({ id, type: \"quote\", content });\n out.push(...trailing);\n return;\n }\n case TIPTAP_NODES.callout: {\n const id = readId(source, ctx);\n const raw = source.attrs?.variant;\n const variant: CalloutVariant = CALLOUT_VARIANTS.find((candidate) => candidate === raw) ?? \"info\";\n if (variant !== raw) {\n warn(ctx, \"invalid-value\", `Callout variant \"${String(raw)}\" became \"info\".`, { blockId: id, nodeType: \"callout\" });\n }\n out.push({ id, type: \"callout\", variant, content: inlineOfTextblock(source, ctx) });\n return;\n }\n case TIPTAP_NODES.toggle: {\n const id = readId(source, ctx);\n const [first, ...rest] = source.content ?? [];\n const hasSummary = first?.type === TIPTAP_NODES.toggleSummary;\n const children: Block[] = [];\n for (const child of hasSummary ? rest : (source.content ?? [])) blockFromTiptap(child, ctx, children);\n out.push({\n id,\n type: \"toggle\",\n summary: hasSummary && first ? inlineOfTextblock(first, ctx) : [],\n children,\n });\n return;\n }\n case TIPTAP_NODES.horizontalRule:\n out.push({ id: readId(source, ctx), type: \"divider\" });\n return;\n case TIPTAP_NODES.bulletList:\n out.push(listFromTiptap(source, \"bulleted-list\", ctx));\n return;\n case TIPTAP_NODES.orderedList:\n out.push(listFromTiptap(source, \"numbered-list\", ctx));\n return;\n case TIPTAP_NODES.taskList:\n out.push(listFromTiptap(source, \"task-list\", ctx));\n return;\n case TIPTAP_NODES.codeBlock: {\n const block: Extract<Block, { type: \"code\" }> = {\n id: readId(source, ctx),\n type: \"code\",\n code: codeTextOf(source),\n };\n const language = optionalString(source.attrs?.language);\n if (language !== undefined) block.language = language;\n out.push(block);\n return;\n }\n case TIPTAP_NODES.equation:\n out.push({ id: readId(source, ctx), type: \"equation\", latex: codeTextOf(source) });\n return;\n case TIPTAP_NODES.table:\n out.push(tableFromTiptap(source, ctx));\n return;\n case TIPTAP_NODES.image: {\n const block: Extract<Block, { type: \"image\" }> = {\n id: readId(source, ctx),\n type: \"image\",\n src: safeUrl(source.attrs?.src, ctx, true),\n alt: str(source.attrs?.alt),\n };\n const caption = captionOf(source.attrs?.caption, ctx);\n if (caption !== undefined) block.caption = caption;\n const align = ALIGNMENTS.find((candidate) => candidate === source.attrs?.align);\n if (align !== undefined) block.align = align;\n const width = optionalNumber(source.attrs?.width);\n if (width !== undefined) block.width = width;\n out.push(block);\n return;\n }\n case TIPTAP_NODES.media: {\n const block: Extract<Block, { type: \"video\" | \"audio\" }> = {\n id: readId(source, ctx),\n type: source.attrs?.kind === \"audio\" ? \"audio\" : \"video\",\n src: safeUrl(source.attrs?.src, ctx, true),\n };\n const caption = captionOf(source.attrs?.caption, ctx);\n if (caption !== undefined) block.caption = caption;\n out.push(block);\n return;\n }\n case TIPTAP_NODES.file: {\n const block: Extract<Block, { type: \"file\" }> = {\n id: readId(source, ctx),\n type: \"file\",\n src: safeUrl(source.attrs?.src, ctx, false),\n name: str(source.attrs?.name),\n };\n const size = optionalNumber(source.attrs?.size);\n if (size !== undefined) block.size = size;\n out.push(block);\n return;\n }\n case TIPTAP_NODES.bookmark: {\n const block: Extract<Block, { type: \"bookmark\" }> = {\n id: readId(source, ctx),\n type: \"bookmark\",\n url: safeUrl(source.attrs?.url, ctx, false),\n };\n const title = optionalString(source.attrs?.title);\n const description = optionalString(source.attrs?.description);\n if (title !== undefined) block.title = title;\n if (description !== undefined) block.description = description;\n out.push(block);\n return;\n }\n case TIPTAP_NODES.columns: {\n const id = readId(source, ctx);\n const columns: Block[][] = [];\n for (const column of source.content ?? []) {\n if (column.type !== TIPTAP_NODES.column) continue;\n const blocks: Block[] = [];\n for (const child of column.content ?? []) blockFromTiptap(child, ctx, blocks);\n columns.push(blocks);\n }\n out.push({ id, type: \"columns\", columns });\n return;\n }\n case TIPTAP_NODES.pageBreak:\n out.push({ id: readId(source, ctx), type: \"page-break\" });\n return;\n case TIPTAP_NODES.tableOfContents:\n out.push({ id: readId(source, ctx), type: \"table-of-contents\" });\n return;\n case TIPTAP_NODES.chart:\n out.push({\n id: readId(source, ctx),\n type: \"chart\",\n spec: cloneJson(source.attrs?.spec) as never,\n });\n return;\n case TIPTAP_NODES.diagram: {\n const block: Extract<Block, { type: \"diagram\" }> = {\n id: readId(source, ctx),\n type: \"diagram\",\n engine: DIAGRAM_ENGINES.find((candidate) => candidate === source.attrs?.engine) ?? \"mermaid\",\n };\n if (isRecord(source.attrs?.diagram)) block.diagram = cloneJson(source.attrs?.diagram) as never;\n const diagramSource = optionalString(source.attrs?.source);\n if (diagramSource !== undefined) block.source = diagramSource;\n out.push(block);\n return;\n }\n case TIPTAP_NODES.dataView:\n out.push({\n id: readId(source, ctx),\n type: \"data-view\",\n dataset: str(source.attrs?.dataset),\n view: cloneJson(source.attrs?.view) as never,\n });\n return;\n case TIPTAP_NODES.aiBlock: {\n const block: Extract<Block, { type: \"ai\" }> = {\n id: readId(source, ctx),\n type: \"ai\",\n prompt: str(source.attrs?.prompt),\n };\n if (Array.isArray(source.attrs?.result)) block.result = cloneJson(source.attrs?.result) as Block[];\n out.push(block);\n return;\n }\n case TIPTAP_NODES.unknownBlock: {\n const payload = source.attrs?.payload;\n if (isRecord(payload)) {\n const copy = cloneJson(payload);\n const id = optionalString(copy.id) ?? optionalString(source.attrs?.id) ?? ctx.generateId();\n copy.id = id;\n ctx.seenIds.add(id);\n warn(ctx, \"unknown-block\", `The block type \"${String(copy.type)}\" is not supported; it was kept as is.`, {\n blockId: id,\n nodeType: String(copy.type),\n });\n out.push(copy as unknown as Block);\n }\n return;\n }\n case TIPTAP_NODES.text:\n case TIPTAP_NODES.hardBreak:\n case TIPTAP_NODES.mention:\n case TIPTAP_NODES.emoji:\n // Inline content directly under the document or a container: wrap it.\n out.push({ id: ctx.generateId(), type: \"paragraph\", content: inlineFromTiptap([source], ctx) });\n return;\n default: {\n // A node from another schema. Keep what we can: text containers become\n // paragraphs, containers are flattened, atoms are flagged and dropped.\n const children = source.content ?? [];\n const hasInlineOnly = children.length > 0 && children.every((child) =>\n child.type === TIPTAP_NODES.text || child.type === TIPTAP_NODES.hardBreak || child.type === TIPTAP_NODES.mention || child.type === TIPTAP_NODES.emoji,\n );\n warn(ctx, \"unknown-node\", `The node \"${source.type}\" is not supported and was converted to plain blocks.`, {\n nodeType: source.type,\n });\n if (hasInlineOnly) {\n out.push({ id: readId(source, ctx), type: \"paragraph\", content: inlineOfTextblock(source, ctx) });\n } else {\n for (const child of children) blockFromTiptap(child, ctx, out);\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Converts a stored document into Tiptap / ProseMirror JSON, ready for\n * `editor.commands.setContent`. Blocks of an unknown type become `unknownBlock`\n * atoms and add an `\"unknown-block\"` warning.\n */\nexport function documentToTiptap(doc: EditorDocument, options?: ConvertOptions): TiptapDoc {\n const ctx = createContext(options);\n const content = blocksToTiptap(doc.blocks, ctx);\n const result: TiptapDoc = {\n type: \"doc\",\n content: content.length > 0 ? content : [{ type: TIPTAP_NODES.paragraph, attrs: { id: ctx.generateId() } }],\n };\n if (doc.title !== undefined) result.attrs = { title: doc.title };\n return result;\n}\n\n/**\n * Converts Tiptap / ProseMirror JSON (for example from `editor.getJSON()`)\n * back into a stored document. Ids are kept; blocks without one get a new id.\n */\nexport function tiptapToDocument(json: TiptapNode, options?: ConvertOptions): EditorDocument {\n const ctx = createContext(options);\n const blocks: Block[] = [];\n const top = json.type === \"doc\" ? (json.content ?? []) : [json];\n for (const child of top) blockFromTiptap(child, ctx, blocks);\n const doc: EditorDocument = { version: DOCUMENT_VERSION, blocks };\n const title = optionalString(json.attrs?.title);\n if (title !== undefined) doc.title = title;\n return doc;\n}\n\n/**\n * Rewrites a document into canonical form (see the list at the top of this\n * file). A document that is already canonical comes back deep-equal.\n */\nexport function normalizeDocument(doc: EditorDocument, options?: ConvertOptions): EditorDocument {\n const ctx: ConvertOptions = { ...options };\n return tiptapToDocument(documentToTiptap(doc, ctx), ctx);\n}\n","/**\n * A small shortcode table for the `emoji` inline node, so exports and the\n * editor can show a character without an emoji dependency. Unknown shortcodes\n * render as `:shortcode:`, which is also what Markdown uses.\n */\nexport const EMOJI_SHORTCODES: Readonly<Record<string, string>> = {\n smile: \"\\u{1F604}\",\n grin: \"\\u{1F601}\",\n joy: \"\\u{1F602}\",\n wink: \"\\u{1F609}\",\n heart: \"\\u2764\\uFE0F\",\n thumbsup: \"\\u{1F44D}\",\n \"+1\": \"\\u{1F44D}\",\n thumbsdown: \"\\u{1F44E}\",\n \"-1\": \"\\u{1F44E}\",\n clap: \"\\u{1F44F}\",\n pray: \"\\u{1F64F}\",\n fire: \"\\u{1F525}\",\n rocket: \"\\u{1F680}\",\n tada: \"\\u{1F389}\",\n eyes: \"\\u{1F440}\",\n thinking: \"\\u{1F914}\",\n sparkles: \"\\u2728\",\n star: \"\\u2B50\",\n warning: \"\\u26A0\\uFE0F\",\n check: \"\\u2705\",\n white_check_mark: \"\\u2705\",\n x: \"\\u274C\",\n bulb: \"\\u{1F4A1}\",\n memo: \"\\u{1F4DD}\",\n book: \"\\u{1F4D6}\",\n calendar: \"\\u{1F4C5}\",\n lock: \"\\u{1F512}\",\n link: \"\\u{1F517}\",\n pushpin: \"\\u{1F4CC}\",\n hourglass: \"\\u231B\",\n zap: \"\\u26A1\",\n bug: \"\\u{1F41B}\",\n wave: \"\\u{1F44B}\",\n muscle: \"\\u{1F4AA}\",\n ok_hand: \"\\u{1F44C}\",\n coffee: \"\\u2615\",\n sunny: \"\\u2600\\uFE0F\",\n question: \"\\u2753\",\n exclamation: \"\\u2757\",\n};\n\n/** The character for a shortcode (with or without colons), or `null` when it is not in the table. */\nexport function emojiForShortcode(shortcode: string): string | null {\n const key = shortcode.replace(/^:|:$/g, \"\").toLowerCase();\n return EMOJI_SHORTCODES[key] ?? null;\n}\n\n/** The character when known, otherwise `:shortcode:`. */\nexport function emojiToText(shortcode: string): string {\n return emojiForShortcode(shortcode) ?? `:${shortcode.replace(/^:|:$/g, \"\")}:`;\n}\n","/**\n * Plain text and statistics: search indexing, previews, screen reader\n * summaries, AI prompts and word counts all start here.\n */\nimport { emojiToText } from \"./emoji\";\nimport type { Block, EditorDocument, Inline, ListItem, TaskItem } from \"./schema\";\n\n/** Plain text of an inline run: marks dropped, mentions as `@label`, emoji as characters. */\nexport function inlineToPlainText(inline: Inline | undefined): string {\n let text = \"\";\n for (const node of inline ?? []) {\n if (node.type === \"text\") text += node.text;\n else if (node.type === \"mention\") text += `@${node.label}`;\n else if (node.type === \"emoji\") text += emojiToText(node.shortcode);\n }\n return text;\n}\n\nexport interface PlainTextOptions {\n /** Text between blocks. Defaults to a blank line. */\n blockSeparator?: string;\n /** Prefix list items with `-`, `1.` and `[x]`. Defaults to true. Counting turns it off. */\n markers?: boolean;\n}\n\nfunction indent(depth: number): string {\n return \" \".repeat(depth);\n}\n\nfunction listLines(\n items: ReadonlyArray<ListItem | TaskItem>,\n kind: \"bulleted\" | \"numbered\" | \"task\",\n markers: boolean,\n depth: number,\n): string[] {\n const lines: string[] = [];\n items.forEach((item, index) => {\n let marker = \"\";\n if (markers) {\n if (kind === \"bulleted\") marker = \"- \";\n else if (kind === \"numbered\") marker = `${index + 1}. `;\n else marker = `[${(item as TaskItem).checked ? \"x\" : \" \"}] `;\n }\n lines.push(`${markers ? indent(depth) : \"\"}${marker}${inlineToPlainText(item.content)}`);\n if (item.children) lines.push(...listLines(item.children, kind, markers, depth + 1));\n });\n return lines;\n}\n\nfunction blockText(block: Block, options: Required<PlainTextOptions>): string {\n switch (block.type) {\n case \"paragraph\":\n case \"heading\":\n case \"quote\":\n case \"callout\":\n return inlineToPlainText(block.content);\n case \"toggle\": {\n const parts = [inlineToPlainText(block.summary), ...blocksText(block.children ?? [], options)];\n return parts.filter((part) => part !== \"\").join(options.blockSeparator);\n }\n case \"divider\":\n case \"page-break\":\n case \"table-of-contents\":\n return \"\";\n case \"bulleted-list\":\n return listLines(block.items ?? [], \"bulleted\", options.markers, 0).join(\"\\n\");\n case \"numbered-list\":\n return listLines(block.items ?? [], \"numbered\", options.markers, 0).join(\"\\n\");\n case \"task-list\":\n return listLines(block.items ?? [], \"task\", options.markers, 0).join(\"\\n\");\n case \"code\":\n return block.code;\n case \"equation\":\n return block.latex;\n case \"table\":\n return (block.rows ?? []).map((row) => row.map((cell) => inlineToPlainText(cell.content)).join(\"\\t\")).join(\"\\n\");\n case \"image\":\n return [block.alt, inlineToPlainText(block.caption)].filter((part) => part !== \"\").join(\"\\n\");\n case \"video\":\n case \"audio\":\n return inlineToPlainText(block.caption);\n case \"file\":\n return block.name;\n case \"bookmark\":\n return [block.title, block.description, block.url].filter((part): part is string => !!part).join(\"\\n\");\n case \"columns\":\n return (block.columns ?? [])\n .flatMap((column) => blocksText(column, options))\n .join(options.blockSeparator);\n case \"chart\":\n return [block.spec?.title, block.spec?.subtitle].filter((part): part is string => !!part).join(\"\\n\");\n case \"diagram\":\n return block.diagram?.title ?? block.source ?? \"\";\n case \"data-view\":\n return [block.view?.name, block.dataset].filter((part): part is string => !!part).join(\"\\n\");\n case \"ai\":\n return [block.prompt, ...blocksText(block.result ?? [], options)].filter((part) => part !== \"\").join(options.blockSeparator);\n default:\n return \"\";\n }\n}\n\nfunction blocksText(blocks: readonly Block[], options: Required<PlainTextOptions>): string[] {\n return blocks.map((block) => blockText(block, options)).filter((text) => text !== \"\");\n}\n\n/**\n * The document as plain text. Blocks are separated by a blank line, lists keep\n * their markers and tables become tab-separated rows. Blocks with no text\n * (dividers, page breaks) are skipped. Columns read in order.\n */\nexport function documentToPlainText(doc: EditorDocument, options: PlainTextOptions = {}): string {\n const resolved: Required<PlainTextOptions> = {\n blockSeparator: options.blockSeparator ?? \"\\n\\n\",\n markers: options.markers ?? true,\n };\n return blocksText(doc.blocks ?? [], resolved).join(resolved.blockSeparator);\n}\n\n// ---------------------------------------------------------------------------\n// Counts\n// ---------------------------------------------------------------------------\n\ntype SegmenterCtor = new (\n locale?: string | string[],\n options?: { granularity: \"grapheme\" | \"word\" | \"sentence\" },\n) => { segment(input: string): Iterable<{ segment: string; isWordLike?: boolean }> };\n\nfunction getSegmenter(): SegmenterCtor | undefined {\n return (Intl as unknown as { Segmenter?: SegmenterCtor }).Segmenter;\n}\n\n/**\n * Counts words. Uses `Intl.Segmenter` when available, so Hebrew, Arabic and\n * CJK text count correctly; otherwise it splits on whitespace.\n */\nexport function countWords(text: string, locale?: string): number {\n if (text.trim() === \"\") return 0;\n const Segmenter = getSegmenter();\n if (Segmenter) {\n const segmenter = new Segmenter(locale, { granularity: \"word\" });\n let count = 0;\n for (const part of segmenter.segment(text)) if (part.isWordLike) count += 1;\n return count;\n }\n return text.trim().split(/\\s+/).length;\n}\n\n/** Counts characters as the reader sees them (grapheme clusters), not UTF-16 units. */\nexport function countCharacters(text: string, options: { includeSpaces?: boolean } = {}): number {\n const source = options.includeSpaces === false ? text.replace(/\\s+/g, \"\") : text;\n const Segmenter = getSegmenter();\n if (Segmenter) {\n let count = 0;\n for (const _ of new Segmenter(undefined, { granularity: \"grapheme\" }).segment(source)) {\n void _;\n count += 1;\n }\n return count;\n }\n return [...source].length;\n}\n\nexport interface DocumentStats {\n words: number;\n characters: number;\n charactersNoSpaces: number;\n /** Top-level blocks. */\n blocks: number;\n /** Reading time at 200 words per minute, rounded up, at least 1 when there is any text. */\n readingMinutes: number;\n}\n\n/** Word, character and block counts for a document. */\nexport function getDocumentStats(doc: EditorDocument, options: { locale?: string } = {}): DocumentStats {\n const text = documentToPlainText(doc, { markers: false, blockSeparator: \"\\n\" });\n const words = countWords(text, options.locale);\n return {\n words,\n characters: countCharacters(text.replace(/\\n/g, \" \")),\n charactersNoSpaces: countCharacters(text, { includeSpaces: false }),\n blocks: doc.blocks?.length ?? 0,\n readingMinutes: words === 0 ? 0 : Math.max(1, Math.ceil(words / 200)),\n };\n}\n","/**\n * Outline (table of contents) extraction. Headings anywhere in the document\n * count, including those inside toggles and columns.\n */\nimport { walkBlocks } from \"./ids\";\nimport type { EditorDocument } from \"./schema\";\nimport { inlineToPlainText } from \"./text\";\n\nexport interface OutlineItem {\n /** Id of the heading block. */\n id: string;\n level: 1 | 2 | 3 | 4;\n text: string;\n}\n\nexport interface OutlineNode extends OutlineItem {\n children: OutlineNode[];\n}\n\nexport interface OutlineOptions {\n /** Keep headings with no text. Defaults to false. */\n includeEmpty?: boolean;\n /** Deepest heading level to include (1 to 4). Defaults to 4. */\n maxLevel?: 1 | 2 | 3 | 4;\n}\n\n/** Headings in document order. */\nexport function getOutline(doc: EditorDocument, options: OutlineOptions = {}): OutlineItem[] {\n const items: OutlineItem[] = [];\n const maxLevel = options.maxLevel ?? 4;\n walkBlocks(doc.blocks ?? [], (block) => {\n if (block.type !== \"heading\" || block.level > maxLevel) return;\n const text = inlineToPlainText(block.content).trim();\n if (text === \"\" && options.includeEmpty !== true) return;\n items.push({ id: block.id, level: block.level, text });\n });\n return items;\n}\n\n/**\n * Nests a flat outline by level. A heading becomes a child of the nearest\n * previous heading with a lower level; skipped levels (an H3 straight after\n * an H1) nest under the closest ancestor.\n */\nexport function buildOutlineTree(items: readonly OutlineItem[]): OutlineNode[] {\n const roots: OutlineNode[] = [];\n const stack: OutlineNode[] = [];\n for (const item of items) {\n const entry: OutlineNode = { ...item, children: [] };\n while (stack.length > 0 && (stack[stack.length - 1] as OutlineNode).level >= entry.level) stack.pop();\n const parent = stack[stack.length - 1];\n if (parent) parent.children.push(entry);\n else roots.push(entry);\n stack.push(entry);\n }\n return roots;\n}\n\n/** A URL-safe, Unicode-aware slug: `Héllo Wörld` becomes `héllo-wörld`; Hebrew and Arabic letters stay. */\nexport function slugifyHeading(text: string): string {\n return text\n .normalize(\"NFKC\")\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}\\s-]+/gu, \"\")\n .trim()\n .replace(/[\\s-]+/g, \"-\");\n}\n","/**\n * Safe HTML export. Every text and attribute value is escaped; every URL goes\n * through `sanitizeUrl` (so `javascript:` links disappear); colors render only\n * from the token allow-list. The output has no scripts, event handlers or raw\n * styles, so it is safe to inject with `innerHTML` or `dangerouslySetInnerHTML`.\n */\nimport { emojiToText } from \"./emoji\";\nimport type { Block, EditorDocument, Inline, ListItem, Mark, TaskItem } from \"./schema\";\nimport { buildOutlineTree, getOutline, type OutlineNode } from \"./outline\";\nimport { sanitizeMediaUrl, sanitizeUrl } from \"./url\";\nimport { highlightToCss, textColorToCss } from \"./tokens\";\n\n/** English labels for the few strings an export needs. Pass `labels` to translate them. */\nexport interface ExportLabels {\n tableOfContents: string;\n chart: string;\n diagram: string;\n dataView: string;\n ai: string;\n file: string;\n}\n\nexport const defaultExportLabels: ExportLabels = {\n tableOfContents: \"Table of contents\",\n chart: \"Chart\",\n diagram: \"Diagram\",\n dataView: \"Data view\",\n ai: \"AI\",\n file: \"File\",\n};\n\nexport interface HtmlOptions {\n /** Prefix for generated element ids (headings, task labels). Defaults to `kit-`. */\n idPrefix?: string;\n /** Wrap the output in `<div data-kit=\"editor-view\">`. Defaults to false. */\n wrap?: boolean;\n labels?: Partial<ExportLabels>;\n /** Locale for number formatting (file sizes). */\n locale?: string;\n}\n\nconst ESCAPES: Record<string, string> = {\n \"&\": \"&\",\n \"<\": \"<\",\n \">\": \">\",\n '\"': \""\",\n \"'\": \"'\",\n};\n\n/** Escapes text for use in HTML content or a quoted attribute. */\nexport function escapeHtml(value: string): string {\n return value.replace(/[&<>\"']/g, (char) => ESCAPES[char] ?? char);\n}\n\ninterface Ctx {\n idPrefix: string;\n labels: ExportLabels;\n locale: string | undefined;\n outline: OutlineNode[];\n}\n\nfunction attrs(values: Record<string, string | number | boolean | null | undefined>): string {\n let out = \"\";\n for (const [name, value] of Object.entries(values)) {\n if (value === undefined || value === null || value === false) continue;\n out += value === true ? ` ${name}` : ` ${name}=\"${escapeHtml(String(value))}\"`;\n }\n return out;\n}\n\n/** Keeps a class or data value to a conservative character set. */\nfunction safeToken(value: string): string {\n return value.replace(/[^a-zA-Z0-9_+.-]/g, \"\");\n}\n\n// ---------------------------------------------------------------------------\n// Inline\n// ---------------------------------------------------------------------------\n\nfunction applyMark(html: string, mark: Mark): string {\n switch (mark.type) {\n case \"bold\":\n return `<strong>${html}</strong>`;\n case \"italic\":\n return `<em>${html}</em>`;\n case \"underline\":\n return `<u>${html}</u>`;\n case \"strike\":\n return `<s>${html}</s>`;\n case \"code\":\n return `<code>${html}</code>`;\n case \"link\": {\n const href = sanitizeUrl(mark.href);\n return href === null ? html : `<a${attrs({ href, rel: \"noopener noreferrer\" })}>${html}</a>`;\n }\n case \"color\": {\n const css = textColorToCss(mark.token);\n return css === null\n ? html\n : `<span${attrs({ \"data-kit\": \"editor-text-color\", \"data-token\": mark.token, style: `color: ${css}` })}>${html}</span>`;\n }\n case \"highlight\": {\n const css = highlightToCss(mark.token);\n return css === null\n ? html\n : `<mark${attrs({ \"data-kit\": \"editor-highlight\", \"data-token\": mark.token, style: `background-color: ${css}` })}>${html}</mark>`;\n }\n default:\n return html;\n }\n}\n\n// Innermost first, so the output nests link > color > highlight > bold > ... > code.\nconst APPLY_ORDER: Mark[\"type\"][] = [\"code\", \"strike\", \"underline\", \"italic\", \"bold\", \"highlight\", \"color\", \"link\"];\n\nfunction renderInline(inline: Inline | undefined): string {\n let html = \"\";\n for (const node of inline ?? []) {\n if (node.type === \"text\") {\n let part = escapeHtml(node.text).replace(/\\n/g, \"<br>\");\n const marks = node.marks ?? [];\n for (const type of APPLY_ORDER) {\n const mark = marks.find((candidate) => candidate.type === type);\n if (mark) part = applyMark(part, mark);\n }\n html += part;\n } else if (node.type === \"mention\") {\n html += `<span${attrs({ \"data-kit\": \"editor-mention\", \"data-kind\": node.kind, \"data-id\": node.id })}>@${escapeHtml(node.label)}</span>`;\n } else if (node.type === \"emoji\") {\n html += `<span${attrs({ \"data-kit\": \"editor-emoji\", \"data-shortcode\": node.shortcode })}>${escapeHtml(emojiToText(node.shortcode))}</span>`;\n }\n }\n return html;\n}\n\n// ---------------------------------------------------------------------------\n// Blocks\n// ---------------------------------------------------------------------------\n\nfunction renderItems(items: ReadonlyArray<ListItem | TaskItem>, kind: \"ul\" | \"ol\" | \"task\", ctx: Ctx): string {\n const tag = kind === \"ol\" ? \"ol\" : \"ul\";\n const open = kind === \"task\" ? `<ul${attrs({ \"data-kit\": \"editor-task-list\" })}>` : `<${tag}>`;\n let html = open;\n for (const item of items) {\n const nested = item.children && item.children.length > 0 ? renderItems(item.children, kind, ctx) : \"\";\n if (kind === \"task\") {\n const checked = (item as TaskItem).checked === true;\n const labelId = `${ctx.idPrefix}${item.id}-label`;\n html += `<li${attrs({ \"data-kit\": \"editor-task-item\", \"data-checked\": checked ? \"true\" : \"false\" })}>`;\n html += `<input${attrs({ type: \"checkbox\", disabled: true, checked, \"aria-labelledby\": labelId })}>`;\n html += `<span${attrs({ id: labelId, dir: \"auto\" })}>${renderInline(item.content)}</span>${nested}</li>`;\n } else {\n html += `<li${attrs({ dir: \"auto\" })}>${renderInline(item.content)}${nested}</li>`;\n }\n }\n return `${html}</${tag}>`;\n}\n\nfunction formatBytes(size: number, locale: string | undefined): string {\n const units = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"];\n let value = size;\n let unit = 0;\n while (value >= 1024 && unit < units.length - 1) {\n value /= 1024;\n unit += 1;\n }\n const formatted = new Intl.NumberFormat(locale, { maximumFractionDigits: unit === 0 ? 0 : 1 }).format(value);\n return `${formatted} ${units[unit]}`;\n}\n\nfunction renderCaption(caption: Inline | undefined): string {\n return caption && caption.length > 0 ? `<figcaption dir=\"auto\">${renderInline(caption)}</figcaption>` : \"\";\n}\n\nfunction renderOutline(nodes: readonly OutlineNode[], ctx: Ctx): string {\n if (nodes.length === 0) return \"\";\n let html = \"<ol>\";\n for (const node of nodes) {\n html += `<li><a href=\"#${escapeHtml(ctx.idPrefix + node.id)}\">${escapeHtml(node.text)}</a>${renderOutline(node.children, ctx)}</li>`;\n }\n return `${html}</ol>`;\n}\n\nfunction renderEmbed(blockId: string, type: string, title: string, subtitle: string | undefined, label: string, body = \"\"): string {\n const heading = `<figcaption><span data-kit=\"editor-embed-kind\">${escapeHtml(label)}</span> ${escapeHtml(title)}${\n subtitle ? ` <small>${escapeHtml(subtitle)}</small>` : \"\"\n }</figcaption>`;\n return `<figure${attrs({ \"data-block-id\": blockId, \"data-kit\": \"editor-embed\", \"data-block-type\": type, role: \"group\", \"aria-label\": title || label })}>${heading}${body}</figure>`;\n}\n\nfunction renderBlock(block: Block, ctx: Ctx): string {\n const id = attrs({ \"data-block-id\": block.id });\n switch (block.type) {\n case \"paragraph\":\n return `<p${id}${attrs({ dir: \"auto\" })}>${renderInline(block.content)}</p>`;\n case \"heading\": {\n const level = Math.min(4, Math.max(1, Math.round(block.level)));\n return `<h${level}${attrs({ id: ctx.idPrefix + block.id, dir: \"auto\" })}${id}>${renderInline(block.content)}</h${level}>`;\n }\n case \"quote\":\n return `<blockquote${id}${attrs({ dir: \"auto\" })}>${renderInline(block.content)}</blockquote>`;\n case \"callout\":\n return `<div${id}${attrs({ \"data-kit\": \"editor-callout\", \"data-variant\": safeToken(block.variant), role: \"note\", dir: \"auto\" })}>${renderInline(block.content)}</div>`;\n case \"toggle\":\n return `<details${id}${attrs({ \"data-kit\": \"editor-toggle\" })}><summary${attrs({ dir: \"auto\" })}>${renderInline(block.summary)}</summary>${renderBlocks(block.children ?? [], ctx)}</details>`;\n case \"divider\":\n return `<hr${id}>`;\n case \"bulleted-list\":\n return renderListBlock(block, \"ul\", ctx);\n case \"numbered-list\":\n return renderListBlock(block, \"ol\", ctx);\n case \"task-list\":\n return renderListBlock(block, \"task\", ctx);\n case \"code\": {\n const language = block.language ? safeToken(block.language) : \"\";\n return `<pre${id}${attrs({ \"data-kit\": \"editor-code-block\", \"data-language\": language || undefined, dir: \"ltr\" })}><code${attrs({ class: language ? `language-${language}` : undefined })}>${escapeHtml(block.code)}</code></pre>`;\n }\n case \"equation\":\n return `<pre${id}${attrs({ \"data-kit\": \"editor-equation\", dir: \"ltr\" })}><code>${escapeHtml(block.latex)}</code></pre>`;\n case \"table\":\n return renderTable(block);\n case \"image\": {\n const src = sanitizeMediaUrl(block.src);\n const img =\n src === null\n ? \"\"\n : `<img${attrs({ src, alt: block.alt ?? \"\", loading: \"lazy\", decoding: \"async\", width: block.width })}>`;\n return `<figure${id}${attrs({ \"data-kit\": \"editor-image\", \"data-align\": block.align })}>${img}${renderCaption(block.caption)}</figure>`;\n }\n case \"video\":\n case \"audio\": {\n const src = sanitizeMediaUrl(block.src);\n const media =\n src === null ? \"\" : `<${block.type}${attrs({ src, controls: true, preload: \"none\" })}></${block.type}>`;\n return `<figure${id}${attrs({ \"data-kit\": \"editor-media\", \"data-kind\": block.type })}>${media}${renderCaption(block.caption)}</figure>`;\n }\n case \"file\": {\n const href = sanitizeUrl(block.src);\n const name = escapeHtml(block.name);\n const link = href === null ? name : `<a${attrs({ href, download: true, rel: \"noopener noreferrer\" })}>${name}</a>`;\n const size = typeof block.size === \"number\" ? ` <span data-kit=\"editor-file-size\">(${escapeHtml(formatBytes(block.size, ctx.locale))})</span>` : \"\";\n return `<p${id}${attrs({ \"data-kit\": \"editor-file\", dir: \"auto\" })}>${link}${size}</p>`;\n }\n case \"bookmark\": {\n const href = sanitizeUrl(block.url);\n const title = block.title ? `<strong>${escapeHtml(block.title)}</strong>` : escapeHtml(block.url);\n const description = block.description ? `<span>${escapeHtml(block.description)}</span>` : \"\";\n const inner = `${title}${description}`;\n return href === null\n ? `<div${id}${attrs({ \"data-kit\": \"editor-bookmark\" })}>${inner}</div>`\n : `<a${id}${attrs({ \"data-kit\": \"editor-bookmark\", href, rel: \"noopener noreferrer\" })}>${inner}</a>`;\n }\n case \"columns\": {\n const columns = block.columns ?? [];\n return `<div${id}${attrs({ \"data-kit\": \"editor-columns\", \"data-count\": columns.length })}>${columns\n .map((column) => `<div data-kit=\"editor-column\">${renderBlocks(column, ctx)}</div>`)\n .join(\"\")}</div>`;\n }\n case \"page-break\":\n return `<hr${id}${attrs({ \"data-kit\": \"editor-page-break\" })}>`;\n case \"table-of-contents\":\n return `<nav${id}${attrs({ \"data-kit\": \"editor-toc\", \"aria-label\": ctx.labels.tableOfContents })}>${renderOutline(ctx.outline, ctx)}</nav>`;\n case \"chart\":\n return renderEmbed(\n block.id,\n \"chart\",\n block.spec?.title ?? \"\",\n block.spec?.subtitle,\n ctx.labels.chart,\n block.spec?.a11y?.description ? `<p dir=\"auto\">${escapeHtml(block.spec.a11y.description)}</p>` : \"\",\n );\n case \"diagram\": {\n const title = block.diagram?.title ?? \"\";\n const body = block.source ? `<pre dir=\"ltr\"><code>${escapeHtml(block.source)}</code></pre>` : \"\";\n return renderEmbed(block.id, \"diagram\", title, undefined, ctx.labels.diagram, body);\n }\n case \"data-view\":\n return renderEmbed(block.id, \"data-view\", block.view?.name ?? block.dataset, block.view?.name ? block.dataset : undefined, ctx.labels.dataView);\n case \"ai\":\n return renderEmbed(block.id, \"ai\", block.prompt, undefined, ctx.labels.ai, renderBlocks(block.result ?? [], ctx));\n default: {\n const unknownType = String((block as { type?: unknown }).type);\n return `<div${id}${attrs({ \"data-kit\": \"editor-unknown\", \"data-block-type\": unknownType, hidden: true })}></div>`;\n }\n }\n}\n\nfunction renderListBlock(\n block: { items: Array<ListItem | TaskItem>; id: string },\n kind: \"ul\" | \"ol\" | \"task\",\n ctx: Ctx,\n): string {\n const html = renderItems(block.items ?? [], kind, ctx);\n // Put the block id on the list element itself.\n return html.replace(/^<(ul|ol)/, `<$1${attrs({ \"data-block-id\": block.id })}`);\n}\n\nfunction renderTable(block: Extract<Block, { type: \"table\" }>): string {\n const rows = block.rows ?? [];\n const renderRow = (row: (typeof rows)[number], rowIndex: number) =>\n `<tr>${row\n .map((cell, columnIndex) => {\n const header =\n cell.header === true ||\n (block.headerRow === true && rowIndex === 0) ||\n (block.headerColumn === true && columnIndex === 0);\n const tag = header ? \"th\" : \"td\";\n let scope: \"col\" | \"row\" | undefined;\n if (header && block.headerRow === true && rowIndex === 0) scope = \"col\";\n else if (header && block.headerColumn === true && columnIndex === 0) scope = \"row\";\n return `<${tag}${attrs({\n scope,\n colspan: cell.colSpan && cell.colSpan > 1 ? cell.colSpan : undefined,\n rowspan: cell.rowSpan && cell.rowSpan > 1 ? cell.rowSpan : undefined,\n dir: \"auto\",\n })}>${renderInline(cell.content)}</${tag}>`;\n })\n .join(\"\")}</tr>`;\n\n const headRow = block.headerRow === true ? rows[0] : undefined;\n const bodyRows = headRow ? rows.slice(1) : rows;\n const thead = headRow ? `<thead>${renderRow(headRow, 0)}</thead>` : \"\";\n const tbody = `<tbody>${bodyRows.map((row, index) => renderRow(row, headRow ? index + 1 : index)).join(\"\")}</tbody>`;\n return `<div${attrs({ \"data-kit\": \"editor-table-wrapper\", \"data-block-id\": block.id })}><table${attrs({ \"data-kit\": \"editor-table\" })}>${thead}${tbody}</table></div>`;\n}\n\nfunction renderBlocks(blocks: readonly Block[], ctx: Ctx): string {\n return blocks.map((block) => renderBlock(block, ctx)).join(\"\");\n}\n\n/**\n * Renders the document as safe HTML (see the note at the top of this file).\n * Block ids become `data-block-id`; headings get an `id` so a table of\n * contents block can link to them.\n */\nexport function documentToHtml(doc: EditorDocument, options: HtmlOptions = {}): string {\n const ctx: Ctx = {\n idPrefix: options.idPrefix ?? \"kit-\",\n labels: { ...defaultExportLabels, ...options.labels },\n locale: options.locale,\n outline: buildOutlineTree(getOutline(doc)),\n };\n const html = renderBlocks(doc.blocks ?? [], ctx);\n return options.wrap === true ? `<div data-kit=\"editor-view\">${html}</div>` : html;\n}","/**\n * Markdown export (CommonMark plus GitHub tables, task lists and alerts).\n *\n * Everything the schema holds has a Markdown form, so `markdownToDocument`\n * can read it back: kit blocks become fenced blocks with a JSON payload\n * (`kit-chart`, `kit-diagram`, `kit-data-view`, `kit-ai`), Mermaid diagrams\n * become ```mermaid fences, callouts become `> [!INFO]` alerts, toggles become\n * `<details>`. What Markdown cannot say is documented in the README: block ids,\n * empty paragraphs, table spans, image alignment and width, and the file and\n * bookmark block types (they export as links).\n */\nimport { emojiForShortcode, emojiToText } from \"./emoji\";\nimport { normalizeInline } from \"./convert\";\nimport type { Block, EditorDocument, Inline, ListItem, Mark, TaskItem } from \"./schema\";\nimport { escapeHtml } from \"./html\";\nimport { sanitizeMediaUrl, sanitizeUrl } from \"./url\";\nimport { isHighlightToken, isTextColorToken } from \"./tokens\";\n\nexport interface MarkdownOptions {\n /** Keep marks Markdown has no syntax for (underline, color, highlight) as inline HTML. Defaults to true. */\n inlineHtml?: boolean;\n}\n\ninterface Ctx {\n inlineHtml: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Escaping\n// ---------------------------------------------------------------------------\n\n/** Escapes characters that would start Markdown syntax inside running text. */\nexport function escapeMarkdown(text: string): string {\n return text.replace(/([\\\\`*_[\\]<>~|])/g, \"\\\\$1\");\n}\n\n/** Markdown has no multi-line labels, so single-line text replaces newlines and runs of spaces. */\nfunction oneLine(text: string): string {\n return text.replace(/\\s+/g, \" \").trim();\n}\n\nfunction escapeLineStart(line: string): string {\n return line\n .replace(/^(\\s*)([#>+-])/, \"$1\\\\$2\")\n .replace(/^(\\s*)(\\d+)([.)])(\\s|$)/, \"$1$2\\\\$3$4\")\n .replace(/^(\\s*)([=]{2,}|[-]{2,})\\s*$/, \"$1\\\\$2\")\n .replace(/^(\\s*)(:{1}[a-z0-9_+-]+:)/i, \"$1\\\\$2\");\n}\n\nfunction codeSpan(text: string): string {\n const runs = text.match(/`+/g) ?? [];\n const longest = runs.reduce((max, run) => Math.max(max, run.length), 0);\n const fence = \"`\".repeat(longest + 1);\n const pad = text.startsWith(\"`\") || text.endsWith(\"`\") || (text.startsWith(\" \") && text.endsWith(\" \") && text.trim() !== \"\") ? \" \" : \"\";\n return `${fence}${pad}${text}${pad}${fence}`;\n}\n\nfunction encodeDestination(href: string): string {\n return href.replace(/ /g, \"%20\").replace(/\\(/g, \"%28\").replace(/\\)/g, \"%29\").replace(/</g, \"%3C\").replace(/>/g, \"%3E\");\n}\n\n// ---------------------------------------------------------------------------\n// Inline\n// ---------------------------------------------------------------------------\n\ntype MarkKey = string;\n\nfunction markKey(mark: Mark): MarkKey {\n return JSON.stringify(mark);\n}\n\nfunction openToken(mark: Mark, ctx: Ctx): string | null {\n switch (mark.type) {\n case \"bold\":\n return \"**\";\n case \"italic\":\n return \"*\";\n case \"strike\":\n return \"~~\";\n case \"underline\":\n return ctx.inlineHtml ? \"<u>\" : \"\";\n case \"link\":\n return sanitizeUrl(mark.href) === null ? \"\" : \"[\";\n case \"color\":\n return ctx.inlineHtml && isTextColorToken(mark.token) ? `<span data-color-token=\"${escapeHtml(mark.token)}\">` : \"\";\n case \"highlight\":\n return ctx.inlineHtml && isHighlightToken(mark.token) ? `<mark data-token=\"${escapeHtml(mark.token)}\">` : \"\";\n default:\n return \"\";\n }\n}\n\nfunction closeToken(mark: Mark, ctx: Ctx): string {\n switch (mark.type) {\n case \"bold\":\n return \"**\";\n case \"italic\":\n return \"*\";\n case \"strike\":\n return \"~~\";\n case \"underline\":\n return ctx.inlineHtml ? \"</u>\" : \"\";\n case \"link\": {\n const href = sanitizeUrl(mark.href);\n return href === null ? \"\" : `](${encodeDestination(href)})`;\n }\n case \"color\":\n return ctx.inlineHtml && isTextColorToken(mark.token) ? \"</span>\" : \"\";\n case \"highlight\":\n return ctx.inlineHtml && isHighlightToken(mark.token) ? \"</mark>\" : \"\";\n default:\n return \"\";\n }\n}\n\n/**\n * Renders inline content. Marks nest by their shared prefix (they arrive in\n * canonical order), and whitespace at the edge of a span moves outside the\n * delimiters, because `** bold **` is not emphasis in CommonMark.\n */\nfunction renderInline(inline: Inline | undefined, ctx: Ctx, escapeLines = true): string {\n const nodes = normalizeInline(inline);\n let out = \"\";\n let active: Mark[] = [];\n\n const closeFrom = (keep: number) => {\n for (let index = active.length - 1; index >= keep; index -= 1) {\n const mark = active[index] as Mark;\n if (mark.type === \"code\") continue;\n const token = closeToken(mark, ctx);\n if (token === \"\") continue;\n const trailing = /\\s+$/.exec(out)?.[0] ?? \"\";\n if (trailing !== \"\" && mark.type !== \"link\") out = out.slice(0, out.length - trailing.length);\n out += token + (mark.type !== \"link\" ? trailing : \"\");\n }\n active = active.slice(0, keep);\n };\n\n for (const node of nodes) {\n if (node.type !== \"text\") {\n closeFrom(0);\n if (node.type === \"mention\") {\n out += `[@${escapeMarkdown(node.label)}](kit:mention/${node.kind}/${encodeURIComponent(node.id)})`;\n } else {\n const code = node.shortcode.replace(/^:|:$/g, \"\");\n // Only shortcodes the importer knows stay as `:code:`; others are plain, escaped text.\n out += emojiForShortcode(code) !== null ? `:${code}:` : escapeMarkdown(`:${code}:`);\n }\n continue;\n }\n\n const marks = (node.marks ?? []).filter((mark) => mark.type !== \"code\");\n const hasCode = (node.marks ?? []).some((mark) => mark.type === \"code\");\n\n let keep = 0;\n while (keep < active.length && keep < marks.length && markKey(active[keep] as Mark) === markKey(marks[keep] as Mark)) keep += 1;\n closeFrom(keep);\n\n let text = node.text;\n let lead = \"\";\n if (marks.length > keep) {\n const match = /^\\s+/.exec(text);\n if (match && text.trim() !== \"\") {\n lead = match[0];\n text = text.slice(lead.length);\n }\n if (text.trim() === \"\") {\n // Whitespace only: no emphasis around it.\n out += node.text.replace(/\\n/g, \"\\\\\\n\");\n continue;\n }\n }\n out += lead;\n for (let index = keep; index < marks.length; index += 1) {\n const mark = marks[index] as Mark;\n out += openToken(mark, ctx) ?? \"\";\n active.push(mark);\n }\n\n if (hasCode && !text.includes(\"\\n\")) out += codeSpan(text);\n else\n out += text\n .split(\"\\n\")\n .map((part, position) => (position === 0 || !escapeLines ? escapeMarkdown(part) : escapeLineStart(escapeMarkdown(part))))\n .join(\"\\\\\\n\");\n }\n closeFrom(0);\n return out;\n}\n\n/** Inline content on a single line (headings, table cells, link-free summaries). */\nfunction renderInlineLine(inline: Inline | undefined, ctx: Ctx, newline: string): string {\n return renderInline(inline, ctx, false).replace(/\\\\\\n/g, newline).replace(/\\n/g, newline);\n}\n\n// ---------------------------------------------------------------------------\n// Blocks\n// ---------------------------------------------------------------------------\n\nconst CALLOUT_LABEL: Record<string, string> = {\n info: \"INFO\",\n success: \"SUCCESS\",\n warning: \"WARNING\",\n danger: \"DANGER\",\n neutral: \"NEUTRAL\",\n};\n\nfunction fence(content: string, info: string): string {\n const runs = content.match(/`+/g) ?? [];\n const longest = runs.reduce((max, run) => Math.max(max, run.length), 0);\n const marker = \"`\".repeat(Math.max(3, longest + 1));\n return `${marker}${info}\\n${content}\\n${marker}`;\n}\n\nfunction safeInfo(value: string): string {\n return value.replace(/[^a-zA-Z0-9_+.#-]/g, \"\");\n}\n\nfunction prefixLines(text: string, first: string, rest: string): string {\n return text\n .split(\"\\n\")\n .map((line, index) => (index === 0 ? first : rest) + line)\n .join(\"\\n\");\n}\n\nfunction renderItems(\n items: ReadonlyArray<ListItem | TaskItem>,\n kind: \"bulleted\" | \"numbered\" | \"task\",\n ctx: Ctx,\n): string[] {\n const lines: string[] = [];\n items.forEach((item, index) => {\n const marker = kind === \"numbered\" ? `${index + 1}. ` : \"- \";\n const checkbox = kind === \"task\" ? `[${(item as TaskItem).checked ? \"x\" : \" \"}] ` : \"\";\n // Text after a checkbox is still at the start of a block when read back, so it needs the same escaping.\n const body = escapeLineStart(renderInline(item.content, ctx));\n const pad = \" \".repeat(marker.length);\n lines.push(prefixLines(`${checkbox}${body}`, marker, pad).replace(/ +$/, \"\"));\n if (item.children && item.children.length > 0) {\n const nested = renderItems(item.children, kind, ctx).join(\"\\n\");\n lines.push(prefixLines(nested, pad, pad));\n }\n });\n return lines;\n}\n\nfunction renderTable(block: Extract<Block, { type: \"table\" }>, ctx: Ctx): string {\n const rows = block.rows ?? [];\n const width = rows.reduce((max, row) => Math.max(max, row.length), 0);\n if (rows.length === 0 || width === 0) return \"\";\n const cell = (inline: Inline | undefined) => renderInlineLine(inline, ctx, \"<br>\").replace(/\\|/g, \"\\\\|\") || \" \";\n const toLine = (row: (typeof rows)[number]) =>\n `| ${Array.from({ length: width }, (_, index) => (row[index] ? cell(row[index]?.content) : \" \")).join(\" | \")} |`;\n const [head, ...body] = rows;\n const delimiter = `| ${Array.from({ length: width }, () => \"---\").join(\" | \")} |`;\n return [toLine(head ?? []), delimiter, ...body.map(toLine)].join(\"\\n\");\n}\n\nfunction renderBlock(block: Block, ctx: Ctx): string {\n switch (block.type) {\n case \"paragraph\": {\n const text = renderInline(block.content, ctx);\n return text === \"\" ? \"\" : escapeLineStart(text);\n }\n case \"heading\": {\n const level = Math.min(4, Math.max(1, Math.round(block.level)));\n return `${\"#\".repeat(level)} ${renderInlineLine(block.content, ctx, \" \")}`.trimEnd();\n }\n case \"quote\":\n return prefixLines(escapeLineStart(renderInline(block.content, ctx)), \"> \", \"> \");\n case \"callout\": {\n const label = CALLOUT_LABEL[block.variant] ?? \"INFO\";\n const body = escapeLineStart(renderInline(block.content, ctx));\n return prefixLines(`[!${label}]${body === \"\" ? \"\" : `\\n${body}`}`, \"> \", \"> \");\n }\n case \"toggle\": {\n const summary = escapeHtml(\n normalizeInline(block.summary)\n .map((node) => (node.type === \"text\" ? node.text : node.type === \"mention\" ? `@${node.label}` : emojiToText(node.shortcode)))\n .join(\"\")\n .replace(/\\n/g, \" \"),\n );\n const body = renderBlocks(block.children ?? [], ctx);\n return `<details>\\n<summary>${summary}</summary>\\n${body === \"\" ? \"\" : `\\n${body}\\n`}\\n</details>`;\n }\n case \"divider\":\n return \"---\";\n case \"bulleted-list\":\n return renderItems(block.items ?? [], \"bulleted\", ctx).join(\"\\n\");\n case \"numbered-list\":\n return renderItems(block.items ?? [], \"numbered\", ctx).join(\"\\n\");\n case \"task-list\":\n return renderItems(block.items ?? [], \"task\", ctx).join(\"\\n\");\n case \"code\":\n return fence(block.code, safeInfo(block.language ?? \"\"));\n case \"equation\":\n return `$$\\n${block.latex}\\n$$`;\n case \"table\":\n return renderTable(block, ctx);\n case \"image\": {\n const src = sanitizeMediaUrl(block.src);\n const alt = escapeMarkdown(oneLine(block.alt ?? \"\"));\n if (src === null) return alt;\n const caption = normalizeInline(block.caption)\n .map((node) => (node.type === \"text\" ? node.text : \"\"))\n .join(\"\")\n .replace(/\\s+/g, \" \")\n .trim();\n const title = caption === \"\" ? \"\" : ` \"${caption.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"`;\n return `}${title})`;\n }\n case \"video\":\n case \"audio\": {\n const src = sanitizeMediaUrl(block.src);\n if (src === null) return \"\";\n const caption = normalizeInline(block.caption)\n .map((node) => (node.type === \"text\" ? node.text : \"\"))\n .join(\"\")\n .replace(/\\s+/g, \" \")\n .trim();\n return `<${block.type} src=\"${escapeHtml(src)}\"${caption === \"\" ? \"\" : ` title=\"${escapeHtml(caption)}\"`} controls></${block.type}>`;\n }\n case \"file\": {\n const href = sanitizeUrl(block.src);\n const name = escapeMarkdown(oneLine(block.name));\n return href === null ? name : `[${name}](${encodeDestination(href)})`;\n }\n case \"bookmark\": {\n const href = sanitizeUrl(block.url);\n const label = escapeMarkdown(oneLine(block.title || block.url));\n return href === null ? label : `[${label}](${encodeDestination(href)})`;\n }\n case \"columns\":\n return (block.columns ?? []).map((column) => renderBlocks(column, ctx)).filter((text) => text !== \"\").join(\"\\n\\n\");\n case \"page-break\":\n return \"<!-- page-break -->\";\n case \"table-of-contents\":\n return \"[TOC]\";\n case \"chart\":\n return fence(JSON.stringify(block.spec, null, 2), \"kit-chart\");\n case \"diagram\":\n if (block.engine === \"mermaid\" && typeof block.source === \"string\" && block.diagram === undefined) {\n return fence(block.source, \"mermaid\");\n }\n return fence(JSON.stringify({ engine: block.engine, diagram: block.diagram, source: block.source }, null, 2), \"kit-diagram\");\n case \"data-view\":\n return fence(JSON.stringify({ dataset: block.dataset, view: block.view }, null, 2), \"kit-data-view\");\n case \"ai\":\n return fence(JSON.stringify({ prompt: block.prompt, result: block.result }, null, 2), \"kit-ai\");\n default:\n // An unknown block type: keep the data as a fenced JSON block.\n return fence(JSON.stringify(block, null, 2), \"kit-block\");\n }\n}\n\nconst LIST_TYPES = new Set<string>([\"bulleted-list\", \"numbered-list\", \"task-list\"]);\n\n/** Columns have no Markdown form; their blocks follow one another. */\nfunction flattenColumns(blocks: readonly Block[]): Block[] {\n return blocks.flatMap((block) => (block.type === \"columns\" ? flattenColumns((block.columns ?? []).flat()) : [block]));\n}\n\nfunction renderBlocks(blocks: readonly Block[], ctx: Ctx): string {\n const parts: string[] = [];\n let previous: Block | undefined;\n for (const block of flattenColumns(blocks)) {\n const text = renderBlock(block, ctx);\n if (text === \"\") continue;\n // Two neighbouring lists of one kind would merge when read back; an empty comment keeps them apart.\n if (previous && block.type === previous.type && LIST_TYPES.has(block.type)) parts.push(\"<!-- -->\");\n parts.push(text);\n previous = block;\n }\n return parts.join(\"\\n\\n\");\n}\n\n/**\n * Renders the document as Markdown. A level 1 `title` is not added; the\n * document's `title` field is metadata, not content.\n */\nexport function documentToMarkdown(doc: EditorDocument, options: MarkdownOptions = {}): string {\n const ctx: Ctx = { inlineHtml: options.inlineHtml ?? true };\n const body = renderBlocks(doc.blocks ?? [], ctx);\n return body === \"\" ? \"\" : `${body}\\n`;\n}\n"],"mappings":";AAWO,IAAM,mBAAmB;AA0FzB,SAAS,oBAAoB,KAAK,QAAwB;AAC/D,SAAO;AAAA,IACL,SAAS;AAAA,IACT,QAAQ,CAAC,EAAE,IAAI,MAAM,aAAa,SAAS,CAAC,EAAE,CAAC;AAAA,EACjD;AACF;AAmCO,IAAM,cAAc;AAAA,EACzB;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;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,IAAM,aAAa;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,mBAAmB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,eAAoC,IAAI,IAAI,WAAW;AAGtD,SAAS,iBAAiB,MAAkC;AACjE,SAAO,OAAO,SAAS,YAAY,aAAa,IAAI,IAAI;AAC1D;AAGO,SAAS,gBAAgB,IAAY,OAAO,IAA2C;AAC5F,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AAAA,IACN,SAAS,SAAS,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,QAAQ,KAAK,CAAC;AAAA,EACrD;AACF;;;ACpMA,IAAM,WAAW;AACjB,IAAM,YAAY;AAOX,SAAS,kBAA0B;AACxC,QAAM,QAAQ,IAAI,WAAW,SAAS;AACtC,QAAM,YAAa,WAAmC;AACtD,MAAI,WAAW,iBAAiB;AAC9B,cAAU,gBAAgB,KAAK;AAAA,EACjC,OAAO;AACL,aAAS,QAAQ,GAAG,QAAQ,WAAW,SAAS,EAAG,OAAM,KAAK,IAAI,KAAK,MAAM,KAAK,OAAO,IAAI,GAAG;AAAA,EAClG;AACA,MAAI,KAAK;AACT,aAAW,QAAQ,MAAO,OAAM,SAAS,OAAO,OAAO,SAAS,MAAM;AACtE,SAAO;AACT;AAGO,SAAS,mBAAmB,MAA4B;AAC7D,MAAI,QAAQ,SAAS;AACrB,SAAO,MAAM;AACX,YAAS,QAAQ,eAAgB;AACjC,QAAI,QAAQ;AACZ,YAAQ,KAAK,KAAK,QAAS,UAAU,IAAK,QAAQ,CAAC;AACnD,aAAS,QAAQ,KAAK,KAAK,QAAS,UAAU,GAAI,QAAQ,EAAE;AAC5D,aAAS,QAAS,UAAU,QAAS,KAAK;AAAA,EAC5C;AACF;AAMO,SAAS,4BAA4B,SAAS,KAAK,QAAQ,GAAiB;AACjF,MAAI,UAAU;AACd,SAAO,MAAM;AACX,UAAM,KAAK,GAAG,MAAM,GAAG,OAAO;AAC9B,eAAW;AACX,WAAO;AAAA,EACT;AACF;AAEA,SAAS,cAAc,OAA2C,OAAmC;AACnG,aAAW,QAAQ,OAAO;AACxB,UAAM,KAAK,EAAE;AACb,QAAI,KAAK,SAAU,eAAc,KAAK,UAAU,KAAK;AAAA,EACvD;AACF;AAGO,SAAS,WAAW,QAA0B,OAAqD,SAAuB,MAAY;AAC3I,aAAW,SAAS,QAAQ;AAC1B,UAAM,OAAO,MAAM;AACnB,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK;AACH,mBAAW,MAAM,YAAY,CAAC,GAAG,OAAO,KAAK;AAC7C;AAAA,MACF,KAAK;AACH,mBAAW,UAAU,MAAM,WAAW,CAAC,EAAG,YAAW,QAAQ,OAAO,KAAK;AACzE;AAAA,MACF,KAAK;AACH,YAAI,MAAM,OAAQ,YAAW,MAAM,QAAQ,OAAO,KAAK;AACvD;AAAA,MACF;AACE;AAAA,IACJ;AAAA,EACF;AACF;AAGO,SAAS,WAAW,KAA+B;AACxD,QAAM,MAAgB,CAAC;AACvB,aAAW,IAAI,QAAQ,CAAC,UAAU;AAChC,QAAI,KAAK,MAAM,EAAE;AACjB,QAAI,MAAM,SAAS,mBAAmB,MAAM,SAAS,mBAAmB,MAAM,SAAS,aAAa;AAClG,oBAAc,MAAM,SAAS,CAAC,GAAG,CAAC,OAAO,IAAI,KAAK,EAAE,CAAC;AAAA,IACvD;AAAA,EACF,CAAC;AACD,SAAO;AACT;AAGO,SAAS,iBAAiB,KAA+B;AAC9D,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,aAAa,oBAAI,IAAY;AACnC,aAAW,MAAM,WAAW,GAAG,GAAG;AAChC,QAAI,KAAK,IAAI,EAAE,EAAG,YAAW,IAAI,EAAE;AACnC,SAAK,IAAI,EAAE;AAAA,EACb;AACA,SAAO,CAAC,GAAG,UAAU;AACvB;;;ACtFA,IAAM,oBAAuC,CAAC,QAAQ,SAAS,UAAU,KAAK;AAK9E,IAAM,YAAY;AAClB,IAAM,SAAS;AACf,IAAM,aAAa;AAMZ,SAAS,YAAY,OAAgB,UAA8B,CAAC,GAAkB;AAC3F,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,YAAY,GAAI,QAAO;AAE3B,QAAM,UAAU,QAAQ,QAAQ,WAAW,EAAE;AAC7C,QAAM,SAAS,OAAO,KAAK,OAAO;AAClC,MAAI,WAAW,MAAM;AAGnB,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,OAAO,CAAC,KAAK,IAAI,YAAY;AAC/C,MAAI,aAAa,QAAQ;AACvB,WAAO,QAAQ,mBAAmB,QAAQ,WAAW,KAAK,OAAO,IAAI,UAAU;AAAA,EACjF;AACA,QAAM,UAAU,QAAQ,oBAAoB;AAC5C,SAAO,QAAQ,SAAS,QAAQ,IAAI,UAAU;AAChD;AAGO,SAAS,UAAU,OAAgB,SAAuC;AAC/E,SAAO,YAAY,OAAO,OAAO,MAAM;AACzC;AAGO,SAAS,iBAAiB,OAA+B;AAC9D,SAAO,YAAY,OAAO,EAAE,gBAAgB,KAAK,CAAC;AACpD;AAEA,IAAM,cAAc;AACpB,IAAM,aAAa;AAOZ,SAAS,kBAAkB,OAAuB;AACvD,QAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,YAAY,GAAI,QAAO;AAC3B,MAAI,WAAW,KAAK,OAAO,EAAG,QAAO,UAAU,OAAO;AAEtD,MAAI,YAAY,KAAK,OAAO,EAAG,QAAO,WAAW,OAAO;AACxD,SAAO;AACT;;;AC/DO,IAAM,oBAAoB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,IAAM,mBAAmB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKA,IAAM,eAAoC,IAAI,IAAI,iBAAiB;AACnE,IAAM,eAAoC,IAAI,IAAI,gBAAgB;AAE3D,SAAS,iBAAiB,OAAyC;AACxE,SAAO,OAAO,UAAU,YAAY,aAAa,IAAI,KAAK;AAC5D;AAEO,SAAS,iBAAiB,OAAyC;AACxE,SAAO,OAAO,UAAU,YAAY,aAAa,IAAI,KAAK;AAC5D;AAEA,IAAM,UAAU,CAAC,YAAoB,QAAQ,QAAQ,sBAAsB,OAAO,EAAE,YAAY;AAGzF,SAAS,kBAAkB,OAAuB;AACvD,SAAO,SAAS,MAAM,MAAM,GAAG,EAAE,IAAI,OAAO,EAAE,KAAK,GAAG,CAAC;AACzD;AAGO,SAAS,eAAe,OAA+B;AAC5D,SAAO,iBAAiB,KAAK,IAAI,OAAO,kBAAkB,KAAK,CAAC,MAAM;AACxE;AAGO,SAAS,eAAe,OAA+B;AAC5D,SAAO,iBAAiB,KAAK,IAAI,OAAO,kBAAkB,KAAK,CAAC,MAAM;AACxE;;;ACjCO,IAAM,eAAe;AAAA,EAC1B,KAAK;AAAA,EACL,MAAM;AAAA,EACN,WAAW;AAAA,EACX,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,WAAW;AAAA,EACX,UAAU;AAAA,EACV,OAAO;AAAA,EACP,UAAU;AAAA,EACV,WAAW;AAAA,EACX,aAAa;AAAA,EACb,OAAO;AAAA,EACP,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU;AAAA,EACV,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,iBAAiB;AAAA,EACjB,OAAO;AAAA,EACP,SAAS;AAAA,EACT,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAc;AAAA,EACd,WAAW;AAAA,EACX,SAAS;AAAA,EACT,OAAO;AACT;AAIO,IAAM,eAAe;AAAA,EAC1B,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,WAAW;AACb;AAGO,IAAM,iBAAoC;AAAA,EAC/C,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AACf;;;AC1BA,SAAS,cAAc,SAA8C;AACnE,SAAO;AAAA,IACL,UAAU,SAAS;AAAA,IACnB,YAAY,SAAS,cAAc;AAAA,IACnC,SAAS,oBAAI,IAAI;AAAA,EACnB;AACF;AAEA,SAAS,KACP,KACA,MACA,SACA,QAAyE,CAAC,GACpE;AACN,MAAI,CAAC,IAAI,SAAU;AACnB,QAAM,UAA6B,EAAE,MAAM,QAAQ;AACnD,MAAI,MAAM,YAAY,OAAW,SAAQ,UAAU,MAAM;AACzD,MAAI,MAAM,aAAa,OAAW,SAAQ,WAAW,MAAM;AAC3D,MAAI,SAAS,KAAK,OAAO;AAC3B;AAQA,SAAS,SAAS,OAA+B;AAC/C,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,IAAI,OAAgB,WAAW,IAAY;AAClD,SAAO,OAAO,UAAU,WAAW,QAAQ;AAC7C;AAEA,SAAS,eAAe,OAAoC;AAC1D,SAAO,OAAO,UAAU,WAAW,QAAQ;AAC7C;AAGA,SAAS,QAAQ,OAAgB,KAAc,OAAwB;AACrE,QAAM,MAAM,IAAI,KAAK;AACrB,MAAI,QAAQ,GAAI,QAAO;AACvB,QAAM,OAAO,QAAQ,iBAAiB,GAAG,IAAI,YAAY,GAAG;AAC5D,MAAI,SAAS,MAAM;AACjB,SAAK,KAAK,iBAAiB,+CAA+C;AAC1E,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,eAAe,OAAoC;AAC1D,SAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IAAI,QAAQ;AACvE;AAGA,SAAS,UAAa,OAAa;AACjC,SAAO,KAAK,MAAM,KAAK,UAAU,KAAK,CAAC;AACzC;AAEA,SAAS,SAAY,OAAgC;AACnD,SAAO,UAAU,SAAY,OAAO;AACtC;AAEA,SAAS,KAAK,MAAcA,QAAc,SAAoC;AAC5E,QAAM,SAAqB,EAAE,KAAK;AAClC,MAAIA,WAAU,OAAW,QAAO,QAAQA;AACxC,MAAI,YAAY,UAAa,QAAQ,SAAS,EAAG,QAAO,UAAU;AAClE,SAAO;AACT;AAEA,IAAM,YAAY,IAAI,IAAoB,WAAW,IAAI,CAAC,MAAM,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC;AAMxF,SAAS,aAAa,MAAY,KAAiC;AACjE,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO,EAAE,MAAM,KAAK,KAAK;AAAA,IAC3B,KAAK;AACH,UAAI,OAAO,KAAK,SAAS,YAAY,KAAK,SAAS,IAAI;AACrD,aAAK,KAAK,gBAAgB,4CAA4C,EAAE,UAAU,OAAO,CAAC;AAC1F,eAAO;AAAA,MACT;AACA,UAAI,YAAY,KAAK,IAAI,MAAM,MAAM;AACnC,aAAK,KAAK,gBAAgB,0CAA0C,EAAE,UAAU,OAAO,CAAC;AACxF,eAAO;AAAA,MACT;AACA,aAAO,EAAE,MAAM,aAAa,MAAM,OAAO,EAAE,MAAM,KAAK,KAAK,EAAE;AAAA,IAC/D,KAAK;AAAA,IACL,KAAK;AACH,UAAI,OAAO,KAAK,UAAU,YAAY,KAAK,UAAU,IAAI;AACvD,aAAK,KAAK,gBAAgB,KAAK,KAAK,IAAI,sCAAsC,EAAE,UAAU,KAAK,KAAK,CAAC;AACrG,eAAO;AAAA,MACT;AACA,aAAO,EAAE,MAAM,KAAK,MAAM,OAAO,EAAE,OAAO,KAAK,MAAM,EAAE;AAAA,IACzD,SAAS;AACP,YAAM,UAAU;AAChB,WAAK,KAAK,gBAAgB,aAAa,OAAO,QAAQ,IAAI,CAAC,uCAAuC;AAAA,QAChG,UAAU,OAAO,QAAQ,IAAI;AAAA,MAC/B,CAAC;AACD,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,SAAS,UAAU,OAAmC;AACpD,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,SAAS,MAAM,OAAO,CAAC,SAAS;AACpC,QAAI,KAAK,IAAI,KAAK,IAAI,EAAG,QAAO;AAChC,SAAK,IAAI,KAAK,IAAI;AAClB,WAAO;AAAA,EACT,CAAC;AACD,SAAO,OACJ,IAAI,CAAC,MAAM,WAAW,EAAE,MAAM,MAAM,EAAE,EACtC,KAAK,CAAC,GAAG,OAAO,UAAU,IAAI,EAAE,KAAK,IAAI,KAAK,OAAO,UAAU,IAAI,EAAE,KAAK,IAAI,KAAK,OAAO,EAAE,QAAQ,EAAE,KAAK,EAC3G,IAAI,CAAC,UAAU,MAAM,IAAI;AAC9B;AAEA,SAAS,cAAc,OAAoC,KAAwC;AACjG,MAAI,CAAC,SAAS,MAAM,WAAW,EAAG,QAAO;AACzC,QAAM,YAA0B,CAAC;AACjC,aAAW,QAAQ,OAAO;AACxB,UAAM,SAAS,aAAa,MAAM,GAAG;AACrC,QAAI,OAAQ,WAAU,KAAK,MAAM;AAAA,EACnC;AACA,QAAM,SAAS,UAAU,SAAS;AAClC,SAAO,OAAO,SAAS,IAAI,SAAS;AACtC;AAEA,SAAS,UAAU,MAAkB,OAA6C;AAChF,MAAI,MAAO,MAAK,QAAQ,MAAM,IAAI,CAAC,UAAU,EAAE,GAAG,MAAM,GAAI,KAAK,QAAQ,EAAE,OAAO,EAAE,GAAG,KAAK,MAAM,EAAE,IAAI,CAAC,EAAG,EAAE;AAC9G,SAAO;AACT;AAEA,SAAS,eAAe,QAA4B,KAA4B;AAC9E,QAAM,MAAoB,CAAC;AAC3B,aAAW,QAAQ,UAAU,CAAC,GAAG;AAC/B,QAAI,CAAC,SAAS,IAAI,EAAG;AACrB,YAAQ,KAAK,MAAM;AAAA,MACjB,KAAK,QAAQ;AACX,cAAM,QAAQ,cAAc,KAAK,OAAO,GAAG;AAC3C,cAAM,QAAQ,IAAI,KAAK,IAAI,EAAE,MAAM,IAAI;AACvC,cAAM,QAAQ,CAAC,MAAM,UAAU;AAC7B,cAAI,QAAQ,EAAG,KAAI,KAAK,UAAU,EAAE,MAAM,aAAa,UAAU,GAAG,KAAK,CAAC;AAC1E,cAAI,SAAS,GAAI,KAAI,KAAK,UAAU,EAAE,MAAM,aAAa,MAAM,MAAM,KAAK,GAAG,KAAK,CAAC;AAAA,QACrF,CAAC;AACD;AAAA,MACF;AAAA,MACA,KAAK;AACH,YAAI,KAAK;AAAA,UACP,MAAM,aAAa;AAAA,UACnB,OAAO,EAAE,MAAM,IAAI,KAAK,MAAM,QAAQ,GAAG,IAAI,IAAI,KAAK,EAAE,GAAG,OAAO,IAAI,KAAK,KAAK,EAAE;AAAA,QACpF,CAAC;AACD;AAAA,MACF,KAAK;AACH,YAAI,KAAK,EAAE,MAAM,aAAa,OAAO,OAAO,EAAE,WAAW,IAAI,KAAK,SAAS,EAAE,EAAE,CAAC;AAChF;AAAA,MACF;AACE,aAAK,KAAK,kBAAkB,oBAAoB,OAAQ,KAA4B,IAAI,CAAC,gBAAgB;AAAA,IAC7G;AAAA,EACF;AACA,SAAO;AACT;AAMA,SAAS,gBAAgB,OAA0C,KAAsB;AACvF,MAAI,CAAC,SAAS,MAAM,WAAW,EAAG,QAAO,CAAC;AAC1C,QAAM,YAA0B,CAAC;AACjC,aAAW,QAAQ,OAAO;AACxB,QAAI,CAAC,SAAS,IAAI,EAAG;AACrB,YAAQ,KAAK,MAAM;AAAA,MACjB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACH,kBAAU,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC;AAClC;AAAA,MACF,KAAK,QAAQ;AACX,cAAM,OAAO,eAAe,KAAK,OAAO,IAAI;AAC5C,YAAI,SAAS,UAAa,SAAS,IAAI;AACrC,eAAK,KAAK,gBAAgB,4CAA4C,EAAE,UAAU,OAAO,CAAC;AAAA,QAC5F,WAAW,YAAY,IAAI,MAAM,MAAM;AACrC,eAAK,KAAK,gBAAgB,0CAA0C,EAAE,UAAU,OAAO,CAAC;AAAA,QAC1F,OAAO;AACL,oBAAU,KAAK,EAAE,MAAM,QAAQ,OAAO,EAAE,KAAK,EAAE,CAAC;AAAA,QAClD;AACA;AAAA,MACF;AAAA,MACA,KAAK;AAAA,MACL,KAAK,aAAa;AAChB,cAAM,QAAQ,eAAe,KAAK,OAAO,KAAK;AAC9C,YAAI,UAAU,UAAa,UAAU,IAAI;AACvC,eAAK,KAAK,gBAAgB,KAAK,KAAK,IAAI,2CAA2C,EAAE,UAAU,KAAK,KAAK,CAAC;AAAA,QAC5G,OAAO;AACL,oBAAU,KAAK,EAAE,MAAM,KAAK,MAAM,OAAO,EAAE,MAAM,EAAE,CAAC;AAAA,QACtD;AACA;AAAA,MACF;AAAA,MACA;AACE,aAAK,KAAK,gBAAgB,aAAa,OAAO,KAAK,IAAI,CAAC,uCAAuC;AAAA,UAC7F,UAAU,OAAO,KAAK,IAAI;AAAA,QAC5B,CAAC;AAAA,IACL;AAAA,EACF;AACA,SAAO,UAAU,SAAS,EAAE,IAAI,CAAC,SAAe;AAC9C,YAAQ,KAAK,MAAM;AAAA,MACjB,KAAK;AACH,eAAO,EAAE,MAAM,QAAQ,MAAM,IAAI,KAAK,OAAO,IAAI,EAAE;AAAA,MACrD,KAAK;AACH,eAAO,EAAE,MAAM,SAAS,OAAO,IAAI,KAAK,OAAO,KAAK,EAAE;AAAA,MACxD,KAAK;AACH,eAAO,EAAE,MAAM,aAAa,OAAO,IAAI,KAAK,OAAO,KAAK,EAAE;AAAA,MAC5D;AACE,eAAO,EAAE,MAAM,KAAK,KAAK;AAAA,IAC7B;AAAA,EACF,CAAC;AACH;AAEA,SAAS,WAAW,GAAgC,GAA6B;AAC/E,QAAM,OAAO,KAAK,CAAC;AACnB,MAAI,KAAK,WAAW,EAAE,OAAQ,QAAO;AACrC,SAAO,KAAK,MAAM,CAAC,MAAM,UAAU,KAAK,UAAU,IAAI,MAAM,KAAK,UAAU,EAAE,KAAK,CAAC,CAAC;AACtF;AAEA,IAAM,gBAAgB,CAAC,UAAU,QAAQ,MAAM;AAE/C,SAAS,iBAAiB,OAA0C,KAAsB;AACxF,QAAM,MAAoB,CAAC;AAC3B,QAAM,WAAW,CAAC,MAAc,UAAkB;AAChD,QAAI,SAAS,GAAI;AACjB,UAAM,OAAO,IAAI,IAAI,SAAS,CAAC;AAC/B,QAAI,QAAQ,KAAK,SAAS,UAAU,WAAW,KAAK,OAAO,KAAK,GAAG;AACjE,WAAK,QAAQ;AAAA,IACf,OAAO;AACL,UAAI,KAAK,MAAM,SAAS,IAAI,EAAE,MAAM,QAAQ,MAAM,MAAM,IAAI,EAAE,MAAM,QAAQ,KAAK,CAAC;AAAA,IACpF;AAAA,EACF;AAEA,aAAW,QAAQ,SAAS,CAAC,GAAG;AAC9B,QAAI,CAAC,SAAS,IAAI,EAAG;AACrB,YAAQ,KAAK,MAAM;AAAA,MACjB,KAAK,aAAa;AAChB,iBAAS,IAAI,KAAK,IAAI,GAAG,gBAAgB,KAAK,OAAO,GAAG,CAAC;AACzD;AAAA,MACF,KAAK,aAAa;AAChB,iBAAS,MAAM,gBAAgB,KAAK,OAAO,GAAG,CAAC;AAC/C;AAAA,MACF,KAAK,aAAa,SAAS;AACzB,cAAM,OAAO,cAAc,KAAK,CAAC,cAAc,cAAc,KAAK,OAAO,IAAI,KAAK;AAClF,YAAI,KAAK,EAAE,MAAM,WAAW,MAAM,IAAI,IAAI,KAAK,OAAO,EAAE,GAAG,OAAO,IAAI,KAAK,OAAO,KAAK,EAAE,CAAC;AAC1F;AAAA,MACF;AAAA,MACA,KAAK,aAAa;AAChB,YAAI,KAAK,EAAE,MAAM,SAAS,WAAW,IAAI,KAAK,OAAO,SAAS,EAAE,CAAC;AACjE;AAAA,MACF;AAGE,aAAK,KAAK,kBAAkB,oBAAoB,KAAK,IAAI,kBAAkB,EAAE,UAAU,KAAK,KAAK,CAAC;AAClG,YAAI,OAAO,KAAK,SAAS,SAAU,UAAS,KAAK,MAAM,gBAAgB,KAAK,OAAO,GAAG,CAAC;AAAA,IAC3F;AAAA,EACF;AACA,SAAO;AACT;AAMO,SAAS,gBAAgB,QAAoC;AAClE,QAAM,MAAM,cAAc,MAAS;AACnC,SAAO,iBAAiB,eAAe,QAAQ,GAAG,GAAG,GAAG;AAC1D;AAEA,SAAS,YAAY,OAAyB;AAC5C,QAAM,SAAiB,CAAC;AACxB,QAAM,QAAQ,CAAC,MAAM,UAAU;AAC7B,QAAI,QAAQ,EAAG,QAAO,KAAK,EAAE,MAAM,QAAQ,MAAM,KAAK,CAAC;AACvD,WAAO,KAAK,GAAG,IAAI;AAAA,EACrB,CAAC;AACD,SAAO;AACT;AAEA,SAAS,YAAY,YAAgC;AACnD,MAAI,OAAO,WAAW,SAAS,SAAU,QAAO,WAAW;AAC3D,MAAI,WAAW,SAAS,aAAa,UAAW,QAAO;AACvD,QAAM,WAAW,WAAW,WAAW,CAAC;AACxC,QAAM,YAAY,SAAS,KAAK,CAAC,UAAU,EAAE,MAAM,SAAS,aAAa,QAAQ,MAAM,SAAS,aAAa,UAAU,IACnH,OACA;AACJ,SAAO,SAAS,IAAI,WAAW,EAAE,KAAK,SAAS;AACjD;AAMA,IAAM,kBAAkB,OAAmB,EAAE,MAAM,aAAa,UAAU;AAE1E,SAAS,YAAY,QAA4B,KAA0B;AACzE,SAAO,KAAK,aAAa,WAAW,QAAW,eAAe,QAAQ,GAAG,CAAC;AAC5E;AAEA,SAAS,iBACP,MACA,UACA,UACA,KACY;AACZ,QAAMA,SAAc,EAAE,IAAI,KAAK,GAAG;AAClC,MAAI,aAAa,aAAa,SAAU,CAAAA,OAAM,UAAW,KAAkB,YAAY;AACvF,QAAM,UAAwB,CAAC,YAAY,KAAK,SAAS,GAAG,CAAC;AAC7D,MAAI,KAAK,YAAY,KAAK,SAAS,SAAS,GAAG;AAC7C,YAAQ;AAAA,MACN;AAAA,QACE;AAAA,QACA;AAAA,QACA,KAAK,SAAS,IAAI,CAAC,UAAU,iBAAiB,OAAO,UAAU,UAAU,GAAG,CAAC;AAAA,MAC/E;AAAA,IACF;AAAA,EACF;AACA,SAAO,KAAK,UAAUA,QAAO,OAAO;AACtC;AAEA,SAAS,aACP,OACA,UACA,UACA,KACY;AACZ,QAAM,QAAQ,MAAM,SAAS,MAAM,MAAM,SAAS,IAAI,MAAM,QAAQ,CAAC,EAAE,IAAI,IAAI,WAAW,GAAG,SAAS,CAAC,EAAE,CAAC;AAC1G,SAAO;AAAA,IACL;AAAA,IACA,EAAE,IAAI,MAAM,GAAG;AAAA,IACf,MAAM,IAAI,CAAC,SAAS,iBAAiB,MAAM,UAAU,UAAU,GAAG,CAAC;AAAA,EACrE;AACF;AAEA,SAAS,eAAe,QAAsC,KAA4B;AACxF,UAAQ,UAAU,CAAC,GAAG,IAAI,CAAC,UAAU,cAAc,OAAO,GAAG,CAAC;AAChE;AAEA,SAAS,cAAc,OAAc,KAA0B;AAC7D,QAAM,KAAK,MAAM;AACjB,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,aAAO,KAAK,aAAa,WAAW,EAAE,GAAG,GAAG,eAAe,MAAM,SAAS,GAAG,CAAC;AAAA,IAChF,KAAK;AACH,aAAO,KAAK,aAAa,SAAS,EAAE,IAAI,OAAO,MAAM,MAAM,GAAG,eAAe,MAAM,SAAS,GAAG,CAAC;AAAA,IAClG,KAAK;AACH,aAAO,KAAK,aAAa,YAAY,EAAE,GAAG,GAAG,CAAC,YAAY,MAAM,SAAS,GAAG,CAAC,CAAC;AAAA,IAChF,KAAK;AACH,aAAO,KAAK,aAAa,SAAS,EAAE,IAAI,SAAS,MAAM,QAAQ,GAAG,eAAe,MAAM,SAAS,GAAG,CAAC;AAAA,IACtG,KAAK;AACH,aAAO,KAAK,aAAa,QAAQ,EAAE,GAAG,GAAG;AAAA,QACvC,KAAK,aAAa,eAAe,QAAW,eAAe,MAAM,SAAS,GAAG,CAAC;AAAA,QAC9E,GAAG,eAAe,MAAM,UAAU,GAAG;AAAA,MACvC,CAAC;AAAA,IACH,KAAK;AACH,aAAO,KAAK,aAAa,gBAAgB,EAAE,GAAG,CAAC;AAAA,IACjD,KAAK;AACH,aAAO,aAAa,OAAO,aAAa,YAAY,aAAa,UAAU,GAAG;AAAA,IAChF,KAAK;AACH,aAAO,aAAa,OAAO,aAAa,aAAa,aAAa,UAAU,GAAG;AAAA,IACjF,KAAK;AACH,aAAO,aAAa,OAAO,aAAa,UAAU,aAAa,UAAU,GAAG;AAAA,IAC9E,KAAK;AACH,aAAO;AAAA,QACL,aAAa;AAAA,QACb,EAAE,IAAI,UAAU,SAAS,MAAM,QAAQ,EAAE;AAAA,QACzC,MAAM,OAAO,CAAC,EAAE,MAAM,aAAa,MAAM,MAAM,MAAM,KAAK,CAAC,IAAI,CAAC;AAAA,MAClE;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,aAAa;AAAA,QACb,EAAE,GAAG;AAAA,QACL,MAAM,QAAQ,CAAC,EAAE,MAAM,aAAa,MAAM,MAAM,MAAM,MAAM,CAAC,IAAI,CAAC;AAAA,MACpE;AAAA,IACF,KAAK;AACH,aAAO,cAAc,OAAO,GAAG;AAAA,IACjC,KAAK;AACH,aAAO;AAAA,QACL,MAAM,aAAa;AAAA,QACnB,OAAO;AAAA,UACL;AAAA,UACA,KAAK,MAAM;AAAA,UACX,KAAK,MAAM,OAAO;AAAA,UAClB,SAAS,MAAM,YAAY,SAAY,OAAO,gBAAgB,MAAM,OAAO;AAAA,UAC3E,OAAO,SAAS,MAAM,KAAK;AAAA,UAC3B,OAAO,SAAS,MAAM,KAAK;AAAA,QAC7B;AAAA,MACF;AAAA,IACF,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,QACL,MAAM,aAAa;AAAA,QACnB,OAAO;AAAA,UACL;AAAA,UACA,MAAM,MAAM;AAAA,UACZ,KAAK,MAAM;AAAA,UACX,SAAS,MAAM,YAAY,SAAY,OAAO,gBAAgB,MAAM,OAAO;AAAA,QAC7E;AAAA,MACF;AAAA,IACF,KAAK;AACH,aAAO,EAAE,MAAM,aAAa,MAAM,OAAO,EAAE,IAAI,KAAK,MAAM,KAAK,MAAM,MAAM,MAAM,MAAM,SAAS,MAAM,IAAI,EAAE,EAAE;AAAA,IAChH,KAAK;AACH,aAAO;AAAA,QACL,MAAM,aAAa;AAAA,QACnB,OAAO,EAAE,IAAI,KAAK,MAAM,KAAK,OAAO,SAAS,MAAM,KAAK,GAAG,aAAa,SAAS,MAAM,WAAW,EAAE;AAAA,MACtG;AAAA,IACF,KAAK,WAAW;AACd,YAAM,UAAU,MAAM,WAAW,MAAM,QAAQ,SAAS,IAAI,MAAM,UAAU,CAAC,CAAC,CAAC;AAC/E,aAAO;AAAA,QACL,aAAa;AAAA,QACb,EAAE,GAAG;AAAA,QACL,QAAQ,IAAI,CAAC,WAAW;AACtB,gBAAM,UAAU,eAAe,QAAQ,GAAG;AAC1C,iBAAO,KAAK,aAAa,QAAQ,QAAW,QAAQ,SAAS,IAAI,UAAU,CAAC,gBAAgB,CAAC,CAAC;AAAA,QAChG,CAAC;AAAA,MACH;AAAA,IACF;AAAA,IACA,KAAK;AACH,aAAO,EAAE,MAAM,aAAa,WAAW,OAAO,EAAE,GAAG,EAAE;AAAA,IACvD,KAAK;AACH,aAAO,EAAE,MAAM,aAAa,iBAAiB,OAAO,EAAE,GAAG,EAAE;AAAA,IAC7D,KAAK;AACH,aAAO,EAAE,MAAM,aAAa,OAAO,OAAO,EAAE,IAAI,MAAM,UAAU,MAAM,IAAI,EAAE,EAAE;AAAA,IAChF,KAAK;AACH,aAAO;AAAA,QACL,MAAM,aAAa;AAAA,QACnB,OAAO;AAAA,UACL;AAAA,UACA,QAAQ,MAAM;AAAA,UACd,SAAS,MAAM,YAAY,SAAY,OAAO,UAAU,MAAM,OAAO;AAAA,UACrE,QAAQ,SAAS,MAAM,MAAM;AAAA,QAC/B;AAAA,MACF;AAAA,IACF,KAAK;AACH,aAAO,EAAE,MAAM,aAAa,UAAU,OAAO,EAAE,IAAI,SAAS,MAAM,SAAS,MAAM,UAAU,MAAM,IAAI,EAAE,EAAE;AAAA,IAC3G,KAAK;AACH,aAAO;AAAA,QACL,MAAM,aAAa;AAAA,QACnB,OAAO,EAAE,IAAI,QAAQ,MAAM,QAAQ,QAAQ,MAAM,WAAW,SAAY,OAAO,UAAU,MAAM,MAAM,EAAE;AAAA,MACzG;AAAA,IACF,SAAS;AACP,YAAM,UAAU;AAChB,YAAM,YAAY,OAAO,QAAQ,IAAI;AACrC,YAAM,UAAU,eAAe,QAAQ,EAAE;AACzC,WAAK,KAAK,iBAAiB,mBAAmB,SAAS,sDAAsD;AAAA,QAC3G;AAAA,QACA,UAAU;AAAA,MACZ,CAAC;AACD,aAAO;AAAA,QACL,MAAM,aAAa;AAAA,QACnB,OAAO,EAAE,IAAI,SAAS,OAAO,GAAG,WAAW,SAAS,UAAU,OAAO,EAAE;AAAA,MACzE;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,cAAc,OAA0C,KAA0B;AACzF,QAAM,OAAsB,MAAM,QAAQ,MAAM,KAAK,SAAS,IAAI,MAAM,OAAO,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;AACjG,QAAM,YAAY,MAAM;AACxB,QAAM,eAAe,MAAM;AAC3B,SAAO;AAAA,IACL,aAAa;AAAA,IACb,EAAE,IAAI,MAAM,IAAI,WAAW,SAAS,SAAS,GAAG,cAAc,SAAS,YAAY,EAAE;AAAA,IACrF,KAAK;AAAA,MAAI,CAAC,KAAK,aACb;AAAA,QACE,aAAa;AAAA,QACb;AAAA,QACA,IAAI,IAAI,CAAC,MAAM,gBAAgB;AAC7B,gBAAM,WACJ,KAAK,WAAW,QACf,cAAc,QAAQ,aAAa,KACnC,iBAAiB,QAAQ,gBAAgB;AAC5C,iBAAO;AAAA,YACL,WAAW,aAAa,cAAc,aAAa;AAAA,YACnD,EAAE,SAAS,KAAK,WAAW,GAAG,SAAS,KAAK,WAAW,GAAG,UAAU,KAAK;AAAA,YACzE,CAAC,YAAY,KAAK,SAAS,GAAG,CAAC;AAAA,UACjC;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;AAMA,SAAS,OAAO,QAAoB,KAAsB;AACxD,QAAM,YAAY,OAAO,OAAO;AAChC,MAAI,KAAK,OAAO,cAAc,YAAY,cAAc,KAAK,YAAY;AACzE,MAAI,OAAO,MAAM,IAAI,QAAQ,IAAI,EAAE,GAAG;AACpC,SAAK,KAAK,gBAAgB,WAAW,EAAE,oDAAoD;AAAA,MACzF,SAAS;AAAA,MACT,UAAU,OAAO;AAAA,IACnB,CAAC;AACD,SAAK;AAAA,EACP;AACA,MAAI,OAAO,IAAI;AACb,OAAG;AACD,WAAK,IAAI,WAAW;AAAA,IACtB,SAAS,IAAI,QAAQ,IAAI,EAAE;AAAA,EAC7B;AACA,MAAI,QAAQ,IAAI,EAAE;AAClB,SAAO;AACT;AAGA,SAAS,kBAAkB,WAAuB,KAAsB;AACtE,SAAO,iBAAiB,UAAU,SAAS,GAAG;AAChD;AAGA,SAAS,kBAAkB,WAAuB,KAAc,aAA+B;AAC7F,QAAM,OAAiB,CAAC;AACxB,aAAW,SAAS,UAAU,WAAW,CAAC,GAAG;AAC3C,QAAI,MAAM,SAAS,aAAa,aAAa,MAAM,SAAS,aAAa,SAAS;AAChF,WAAK,KAAK,kBAAkB,OAAO,GAAG,CAAC;AAAA,IACzC,WAAW,aAAa;AACtB,sBAAgB,OAAO,KAAK,WAAW;AAAA,IACzC,OAAO;AACL,YAAM,OAAO,YAAY,KAAK;AAC9B,WAAK,KAAK,SAAS,MAAM,MAAM,IAAI,cAAc,UAAU,IAAI,+BAA+B;AAAA,QAC5F,UAAU,MAAM;AAAA,MAClB,CAAC;AACD,UAAI,SAAS,GAAI,MAAK,KAAK,CAAC,EAAE,MAAM,QAAQ,KAAK,CAAC,CAAC;AAAA,IACrD;AAAA,EACF;AACA,SAAO,gBAAgB,YAAY,IAAI,CAAC;AAC1C;AAIA,SAAS,mBACP,QACA,gBACA,QACA,KACU;AACV,QAAM,KAAK,OAAO,QAAQ,GAAG;AAC7B,QAAM,OAAiB,CAAC;AACxB,QAAM,WAAuB,CAAC;AAE9B,aAAW,SAAS,OAAO,WAAW,CAAC,GAAG;AACxC,QAAI,MAAM,SAAS,aAAa,WAAW;AACzC,WAAK,KAAK,kBAAkB,OAAO,GAAG,CAAC;AAAA,IACzC,WACE,MAAM,SAAS,aAAa,cAC5B,MAAM,SAAS,aAAa,eAC5B,MAAM,SAAS,aAAa,UAC5B;AACA,UAAI,MAAM,SAAS,gBAAgB;AACjC,aAAK,KAAK,SAAS,YAAY,MAAM,IAAI,aAAa,cAAc,sCAAsC;AAAA,UACxG,UAAU,MAAM;AAAA,QAClB,CAAC;AAAA,MACH;AACA,iBAAW,UAAU,MAAM,WAAW,CAAC,GAAG;AACxC,YAAI,OAAO,SAAS,aAAa,YAAY,OAAO,SAAS,aAAa,UAAU;AAClF,mBAAS,KAAK,mBAAmB,QAAQ,gBAAgB,QAAQ,GAAG,CAAC;AAAA,QACvE;AAAA,MACF;AAAA,IACF,OAAO;AACL,YAAM,OAAO,YAAY,KAAK;AAC9B,WAAK,KAAK,SAAS,MAAM,MAAM,IAAI,mDAAmD,EAAE,UAAU,MAAM,KAAK,CAAC;AAC9G,UAAI,SAAS,GAAI,MAAK,KAAK,CAAC,EAAE,MAAM,QAAQ,KAAK,CAAC,CAAC;AAAA,IACrD;AAAA,EACF;AAEA,QAAM,UAAU,gBAAgB,YAAY,IAAI,CAAC;AACjD,QAAM,SAAmB,SACrB,EAAE,IAAI,SAAS,SAAS,OAAO,OAAO,YAAY,KAAK,IACvD,EAAE,IAAI,QAAQ;AAClB,MAAI,SAAS,SAAS,EAAG,QAAO,WAAW;AAC3C,SAAO;AACT;AAEA,SAAS,eACP,QACA,MACA,KACO;AACP,QAAM,KAAK,OAAO,QAAQ,GAAG;AAC7B,QAAM,SAAS,SAAS;AACxB,QAAM,QAAoB,CAAC;AAC3B,aAAW,SAAS,OAAO,WAAW,CAAC,GAAG;AACxC,QAAI,MAAM,SAAS,aAAa,YAAY,MAAM,SAAS,aAAa,UAAU;AAChF,YAAM,KAAK,mBAAmB,OAAO,OAAO,MAAM,QAAQ,GAAG,CAAC;AAAA,IAChE;AAAA,EACF;AACA,SAAO,EAAE,IAAI,MAAM,MAAM;AAC3B;AAEA,IAAM,qBAAqB,CAAC,MAAM,KAAK;AAEvC,SAAS,SAAS,OAAgC;AAChD,SAAO,mBAAmB,KAAK,CAAC,cAAc,cAAc,KAAK,KAAK;AACxE;AAEA,SAAS,kBAAkB,MAAsB,WAAoB,WAAyC;AAC5G,MAAI,SAAS,KAAM,QAAO;AAC1B,MAAI,SAAS,MAAO,QAAO;AAC3B,SAAO,aAAa,CAAC,YAAY,OAAO;AAC1C;AAEA,SAAS,gBAAgB,QAAoB,KAAqB;AAChE,QAAM,KAAK,OAAO,QAAQ,GAAG;AAC7B,QAAM,YAAY,OAAO,WAAW,CAAC,GAAG,OAAO,CAAC,QAAQ,IAAI,SAAS,aAAa,QAAQ;AAC1F,QAAM,OAAO,SAAS;AAAA,IAAI,CAAC,SACxB,IAAI,WAAW,CAAC,GAAG;AAAA,MAClB,CAAC,SAAS,KAAK,SAAS,aAAa,aAAa,KAAK,SAAS,aAAa;AAAA,IAC/E;AAAA,EACF;AAEA,QAAM,WAAW,CAAC,SAAqB,KAAK,SAAS,aAAa;AAClE,QAAM,WAAW,KAAK,CAAC,KAAK,CAAC;AAC7B,QAAM,SAAS,SAAS,SAAS,KAAK,SAAS,MAAM,QAAQ;AAC7D,QAAM,YAAY,KAAK,SAAS,KAAK,KAAK,MAAM,CAAC,QAAQ,IAAI,SAAS,KAAK,SAAS,IAAI,CAAC,CAAe,CAAC;AAEzG,QAAM,YAAY;AAAA,IAChB,SAAS,OAAO,OAAO,SAAS;AAAA,IAChC;AAAA,IACA,SAAS,WAAW,KAAK;AAAA,EAC3B;AACA,QAAM,eAAe;AAAA,IACnB,SAAS,OAAO,OAAO,YAAY;AAAA,IACnC;AAAA,IACA,KAAK,WAAW,KAAK;AAAA,EACvB;AAEA,QAAM,OAAsB,KAAK;AAAA,IAAI,CAAC,KAAK,aACzC,IAAI,IAAI,CAAC,UAAU,gBAAgB;AACjC,YAAM,OAAkB,EAAE,SAAS,kBAAkB,UAAU,GAAG,EAAE;AACpE,YAAM,UAAU,eAAe,SAAS,OAAO,OAAO;AACtD,YAAM,UAAU,eAAe,SAAS,OAAO,OAAO;AACtD,UAAI,YAAY,UAAa,UAAU,EAAG,MAAK,UAAU;AACzD,UAAI,YAAY,UAAa,UAAU,EAAG,MAAK,UAAU;AACzD,YAAM,eAAe,cAAc,QAAQ,aAAa;AACxD,YAAM,kBAAkB,iBAAiB,QAAQ,gBAAgB;AACjE,UAAI,SAAS,QAAQ,KAAK,CAAC,gBAAgB,CAAC,gBAAiB,MAAK,SAAS;AAC3E,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AACA,MAAI,KAAK,WAAW,EAAG,MAAK,KAAK,CAAC,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;AAElD,QAAM,QAA2C,EAAE,IAAI,MAAM,SAAS,KAAK;AAC3E,MAAI,cAAc,OAAW,OAAM,YAAY;AAC/C,MAAI,iBAAiB,OAAW,OAAM,eAAe;AACrD,SAAO;AACT;AAEA,SAAS,WAAW,QAA4B;AAC9C,UAAQ,OAAO,WAAW,CAAC,GAAG,IAAI,CAAC,UAAW,MAAM,SAAS,aAAa,YAAY,OAAO,IAAI,MAAM,IAAI,CAAE,EAAE,KAAK,EAAE;AACxH;AAEA,SAAS,UAAU,OAAgB,KAAkC;AACnE,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO;AAClC,QAAM,SAAS,iBAAiB,eAAe,OAAiB,GAAG,GAAG,GAAG;AACzE,SAAO;AACT;AAEA,IAAM,aAAa,CAAC,SAAS,UAAU,KAAK;AAC5C,IAAM,kBAAkB,CAAC,WAAW,UAAU,YAAY;AAE1D,SAAS,gBAAgB,QAAoB,KAAc,KAAoB;AAC7E,MAAI,CAAC,SAAS,MAAM,EAAG;AACvB,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK,aAAa;AAChB,UAAI,KAAK,EAAE,IAAI,OAAO,QAAQ,GAAG,GAAG,MAAM,aAAa,SAAS,kBAAkB,QAAQ,GAAG,EAAE,CAAC;AAChG;AAAA,IACF,KAAK,aAAa,SAAS;AACzB,YAAM,KAAK,OAAO,QAAQ,GAAG;AAC7B,YAAM,MAAM,eAAe,OAAO,OAAO,KAAK,KAAK;AACnD,YAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,MAAM,GAAG,CAAC,CAAC;AACtD,UAAI,UAAU,KAAK;AACjB,aAAK,KAAK,iBAAiB,iBAAiB,GAAG,mBAAmB,KAAK,KAAK,EAAE,SAAS,IAAI,UAAU,UAAU,CAAC;AAAA,MAClH;AACA,UAAI,KAAK,EAAE,IAAI,MAAM,WAAW,OAAO,SAAS,kBAAkB,QAAQ,GAAG,EAAE,CAAC;AAChF;AAAA,IACF;AAAA,IACA,KAAK,aAAa,YAAY;AAC5B,YAAM,KAAK,OAAO,QAAQ,GAAG;AAC7B,YAAM,WAAoB,CAAC;AAC3B,YAAM,UAAU,kBAAkB,QAAQ,KAAK,QAAQ;AACvD,YAAM,WAAW,OAAO,WAAW,CAAC,GAAG;AAAA,QACrC,CAAC,UAAU,MAAM,SAAS,aAAa,aAAa,MAAM,SAAS,aAAa;AAAA,MAClF;AACA,UAAI,WAAW,SAAS,WAAW,EAAG,KAAI,KAAK,EAAE,IAAI,MAAM,SAAS,QAAQ,CAAC;AAC7E,UAAI,KAAK,GAAG,QAAQ;AACpB;AAAA,IACF;AAAA,IACA,KAAK,aAAa,SAAS;AACzB,YAAM,KAAK,OAAO,QAAQ,GAAG;AAC7B,YAAM,MAAM,OAAO,OAAO;AAC1B,YAAM,UAA0B,iBAAiB,KAAK,CAAC,cAAc,cAAc,GAAG,KAAK;AAC3F,UAAI,YAAY,KAAK;AACnB,aAAK,KAAK,iBAAiB,oBAAoB,OAAO,GAAG,CAAC,oBAAoB,EAAE,SAAS,IAAI,UAAU,UAAU,CAAC;AAAA,MACpH;AACA,UAAI,KAAK,EAAE,IAAI,MAAM,WAAW,SAAS,SAAS,kBAAkB,QAAQ,GAAG,EAAE,CAAC;AAClF;AAAA,IACF;AAAA,IACA,KAAK,aAAa,QAAQ;AACxB,YAAM,KAAK,OAAO,QAAQ,GAAG;AAC7B,YAAM,CAAC,OAAO,GAAG,IAAI,IAAI,OAAO,WAAW,CAAC;AAC5C,YAAM,aAAa,OAAO,SAAS,aAAa;AAChD,YAAM,WAAoB,CAAC;AAC3B,iBAAW,SAAS,aAAa,OAAQ,OAAO,WAAW,CAAC,EAAI,iBAAgB,OAAO,KAAK,QAAQ;AACpG,UAAI,KAAK;AAAA,QACP;AAAA,QACA,MAAM;AAAA,QACN,SAAS,cAAc,QAAQ,kBAAkB,OAAO,GAAG,IAAI,CAAC;AAAA,QAChE;AAAA,MACF,CAAC;AACD;AAAA,IACF;AAAA,IACA,KAAK,aAAa;AAChB,UAAI,KAAK,EAAE,IAAI,OAAO,QAAQ,GAAG,GAAG,MAAM,UAAU,CAAC;AACrD;AAAA,IACF,KAAK,aAAa;AAChB,UAAI,KAAK,eAAe,QAAQ,iBAAiB,GAAG,CAAC;AACrD;AAAA,IACF,KAAK,aAAa;AAChB,UAAI,KAAK,eAAe,QAAQ,iBAAiB,GAAG,CAAC;AACrD;AAAA,IACF,KAAK,aAAa;AAChB,UAAI,KAAK,eAAe,QAAQ,aAAa,GAAG,CAAC;AACjD;AAAA,IACF,KAAK,aAAa,WAAW;AAC3B,YAAM,QAA0C;AAAA,QAC9C,IAAI,OAAO,QAAQ,GAAG;AAAA,QACtB,MAAM;AAAA,QACN,MAAM,WAAW,MAAM;AAAA,MACzB;AACA,YAAM,WAAW,eAAe,OAAO,OAAO,QAAQ;AACtD,UAAI,aAAa,OAAW,OAAM,WAAW;AAC7C,UAAI,KAAK,KAAK;AACd;AAAA,IACF;AAAA,IACA,KAAK,aAAa;AAChB,UAAI,KAAK,EAAE,IAAI,OAAO,QAAQ,GAAG,GAAG,MAAM,YAAY,OAAO,WAAW,MAAM,EAAE,CAAC;AACjF;AAAA,IACF,KAAK,aAAa;AAChB,UAAI,KAAK,gBAAgB,QAAQ,GAAG,CAAC;AACrC;AAAA,IACF,KAAK,aAAa,OAAO;AACvB,YAAM,QAA2C;AAAA,QAC/C,IAAI,OAAO,QAAQ,GAAG;AAAA,QACtB,MAAM;AAAA,QACN,KAAK,QAAQ,OAAO,OAAO,KAAK,KAAK,IAAI;AAAA,QACzC,KAAK,IAAI,OAAO,OAAO,GAAG;AAAA,MAC5B;AACA,YAAM,UAAU,UAAU,OAAO,OAAO,SAAS,GAAG;AACpD,UAAI,YAAY,OAAW,OAAM,UAAU;AAC3C,YAAM,QAAQ,WAAW,KAAK,CAAC,cAAc,cAAc,OAAO,OAAO,KAAK;AAC9E,UAAI,UAAU,OAAW,OAAM,QAAQ;AACvC,YAAM,QAAQ,eAAe,OAAO,OAAO,KAAK;AAChD,UAAI,UAAU,OAAW,OAAM,QAAQ;AACvC,UAAI,KAAK,KAAK;AACd;AAAA,IACF;AAAA,IACA,KAAK,aAAa,OAAO;AACvB,YAAM,QAAqD;AAAA,QACzD,IAAI,OAAO,QAAQ,GAAG;AAAA,QACtB,MAAM,OAAO,OAAO,SAAS,UAAU,UAAU;AAAA,QACjD,KAAK,QAAQ,OAAO,OAAO,KAAK,KAAK,IAAI;AAAA,MAC3C;AACA,YAAM,UAAU,UAAU,OAAO,OAAO,SAAS,GAAG;AACpD,UAAI,YAAY,OAAW,OAAM,UAAU;AAC3C,UAAI,KAAK,KAAK;AACd;AAAA,IACF;AAAA,IACA,KAAK,aAAa,MAAM;AACtB,YAAM,QAA0C;AAAA,QAC9C,IAAI,OAAO,QAAQ,GAAG;AAAA,QACtB,MAAM;AAAA,QACN,KAAK,QAAQ,OAAO,OAAO,KAAK,KAAK,KAAK;AAAA,QAC1C,MAAM,IAAI,OAAO,OAAO,IAAI;AAAA,MAC9B;AACA,YAAM,OAAO,eAAe,OAAO,OAAO,IAAI;AAC9C,UAAI,SAAS,OAAW,OAAM,OAAO;AACrC,UAAI,KAAK,KAAK;AACd;AAAA,IACF;AAAA,IACA,KAAK,aAAa,UAAU;AAC1B,YAAM,QAA8C;AAAA,QAClD,IAAI,OAAO,QAAQ,GAAG;AAAA,QACtB,MAAM;AAAA,QACN,KAAK,QAAQ,OAAO,OAAO,KAAK,KAAK,KAAK;AAAA,MAC5C;AACA,YAAM,QAAQ,eAAe,OAAO,OAAO,KAAK;AAChD,YAAM,cAAc,eAAe,OAAO,OAAO,WAAW;AAC5D,UAAI,UAAU,OAAW,OAAM,QAAQ;AACvC,UAAI,gBAAgB,OAAW,OAAM,cAAc;AACnD,UAAI,KAAK,KAAK;AACd;AAAA,IACF;AAAA,IACA,KAAK,aAAa,SAAS;AACzB,YAAM,KAAK,OAAO,QAAQ,GAAG;AAC7B,YAAM,UAAqB,CAAC;AAC5B,iBAAW,UAAU,OAAO,WAAW,CAAC,GAAG;AACzC,YAAI,OAAO,SAAS,aAAa,OAAQ;AACzC,cAAM,SAAkB,CAAC;AACzB,mBAAW,SAAS,OAAO,WAAW,CAAC,EAAG,iBAAgB,OAAO,KAAK,MAAM;AAC5E,gBAAQ,KAAK,MAAM;AAAA,MACrB;AACA,UAAI,KAAK,EAAE,IAAI,MAAM,WAAW,QAAQ,CAAC;AACzC;AAAA,IACF;AAAA,IACA,KAAK,aAAa;AAChB,UAAI,KAAK,EAAE,IAAI,OAAO,QAAQ,GAAG,GAAG,MAAM,aAAa,CAAC;AACxD;AAAA,IACF,KAAK,aAAa;AAChB,UAAI,KAAK,EAAE,IAAI,OAAO,QAAQ,GAAG,GAAG,MAAM,oBAAoB,CAAC;AAC/D;AAAA,IACF,KAAK,aAAa;AAChB,UAAI,KAAK;AAAA,QACP,IAAI,OAAO,QAAQ,GAAG;AAAA,QACtB,MAAM;AAAA,QACN,MAAM,UAAU,OAAO,OAAO,IAAI;AAAA,MACpC,CAAC;AACD;AAAA,IACF,KAAK,aAAa,SAAS;AACzB,YAAM,QAA6C;AAAA,QACjD,IAAI,OAAO,QAAQ,GAAG;AAAA,QACtB,MAAM;AAAA,QACN,QAAQ,gBAAgB,KAAK,CAAC,cAAc,cAAc,OAAO,OAAO,MAAM,KAAK;AAAA,MACrF;AACA,UAAI,SAAS,OAAO,OAAO,OAAO,EAAG,OAAM,UAAU,UAAU,OAAO,OAAO,OAAO;AACpF,YAAM,gBAAgB,eAAe,OAAO,OAAO,MAAM;AACzD,UAAI,kBAAkB,OAAW,OAAM,SAAS;AAChD,UAAI,KAAK,KAAK;AACd;AAAA,IACF;AAAA,IACA,KAAK,aAAa;AAChB,UAAI,KAAK;AAAA,QACP,IAAI,OAAO,QAAQ,GAAG;AAAA,QACtB,MAAM;AAAA,QACN,SAAS,IAAI,OAAO,OAAO,OAAO;AAAA,QAClC,MAAM,UAAU,OAAO,OAAO,IAAI;AAAA,MACpC,CAAC;AACD;AAAA,IACF,KAAK,aAAa,SAAS;AACzB,YAAM,QAAwC;AAAA,QAC5C,IAAI,OAAO,QAAQ,GAAG;AAAA,QACtB,MAAM;AAAA,QACN,QAAQ,IAAI,OAAO,OAAO,MAAM;AAAA,MAClC;AACA,UAAI,MAAM,QAAQ,OAAO,OAAO,MAAM,EAAG,OAAM,SAAS,UAAU,OAAO,OAAO,MAAM;AACtF,UAAI,KAAK,KAAK;AACd;AAAA,IACF;AAAA,IACA,KAAK,aAAa,cAAc;AAC9B,YAAM,UAAU,OAAO,OAAO;AAC9B,UAAI,SAAS,OAAO,GAAG;AACrB,cAAM,OAAO,UAAU,OAAO;AAC9B,cAAM,KAAK,eAAe,KAAK,EAAE,KAAK,eAAe,OAAO,OAAO,EAAE,KAAK,IAAI,WAAW;AACzF,aAAK,KAAK;AACV,YAAI,QAAQ,IAAI,EAAE;AAClB,aAAK,KAAK,iBAAiB,mBAAmB,OAAO,KAAK,IAAI,CAAC,0CAA0C;AAAA,UACvG,SAAS;AAAA,UACT,UAAU,OAAO,KAAK,IAAI;AAAA,QAC5B,CAAC;AACD,YAAI,KAAK,IAAwB;AAAA,MACnC;AACA;AAAA,IACF;AAAA,IACA,KAAK,aAAa;AAAA,IAClB,KAAK,aAAa;AAAA,IAClB,KAAK,aAAa;AAAA,IAClB,KAAK,aAAa;AAEhB,UAAI,KAAK,EAAE,IAAI,IAAI,WAAW,GAAG,MAAM,aAAa,SAAS,iBAAiB,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;AAC9F;AAAA,IACF,SAAS;AAGP,YAAM,WAAW,OAAO,WAAW,CAAC;AACpC,YAAM,gBAAgB,SAAS,SAAS,KAAK,SAAS;AAAA,QAAM,CAAC,UAC3D,MAAM,SAAS,aAAa,QAAQ,MAAM,SAAS,aAAa,aAAa,MAAM,SAAS,aAAa,WAAW,MAAM,SAAS,aAAa;AAAA,MAClJ;AACA,WAAK,KAAK,gBAAgB,aAAa,OAAO,IAAI,yDAAyD;AAAA,QACzG,UAAU,OAAO;AAAA,MACnB,CAAC;AACD,UAAI,eAAe;AACjB,YAAI,KAAK,EAAE,IAAI,OAAO,QAAQ,GAAG,GAAG,MAAM,aAAa,SAAS,kBAAkB,QAAQ,GAAG,EAAE,CAAC;AAAA,MAClG,OAAO;AACL,mBAAW,SAAS,SAAU,iBAAgB,OAAO,KAAK,GAAG;AAAA,MAC/D;AAAA,IACF;AAAA,EACF;AACF;AAWO,SAAS,iBAAiB,KAAqB,SAAqC;AACzF,QAAM,MAAM,cAAc,OAAO;AACjC,QAAM,UAAU,eAAe,IAAI,QAAQ,GAAG;AAC9C,QAAM,SAAoB;AAAA,IACxB,MAAM;AAAA,IACN,SAAS,QAAQ,SAAS,IAAI,UAAU,CAAC,EAAE,MAAM,aAAa,WAAW,OAAO,EAAE,IAAI,IAAI,WAAW,EAAE,EAAE,CAAC;AAAA,EAC5G;AACA,MAAI,IAAI,UAAU,OAAW,QAAO,QAAQ,EAAE,OAAO,IAAI,MAAM;AAC/D,SAAO;AACT;AAMO,SAAS,iBAAiB,MAAkB,SAA0C;AAC3F,QAAM,MAAM,cAAc,OAAO;AACjC,QAAM,SAAkB,CAAC;AACzB,QAAM,MAAM,KAAK,SAAS,QAAS,KAAK,WAAW,CAAC,IAAK,CAAC,IAAI;AAC9D,aAAW,SAAS,IAAK,iBAAgB,OAAO,KAAK,MAAM;AAC3D,QAAM,MAAsB,EAAE,SAAS,kBAAkB,OAAO;AAChE,QAAM,QAAQ,eAAe,KAAK,OAAO,KAAK;AAC9C,MAAI,UAAU,OAAW,KAAI,QAAQ;AACrC,SAAO;AACT;AAMO,SAAS,kBAAkB,KAAqB,SAA0C;AAC/F,QAAM,MAAsB,EAAE,GAAG,QAAQ;AACzC,SAAO,iBAAiB,iBAAiB,KAAK,GAAG,GAAG,GAAG;AACzD;;;AC//BO,IAAM,mBAAqD;AAAA,EAChE,OAAO;AAAA,EACP,MAAM;AAAA,EACN,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP,UAAU;AAAA,EACV,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,MAAM;AAAA,EACN,UAAU;AAAA,EACV,UAAU;AAAA,EACV,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EACP,kBAAkB;AAAA,EAClB,GAAG;AAAA,EACH,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,UAAU;AAAA,EACV,MAAM;AAAA,EACN,MAAM;AAAA,EACN,SAAS;AAAA,EACT,WAAW;AAAA,EACX,KAAK;AAAA,EACL,KAAK;AAAA,EACL,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,UAAU;AAAA,EACV,aAAa;AACf;AAGO,SAAS,kBAAkB,WAAkC;AAClE,QAAM,MAAM,UAAU,QAAQ,UAAU,EAAE,EAAE,YAAY;AACxD,SAAO,iBAAiB,GAAG,KAAK;AAClC;AAGO,SAAS,YAAY,WAA2B;AACrD,SAAO,kBAAkB,SAAS,KAAK,IAAI,UAAU,QAAQ,UAAU,EAAE,CAAC;AAC5E;;;AChDO,SAAS,kBAAkB,QAAoC;AACpE,MAAI,OAAO;AACX,aAAWC,SAAQ,UAAU,CAAC,GAAG;AAC/B,QAAIA,MAAK,SAAS,OAAQ,SAAQA,MAAK;AAAA,aAC9BA,MAAK,SAAS,UAAW,SAAQ,IAAIA,MAAK,KAAK;AAAA,aAC/CA,MAAK,SAAS,QAAS,SAAQ,YAAYA,MAAK,SAAS;AAAA,EACpE;AACA,SAAO;AACT;AASA,SAAS,OAAO,OAAuB;AACrC,SAAO,KAAK,OAAO,KAAK;AAC1B;AAEA,SAAS,UACP,OACA,MACA,SACA,OACU;AACV,QAAM,QAAkB,CAAC;AACzB,QAAM,QAAQ,CAAC,MAAM,UAAU;AAC7B,QAAI,SAAS;AACb,QAAI,SAAS;AACX,UAAI,SAAS,WAAY,UAAS;AAAA,eACzB,SAAS,WAAY,UAAS,GAAG,QAAQ,CAAC;AAAA,UAC9C,UAAS,IAAK,KAAkB,UAAU,MAAM,GAAG;AAAA,IAC1D;AACA,UAAM,KAAK,GAAG,UAAU,OAAO,KAAK,IAAI,EAAE,GAAG,MAAM,GAAG,kBAAkB,KAAK,OAAO,CAAC,EAAE;AACvF,QAAI,KAAK,SAAU,OAAM,KAAK,GAAG,UAAU,KAAK,UAAU,MAAM,SAAS,QAAQ,CAAC,CAAC;AAAA,EACrF,CAAC;AACD,SAAO;AACT;AAEA,SAAS,UAAU,OAAc,SAA6C;AAC5E,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO,kBAAkB,MAAM,OAAO;AAAA,IACxC,KAAK,UAAU;AACb,YAAM,QAAQ,CAAC,kBAAkB,MAAM,OAAO,GAAG,GAAG,WAAW,MAAM,YAAY,CAAC,GAAG,OAAO,CAAC;AAC7F,aAAO,MAAM,OAAO,CAAC,SAAS,SAAS,EAAE,EAAE,KAAK,QAAQ,cAAc;AAAA,IACxE;AAAA,IACA,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO,UAAU,MAAM,SAAS,CAAC,GAAG,YAAY,QAAQ,SAAS,CAAC,EAAE,KAAK,IAAI;AAAA,IAC/E,KAAK;AACH,aAAO,UAAU,MAAM,SAAS,CAAC,GAAG,YAAY,QAAQ,SAAS,CAAC,EAAE,KAAK,IAAI;AAAA,IAC/E,KAAK;AACH,aAAO,UAAU,MAAM,SAAS,CAAC,GAAG,QAAQ,QAAQ,SAAS,CAAC,EAAE,KAAK,IAAI;AAAA,IAC3E,KAAK;AACH,aAAO,MAAM;AAAA,IACf,KAAK;AACH,aAAO,MAAM;AAAA,IACf,KAAK;AACH,cAAQ,MAAM,QAAQ,CAAC,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,SAAS,kBAAkB,KAAK,OAAO,CAAC,EAAE,KAAK,GAAI,CAAC,EAAE,KAAK,IAAI;AAAA,IACjH,KAAK;AACH,aAAO,CAAC,MAAM,KAAK,kBAAkB,MAAM,OAAO,CAAC,EAAE,OAAO,CAAC,SAAS,SAAS,EAAE,EAAE,KAAK,IAAI;AAAA,IAC9F,KAAK;AAAA,IACL,KAAK;AACH,aAAO,kBAAkB,MAAM,OAAO;AAAA,IACxC,KAAK;AACH,aAAO,MAAM;AAAA,IACf,KAAK;AACH,aAAO,CAAC,MAAM,OAAO,MAAM,aAAa,MAAM,GAAG,EAAE,OAAO,CAAC,SAAyB,CAAC,CAAC,IAAI,EAAE,KAAK,IAAI;AAAA,IACvG,KAAK;AACH,cAAQ,MAAM,WAAW,CAAC,GACvB,QAAQ,CAAC,WAAW,WAAW,QAAQ,OAAO,CAAC,EAC/C,KAAK,QAAQ,cAAc;AAAA,IAChC,KAAK;AACH,aAAO,CAAC,MAAM,MAAM,OAAO,MAAM,MAAM,QAAQ,EAAE,OAAO,CAAC,SAAyB,CAAC,CAAC,IAAI,EAAE,KAAK,IAAI;AAAA,IACrG,KAAK;AACH,aAAO,MAAM,SAAS,SAAS,MAAM,UAAU;AAAA,IACjD,KAAK;AACH,aAAO,CAAC,MAAM,MAAM,MAAM,MAAM,OAAO,EAAE,OAAO,CAAC,SAAyB,CAAC,CAAC,IAAI,EAAE,KAAK,IAAI;AAAA,IAC7F,KAAK;AACH,aAAO,CAAC,MAAM,QAAQ,GAAG,WAAW,MAAM,UAAU,CAAC,GAAG,OAAO,CAAC,EAAE,OAAO,CAAC,SAAS,SAAS,EAAE,EAAE,KAAK,QAAQ,cAAc;AAAA,IAC7H;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,WAAW,QAA0B,SAA+C;AAC3F,SAAO,OAAO,IAAI,CAAC,UAAU,UAAU,OAAO,OAAO,CAAC,EAAE,OAAO,CAAC,SAAS,SAAS,EAAE;AACtF;AAOO,SAAS,oBAAoB,KAAqB,UAA4B,CAAC,GAAW;AAC/F,QAAM,WAAuC;AAAA,IAC3C,gBAAgB,QAAQ,kBAAkB;AAAA,IAC1C,SAAS,QAAQ,WAAW;AAAA,EAC9B;AACA,SAAO,WAAW,IAAI,UAAU,CAAC,GAAG,QAAQ,EAAE,KAAK,SAAS,cAAc;AAC5E;AAWA,SAAS,eAA0C;AACjD,SAAQ,KAAkD;AAC5D;AAMO,SAAS,WAAW,MAAc,QAAyB;AAChE,MAAI,KAAK,KAAK,MAAM,GAAI,QAAO;AAC/B,QAAM,YAAY,aAAa;AAC/B,MAAI,WAAW;AACb,UAAM,YAAY,IAAI,UAAU,QAAQ,EAAE,aAAa,OAAO,CAAC;AAC/D,QAAI,QAAQ;AACZ,eAAW,QAAQ,UAAU,QAAQ,IAAI,EAAG,KAAI,KAAK,WAAY,UAAS;AAC1E,WAAO;AAAA,EACT;AACA,SAAO,KAAK,KAAK,EAAE,MAAM,KAAK,EAAE;AAClC;AAGO,SAAS,gBAAgB,MAAc,UAAuC,CAAC,GAAW;AAC/F,QAAM,SAAS,QAAQ,kBAAkB,QAAQ,KAAK,QAAQ,QAAQ,EAAE,IAAI;AAC5E,QAAM,YAAY,aAAa;AAC/B,MAAI,WAAW;AACb,QAAI,QAAQ;AACZ,eAAW,KAAK,IAAI,UAAU,QAAW,EAAE,aAAa,WAAW,CAAC,EAAE,QAAQ,MAAM,GAAG;AACrF,WAAK;AACL,eAAS;AAAA,IACX;AACA,WAAO;AAAA,EACT;AACA,SAAO,CAAC,GAAG,MAAM,EAAE;AACrB;AAaO,SAAS,iBAAiB,KAAqB,UAA+B,CAAC,GAAkB;AACtG,QAAM,OAAO,oBAAoB,KAAK,EAAE,SAAS,OAAO,gBAAgB,KAAK,CAAC;AAC9E,QAAM,QAAQ,WAAW,MAAM,QAAQ,MAAM;AAC7C,SAAO;AAAA,IACL;AAAA,IACA,YAAY,gBAAgB,KAAK,QAAQ,OAAO,GAAG,CAAC;AAAA,IACpD,oBAAoB,gBAAgB,MAAM,EAAE,eAAe,MAAM,CAAC;AAAA,IAClE,QAAQ,IAAI,QAAQ,UAAU;AAAA,IAC9B,gBAAgB,UAAU,IAAI,IAAI,KAAK,IAAI,GAAG,KAAK,KAAK,QAAQ,GAAG,CAAC;AAAA,EACtE;AACF;;;AC7JO,SAAS,WAAW,KAAqB,UAA0B,CAAC,GAAkB;AAC3F,QAAM,QAAuB,CAAC;AAC9B,QAAM,WAAW,QAAQ,YAAY;AACrC,aAAW,IAAI,UAAU,CAAC,GAAG,CAAC,UAAU;AACtC,QAAI,MAAM,SAAS,aAAa,MAAM,QAAQ,SAAU;AACxD,UAAM,OAAO,kBAAkB,MAAM,OAAO,EAAE,KAAK;AACnD,QAAI,SAAS,MAAM,QAAQ,iBAAiB,KAAM;AAClD,UAAM,KAAK,EAAE,IAAI,MAAM,IAAI,OAAO,MAAM,OAAO,KAAK,CAAC;AAAA,EACvD,CAAC;AACD,SAAO;AACT;AAOO,SAAS,iBAAiB,OAA8C;AAC7E,QAAM,QAAuB,CAAC;AAC9B,QAAM,QAAuB,CAAC;AAC9B,aAAW,QAAQ,OAAO;AACxB,UAAM,QAAqB,EAAE,GAAG,MAAM,UAAU,CAAC,EAAE;AACnD,WAAO,MAAM,SAAS,KAAM,MAAM,MAAM,SAAS,CAAC,EAAkB,SAAS,MAAM,MAAO,OAAM,IAAI;AACpG,UAAM,SAAS,MAAM,MAAM,SAAS,CAAC;AACrC,QAAI,OAAQ,QAAO,SAAS,KAAK,KAAK;AAAA,QACjC,OAAM,KAAK,KAAK;AACrB,UAAM,KAAK,KAAK;AAAA,EAClB;AACA,SAAO;AACT;AAGO,SAAS,eAAe,MAAsB;AACnD,SAAO,KACJ,UAAU,MAAM,EAChB,YAAY,EACZ,QAAQ,uBAAuB,EAAE,EACjC,KAAK,EACL,QAAQ,WAAW,GAAG;AAC3B;;;AC5CO,IAAM,sBAAoC;AAAA,EAC/C,iBAAiB;AAAA,EACjB,OAAO;AAAA,EACP,SAAS;AAAA,EACT,UAAU;AAAA,EACV,IAAI;AAAA,EACJ,MAAM;AACR;AAYA,IAAM,UAAkC;AAAA,EACtC,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AACP;AAGO,SAAS,WAAW,OAAuB;AAChD,SAAO,MAAM,QAAQ,YAAY,CAAC,SAAS,QAAQ,IAAI,KAAK,IAAI;AAClE;AASA,SAAS,MAAM,QAA8E;AAC3F,MAAI,MAAM;AACV,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AAClD,QAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,MAAO;AAC9D,WAAO,UAAU,OAAO,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,WAAW,OAAO,KAAK,CAAC,CAAC;AAAA,EAC7E;AACA,SAAO;AACT;AAGA,SAAS,UAAU,OAAuB;AACxC,SAAO,MAAM,QAAQ,qBAAqB,EAAE;AAC9C;AAMA,SAAS,UAAU,MAAc,MAAoB;AACnD,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAK;AACH,aAAO,WAAW,IAAI;AAAA,IACxB,KAAK;AACH,aAAO,OAAO,IAAI;AAAA,IACpB,KAAK;AACH,aAAO,MAAM,IAAI;AAAA,IACnB,KAAK;AACH,aAAO,MAAM,IAAI;AAAA,IACnB,KAAK;AACH,aAAO,SAAS,IAAI;AAAA,IACtB,KAAK,QAAQ;AACX,YAAM,OAAO,YAAY,KAAK,IAAI;AAClC,aAAO,SAAS,OAAO,OAAO,KAAK,MAAM,EAAE,MAAM,KAAK,sBAAsB,CAAC,CAAC,IAAI,IAAI;AAAA,IACxF;AAAA,IACA,KAAK,SAAS;AACZ,YAAM,MAAM,eAAe,KAAK,KAAK;AACrC,aAAO,QAAQ,OACX,OACA,QAAQ,MAAM,EAAE,YAAY,qBAAqB,cAAc,KAAK,OAAO,OAAO,UAAU,GAAG,GAAG,CAAC,CAAC,IAAI,IAAI;AAAA,IAClH;AAAA,IACA,KAAK,aAAa;AAChB,YAAM,MAAM,eAAe,KAAK,KAAK;AACrC,aAAO,QAAQ,OACX,OACA,QAAQ,MAAM,EAAE,YAAY,oBAAoB,cAAc,KAAK,OAAO,OAAO,qBAAqB,GAAG,GAAG,CAAC,CAAC,IAAI,IAAI;AAAA,IAC5H;AAAA,IACA;AACE,aAAO;AAAA,EACX;AACF;AAGA,IAAM,cAA8B,CAAC,QAAQ,UAAU,aAAa,UAAU,QAAQ,aAAa,SAAS,MAAM;AAElH,SAAS,aAAa,QAAoC;AACxD,MAAI,OAAO;AACX,aAAWC,SAAQ,UAAU,CAAC,GAAG;AAC/B,QAAIA,MAAK,SAAS,QAAQ;AACxB,UAAI,OAAO,WAAWA,MAAK,IAAI,EAAE,QAAQ,OAAO,MAAM;AACtD,YAAM,QAAQA,MAAK,SAAS,CAAC;AAC7B,iBAAW,QAAQ,aAAa;AAC9B,cAAM,OAAO,MAAM,KAAK,CAAC,cAAc,UAAU,SAAS,IAAI;AAC9D,YAAI,KAAM,QAAO,UAAU,MAAM,IAAI;AAAA,MACvC;AACA,cAAQ;AAAA,IACV,WAAWA,MAAK,SAAS,WAAW;AAClC,cAAQ,QAAQ,MAAM,EAAE,YAAY,kBAAkB,aAAaA,MAAK,MAAM,WAAWA,MAAK,GAAG,CAAC,CAAC,KAAK,WAAWA,MAAK,KAAK,CAAC;AAAA,IAChI,WAAWA,MAAK,SAAS,SAAS;AAChC,cAAQ,QAAQ,MAAM,EAAE,YAAY,gBAAgB,kBAAkBA,MAAK,UAAU,CAAC,CAAC,IAAI,WAAW,YAAYA,MAAK,SAAS,CAAC,CAAC;AAAA,IACpI;AAAA,EACF;AACA,SAAO;AACT;AAMA,SAAS,YAAY,OAA2C,MAA4B,KAAkB;AAC5G,QAAM,MAAM,SAAS,OAAO,OAAO;AACnC,QAAM,OAAO,SAAS,SAAS,MAAM,MAAM,EAAE,YAAY,mBAAmB,CAAC,CAAC,MAAM,IAAI,GAAG;AAC3F,MAAI,OAAO;AACX,aAAW,QAAQ,OAAO;AACxB,UAAM,SAAS,KAAK,YAAY,KAAK,SAAS,SAAS,IAAI,YAAY,KAAK,UAAU,MAAM,GAAG,IAAI;AACnG,QAAI,SAAS,QAAQ;AACnB,YAAM,UAAW,KAAkB,YAAY;AAC/C,YAAM,UAAU,GAAG,IAAI,QAAQ,GAAG,KAAK,EAAE;AACzC,cAAQ,MAAM,MAAM,EAAE,YAAY,oBAAoB,gBAAgB,UAAU,SAAS,QAAQ,CAAC,CAAC;AACnG,cAAQ,SAAS,MAAM,EAAE,MAAM,YAAY,UAAU,MAAM,SAAS,mBAAmB,QAAQ,CAAC,CAAC;AACjG,cAAQ,QAAQ,MAAM,EAAE,IAAI,SAAS,KAAK,OAAO,CAAC,CAAC,IAAI,aAAa,KAAK,OAAO,CAAC,UAAU,MAAM;AAAA,IACnG,OAAO;AACL,cAAQ,MAAM,MAAM,EAAE,KAAK,OAAO,CAAC,CAAC,IAAI,aAAa,KAAK,OAAO,CAAC,GAAG,MAAM;AAAA,IAC7E;AAAA,EACF;AACA,SAAO,GAAG,IAAI,KAAK,GAAG;AACxB;AAEA,SAAS,YAAY,MAAc,QAAoC;AACrE,QAAM,QAAQ,CAAC,KAAK,MAAM,MAAM,MAAM,IAAI;AAC1C,MAAI,QAAQ;AACZ,MAAI,OAAO;AACX,SAAO,SAAS,QAAQ,OAAO,MAAM,SAAS,GAAG;AAC/C,aAAS;AACT,YAAQ;AAAA,EACV;AACA,QAAM,YAAY,IAAI,KAAK,aAAa,QAAQ,EAAE,uBAAuB,SAAS,IAAI,IAAI,EAAE,CAAC,EAAE,OAAO,KAAK;AAC3G,SAAO,GAAG,SAAS,IAAI,MAAM,IAAI,CAAC;AACpC;AAEA,SAAS,cAAc,SAAqC;AAC1D,SAAO,WAAW,QAAQ,SAAS,IAAI,0BAA0B,aAAa,OAAO,CAAC,kBAAkB;AAC1G;AAEA,SAAS,cAAc,OAA+B,KAAkB;AACtE,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,MAAI,OAAO;AACX,aAAWA,SAAQ,OAAO;AACxB,YAAQ,iBAAiB,WAAW,IAAI,WAAWA,MAAK,EAAE,CAAC,KAAK,WAAWA,MAAK,IAAI,CAAC,OAAO,cAAcA,MAAK,UAAU,GAAG,CAAC;AAAA,EAC/H;AACA,SAAO,GAAG,IAAI;AAChB;AAEA,SAAS,YAAY,SAAiB,MAAc,OAAe,UAA8B,OAAe,OAAO,IAAY;AACjI,QAAM,UAAU,kDAAkD,WAAW,KAAK,CAAC,WAAW,WAAW,KAAK,CAAC,GAC7G,WAAW,WAAW,WAAW,QAAQ,CAAC,aAAa,EACzD;AACA,SAAO,UAAU,MAAM,EAAE,iBAAiB,SAAS,YAAY,gBAAgB,mBAAmB,MAAM,MAAM,SAAS,cAAc,SAAS,MAAM,CAAC,CAAC,IAAI,OAAO,GAAG,IAAI;AAC1K;AAEA,SAAS,YAAY,OAAc,KAAkB;AACnD,QAAM,KAAK,MAAM,EAAE,iBAAiB,MAAM,GAAG,CAAC;AAC9C,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,aAAO,KAAK,EAAE,GAAG,MAAM,EAAE,KAAK,OAAO,CAAC,CAAC,IAAI,aAAa,MAAM,OAAO,CAAC;AAAA,IACxE,KAAK,WAAW;AACd,YAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,MAAM,MAAM,KAAK,CAAC,CAAC;AAC9D,aAAO,KAAK,KAAK,GAAG,MAAM,EAAE,IAAI,IAAI,WAAW,MAAM,IAAI,KAAK,OAAO,CAAC,CAAC,GAAG,EAAE,IAAI,aAAa,MAAM,OAAO,CAAC,MAAM,KAAK;AAAA,IACxH;AAAA,IACA,KAAK;AACH,aAAO,cAAc,EAAE,GAAG,MAAM,EAAE,KAAK,OAAO,CAAC,CAAC,IAAI,aAAa,MAAM,OAAO,CAAC;AAAA,IACjF,KAAK;AACH,aAAO,OAAO,EAAE,GAAG,MAAM,EAAE,YAAY,kBAAkB,gBAAgB,UAAU,MAAM,OAAO,GAAG,MAAM,QAAQ,KAAK,OAAO,CAAC,CAAC,IAAI,aAAa,MAAM,OAAO,CAAC;AAAA,IAChK,KAAK;AACH,aAAO,WAAW,EAAE,GAAG,MAAM,EAAE,YAAY,gBAAgB,CAAC,CAAC,YAAY,MAAM,EAAE,KAAK,OAAO,CAAC,CAAC,IAAI,aAAa,MAAM,OAAO,CAAC,aAAa,aAAa,MAAM,YAAY,CAAC,GAAG,GAAG,CAAC;AAAA,IACpL,KAAK;AACH,aAAO,MAAM,EAAE;AAAA,IACjB,KAAK;AACH,aAAO,gBAAgB,OAAO,MAAM,GAAG;AAAA,IACzC,KAAK;AACH,aAAO,gBAAgB,OAAO,MAAM,GAAG;AAAA,IACzC,KAAK;AACH,aAAO,gBAAgB,OAAO,QAAQ,GAAG;AAAA,IAC3C,KAAK,QAAQ;AACX,YAAM,WAAW,MAAM,WAAW,UAAU,MAAM,QAAQ,IAAI;AAC9D,aAAO,OAAO,EAAE,GAAG,MAAM,EAAE,YAAY,qBAAqB,iBAAiB,YAAY,QAAW,KAAK,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,OAAO,WAAW,YAAY,QAAQ,KAAK,OAAU,CAAC,CAAC,IAAI,WAAW,MAAM,IAAI,CAAC;AAAA,IACrN;AAAA,IACA,KAAK;AACH,aAAO,OAAO,EAAE,GAAG,MAAM,EAAE,YAAY,mBAAmB,KAAK,MAAM,CAAC,CAAC,UAAU,WAAW,MAAM,KAAK,CAAC;AAAA,IAC1G,KAAK;AACH,aAAO,YAAY,KAAK;AAAA,IAC1B,KAAK,SAAS;AACZ,YAAM,MAAM,iBAAiB,MAAM,GAAG;AACtC,YAAM,MACJ,QAAQ,OACJ,KACA,OAAO,MAAM,EAAE,KAAK,KAAK,MAAM,OAAO,IAAI,SAAS,QAAQ,UAAU,SAAS,OAAO,MAAM,MAAM,CAAC,CAAC;AACzG,aAAO,UAAU,EAAE,GAAG,MAAM,EAAE,YAAY,gBAAgB,cAAc,MAAM,MAAM,CAAC,CAAC,IAAI,GAAG,GAAG,cAAc,MAAM,OAAO,CAAC;AAAA,IAC9H;AAAA,IACA,KAAK;AAAA,IACL,KAAK,SAAS;AACZ,YAAM,MAAM,iBAAiB,MAAM,GAAG;AACtC,YAAM,QACJ,QAAQ,OAAO,KAAK,IAAI,MAAM,IAAI,GAAG,MAAM,EAAE,KAAK,UAAU,MAAM,SAAS,OAAO,CAAC,CAAC,MAAM,MAAM,IAAI;AACtG,aAAO,UAAU,EAAE,GAAG,MAAM,EAAE,YAAY,gBAAgB,aAAa,MAAM,KAAK,CAAC,CAAC,IAAI,KAAK,GAAG,cAAc,MAAM,OAAO,CAAC;AAAA,IAC9H;AAAA,IACA,KAAK,QAAQ;AACX,YAAM,OAAO,YAAY,MAAM,GAAG;AAClC,YAAM,OAAO,WAAW,MAAM,IAAI;AAClC,YAAM,OAAO,SAAS,OAAO,OAAO,KAAK,MAAM,EAAE,MAAM,UAAU,MAAM,KAAK,sBAAsB,CAAC,CAAC,IAAI,IAAI;AAC5G,YAAM,OAAO,OAAO,MAAM,SAAS,WAAW,uCAAuC,WAAW,YAAY,MAAM,MAAM,IAAI,MAAM,CAAC,CAAC,aAAa;AACjJ,aAAO,KAAK,EAAE,GAAG,MAAM,EAAE,YAAY,eAAe,KAAK,OAAO,CAAC,CAAC,IAAI,IAAI,GAAG,IAAI;AAAA,IACnF;AAAA,IACA,KAAK,YAAY;AACf,YAAM,OAAO,YAAY,MAAM,GAAG;AAClC,YAAM,QAAQ,MAAM,QAAQ,WAAW,WAAW,MAAM,KAAK,CAAC,cAAc,WAAW,MAAM,GAAG;AAChG,YAAM,cAAc,MAAM,cAAc,SAAS,WAAW,MAAM,WAAW,CAAC,YAAY;AAC1F,YAAM,QAAQ,GAAG,KAAK,GAAG,WAAW;AACpC,aAAO,SAAS,OACZ,OAAO,EAAE,GAAG,MAAM,EAAE,YAAY,kBAAkB,CAAC,CAAC,IAAI,KAAK,WAC7D,KAAK,EAAE,GAAG,MAAM,EAAE,YAAY,mBAAmB,MAAM,KAAK,sBAAsB,CAAC,CAAC,IAAI,KAAK;AAAA,IACnG;AAAA,IACA,KAAK,WAAW;AACd,YAAM,UAAU,MAAM,WAAW,CAAC;AAClC,aAAO,OAAO,EAAE,GAAG,MAAM,EAAE,YAAY,kBAAkB,cAAc,QAAQ,OAAO,CAAC,CAAC,IAAI,QACzF,IAAI,CAAC,WAAW,iCAAiC,aAAa,QAAQ,GAAG,CAAC,QAAQ,EAClF,KAAK,EAAE,CAAC;AAAA,IACb;AAAA,IACA,KAAK;AACH,aAAO,MAAM,EAAE,GAAG,MAAM,EAAE,YAAY,oBAAoB,CAAC,CAAC;AAAA,IAC9D,KAAK;AACH,aAAO,OAAO,EAAE,GAAG,MAAM,EAAE,YAAY,cAAc,cAAc,IAAI,OAAO,gBAAgB,CAAC,CAAC,IAAI,cAAc,IAAI,SAAS,GAAG,CAAC;AAAA,IACrI,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN;AAAA,QACA,MAAM,MAAM,SAAS;AAAA,QACrB,MAAM,MAAM;AAAA,QACZ,IAAI,OAAO;AAAA,QACX,MAAM,MAAM,MAAM,cAAc,iBAAiB,WAAW,MAAM,KAAK,KAAK,WAAW,CAAC,SAAS;AAAA,MACnG;AAAA,IACF,KAAK,WAAW;AACd,YAAM,QAAQ,MAAM,SAAS,SAAS;AACtC,YAAM,OAAO,MAAM,SAAS,wBAAwB,WAAW,MAAM,MAAM,CAAC,kBAAkB;AAC9F,aAAO,YAAY,MAAM,IAAI,WAAW,OAAO,QAAW,IAAI,OAAO,SAAS,IAAI;AAAA,IACpF;AAAA,IACA,KAAK;AACH,aAAO,YAAY,MAAM,IAAI,aAAa,MAAM,MAAM,QAAQ,MAAM,SAAS,MAAM,MAAM,OAAO,MAAM,UAAU,QAAW,IAAI,OAAO,QAAQ;AAAA,IAChJ,KAAK;AACH,aAAO,YAAY,MAAM,IAAI,MAAM,MAAM,QAAQ,QAAW,IAAI,OAAO,IAAI,aAAa,MAAM,UAAU,CAAC,GAAG,GAAG,CAAC;AAAA,IAClH,SAAS;AACP,YAAM,cAAc,OAAQ,MAA6B,IAAI;AAC7D,aAAO,OAAO,EAAE,GAAG,MAAM,EAAE,YAAY,kBAAkB,mBAAmB,aAAa,QAAQ,KAAK,CAAC,CAAC;AAAA,IAC1G;AAAA,EACF;AACF;AAEA,SAAS,gBACP,OACA,MACA,KACQ;AACR,QAAM,OAAO,YAAY,MAAM,SAAS,CAAC,GAAG,MAAM,GAAG;AAErD,SAAO,KAAK,QAAQ,aAAa,MAAM,MAAM,EAAE,iBAAiB,MAAM,GAAG,CAAC,CAAC,EAAE;AAC/E;AAEA,SAAS,YAAY,OAAkD;AACrE,QAAM,OAAO,MAAM,QAAQ,CAAC;AAC5B,QAAM,YAAY,CAAC,KAA4B,aAC7C,OAAO,IACJ,IAAI,CAAC,MAAM,gBAAgB;AAC1B,UAAM,SACJ,KAAK,WAAW,QACf,MAAM,cAAc,QAAQ,aAAa,KACzC,MAAM,iBAAiB,QAAQ,gBAAgB;AAClD,UAAM,MAAM,SAAS,OAAO;AAC5B,QAAI;AACJ,QAAI,UAAU,MAAM,cAAc,QAAQ,aAAa,EAAG,SAAQ;AAAA,aACzD,UAAU,MAAM,iBAAiB,QAAQ,gBAAgB,EAAG,SAAQ;AAC7E,WAAO,IAAI,GAAG,GAAG,MAAM;AAAA,MACrB;AAAA,MACA,SAAS,KAAK,WAAW,KAAK,UAAU,IAAI,KAAK,UAAU;AAAA,MAC3D,SAAS,KAAK,WAAW,KAAK,UAAU,IAAI,KAAK,UAAU;AAAA,MAC3D,KAAK;AAAA,IACP,CAAC,CAAC,IAAI,aAAa,KAAK,OAAO,CAAC,KAAK,GAAG;AAAA,EAC1C,CAAC,EACA,KAAK,EAAE,CAAC;AAEb,QAAM,UAAU,MAAM,cAAc,OAAO,KAAK,CAAC,IAAI;AACrD,QAAM,WAAW,UAAU,KAAK,MAAM,CAAC,IAAI;AAC3C,QAAM,QAAQ,UAAU,UAAU,UAAU,SAAS,CAAC,CAAC,aAAa;AACpE,QAAM,QAAQ,UAAU,SAAS,IAAI,CAAC,KAAK,UAAU,UAAU,KAAK,UAAU,QAAQ,IAAI,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC;AAC1G,SAAO,OAAO,MAAM,EAAE,YAAY,wBAAwB,iBAAiB,MAAM,GAAG,CAAC,CAAC,UAAU,MAAM,EAAE,YAAY,eAAe,CAAC,CAAC,IAAI,KAAK,GAAG,KAAK;AACxJ;AAEA,SAAS,aAAa,QAA0B,KAAkB;AAChE,SAAO,OAAO,IAAI,CAAC,UAAU,YAAY,OAAO,GAAG,CAAC,EAAE,KAAK,EAAE;AAC/D;AAOO,SAAS,eAAe,KAAqB,UAAuB,CAAC,GAAW;AACrF,QAAM,MAAW;AAAA,IACf,UAAU,QAAQ,YAAY;AAAA,IAC9B,QAAQ,EAAE,GAAG,qBAAqB,GAAG,QAAQ,OAAO;AAAA,IACpD,QAAQ,QAAQ;AAAA,IAChB,SAAS,iBAAiB,WAAW,GAAG,CAAC;AAAA,EAC3C;AACA,QAAM,OAAO,aAAa,IAAI,UAAU,CAAC,GAAG,GAAG;AAC/C,SAAO,QAAQ,SAAS,OAAO,+BAA+B,IAAI,WAAW;AAC/E;;;ACxTO,SAAS,eAAe,MAAsB;AACnD,SAAO,KAAK,QAAQ,qBAAqB,MAAM;AACjD;AAGA,SAAS,QAAQ,MAAsB;AACrC,SAAO,KAAK,QAAQ,QAAQ,GAAG,EAAE,KAAK;AACxC;AAEA,SAAS,gBAAgB,MAAsB;AAC7C,SAAO,KACJ,QAAQ,kBAAkB,QAAQ,EAClC,QAAQ,2BAA2B,YAAY,EAC/C,QAAQ,+BAA+B,QAAQ,EAC/C,QAAQ,8BAA8B,QAAQ;AACnD;AAEA,SAAS,SAAS,MAAsB;AACtC,QAAM,OAAO,KAAK,MAAM,KAAK,KAAK,CAAC;AACnC,QAAM,UAAU,KAAK,OAAO,CAAC,KAAK,QAAQ,KAAK,IAAI,KAAK,IAAI,MAAM,GAAG,CAAC;AACtE,QAAMC,SAAQ,IAAI,OAAO,UAAU,CAAC;AACpC,QAAM,MAAM,KAAK,WAAW,GAAG,KAAK,KAAK,SAAS,GAAG,KAAM,KAAK,WAAW,GAAG,KAAK,KAAK,SAAS,GAAG,KAAK,KAAK,KAAK,MAAM,KAAM,MAAM;AACrI,SAAO,GAAGA,MAAK,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,GAAGA,MAAK;AAC5C;AAEA,SAAS,kBAAkB,MAAsB;AAC/C,SAAO,KAAK,QAAQ,MAAM,KAAK,EAAE,QAAQ,OAAO,KAAK,EAAE,QAAQ,OAAO,KAAK,EAAE,QAAQ,MAAM,KAAK,EAAE,QAAQ,MAAM,KAAK;AACvH;AAQA,SAAS,QAAQ,MAAqB;AACpC,SAAO,KAAK,UAAU,IAAI;AAC5B;AAEA,SAAS,UAAU,MAAY,KAAyB;AACtD,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO,IAAI,aAAa,QAAQ;AAAA,IAClC,KAAK;AACH,aAAO,YAAY,KAAK,IAAI,MAAM,OAAO,KAAK;AAAA,IAChD,KAAK;AACH,aAAO,IAAI,cAAc,iBAAiB,KAAK,KAAK,IAAI,2BAA2B,WAAW,KAAK,KAAK,CAAC,OAAO;AAAA,IAClH,KAAK;AACH,aAAO,IAAI,cAAc,iBAAiB,KAAK,KAAK,IAAI,qBAAqB,WAAW,KAAK,KAAK,CAAC,OAAO;AAAA,IAC5G;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,WAAW,MAAY,KAAkB;AAChD,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO,IAAI,aAAa,SAAS;AAAA,IACnC,KAAK,QAAQ;AACX,YAAM,OAAO,YAAY,KAAK,IAAI;AAClC,aAAO,SAAS,OAAO,KAAK,KAAK,kBAAkB,IAAI,CAAC;AAAA,IAC1D;AAAA,IACA,KAAK;AACH,aAAO,IAAI,cAAc,iBAAiB,KAAK,KAAK,IAAI,YAAY;AAAA,IACtE,KAAK;AACH,aAAO,IAAI,cAAc,iBAAiB,KAAK,KAAK,IAAI,YAAY;AAAA,IACtE;AACE,aAAO;AAAA,EACX;AACF;AAOA,SAASC,cAAa,QAA4B,KAAU,cAAc,MAAc;AACtF,QAAM,QAAQ,gBAAgB,MAAM;AACpC,MAAI,MAAM;AACV,MAAI,SAAiB,CAAC;AAEtB,QAAM,YAAY,CAAC,SAAiB;AAClC,aAAS,QAAQ,OAAO,SAAS,GAAG,SAAS,MAAM,SAAS,GAAG;AAC7D,YAAM,OAAO,OAAO,KAAK;AACzB,UAAI,KAAK,SAAS,OAAQ;AAC1B,YAAM,QAAQ,WAAW,MAAM,GAAG;AAClC,UAAI,UAAU,GAAI;AAClB,YAAM,WAAW,OAAO,KAAK,GAAG,IAAI,CAAC,KAAK;AAC1C,UAAI,aAAa,MAAM,KAAK,SAAS,OAAQ,OAAM,IAAI,MAAM,GAAG,IAAI,SAAS,SAAS,MAAM;AAC5F,aAAO,SAAS,KAAK,SAAS,SAAS,WAAW;AAAA,IACpD;AACA,aAAS,OAAO,MAAM,GAAG,IAAI;AAAA,EAC/B;AAEA,aAAWC,SAAQ,OAAO;AACxB,QAAIA,MAAK,SAAS,QAAQ;AACxB,gBAAU,CAAC;AACX,UAAIA,MAAK,SAAS,WAAW;AAC3B,eAAO,KAAK,eAAeA,MAAK,KAAK,CAAC,iBAAiBA,MAAK,IAAI,IAAI,mBAAmBA,MAAK,EAAE,CAAC;AAAA,MACjG,OAAO;AACL,cAAM,OAAOA,MAAK,UAAU,QAAQ,UAAU,EAAE;AAEhD,eAAO,kBAAkB,IAAI,MAAM,OAAO,IAAI,IAAI,MAAM,eAAe,IAAI,IAAI,GAAG;AAAA,MACpF;AACA;AAAA,IACF;AAEA,UAAM,SAASA,MAAK,SAAS,CAAC,GAAG,OAAO,CAAC,SAAS,KAAK,SAAS,MAAM;AACtE,UAAM,WAAWA,MAAK,SAAS,CAAC,GAAG,KAAK,CAAC,SAAS,KAAK,SAAS,MAAM;AAEtE,QAAI,OAAO;AACX,WAAO,OAAO,OAAO,UAAU,OAAO,MAAM,UAAU,QAAQ,OAAO,IAAI,CAAS,MAAM,QAAQ,MAAM,IAAI,CAAS,EAAG,SAAQ;AAC9H,cAAU,IAAI;AAEd,QAAI,OAAOA,MAAK;AAChB,QAAI,OAAO;AACX,QAAI,MAAM,SAAS,MAAM;AACvB,YAAM,QAAQ,OAAO,KAAK,IAAI;AAC9B,UAAI,SAAS,KAAK,KAAK,MAAM,IAAI;AAC/B,eAAO,MAAM,CAAC;AACd,eAAO,KAAK,MAAM,KAAK,MAAM;AAAA,MAC/B;AACA,UAAI,KAAK,KAAK,MAAM,IAAI;AAEtB,eAAOA,MAAK,KAAK,QAAQ,OAAO,MAAM;AACtC;AAAA,MACF;AAAA,IACF;AACA,WAAO;AACP,aAAS,QAAQ,MAAM,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACvD,YAAM,OAAO,MAAM,KAAK;AACxB,aAAO,UAAU,MAAM,GAAG,KAAK;AAC/B,aAAO,KAAK,IAAI;AAAA,IAClB;AAEA,QAAI,WAAW,CAAC,KAAK,SAAS,IAAI,EAAG,QAAO,SAAS,IAAI;AAAA;AAEvD,aAAO,KACJ,MAAM,IAAI,EACV,IAAI,CAAC,MAAM,aAAc,aAAa,KAAK,CAAC,cAAc,eAAe,IAAI,IAAI,gBAAgB,eAAe,IAAI,CAAC,CAAE,EACvH,KAAK,MAAM;AAAA,EAClB;AACA,YAAU,CAAC;AACX,SAAO;AACT;AAGA,SAAS,iBAAiB,QAA4B,KAAU,SAAyB;AACvF,SAAOD,cAAa,QAAQ,KAAK,KAAK,EAAE,QAAQ,SAAS,OAAO,EAAE,QAAQ,OAAO,OAAO;AAC1F;AAMA,IAAM,gBAAwC;AAAA,EAC5C,MAAM;AAAA,EACN,SAAS;AAAA,EACT,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SAAS;AACX;AAEA,SAAS,MAAM,SAAiB,MAAsB;AACpD,QAAM,OAAO,QAAQ,MAAM,KAAK,KAAK,CAAC;AACtC,QAAM,UAAU,KAAK,OAAO,CAAC,KAAK,QAAQ,KAAK,IAAI,KAAK,IAAI,MAAM,GAAG,CAAC;AACtE,QAAM,SAAS,IAAI,OAAO,KAAK,IAAI,GAAG,UAAU,CAAC,CAAC;AAClD,SAAO,GAAG,MAAM,GAAG,IAAI;AAAA,EAAK,OAAO;AAAA,EAAK,MAAM;AAChD;AAEA,SAAS,SAAS,OAAuB;AACvC,SAAO,MAAM,QAAQ,sBAAsB,EAAE;AAC/C;AAEA,SAAS,YAAY,MAAc,OAAe,MAAsB;AACtE,SAAO,KACJ,MAAM,IAAI,EACV,IAAI,CAAC,MAAM,WAAW,UAAU,IAAI,QAAQ,QAAQ,IAAI,EACxD,KAAK,IAAI;AACd;AAEA,SAASE,aACP,OACA,MACA,KACU;AACV,QAAM,QAAkB,CAAC;AACzB,QAAM,QAAQ,CAAC,MAAM,UAAU;AAC7B,UAAM,SAAS,SAAS,aAAa,GAAG,QAAQ,CAAC,OAAO;AACxD,UAAM,WAAW,SAAS,SAAS,IAAK,KAAkB,UAAU,MAAM,GAAG,OAAO;AAEpF,UAAM,OAAO,gBAAgBF,cAAa,KAAK,SAAS,GAAG,CAAC;AAC5D,UAAM,MAAM,IAAI,OAAO,OAAO,MAAM;AACpC,UAAM,KAAK,YAAY,GAAG,QAAQ,GAAG,IAAI,IAAI,QAAQ,GAAG,EAAE,QAAQ,OAAO,EAAE,CAAC;AAC5E,QAAI,KAAK,YAAY,KAAK,SAAS,SAAS,GAAG;AAC7C,YAAM,SAASE,aAAY,KAAK,UAAU,MAAM,GAAG,EAAE,KAAK,IAAI;AAC9D,YAAM,KAAK,YAAY,QAAQ,KAAK,GAAG,CAAC;AAAA,IAC1C;AAAA,EACF,CAAC;AACD,SAAO;AACT;AAEA,SAASC,aAAY,OAA0C,KAAkB;AAC/E,QAAM,OAAO,MAAM,QAAQ,CAAC;AAC5B,QAAM,QAAQ,KAAK,OAAO,CAAC,KAAK,QAAQ,KAAK,IAAI,KAAK,IAAI,MAAM,GAAG,CAAC;AACpE,MAAI,KAAK,WAAW,KAAK,UAAU,EAAG,QAAO;AAC7C,QAAM,OAAO,CAAC,WAA+B,iBAAiB,QAAQ,KAAK,MAAM,EAAE,QAAQ,OAAO,KAAK,KAAK;AAC5G,QAAM,SAAS,CAAC,QACd,KAAK,MAAM,KAAK,EAAE,QAAQ,MAAM,GAAG,CAAC,GAAG,UAAW,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,GAAG,OAAO,IAAI,GAAI,EAAE,KAAK,KAAK,CAAC;AAC9G,QAAM,CAAC,MAAM,GAAG,IAAI,IAAI;AACxB,QAAM,YAAY,KAAK,MAAM,KAAK,EAAE,QAAQ,MAAM,GAAG,MAAM,KAAK,EAAE,KAAK,KAAK,CAAC;AAC7E,SAAO,CAAC,OAAO,QAAQ,CAAC,CAAC,GAAG,WAAW,GAAG,KAAK,IAAI,MAAM,CAAC,EAAE,KAAK,IAAI;AACvE;AAEA,SAASC,aAAY,OAAc,KAAkB;AACnD,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK,aAAa;AAChB,YAAM,OAAOJ,cAAa,MAAM,SAAS,GAAG;AAC5C,aAAO,SAAS,KAAK,KAAK,gBAAgB,IAAI;AAAA,IAChD;AAAA,IACA,KAAK,WAAW;AACd,YAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,MAAM,MAAM,KAAK,CAAC,CAAC;AAC9D,aAAO,GAAG,IAAI,OAAO,KAAK,CAAC,IAAI,iBAAiB,MAAM,SAAS,KAAK,GAAG,CAAC,GAAG,QAAQ;AAAA,IACrF;AAAA,IACA,KAAK;AACH,aAAO,YAAY,gBAAgBA,cAAa,MAAM,SAAS,GAAG,CAAC,GAAG,MAAM,IAAI;AAAA,IAClF,KAAK,WAAW;AACd,YAAM,QAAQ,cAAc,MAAM,OAAO,KAAK;AAC9C,YAAM,OAAO,gBAAgBA,cAAa,MAAM,SAAS,GAAG,CAAC;AAC7D,aAAO,YAAY,KAAK,KAAK,IAAI,SAAS,KAAK,KAAK;AAAA,EAAK,IAAI,EAAE,IAAI,MAAM,IAAI;AAAA,IAC/E;AAAA,IACA,KAAK,UAAU;AACb,YAAM,UAAU;AAAA,QACd,gBAAgB,MAAM,OAAO,EAC1B,IAAI,CAACC,UAAUA,MAAK,SAAS,SAASA,MAAK,OAAOA,MAAK,SAAS,YAAY,IAAIA,MAAK,KAAK,KAAK,YAAYA,MAAK,SAAS,CAAE,EAC3H,KAAK,EAAE,EACP,QAAQ,OAAO,GAAG;AAAA,MACvB;AACA,YAAM,OAAOI,cAAa,MAAM,YAAY,CAAC,GAAG,GAAG;AACnD,aAAO;AAAA,WAAuB,OAAO;AAAA,EAAe,SAAS,KAAK,KAAK;AAAA,EAAK,IAAI;AAAA,CAAI;AAAA;AAAA,IACtF;AAAA,IACA,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAOH,aAAY,MAAM,SAAS,CAAC,GAAG,YAAY,GAAG,EAAE,KAAK,IAAI;AAAA,IAClE,KAAK;AACH,aAAOA,aAAY,MAAM,SAAS,CAAC,GAAG,YAAY,GAAG,EAAE,KAAK,IAAI;AAAA,IAClE,KAAK;AACH,aAAOA,aAAY,MAAM,SAAS,CAAC,GAAG,QAAQ,GAAG,EAAE,KAAK,IAAI;AAAA,IAC9D,KAAK;AACH,aAAO,MAAM,MAAM,MAAM,SAAS,MAAM,YAAY,EAAE,CAAC;AAAA,IACzD,KAAK;AACH,aAAO;AAAA,EAAO,MAAM,KAAK;AAAA;AAAA,IAC3B,KAAK;AACH,aAAOC,aAAY,OAAO,GAAG;AAAA,IAC/B,KAAK,SAAS;AACZ,YAAM,MAAM,iBAAiB,MAAM,GAAG;AACtC,YAAM,MAAM,eAAe,QAAQ,MAAM,OAAO,EAAE,CAAC;AACnD,UAAI,QAAQ,KAAM,QAAO;AACzB,YAAM,UAAU,gBAAgB,MAAM,OAAO,EAC1C,IAAI,CAACF,UAAUA,MAAK,SAAS,SAASA,MAAK,OAAO,EAAG,EACrD,KAAK,EAAE,EACP,QAAQ,QAAQ,GAAG,EACnB,KAAK;AACR,YAAM,QAAQ,YAAY,KAAK,KAAK,KAAK,QAAQ,QAAQ,OAAO,MAAM,EAAE,QAAQ,MAAM,KAAK,CAAC;AAC5F,aAAO,KAAK,GAAG,KAAK,kBAAkB,GAAG,CAAC,GAAG,KAAK;AAAA,IACpD;AAAA,IACA,KAAK;AAAA,IACL,KAAK,SAAS;AACZ,YAAM,MAAM,iBAAiB,MAAM,GAAG;AACtC,UAAI,QAAQ,KAAM,QAAO;AACzB,YAAM,UAAU,gBAAgB,MAAM,OAAO,EAC1C,IAAI,CAACA,UAAUA,MAAK,SAAS,SAASA,MAAK,OAAO,EAAG,EACrD,KAAK,EAAE,EACP,QAAQ,QAAQ,GAAG,EACnB,KAAK;AACR,aAAO,IAAI,MAAM,IAAI,SAAS,WAAW,GAAG,CAAC,IAAI,YAAY,KAAK,KAAK,WAAW,WAAW,OAAO,CAAC,GAAG,eAAe,MAAM,IAAI;AAAA,IACnI;AAAA,IACA,KAAK,QAAQ;AACX,YAAM,OAAO,YAAY,MAAM,GAAG;AAClC,YAAM,OAAO,eAAe,QAAQ,MAAM,IAAI,CAAC;AAC/C,aAAO,SAAS,OAAO,OAAO,IAAI,IAAI,KAAK,kBAAkB,IAAI,CAAC;AAAA,IACpE;AAAA,IACA,KAAK,YAAY;AACf,YAAM,OAAO,YAAY,MAAM,GAAG;AAClC,YAAM,QAAQ,eAAe,QAAQ,MAAM,SAAS,MAAM,GAAG,CAAC;AAC9D,aAAO,SAAS,OAAO,QAAQ,IAAI,KAAK,KAAK,kBAAkB,IAAI,CAAC;AAAA,IACtE;AAAA,IACA,KAAK;AACH,cAAQ,MAAM,WAAW,CAAC,GAAG,IAAI,CAAC,WAAWI,cAAa,QAAQ,GAAG,CAAC,EAAE,OAAO,CAAC,SAAS,SAAS,EAAE,EAAE,KAAK,MAAM;AAAA,IACnH,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO,MAAM,KAAK,UAAU,MAAM,MAAM,MAAM,CAAC,GAAG,WAAW;AAAA,IAC/D,KAAK;AACH,UAAI,MAAM,WAAW,aAAa,OAAO,MAAM,WAAW,YAAY,MAAM,YAAY,QAAW;AACjG,eAAO,MAAM,MAAM,QAAQ,SAAS;AAAA,MACtC;AACA,aAAO,MAAM,KAAK,UAAU,EAAE,QAAQ,MAAM,QAAQ,SAAS,MAAM,SAAS,QAAQ,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,aAAa;AAAA,IAC7H,KAAK;AACH,aAAO,MAAM,KAAK,UAAU,EAAE,SAAS,MAAM,SAAS,MAAM,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,eAAe;AAAA,IACrG,KAAK;AACH,aAAO,MAAM,KAAK,UAAU,EAAE,QAAQ,MAAM,QAAQ,QAAQ,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,QAAQ;AAAA,IAChG;AAEE,aAAO,MAAM,KAAK,UAAU,OAAO,MAAM,CAAC,GAAG,WAAW;AAAA,EAC5D;AACF;AAEA,IAAM,aAAa,oBAAI,IAAY,CAAC,iBAAiB,iBAAiB,WAAW,CAAC;AAGlF,SAAS,eAAe,QAAmC;AACzD,SAAO,OAAO,QAAQ,CAAC,UAAW,MAAM,SAAS,YAAY,gBAAgB,MAAM,WAAW,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAE;AACtH;AAEA,SAASA,cAAa,QAA0B,KAAkB;AAChE,QAAM,QAAkB,CAAC;AACzB,MAAI;AACJ,aAAW,SAAS,eAAe,MAAM,GAAG;AAC1C,UAAM,OAAOD,aAAY,OAAO,GAAG;AACnC,QAAI,SAAS,GAAI;AAEjB,QAAI,YAAY,MAAM,SAAS,SAAS,QAAQ,WAAW,IAAI,MAAM,IAAI,EAAG,OAAM,KAAK,UAAU;AACjG,UAAM,KAAK,IAAI;AACf,eAAW;AAAA,EACb;AACA,SAAO,MAAM,KAAK,MAAM;AAC1B;AAMO,SAAS,mBAAmB,KAAqB,UAA2B,CAAC,GAAW;AAC7F,QAAM,MAAW,EAAE,YAAY,QAAQ,cAAc,KAAK;AAC1D,QAAM,OAAOC,cAAa,IAAI,UAAU,CAAC,GAAG,GAAG;AAC/C,SAAO,SAAS,KAAK,KAAK,GAAG,IAAI;AAAA;AACnC;","names":["attrs","node","node","fence","renderInline","node","renderItems","renderTable","renderBlock","renderBlocks"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { E as EditorDocument, B as Block, I as Inline } from './outline-Drc3E0C1.js';
|
|
2
|
+
export { A as AiCommand, a as AiProvider, b as BLOCK_ID_NODES, c as BLOCK_TYPES, d as BlockBase, e as BlockType, C as CALLOUT_VARIANTS, f as CalloutVariant, g as CollaborationProvider, h as ConversionWarning, i as ConversionWarningCode, j as ConvertOptions, D as DOCUMENT_VERSION, k as InlineNode, L as ListItem, M as MARK_TYPES, l as Mark, O as OutlineItem, m as OutlineNode, n as OutlineOptions, T as TIPTAP_MARKS, o as TIPTAP_NODES, p as TableCell, q as TaskItem, r as TiptapDoc, s as TiptapMark, t as TiptapNode, u as TiptapNodeName, v as buildOutlineTree, w as createEmptyDocument, x as createParagraph, y as documentToTiptap, z as getOutline, F as isKnownBlockType, G as normalizeDocument, H as normalizeInline, J as slugifyHeading, K as tiptapToDocument } from './outline-Drc3E0C1.js';
|
|
3
|
+
import '@x12i/charts';
|
|
4
|
+
import '@x12i/data';
|
|
5
|
+
import '@x12i/diagrams';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Block ids. Every block, list item and task item carries a stable id so a
|
|
9
|
+
* diff, a comment anchor or a collaboration layer can refer to it.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A new random block id: 12 lowercase base-36 characters. Uses the Web Crypto
|
|
14
|
+
* API when it exists (browsers, Node 20+, edge runtimes) and falls back to
|
|
15
|
+
* `Math.random`, so it works on the server too.
|
|
16
|
+
*/
|
|
17
|
+
declare function generateBlockId(): string;
|
|
18
|
+
/** A small seeded PRNG (mulberry32). Deterministic across platforms. */
|
|
19
|
+
declare function createSeededRandom(seed: number): () => number;
|
|
20
|
+
/**
|
|
21
|
+
* A deterministic id generator for tests and fixtures: `b1`, `b2`, ... with
|
|
22
|
+
* your own prefix. Never use it for real documents.
|
|
23
|
+
*/
|
|
24
|
+
declare function createSequentialIdGenerator(prefix?: string, start?: number): () => string;
|
|
25
|
+
/** Calls `visit` for every block, including blocks nested in toggles, columns and AI results. */
|
|
26
|
+
declare function walkBlocks(blocks: readonly Block[], visit: (block: Block, parent: Block | null) => void, parent?: Block | null): void;
|
|
27
|
+
/** Every id in the document: blocks (nested too), list items and task items, in document order. */
|
|
28
|
+
declare function collectIds(doc: EditorDocument): string[];
|
|
29
|
+
/** Ids that occur more than once. A healthy document returns an empty array. */
|
|
30
|
+
declare function findDuplicateIds(doc: EditorDocument): string[];
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* URL safety. Links and media in a stored document come from users, so every
|
|
34
|
+
* renderer runs them through here: http, https, mailto, tel and relative URLs
|
|
35
|
+
* pass; `javascript:`, `vbscript:`, `file:` and `data:` do not, except
|
|
36
|
+
* `data:image/*` for image sources.
|
|
37
|
+
*/
|
|
38
|
+
interface SanitizeUrlOptions {
|
|
39
|
+
/** Allow `data:image/*` URLs. Only set this for image sources, never for links. */
|
|
40
|
+
allowDataImage?: boolean;
|
|
41
|
+
/** Schemes (without the colon) that pass, in lower case. Defaults to http, https, mailto, tel. */
|
|
42
|
+
allowedProtocols?: readonly string[];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Returns the trimmed URL when it is safe to render, or `null` when it is not.
|
|
46
|
+
* Relative URLs (`/a`, `./a`, `../a`, `a/b`, `#id`, `?q=1`) are safe.
|
|
47
|
+
*/
|
|
48
|
+
declare function sanitizeUrl(input: unknown, options?: SanitizeUrlOptions): string | null;
|
|
49
|
+
/** True when `sanitizeUrl` accepts the value. */
|
|
50
|
+
declare function isSafeUrl(input: unknown, options?: SanitizeUrlOptions): boolean;
|
|
51
|
+
/** Sanitizer for image, video and audio sources: also lets `data:image/*` through. */
|
|
52
|
+
declare function sanitizeMediaUrl(input: unknown): string | null;
|
|
53
|
+
/**
|
|
54
|
+
* Turns what a person typed in a link field into a URL: bare domains get
|
|
55
|
+
* `https://`, bare email addresses get `mailto:`. Anything else is returned
|
|
56
|
+
* trimmed. Run the result through `sanitizeUrl` before storing it.
|
|
57
|
+
*/
|
|
58
|
+
declare function normalizeUrlInput(input: string): string;
|
|
59
|
+
|
|
60
|
+
/** Text colors. Foreground tokens are chosen to keep 4.5:1 on the surface in every theme. */
|
|
61
|
+
declare const TEXT_COLOR_TOKENS: readonly ["color.text.secondary", "color.text.link", "color.accent.default", "color.status.success.foreground", "color.status.warning.foreground", "color.status.danger.foreground", "color.status.info.foreground", "color.chart.categorical.4"];
|
|
62
|
+
/** Highlight (background) colors. Text keeps the primary text color on top of them. */
|
|
63
|
+
declare const HIGHLIGHT_TOKENS: readonly ["color.highlight", "color.accent.subtle", "color.status.success.background", "color.status.warning.background", "color.status.danger.background", "color.status.info.background"];
|
|
64
|
+
type TextColorToken = (typeof TEXT_COLOR_TOKENS)[number];
|
|
65
|
+
type HighlightToken = (typeof HIGHLIGHT_TOKENS)[number];
|
|
66
|
+
declare function isTextColorToken(token: unknown): token is TextColorToken;
|
|
67
|
+
declare function isHighlightToken(token: unknown): token is HighlightToken;
|
|
68
|
+
/** The CSS custom property for a token path, for example `--kit-color-text-link`. */
|
|
69
|
+
declare function tokenToCssVarName(token: string): string;
|
|
70
|
+
/** `var(--kit-...)` for an allowed text color token, or `null` when the token is not on the list. */
|
|
71
|
+
declare function textColorToCss(token: unknown): string | null;
|
|
72
|
+
/** `var(--kit-...)` for an allowed highlight token, or `null` when the token is not on the list. */
|
|
73
|
+
declare function highlightToCss(token: unknown): string | null;
|
|
74
|
+
|
|
75
|
+
/** Plain text of an inline run: marks dropped, mentions as `@label`, emoji as characters. */
|
|
76
|
+
declare function inlineToPlainText(inline: Inline | undefined): string;
|
|
77
|
+
interface PlainTextOptions {
|
|
78
|
+
/** Text between blocks. Defaults to a blank line. */
|
|
79
|
+
blockSeparator?: string;
|
|
80
|
+
/** Prefix list items with `-`, `1.` and `[x]`. Defaults to true. Counting turns it off. */
|
|
81
|
+
markers?: boolean;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The document as plain text. Blocks are separated by a blank line, lists keep
|
|
85
|
+
* their markers and tables become tab-separated rows. Blocks with no text
|
|
86
|
+
* (dividers, page breaks) are skipped. Columns read in order.
|
|
87
|
+
*/
|
|
88
|
+
declare function documentToPlainText(doc: EditorDocument, options?: PlainTextOptions): string;
|
|
89
|
+
/**
|
|
90
|
+
* Counts words. Uses `Intl.Segmenter` when available, so Hebrew, Arabic and
|
|
91
|
+
* CJK text count correctly; otherwise it splits on whitespace.
|
|
92
|
+
*/
|
|
93
|
+
declare function countWords(text: string, locale?: string): number;
|
|
94
|
+
/** Counts characters as the reader sees them (grapheme clusters), not UTF-16 units. */
|
|
95
|
+
declare function countCharacters(text: string, options?: {
|
|
96
|
+
includeSpaces?: boolean;
|
|
97
|
+
}): number;
|
|
98
|
+
interface DocumentStats {
|
|
99
|
+
words: number;
|
|
100
|
+
characters: number;
|
|
101
|
+
charactersNoSpaces: number;
|
|
102
|
+
/** Top-level blocks. */
|
|
103
|
+
blocks: number;
|
|
104
|
+
/** Reading time at 200 words per minute, rounded up, at least 1 when there is any text. */
|
|
105
|
+
readingMinutes: number;
|
|
106
|
+
}
|
|
107
|
+
/** Word, character and block counts for a document. */
|
|
108
|
+
declare function getDocumentStats(doc: EditorDocument, options?: {
|
|
109
|
+
locale?: string;
|
|
110
|
+
}): DocumentStats;
|
|
111
|
+
|
|
112
|
+
/** English labels for the few strings an export needs. Pass `labels` to translate them. */
|
|
113
|
+
interface ExportLabels {
|
|
114
|
+
tableOfContents: string;
|
|
115
|
+
chart: string;
|
|
116
|
+
diagram: string;
|
|
117
|
+
dataView: string;
|
|
118
|
+
ai: string;
|
|
119
|
+
file: string;
|
|
120
|
+
}
|
|
121
|
+
declare const defaultExportLabels: ExportLabels;
|
|
122
|
+
interface HtmlOptions {
|
|
123
|
+
/** Prefix for generated element ids (headings, task labels). Defaults to `kit-`. */
|
|
124
|
+
idPrefix?: string;
|
|
125
|
+
/** Wrap the output in `<div data-kit="editor-view">`. Defaults to false. */
|
|
126
|
+
wrap?: boolean;
|
|
127
|
+
labels?: Partial<ExportLabels>;
|
|
128
|
+
/** Locale for number formatting (file sizes). */
|
|
129
|
+
locale?: string;
|
|
130
|
+
}
|
|
131
|
+
/** Escapes text for use in HTML content or a quoted attribute. */
|
|
132
|
+
declare function escapeHtml(value: string): string;
|
|
133
|
+
/**
|
|
134
|
+
* Renders the document as safe HTML (see the note at the top of this file).
|
|
135
|
+
* Block ids become `data-block-id`; headings get an `id` so a table of
|
|
136
|
+
* contents block can link to them.
|
|
137
|
+
*/
|
|
138
|
+
declare function documentToHtml(doc: EditorDocument, options?: HtmlOptions): string;
|
|
139
|
+
|
|
140
|
+
interface MarkdownOptions {
|
|
141
|
+
/** Keep marks Markdown has no syntax for (underline, color, highlight) as inline HTML. Defaults to true. */
|
|
142
|
+
inlineHtml?: boolean;
|
|
143
|
+
}
|
|
144
|
+
/** Escapes characters that would start Markdown syntax inside running text. */
|
|
145
|
+
declare function escapeMarkdown(text: string): string;
|
|
146
|
+
/**
|
|
147
|
+
* Renders the document as Markdown. A level 1 `title` is not added; the
|
|
148
|
+
* document's `title` field is metadata, not content.
|
|
149
|
+
*/
|
|
150
|
+
declare function documentToMarkdown(doc: EditorDocument, options?: MarkdownOptions): string;
|
|
151
|
+
|
|
152
|
+
interface MarkdownImportOptions {
|
|
153
|
+
/** Creates block ids. Defaults to `generateBlockId`. */
|
|
154
|
+
generateId?: () => string;
|
|
155
|
+
/** Document title to set. */
|
|
156
|
+
title?: string;
|
|
157
|
+
}
|
|
158
|
+
/** Parses inline Markdown into schema inline content (canonical form). */
|
|
159
|
+
declare function markdownToInline(markdown: string): Inline;
|
|
160
|
+
/**
|
|
161
|
+
* Parses Markdown into a document. Block ids are generated; Markdown has no
|
|
162
|
+
* ids. Line endings of any kind are accepted.
|
|
163
|
+
*/
|
|
164
|
+
declare function markdownToDocument(markdown: string, options?: MarkdownImportOptions): EditorDocument;
|
|
165
|
+
|
|
166
|
+
interface DocumentDiff {
|
|
167
|
+
/** Ids present only in the newer document. */
|
|
168
|
+
added: string[];
|
|
169
|
+
/** Ids present only in the older document. */
|
|
170
|
+
removed: string[];
|
|
171
|
+
/** Ids in both whose own content differs (children of containers are compared by their own ids). */
|
|
172
|
+
changed: string[];
|
|
173
|
+
/** Ids in both, with the same content, that sit in a different order or place. */
|
|
174
|
+
moved: string[];
|
|
175
|
+
/** Ids in both with no difference. */
|
|
176
|
+
unchanged: string[];
|
|
177
|
+
}
|
|
178
|
+
/** Compares two documents by block id (nested blocks included). */
|
|
179
|
+
declare function diffDocuments(previous: EditorDocument, next: EditorDocument): DocumentDiff;
|
|
180
|
+
|
|
181
|
+
type ValidationCode = "invalid-document" | "unsupported-version" | "invalid-block" | "unknown-block-type" | "missing-id" | "duplicate-id" | "invalid-field" | "invalid-inline" | "unsafe-url" | "unknown-token";
|
|
182
|
+
interface ValidationIssue {
|
|
183
|
+
code: ValidationCode;
|
|
184
|
+
/** `error` means the document cannot be rendered as is; `warning` means a renderer will neutralize it. */
|
|
185
|
+
severity: "error" | "warning";
|
|
186
|
+
/** A path such as `blocks[2].items[0].content[1]`. */
|
|
187
|
+
path: string;
|
|
188
|
+
message: string;
|
|
189
|
+
}
|
|
190
|
+
interface ValidationResult {
|
|
191
|
+
/** True when there are no errors. Warnings do not make a document invalid. */
|
|
192
|
+
valid: boolean;
|
|
193
|
+
issues: ValidationIssue[];
|
|
194
|
+
}
|
|
195
|
+
/** Checks an unknown value against the document schema and reports every problem found. */
|
|
196
|
+
declare function validateDocument(value: unknown): ValidationResult;
|
|
197
|
+
/** Type guard: the value has no structural errors (warnings are allowed). */
|
|
198
|
+
declare function isEditorDocument(value: unknown): value is EditorDocument;
|
|
199
|
+
/**
|
|
200
|
+
* Returns a copy of the document that is safe to render: links with unsafe
|
|
201
|
+
* URLs lose the link mark, media with unsafe sources get an empty source,
|
|
202
|
+
* and color marks outside the token allow-list are dropped. Structure and
|
|
203
|
+
* ids are kept. Renderers already neutralize these values; sanitize when
|
|
204
|
+
* you store or forward a document you do not control.
|
|
205
|
+
*/
|
|
206
|
+
declare function sanitizeDocument(doc: EditorDocument): EditorDocument;
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* A small shortcode table for the `emoji` inline node, so exports and the
|
|
210
|
+
* editor can show a character without an emoji dependency. Unknown shortcodes
|
|
211
|
+
* render as `:shortcode:`, which is also what Markdown uses.
|
|
212
|
+
*/
|
|
213
|
+
declare const EMOJI_SHORTCODES: Readonly<Record<string, string>>;
|
|
214
|
+
/** The character for a shortcode (with or without colons), or `null` when it is not in the table. */
|
|
215
|
+
declare function emojiForShortcode(shortcode: string): string | null;
|
|
216
|
+
/** The character when known, otherwise `:shortcode:`. */
|
|
217
|
+
declare function emojiToText(shortcode: string): string;
|
|
218
|
+
|
|
219
|
+
export { Block, EMOJI_SHORTCODES, EditorDocument, HIGHLIGHT_TOKENS, Inline, TEXT_COLOR_TOKENS, collectIds, countCharacters, countWords, createSeededRandom, createSequentialIdGenerator, defaultExportLabels, diffDocuments, documentToHtml, documentToMarkdown, documentToPlainText, emojiForShortcode, emojiToText, escapeHtml, escapeMarkdown, findDuplicateIds, generateBlockId, getDocumentStats, highlightToCss, inlineToPlainText, isEditorDocument, isHighlightToken, isSafeUrl, isTextColorToken, markdownToDocument, markdownToInline, normalizeUrlInput, sanitizeDocument, sanitizeMediaUrl, sanitizeUrl, textColorToCss, tokenToCssVarName, validateDocument, walkBlocks };
|
|
220
|
+
export type { DocumentDiff, DocumentStats, ExportLabels, HighlightToken, HtmlOptions, MarkdownImportOptions, MarkdownOptions, PlainTextOptions, SanitizeUrlOptions, TextColorToken, ValidationCode, ValidationIssue, ValidationResult };
|