@mirrordown/core 0.1.1 → 0.1.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["WHITESPACE","PUNCTUATION","classify","WHITESPACE","WHITESPACE","extractHeaderPara","splitAtGroupStarts","splitBlockquote","buildTree","hash"],"sources":["../src/escapes.ts","../src/github-alerts/types.ts","../src/github-alerts/icons.ts","../src/github-alerts/index.ts","../src/spans.ts","../src/delimited.ts","../src/kbd.ts","../src/scripts.ts","../src/cut-attributes.ts","../src/lazy.ts","../src/line-containers.ts","../src/caption.ts","../src/hast.ts","../src/abbr.ts","../src/steps.ts","../src/tabs.ts","../src/editable.ts","../src/inline-svg.ts","../src/mermaid-pele.ts"],"sourcesContent":["// Parsers resolve backslash escapes before any post-parse transform runs, so a\n// plugin that scans text nodes for delimiters sees `\\==x==` as `==x==`. These\n// helpers recover which characters of a text node were escaped, by aligning its\n// value with the source it came from, and mask them while a plugin scans.\n\n// Only ASCII punctuation can be backslash-escaped (CommonMark §2.4).\nconst ASCII_PUNCTUATION = /^[!-/:-@[-`{-~]$/;\nconst ENTITY = /^&(?:#\\d+|#x[\\da-f]+|[a-z][\\da-z]*);/i;\n\n// Masked characters move into Supplementary Private Use Area-A, where no\n// delimiter pattern can match them; every escapable character maps into\n// U+F0021–U+F007E.\nconst MASK_BASE = 0xf0000;\nconst MASKED = /[\\u{F0021}-\\u{F007E}]/gu;\n\n/**\n * Indices of `value` whose character was backslash-escaped in `source`, where\n * `start`–`end` is the source range the text came from. Characters the parser\n * dropped (backslashes, container prefixes such as `> `, trailing spaces) are\n * skipped, and a character reference stands for the character it decodes to.\n */\nexport const escapedIndices = (\n value: string,\n source: string,\n start: number,\n end: number\n): Set<number> => {\n const escaped = new Set<number>();\n let j = start;\n for (let i = 0; i < value.length && j < end; i++) {\n const char = value.charAt(i);\n let entity: RegExpExecArray | null = null;\n while (j < end && source[j] !== char) {\n entity = source[j] === `&` ? ENTITY.exec(source.slice(j, end)) : null;\n if (entity) break;\n j++;\n }\n if (j >= end) break;\n if (entity) {\n j += entity[0].length;\n continue;\n }\n let slashes = 0;\n for (let k = j - 1; k >= start && source[k] === `\\\\`; k--) slashes++;\n if (slashes % 2 === 1 && ASCII_PUNCTUATION.test(char)) escaped.add(i);\n j++;\n }\n return escaped;\n};\n\n/** Replace the characters at `escaped` with stand-ins no delimiter matches. */\nexport const maskEscaped = (value: string, escaped: Set<number>): string => {\n if (escaped.size === 0) return value;\n let out = ``;\n for (let i = 0; i < value.length; i++) {\n out += escaped.has(i)\n ? String.fromCodePoint(MASK_BASE + value.charCodeAt(i))\n : value[i];\n }\n return out;\n};\n\n/** Restore characters replaced by {@link maskEscaped}. */\nexport const unmaskEscaped = (value: string): string =>\n value.replace(MASKED, (c) =>\n String.fromCharCode(c.codePointAt(0)! - MASK_BASE)\n );\n\n/** The shape of a unist text node this module reads and writes. */\nexport interface TextLikeNode {\n type: string;\n value?: unknown;\n position?:\n | {\n start: { offset?: number | undefined };\n end: { offset?: number | undefined };\n }\n | undefined;\n children?: TextLikeNode[] | undefined;\n}\n\n/**\n * Mask escaped characters in every positioned `text` node of a unist tree, so\n * a delimiter scan skips them. Returns a function that restores them in every\n * node afterwards, including nodes the scan created from masked text.\n */\nexport const maskTreeEscapes = (\n tree: TextLikeNode,\n source: string\n): (() => void) => {\n const walk = (node: TextLikeNode, visit: (n: TextLikeNode) => void): void => {\n visit(node);\n node.children?.forEach((child) => walk(child, visit));\n };\n walk(tree, (node) => {\n const start = node.position?.start.offset;\n const end = node.position?.end.offset;\n if (node.type !== `text` || typeof node.value !== `string`) return;\n if (start === undefined || end === undefined) return;\n node.value = maskEscaped(\n node.value,\n escapedIndices(node.value, source, start, end)\n );\n });\n return () =>\n walk(tree, (node) => {\n if (typeof node.value === `string`)\n node.value = unmaskEscaped(node.value);\n });\n};\n","/** A recognized alert keyword (e.g. `note`, `warning`, `caution`). */\nexport type AlertType =\n | \"note\"\n | \"tip\"\n | \"important\"\n | \"warning\"\n | \"caution\"\n | \"abstract\"\n | \"info\"\n | \"todo\"\n | \"success\"\n | \"question\"\n | \"failure\"\n | \"danger\"\n | \"bug\"\n | \"example\"\n | \"quote\";\n\n// Maps every recognized keyword (lowercase) to its canonical AlertType.\n// Aliases collapse so CSS only needs one selector per canonical type.\n/** Maps every recognized alert keyword (lowercase) to its canonical {@link AlertType}. */\nexport const ALERT_ALIASES: Record<string, AlertType> = {\n // GitHub 5\n note: \"note\",\n tip: \"tip\",\n important: \"important\",\n warning: \"warning\",\n caution: \"caution\",\n // Obsidian extended\n abstract: \"abstract\",\n summary: \"abstract\",\n tldr: \"abstract\",\n info: \"info\",\n todo: \"todo\",\n hint: \"tip\",\n success: \"success\",\n check: \"success\",\n done: \"success\",\n question: \"question\",\n help: \"question\",\n faq: \"question\",\n attention: \"warning\",\n failure: \"failure\",\n fail: \"failure\",\n missing: \"failure\",\n danger: \"danger\",\n error: \"danger\",\n bug: \"bug\",\n example: \"example\",\n quote: \"quote\",\n cite: \"quote\"\n};\n\n/** Default display title for each {@link AlertType}. */\nexport const DEFAULT_TITLE: Record<AlertType, string> = {\n note: \"Note\",\n tip: \"Tip\",\n important: \"Important\",\n warning: \"Warning\",\n caution: \"Caution\",\n abstract: \"Abstract\",\n info: \"Info\",\n todo: \"Todo\",\n success: \"Success\",\n question: \"Question\",\n failure: \"Failure\",\n danger: \"Danger\",\n bug: \"Bug\",\n example: \"Example\",\n quote: \"Quote\"\n};\n\n/** Options shared by the GitHub alerts plugins for every engine. */\nexport interface AlertOptions {\n /**\n * Extra alert types beyond the built-in set. Keys are lowercase keywords\n * (including any aliases you want), values are the canonical type string\n * that appears in the data-alert attribute and CSS class.\n */\n types?: Record<string, string>;\n /** Default display titles, keyed by canonical type. */\n titles?: Partial<Record<AlertType, string>>;\n /** Set false to require exact case on the [!TYPE] keyword. Default: true. */\n matchCaseInsensitive?: boolean;\n /** Set false to suppress the SVG icon in the title. Default: true. */\n icons?: boolean;\n /** CSS class applied to the alert container. Default: \"markdown-alert\". */\n containerClass?: string;\n}\n","import type { AlertType } from \"./types.js\";\n\n// All icons are Lucide SVGs (lucide.dev), stroke=\"currentColor\", 24×24 viewBox.\n// They inherit their color from the --_alert-color CSS variable via `color`.\n\nconst icon = (path: string): string =>\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${path}</svg>`;\n\n/** Inline SVG icon markup for each {@link AlertType}. */\nexport const ICONS: Record<AlertType, string> = {\n // GitHub alert types — Lucide equivalents of the GitHub Octicons\n note: icon(\n '<path d=\"M12 20h9\"></path><path d=\"M16.376 3.622a1 1 0 0 1 3.002 3.002L7.368 18.635a2 2 0 0 1-.855.506l-2.872.838a.5.5 0 0 1-.62-.62l.838-2.872a2 2 0 0 1 .506-.854z\"></path>'\n ),\n tip: icon(\n '<path d=\"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5\"></path><path d=\"M9 18h6\"></path><path d=\"M10 22h4\"></path>'\n ),\n important: icon('<path d=\"M7.9 20A9 9 0 1 0 4 16.1L2 22z\"></path>'),\n warning: icon(\n '<path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"></path><path d=\"M12 9v4\"></path><path d=\"M12 17h.01\"></path>'\n ),\n caution: icon(\n '<circle cx=\"12\" cy=\"12\" r=\"10\"></circle><path d=\"m4.9 4.9 14.2 14.2\"></path><path d=\"M12 8v4\"></path><path d=\"M12 16h.01\"></path>'\n ),\n // Obsidian extended types\n abstract: icon(\n '<rect width=\"8\" height=\"4\" x=\"8\" y=\"2\" rx=\"1\" ry=\"1\"></rect><path d=\"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2\"></path><path d=\"M12 11h4\"></path><path d=\"M12 16h4\"></path><path d=\"M8 11h.01\"></path><path d=\"M8 16h.01\"></path>'\n ),\n info: icon(\n '<circle cx=\"12\" cy=\"12\" r=\"10\"></circle><path d=\"M12 16v-4\"></path><path d=\"M12 8h.01\"></path>'\n ),\n todo: icon(\n '<path d=\"M8 6h13\"></path><path d=\"M8 12h13\"></path><path d=\"M8 18h13\"></path><path d=\"M3 6h.01\"></path><path d=\"M3 12h.01\"></path><path d=\"M3 18h.01\"></path>'\n ),\n success: icon(\n '<path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\"></path><path d=\"m9 11 3 3L22 4\"></path>'\n ),\n question: icon(\n '<circle cx=\"12\" cy=\"12\" r=\"10\"></circle><path d=\"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\"></path><path d=\"M12 17h.01\"></path>'\n ),\n failure: icon(\n '<circle cx=\"12\" cy=\"12\" r=\"10\"></circle><path d=\"m15 9-6 6\"></path><path d=\"m9 9 6 6\"></path>'\n ),\n danger: icon('<path d=\"M13 2 3 14h9l-1 8 10-12h-9l1-8z\"></path>'),\n bug: icon(\n '<path d=\"m8 2 1.88 1.88\"></path><path d=\"M14.12 3.88 16 2\"></path><path d=\"M9 7.13v-1a3.003 3.003 0 1 1 6 0v1\"></path><path d=\"M12 20c-3.3 0-6-2.7-6-6v-3a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v3c0 3.3-2.7 6-6 6\"></path><path d=\"M12 20v-9\"></path><path d=\"M6.53 9C4.6 8.8 3 7.1 3 5\"></path><path d=\"M6 13H2\"></path><path d=\"M3 21c0-2.1 1.7-3.9 3.8-4\"></path><path d=\"M20.97 5c0 2.1-1.6 3.8-3.5 4\"></path><path d=\"M22 13h-4\"></path><path d=\"M17.2 17c2.1.1 3.8 1.9 3.8 4\"></path>'\n ),\n example: icon(\n '<path d=\"M8 6h13\"></path><path d=\"M8 12h13\"></path><path d=\"M8 18h13\"></path><path d=\"M3 6 4 5l1 1-1 1z\"></path><path d=\"M3 12 4 11l1 1-1 1z\"></path><path d=\"M3 18 4 17l1 1-1 1z\"></path>'\n ),\n quote: icon(\n '<path d=\"M3 21c3 0 7-1 7-8V5c0-1.25-.756-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V20c0 1 0 1 1 1z\"></path><path d=\"M15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z\"></path>'\n )\n};\n","import {\n ALERT_ALIASES,\n DEFAULT_TITLE,\n type AlertOptions,\n type AlertType\n} from \"./types.js\";\nimport { ICONS } from \"./icons.js\";\n\nexport { ALERT_ALIASES, DEFAULT_TITLE, ICONS };\nexport type { AlertOptions, AlertType };\n\n// Groups: 1=type keyword, 2=foldable marker (+/-)\nconst MARKER_RE = /^\\[!([^\\]]+)\\]([+-])?/;\n\n/** Whether a source line opens an alert (`> [!NOTE]`), after its `>` markers and indentation, whether or not the alerts plugin reads it: a block that takes the quote after it as more of its content (a step body) leaves an alert be. */\nexport const isAlertMarkerLine = (line: string): boolean =>\n MARKER_RE.test(line.replace(/^[ \t>]*/, ``));\n\nconst capitalize = (s: string): string =>\n s.charAt(0).toUpperCase() + s.slice(1);\n\n/** How an alert keyword resolves under a plugin's options. */\nexport interface AlertResolver {\n /** The canonical type for a `[!KEYWORD]`, or `undefined` if it is not an alert. */\n resolve: (keyword: string) => string | undefined;\n /** The title shown when the alert has no custom title. */\n titleFor: (type: string) => string;\n /** The icon SVG for the title, or `\"\"` when icons are off. */\n iconFor: (type: string) => string;\n /** The alert container's CSS class. */\n containerClass: string;\n}\n\n/** Resolve alert keywords, titles and icons the same way in every engine. */\nexport const createAlertResolver = (\n options: AlertOptions = {}\n): AlertResolver => {\n const {\n types: extraTypes = {},\n titles = {},\n matchCaseInsensitive = true,\n icons = true,\n containerClass = `markdown-alert`\n } = options;\n const aliasMap: Record<string, string> = { ...ALERT_ALIASES, ...extraTypes };\n // Titles may name user-defined types from `options.types` too.\n const customTitles: Partial<Record<string, string>> = titles;\n const isAlertType = (type: string): type is AlertType =>\n type in DEFAULT_TITLE;\n return {\n resolve: (keyword) =>\n aliasMap[matchCaseInsensitive ? keyword.toLowerCase() : keyword],\n // A user-defined type may have no default title; capitalize the keyword as a last resort.\n titleFor: (type) =>\n customTitles[type] ??\n (isAlertType(type) ? DEFAULT_TITLE[type] : undefined) ??\n capitalize(type),\n iconFor: (type) => (icons && isAlertType(type) ? ICONS[type] : ``),\n containerClass\n };\n};\n\n/** The shape of an mdast phrasing node this module reads and builds. */\nexport interface PhrasingLike {\n type: string;\n value?: string;\n alt?: string | null | undefined;\n children?: readonly PhrasingLike[];\n}\n\n/** A paragraph that opens with an alert marker, split into its parts. */\nexport interface AlertParagraph<N extends PhrasingLike> {\n /** The `[!KEYWORD]` text, before alias resolution. */\n keyword: string;\n /** `+` (open) or `-` (closed) for a foldable alert, else `undefined`. */\n fold: `+` | `-` | undefined;\n /** The first line after the marker: the custom title, formatting included. */\n titleNodes: N[];\n /** The title's plain text (text, inline code and image alt), for `aria-label`. */\n titleText: string;\n /** Everything after the first line break (soft or hard): the paragraph's body. */\n bodyNodes: N[];\n}\n\n/** Plain text of inline content: text, inline code and image alt count; raw HTML does not. */\nexport const plainText = (nodes: readonly PhrasingLike[]): string =>\n nodes\n .map((n) =>\n n.type === `text` || n.type === `inlineCode`\n ? (n.value ?? ``)\n : n.type === `image`\n ? (n.alt ?? ``)\n : n.children\n ? plainText(n.children)\n : ``\n )\n .join(``);\n\nconst withValue = <N extends PhrasingLike>(node: N, value: string): N => ({\n ...node,\n value\n});\n\n/**\n * Split an alert's first paragraph (an mdast `paragraph`'s children) into its marker, title and body, or return `null` when it does not open with a `[!KEYWORD]` marker in plain text. The first line is the marker plus an optional title; everything after the first line break — a newline inside a text node (soft) or a `break` node (hard) — is the body. Nothing is dropped. Text nodes are copied; other nodes are reused as they are.\n */\nexport const splitAlertParagraph = <N extends PhrasingLike>(\n children: readonly N[]\n): AlertParagraph<N> | null => {\n const [first, ...rest] = children;\n if (first?.type !== `text` || first.value === undefined) return null;\n const opening = first.value.trimStart();\n const match = MARKER_RE.exec(opening);\n if (!match) return null;\n const [marker, keyword = ``, fold] = match;\n\n const line: N[] = [];\n const body: N[] = [];\n for (const child of [\n withValue(first, opening.slice(marker.length)),\n ...rest\n ]) {\n if (body.length > 0 || line.at(-1)?.type === `break`) {\n body.push(child);\n } else if (child.type === `text` && child.value?.includes(`\\n`)) {\n const at = child.value.indexOf(`\\n`);\n line.push(withValue(child, child.value.slice(0, at)));\n body.push(withValue(child, child.value.slice(at + 1)));\n } else {\n line.push(child);\n }\n }\n if (line.at(-1)?.type === `break`) line.pop();\n\n const trimmed = line.map((n, i) =>\n n.type !== `text`\n ? n\n : withValue(\n n,\n i === 0 && i === line.length - 1\n ? (n.value ?? ``).trim()\n : i === 0\n ? (n.value ?? ``).trimStart()\n : i === line.length - 1\n ? (n.value ?? ``).trimEnd()\n : (n.value ?? ``)\n )\n );\n const titleNodes = trimmed.filter((n) => n.type !== `text` || n.value !== ``);\n const lastTitle = titleNodes.at(-1);\n if (lastTitle?.type === `text`) {\n titleNodes[titleNodes.length - 1] = withValue(\n lastTitle,\n (lastTitle.value ?? ``).trimEnd()\n );\n }\n\n return {\n keyword,\n fold: fold === `+` || fold === `-` ? fold : undefined,\n titleNodes,\n titleText: plainText(titleNodes).trim(),\n bodyNodes: body.filter((n) => n.type !== `text` || n.value !== ``)\n };\n};\n","import { escapedIndices, maskEscaped, unmaskEscaped } from \"./escapes.js\";\nimport type { PhrasingLike } from \"./github-alerts/index.js\";\n\n// The plumbing shared by core's inline span scans (`delimited.ts`, `kbd.ts`): tracking the nodes a scan builds, and masking escaped characters for engines whose nodes are read-only.\n\n/** How a scanned span becomes nodes. */\nexport interface SpanNodes<N extends PhrasingLike> {\n /** A text node with the given value. */\n text: (value: string) => N;\n /** The node a span's content is wrapped in (e.g. an mdast `mark`). */\n wrap: (children: N[]) => N;\n}\n\n/** A node's source range, as unist positions carry it. */\nexport interface Positioned {\n position?:\n | {\n start: { offset?: number | undefined };\n end: { offset?: number | undefined };\n }\n | undefined;\n}\n\n/** A scan over one parent's children, and the nodes it created. */\nexport interface SpanTransform<N extends PhrasingLike> {\n /** Scan `children`, the children of a node of type `parentType`. Returns `children` itself when no span forms. */\n (children: readonly N[], parentType?: string): readonly N[];\n /** Whether `node` was built by this transform (a wrapper or a text node). */\n built: (node: object) => boolean;\n /**\n * The transform for engines whose text values have escapes resolved and whose nodes are read-only, such as Sätteri: escaped characters are masked by aligning each positioned text node with `source`, using copies, and restored in the result. Returns the new children, or `undefined` when no span forms.\n */\n withSource: (\n children: ReadonlyArray<N & Positioned>,\n parentType: string,\n source: string\n ) => N[] | undefined;\n}\n\n/** A scan, given node builders that record what they build. */\nexport type SpanScan<N extends PhrasingLike> = (\n children: readonly N[],\n parentType: string,\n nodes: SpanNodes<N>\n) => readonly N[];\n\n/** Wrap a scan with built-node tracking and source-based escape masking. */\nexport const createSpanTransform = <N extends PhrasingLike>(\n nodes: SpanNodes<N>,\n scan: SpanScan<N>\n): SpanTransform<N> => {\n const built = new WeakSet<object>();\n // Each wrapper's content, kept typed for restoring masked escapes.\n const contents = new WeakMap<object, N[]>();\n const tracked: SpanNodes<N> = {\n text: (value) => {\n const node = nodes.text(value);\n built.add(node);\n return node;\n },\n wrap: (children) => {\n const node = nodes.wrap(children);\n built.add(node);\n contents.set(node, children);\n return node;\n }\n };\n\n const transform = (children: readonly N[], parentType = ``): readonly N[] =>\n scan(children, parentType, tracked);\n\n const restore = (list: readonly N[]): void => {\n for (const node of list) {\n if (!built.has(node)) continue;\n if (node.type === `text` && node.value !== undefined) {\n node.value = unmaskEscaped(node.value);\n } else {\n restore(contents.get(node) ?? []);\n }\n }\n };\n\n const withSource = (\n children: ReadonlyArray<N & Positioned>,\n parentType: string,\n source: string\n ): N[] | undefined => {\n const masked = children.map((node): N => {\n const start = node.position?.start.offset;\n const end = node.position?.end.offset;\n if (\n node.type !== `text` ||\n node.value === undefined ||\n start === undefined ||\n end === undefined\n )\n return node;\n const escaped = escapedIndices(node.value, source, start, end);\n return escaped.size === 0\n ? node\n : tracked.text(maskEscaped(node.value, escaped));\n });\n const next = transform(masked, parentType);\n if (next === masked) return undefined;\n restore(next);\n return [...next];\n };\n\n return Object.assign(transform, {\n built: (node: object) => built.has(node),\n withSource\n });\n};\n","import type { PhrasingLike } from \"./github-alerts/index.js\";\nimport {\n createSpanTransform,\n type SpanNodes,\n type SpanTransform\n} from \"./spans.js\";\n\n// The scan behind `==mark==`, `++ins++`, `--del--` and `||spoiler||`, shared by the remark and Sätteri plugins. It ports markdown-it's delimiter algorithm (the one markdown-it-mark and markdown-it-ins use), so all three engines pair delimiters the same way: runs of the marker split into two-character delimiters that open or close by emphasis-style flanking, each closer pairs with the nearest open opener, pairs nest, and the odd marker of an odd-length run stays outside the tag. It works on one parent's children: text is scanned, other nodes are opaque. It is pure; remark runs it on mutable nodes, Sätteri on read-only ones (it builds new nodes and reuses the rest).\n\n/** A marker whose doubled form delimits a span: `==`, `++`, `--` or `||`. */\nexport type DelimiterMarker = `=` | `+` | `-` | `|`;\n\n// What markdown-it sees beside a run at the edge of a text node: inside an inline parent, that parent's own delimiter (`*`, `[`, `~`…), which is punctuation; at the edge of a block's inline content, the space markdown-it assumes there.\nconst INLINE_PARENTS = new Set([\n `delete`,\n `emphasis`,\n `insert`,\n `link`,\n `linkReference`,\n `mark`,\n `spoiler`,\n `spoilerContent`,\n `strong`,\n `subscript`,\n `superscript`\n]);\n\ntype CharClass = `space` | `punct` | `other`;\n\n// markdown-it's isWhiteSpace, and isMdAsciiPunct || isPunctChar (Unicode P and S).\nconst WHITESPACE =\n /^[\\t\\n\\v\\f\\r \\u00a0\\u1680\\u2000-\\u200a\\u202f\\u205f\\u3000]$/u;\nconst PUNCTUATION = /^[\\p{P}\\p{S}]$/u;\nconst classify = (char: string): CharClass =>\n WHITESPACE.test(char) ? `space` : PUNCTUATION.test(char) ? `punct` : `other`;\n\ninterface Delimiter {\n open: boolean;\n close: boolean;\n /** Index of the paired closer in the delimiter list, or -1. */\n end: number;\n /** Index among the items; consecutive values are delimiters of one run. */\n item: number;\n}\n\ntype Item<N> =\n | { kind: `text`; value: string }\n | { kind: `node`; node: N }\n | { kind: `delimiter` }\n | { kind: `opening` }\n | { kind: `closing` };\n\n/**\n * markdown-it's `balance_pairs` for a single marker. Every delimiter has `length: 0`, as in markdown-it-mark, so the emphasis \"rule of 3\" never applies.\n */\nconst balancePairs = (delimiters: Delimiter[]): void => {\n const jumps: number[] = [];\n const openersBottom = [-1, -1, -1, -1, -1, -1];\n let headerIdx = 0;\n let lastItem = -2;\n delimiters.forEach((closer, closerIdx) => {\n jumps.push(0);\n if (lastItem !== closer.item - 1) headerIdx = closerIdx;\n lastItem = closer.item;\n if (!closer.close) return;\n const bottom = closer.open ? 3 : 0;\n const minOpenerIdx = openersBottom[bottom] ?? -1;\n let openerIdx = headerIdx - (jumps[headerIdx] ?? 0) - 1;\n let newMinOpenerIdx = openerIdx;\n for (; openerIdx > minOpenerIdx; openerIdx -= (jumps[openerIdx] ?? 0) + 1) {\n const opener = delimiters[openerIdx];\n if (!opener?.open || opener.end >= 0) continue;\n const lastJump =\n openerIdx > 0 && delimiters[openerIdx - 1]?.open === false\n ? (jumps[openerIdx - 1] ?? 0) + 1\n : 0;\n jumps[closerIdx] = closerIdx - openerIdx + lastJump;\n jumps[openerIdx] = lastJump;\n closer.open = false;\n opener.end = closerIdx;\n opener.close = false;\n newMinOpenerIdx = -1;\n lastItem = -2;\n break;\n }\n if (newMinOpenerIdx !== -1) openersBottom[bottom] = newMinOpenerIdx;\n });\n};\n\n/** Build the delimiter scan for one marker: `=` (mark), `+` (ins), `-` (del) or `|` (spoiler). */\nexport const createDelimitedTransform = <N extends PhrasingLike>(\n marker: DelimiterMarker,\n nodes: SpanNodes<N>\n): SpanTransform<N> =>\n createSpanTransform(nodes, (children, parentType, { text, wrap }) => {\n const edge: CharClass = INLINE_PARENTS.has(parentType) ? `punct` : `space`;\n // The character class beside a text node, from its sibling: a break is a line ending; any other node ends in its own delimiter or markup.\n const beside = (\n node: N | undefined,\n side: `before` | `after`\n ): CharClass => {\n if (!node) return edge;\n if (node.type === `text` && node.value) {\n return classify(\n side === `before` ? node.value.slice(-1) : node.value.charAt(0)\n );\n }\n return node.type === `break` ? `space` : `punct`;\n };\n\n // markdown-it-mark's tokenizer: text between runs is one item, as markdown-it's pending text becomes one token.\n const items: Array<Item<N>> = [];\n const delimiters: Delimiter[] = [];\n children.forEach((child, index) => {\n const value = child.type === `text` ? child.value : undefined;\n if (value === undefined) {\n items.push({ kind: `node`, node: child });\n return;\n }\n let pending = ``;\n const flush = (): void => {\n if (pending) items.push({ kind: `text`, value: pending });\n pending = ``;\n };\n let i = 0;\n while (i < value.length) {\n let end = i;\n while (value.charAt(end) === marker) end++;\n if (end - i < 2) {\n pending += value.slice(i, Math.max(end, i + 1));\n i = Math.max(end, i + 1);\n continue;\n }\n const last =\n i > 0\n ? classify(value.charAt(i - 1))\n : beside(children[index - 1], `before`);\n const next =\n end < value.length\n ? classify(value.charAt(end))\n : beside(children[index + 1], `after`);\n const open = next !== `space` && (next !== `punct` || last !== `other`);\n const close =\n last !== `space` && (last !== `punct` || next !== `other`);\n flush();\n let length = end - i;\n if (length % 2) {\n items.push({ kind: `text`, value: marker });\n length--;\n }\n for (let pair = 0; pair < length; pair += 2) {\n if (open || close) {\n delimiters.push({ open, close, end: -1, item: items.length });\n items.push({ kind: `delimiter` });\n } else {\n items.push({ kind: `text`, value: marker + marker });\n }\n }\n i = end;\n }\n flush();\n });\n\n balancePairs(delimiters);\n if (!delimiters.some(({ end }) => end >= 0)) return children;\n\n // markdown-it-mark's postProcess: paired delimiters become tags, and the odd marker of an odd-length closing run moves after the closing tags.\n const lone: number[] = [];\n for (const delimiter of delimiters) {\n const closer = delimiters[delimiter.end];\n if (!closer) continue;\n items[delimiter.item] = { kind: `opening` };\n items[closer.item] = { kind: `closing` };\n const previous = items[closer.item - 1];\n if (previous?.kind === `text` && previous.value === marker) {\n lone.push(closer.item - 1);\n }\n }\n for (const i of lone.reverse()) {\n let j = i + 1;\n while (items[j]?.kind === `closing`) j++;\n j--;\n const moved = items[i];\n const target = items[j];\n if (i !== j && moved && target) {\n items[i] = target;\n items[j] = moved;\n }\n }\n\n // Fold the flat items into nested wrappers, merging adjacent text.\n const root: N[] = [];\n const stack: N[][] = [root];\n let buffer = ``;\n const append = (node: N): void => {\n (stack.at(-1) ?? root).push(node);\n };\n const flushText = (): void => {\n if (!buffer) return;\n append(text(buffer));\n buffer = ``;\n };\n for (const item of items) {\n if (item.kind === `text`) {\n buffer += item.value;\n } else if (item.kind === `delimiter`) {\n buffer += marker + marker;\n } else if (item.kind === `node`) {\n flushText();\n append(item.node);\n } else if (item.kind === `opening`) {\n flushText();\n stack.push([]);\n } else {\n flushText();\n append(wrap(stack.pop() ?? []));\n }\n }\n flushText();\n return root;\n });\n","import type { PhrasingLike } from \"./github-alerts/index.js\";\nimport {\n createSpanTransform,\n type SpanNodes,\n type SpanTransform\n} from \"./spans.js\";\n\n// The scan behind `[[key]]`, shared by the remark and Sätteri plugins. It ports markdown-it-kbd's tokenizer: from a `[[`, it walks forward counting nested `[[` and `]]` until the depth returns to zero, gives up at a line ending, and parses the content again for nested keys. It works on one parent's children: text is scanned character by character, other nodes are opaque. One difference is inherent: markdown-it-kbd scans source text, so it claims `[[*a]]*` before emphasis is resolved, while remark and Sätteri have parsed the emphasis before a plugin runs.\n\ntype Unit<N> = { char: string } | { node: N };\n\nconst isChar = (unit: Unit<PhrasingLike> | undefined, char: string): boolean =>\n unit !== undefined && `char` in unit && unit.char === char;\n\n/**\n * The index of the `]]` that closes the `[[` at `start`, or -1. This mirrors markdown-it-kbd's loop, which looks at each character with the one after it, starting from the opener's second `[`, and skips the second character of every pair it consumes.\n */\nconst findClose = <N extends PhrasingLike>(\n units: ReadonlyArray<Unit<N>>,\n start: number\n): number => {\n let depth = 1;\n let skipNext = false;\n for (let i = start + 1; i < units.length; i++) {\n if (skipNext) {\n skipNext = false;\n continue;\n }\n const unit = units[i];\n const next = units[i + 1];\n if (isChar(unit, `]`) && isChar(next, `]`)) {\n depth--;\n if (depth === 0) return i;\n skipNext = true;\n } else if (isChar(unit, `[`) && isChar(next, `[`)) {\n depth++;\n skipNext = true;\n } else if (\n isChar(unit, `\\n`) ||\n (unit && `node` in unit && unit.node.type === `break`)\n ) {\n return -1;\n }\n }\n return -1;\n};\n\n/** Build the `[[key]]` scan. */\nexport const createKbdTransform = <N extends PhrasingLike>(\n nodes: SpanNodes<N>\n): SpanTransform<N> =>\n createSpanTransform(nodes, (children, _parentType, { text, wrap }) => {\n const units: Array<Unit<N>> = children.flatMap((child): Array<Unit<N>> => {\n const value = child.type === `text` ? child.value : undefined;\n return value === undefined\n ? [{ node: child }]\n : Array.from(value, (char) => ({ char }));\n });\n\n // Scan a stretch of units into nodes; a key's content is scanned again, as markdown-it-kbd tokenizes it.\n const scan = (\n list: ReadonlyArray<Unit<N>>\n ): { nodes: N[]; keyed: boolean } => {\n const out: N[] = [];\n let keyed = false;\n let buffer = ``;\n const flushText = (): void => {\n if (buffer) out.push(text(buffer));\n buffer = ``;\n };\n for (let i = 0; i < list.length;) {\n const unit = list[i];\n if (isChar(unit, `[`) && isChar(list[i + 1], `[`)) {\n const end = findClose(list, i);\n if (end >= 0) {\n keyed = true;\n flushText();\n out.push(wrap(scan(list.slice(i + 2, end)).nodes));\n i = end + 2;\n continue;\n }\n }\n if (unit && `char` in unit) buffer += unit.char;\n else if (unit) {\n flushText();\n out.push(unit.node);\n }\n i++;\n }\n flushText();\n return { nodes: out, keyed };\n };\n\n const { nodes: result, keyed } = scan(units);\n return keyed ? result : children;\n });\n","import type {\n Code,\n Construct,\n Event,\n Resolver,\n State,\n TokenizeContext,\n TokenType,\n Effects\n} from \"micromark-util-types\";\n\n// micromark syntax for `~subscript~` and `^superscript^`, shared by remd-sub and remd-sup. Each marker is a single-character delimiter run with emphasis-style flanking. One resolver pairs both markers: it takes closers left to right and pairs each with the nearest opener of the same marker, so crossing runs (`^a~b^c~`) resolve leftmost-first and the two nest, as in markdown-it and Sätteri. It runs once however many of the two constructs a document uses, because micromark calls each `resolveAll` function once.\n\n/** The marker characters, and the micromark token types each produces. */\nconst SCRIPTS = {\n \"~\": { code: 126, type: `subscript` },\n \"^\": { code: 94, type: `superscript` }\n} as const;\n\ntype Marker = keyof typeof SCRIPTS;\n\n// Extensions register their token types by augmenting micromark's TokenTypeMap, which JSR rejects; this one assertion stands in for it.\n// oxlint-disable-next-line typescript/no-unsafe-type-assertion\nconst tokenType = (type: string): TokenType => type as TokenType;\nconst temporary = (type: string): TokenType =>\n tokenType(`${type}SequenceTemporary`);\nconst scriptOf = (tokenType: string): (typeof SCRIPTS)[Marker] | undefined =>\n Object.values(SCRIPTS).find(({ type }) => temporary(type) === tokenType);\n\n// micromark-util-classify-character, inlined: 1 = whitespace, 2 = punctuation.\nconst PUNCTUATION = /\\p{P}|\\p{S}/u;\nconst WHITESPACE = /\\s/;\nconst classify = (code: Code): 1 | 2 | undefined =>\n code === null ||\n code < 0 ||\n code === 32 ||\n WHITESPACE.test(String.fromCharCode(code))\n ? 1\n : PUNCTUATION.test(String.fromCharCode(code))\n ? 2\n : undefined;\n\n// micromark-util-chunked's `splice`, inlined: spreading a long list into Array#splice can overflow the stack.\nconst splice = <T>(\n list: T[],\n start: number,\n remove: number,\n items: T[]\n): void => {\n list.splice(start, remove);\n for (let i = 0; i < items.length; i += 10_000) {\n list.splice(start + i, 0, ...items.slice(i, i + 10_000));\n }\n};\n\n// micromark-util-resolve-all, inlined: run each distinct resolver once.\nconst resolveAll = (\n constructs: ReadonlyArray<Pick<Construct, \"resolveAll\">>,\n events: Event[],\n context: TokenizeContext\n): Event[] => {\n const called: Resolver[] = [];\n let result = events;\n for (const { resolveAll: resolve } of constructs) {\n if (resolve && !called.includes(resolve)) {\n result = resolve(result, context);\n called.push(resolve);\n }\n }\n return result;\n};\n\nconst resolveScripts: Resolver = (events, context) => {\n for (let index = 0; index < events.length; index++) {\n const [kind, closer] = events.at(index) ?? [];\n const script = closer && scriptOf(closer.type);\n if (kind !== `enter` || !closer || !script || !closer._close) continue;\n\n for (let open = index - 1; open >= 0; open--) {\n const [openKind, opener] = events.at(open) ?? [];\n if (\n openKind !== `exit` ||\n !opener ||\n opener.type !== closer.type ||\n !opener._open\n )\n continue;\n\n opener.type = tokenType(`${script.type}Sequence`);\n closer.type = tokenType(`${script.type}Sequence`);\n const span = {\n type: tokenType(script.type),\n start: { ...opener.start },\n end: { ...closer.end }\n };\n const text = {\n type: tokenType(`${script.type}Text`),\n start: { ...opener.end },\n end: { ...closer.start }\n };\n const next: Event[] = [\n [`enter`, span, context],\n [`enter`, opener, context],\n [`exit`, opener, context],\n [`enter`, text, context],\n // Resolve what is between first: runs that open inside the span close inside it or not at all.\n ...resolveAll(\n context.parser.constructs.insideSpan.null ?? [],\n events.slice(open + 1, index),\n context\n ),\n [`exit`, text, context],\n [`enter`, closer, context],\n [`exit`, closer, context],\n [`exit`, span, context]\n ];\n splice(events, open - 1, index - open + 3, next);\n index = open + next.length - 2;\n break;\n }\n }\n // Runs left unpaired are plain text.\n for (const [, token] of events) {\n if (scriptOf(token.type)) token.type = `data`;\n }\n return events;\n};\n\nfunction tokenize(\n this: TokenizeContext,\n effects: Effects,\n ok: State,\n nok: State\n): State {\n const { previous, events } = this;\n return (start: Code) => {\n const script = Object.values(SCRIPTS).find((s) => s.code === start);\n if (!script) return nok(start);\n // Only the start of a run: the rest of a longer run stays text.\n if (\n previous === script.code &&\n events.at(-1)?.[1].type !== `characterEscape`\n )\n return nok(start);\n effects.enter(temporary(script.type));\n effects.consume(start);\n return (after: Code) => {\n // A run of two or more is not a delimiter (`~~` is strikethrough's).\n if (after === script.code) return nok(after);\n const token = effects.exit(temporary(script.type));\n const before = classify(previous);\n const next = classify(after);\n token._open = !next || (next === 2 && Boolean(before));\n token._close = !before || (before === 2 && Boolean(next));\n return ok(after);\n };\n };\n}\n\n/** The shape of a micromark syntax extension this module builds. */\nexport interface ScriptSyntax {\n text: Record<number, unknown>;\n insideSpan: { null: unknown[] };\n}\n\n/**\n * The micromark syntax extension for one of the two markers: `~` (subscript, `subscript` tokens) or `^` (superscript, `superscript` tokens). The constructs of both markers resolve together.\n */\nexport const scriptSyntax = (marker: Marker): ScriptSyntax => {\n const construct: Construct = {\n name: SCRIPTS[marker].type,\n tokenize,\n resolveAll: resolveScripts\n };\n return {\n text: { [SCRIPTS[marker].code]: construct },\n insideSpan: { null: [construct] }\n };\n};\n","// Attribute blocks a lazily continued header hid: a tab or step header right after a body's last paragraph continues it in CommonMark, so a parser that reads attribute blocks before recognition (Sätteri) finds the paragraph's last block mid-paragraph and keeps it as text. Recognition cuts the paragraph before the header; these blocks then end it, and go where the parser would have put them, as markdown-it and remark (whose attrs run after recognition) do.\nimport type { Paragraph, PhrasingContent, Root, RootContent } from \"mdast\";\nimport type { Properties } from \"hast\";\n\n/** Paragraphs recognition rebuilt from lines, as it does where a tab or step header lazily continued them. */\nexport const rebuiltParagraphs = new WeakSet<Paragraph>();\n\n/** The properties an attribute block written after text gives the text's paragraph, as the parser reads them, or `undefined` if it isn't one. */\nexport type ReadAttributes = (block: string) => Properties | undefined;\n\ntype Node = Root | RootContent;\ntype Parent = Extract<Node, { children: unknown }>;\n\n/** A tab or step item recognition built, whose title nodes it shares with its label. */\ninterface TitledItem {\n data: {\n attrsRole: string;\n attrsTitle: PhrasingContent[];\n hProperties?: Properties;\n };\n}\n\n/** Joins `added` into `properties`: classes accumulate, other attributes replace. */\nconst mergeProperties = (\n properties: Properties | undefined,\n added: Properties\n): Properties => {\n const merged: Properties = { ...properties };\n for (const [key, value] of Object.entries(added)) {\n const existing = merged[key];\n merged[key] =\n key === \"className\" && Array.isArray(existing) && Array.isArray(value)\n ? [...existing, ...value]\n : value;\n }\n return merged;\n};\n\n// Whether mdast-util-to-hast wraps the list's paragraphs in `<p>`, as it does in a loose list.\nconst listLoose = (list: Node | undefined): boolean =>\n list?.type !== \"list\" ||\n Boolean(list.spread) ||\n list.children.some((item) => item.spread ?? item.children.length > 1);\n\n/**\n * Places the attribute block now ending each paragraph recognition rebuilt (one a header was cut from), as the parser places one: a block on a line of its own goes on the block it's written after, at the level its `>` markers and indentation put it (the paragraph, its list item in a tight list, or the outermost blockquote or list item it's written outside of, a list item giving its list); a block after text goes on the paragraph, or its list item from the item's first paragraph.\n */\nexport const placeCutAttributes = (\n root: Root,\n sourceLines: readonly string[],\n read: ReadAttributes\n): void => {\n const parents = new Map<Node, Parent>();\n const cut: Paragraph[] = [];\n const items: TitledItem[] = [];\n const walk = (node: Node): void => {\n if (node.type === \"paragraph\" && rebuiltParagraphs.has(node))\n cut.push(node);\n const data: unknown = node.data;\n if (\n typeof data === \"object\" &&\n data !== null &&\n \"attrsRole\" in data &&\n data.attrsRole === \"containerItem\" &&\n \"attrsTitle\" in data &&\n Array.isArray(data.attrsTitle)\n )\n // Recognition's own item nodes, which mdast's types don't name.\n // oxlint-disable-next-line typescript/no-unsafe-type-assertion\n items.push(node as unknown as TitledItem);\n if (!(\"children\" in node)) return;\n for (const child of node.children) {\n parents.set(child, node);\n walk(child);\n }\n };\n walk(root);\n\n for (const para of cut) {\n const children: PhrasingContent[] = para.children;\n const last = children.at(-1);\n if (last?.type !== \"text\") continue;\n const value = last.value.trimEnd();\n const lineStart = value.lastIndexOf(\"\\n\");\n const line = value.slice(lineStart + 1);\n const open = line.lastIndexOf(\"{\");\n if (open === -1) continue;\n const properties = read(line.slice(open));\n if (!properties) continue;\n const before = line.slice(0, open);\n const ownLine =\n before.trim() === \"\" &&\n (lineStart !== -1 || children.at(-2)?.type === \"break\");\n // A block after an element on its line was the element's to take.\n if (before === \"\" && !ownLine) continue;\n\n const ancestors: Parent[] = [];\n for (let p = parents.get(para); p; p = parents.get(p)) ancestors.unshift(p);\n const parent = ancestors.at(-1);\n\n let target: Node = para;\n if (ownLine) {\n const end = last.position?.end;\n const written = end ? (sourceLines[end.line - 1] ?? \"\") : \"\";\n const prefix = /^[ \\t>]*/.exec(written)?.[0] ?? \"\";\n const markers = prefix.split(\">\").length - 1;\n const outside = end\n ? ancestors.findIndex((ancestor) => {\n const start = ancestor.position?.start;\n if (ancestor.type === \"blockquote\" && start) {\n const own = (sourceLines[start.line - 1] ?? \"\").slice(\n 0,\n start.column - 1\n );\n return markers < own.split(\">\").length;\n }\n const first =\n ancestor.type === \"listItem\"\n ? ancestor.children[0]?.position?.start\n : undefined;\n return first !== undefined && prefix.length < first.column - 1;\n })\n : -1;\n const container = ancestors[outside];\n if (container)\n target =\n container.type === \"listItem\"\n ? (ancestors[outside - 1] ?? container)\n : container;\n else if (parent?.type === \"listItem\" && !listLoose(ancestors.at(-2)))\n target = parent;\n } else if (parent?.type === \"listItem\" && parent.children[0] === para) {\n target = parent;\n }\n\n const data: { hProperties?: Properties } | undefined = target.data;\n target.data = {\n ...data,\n hProperties: mergeProperties(data?.hProperties, properties)\n };\n const kept = ownLine\n ? value.slice(0, Math.max(lineStart, 0))\n : value.slice(0, lineStart + 1) + before;\n if (kept.trimEnd() === \"\") children.pop();\n else last.value = kept.trimEnd();\n }\n\n // A header in the middle of its paragraph kept its block as text, which now\n // ends its title: it goes on the item, as mdit-attrs and remd-attrs put a\n // title's block. (A header that ended its paragraph brought the attributes\n // the parser read off it.)\n for (const item of items) {\n const title = item.data.attrsTitle;\n const last = title.at(-1);\n if (last?.type !== \"text\") continue;\n const value = last.value.trimEnd();\n const open = value.lastIndexOf(\"{\");\n if (open === -1) continue;\n const properties = read(value.slice(open));\n if (!properties) continue;\n item.data.hProperties = mergeProperties(item.data.hProperties, properties);\n last.value = value.slice(0, open).trimEnd();\n if (last.value === \"\" && title.length > 1) title.pop();\n }\n};\n","// Lazy continuation, shared by the steps and tabs recognition: CommonMark lets a line without a blockquote's `>` markers continue the paragraph before it, so a header meant for an outer group, and the lines after it, can end up in a paragraph nested in a body. markdown-it reads such lines by their markers instead; with the document's source, so does recognition.\nimport type {\n Blockquote,\n BlockContent,\n DefinitionContent,\n Paragraph,\n PhrasingContent,\n Text\n} from \"mdast\";\nimport type { Properties } from \"hast\";\nimport { rebuiltParagraphs } from \"./cut-attributes.js\";\n\n/** The `>` markers a source line starts with. */\nexport const markerCount = (line: string): number =>\n (/^[ \\t>]*/.exec(line)?.[0] ?? \"\").split(\">\").length - 1;\n\n/** The `>` markers of a blockquote's own lines: those before it on its first line, and its own (that line can open nested blockquotes too). */\nexport const blockquoteMarkers = (\n bq: Blockquote,\n sourceLines: readonly string[]\n): number | undefined => {\n const start = bq.position?.start;\n if (!start) return undefined;\n return (\n markerCount(\n (sourceLines[start.line - 1] ?? \"\").slice(0, start.column - 1)\n ) + 1\n );\n};\n\n/** A paragraph line, with the `>` markers its source line starts with. */\nexport interface MarkedLine {\n segs: PhrasingContent[];\n markers: number;\n}\n\n/**\n * A paragraph's phrasing content split into its lines: text at each line ending, and after a hard break, which stays at the end of its line. With the source, the text on each line keeps its place in it, as remark would give it: from after the line's container prefix to its last non-space character.\n */\nexport const paraToLines = (\n para: Paragraph,\n sourceLines?: readonly string[]\n): PhrasingContent[][] => {\n const lines: PhrasingContent[][] = [[]];\n for (const child of para.children) {\n if (child.type === \"break\") {\n lines.at(-1)?.push(child);\n lines.push([]);\n } else if (child.type === \"text\") {\n const parts = child.value.split(\"\\n\");\n for (const [p, part] of parts.entries()) {\n if (p > 0) lines.push([]);\n if (part === \"\") continue;\n const text: Text = { type: \"text\", value: part };\n const position = child.position;\n if (position) {\n const line = position.start.line + p;\n const source = sourceLines?.[line - 1];\n const start =\n p === 0\n ? position.start\n : source === undefined\n ? undefined\n : {\n line,\n column: (/^[ \\t>]*/.exec(source)?.[0].length ?? 0) + 1\n };\n const end =\n p === parts.length - 1\n ? position.end\n : source === undefined\n ? undefined\n : { line, column: source.trimEnd().length + 1 };\n if (start && end) text.position = { start, end };\n }\n lines.at(-1)?.push(text);\n }\n } else {\n lines.at(-1)?.push(child);\n }\n }\n return lines;\n};\n\n/** The attributes a paragraph carries, which a parser that reads attribute blocks before recognition (Sätteri) read off its end: they belong to its last line. */\nexport const paragraphProperties = (\n para: Paragraph\n): Properties | undefined => {\n const data: { hProperties?: Properties } | undefined = para.data;\n return data?.hProperties;\n};\n\n/** Appends `node` to `children`, merging text into the text before it, as remark keeps a run of text in one node. */\nconst pushPhrasing = (\n children: PhrasingContent[],\n node: PhrasingContent\n): void => {\n const last = children.at(-1);\n if (node.type !== \"text\" || last?.type !== \"text\") {\n children.push(node);\n return;\n }\n // A line ending with no position of its own takes the next line's start.\n const start =\n last.position?.start ??\n (last.value.trim() === \"\" ? node.position?.start : undefined);\n const end = node.position?.end ?? last.position?.end;\n const merged: Text = { type: \"text\", value: last.value + node.value };\n if (start && end) merged.position = { start, end };\n children[children.length - 1] = merged;\n};\n\n/** A paragraph from lines of phrasing content, or `null` for none. Lines join with a line ending, except after a hard break, which is one. */\nexport const linesToParagraph = (\n lines: PhrasingContent[][]\n): Paragraph | null => {\n const children: PhrasingContent[] = [];\n for (const [i, line] of lines.entries()) {\n if (i > 0 && lines[i - 1]?.at(-1)?.type !== \"break\")\n pushPhrasing(children, { type: \"text\", value: \"\\n\" });\n for (const node of line) pushPhrasing(children, node);\n }\n if (children.length === 0) return null;\n const para: Paragraph = { type: \"paragraph\", children };\n const start = children[0]?.position?.start;\n const end = children.at(-1)?.position?.end;\n if (start && end) para.position = { start, end };\n rebuiltParagraphs.add(para);\n return para;\n};\n\n/**\n * The blocks lazily continued lines stand for, from their markers relative to the body they belong to (`level` deep): as such lines go on CommonMark only nests deeper, so a line with more markers opens blockquotes and a new paragraph, and a line with fewer continues the paragraph it follows.\n */\nexport const rebuildLazyLines = (\n lines: MarkedLine[],\n level: number\n): Array<BlockContent | DefinitionContent> => {\n const deeper = lines.findIndex(({ markers }) => markers > level);\n const own = deeper === -1 ? lines : lines.slice(0, deeper);\n const para = linesToParagraph(own.map(({ segs }) => segs));\n const blocks: Array<BlockContent | DefinitionContent> = para ? [para] : [];\n if (deeper !== -1) {\n const quote: Blockquote = {\n type: \"blockquote\",\n children: rebuildLazyLines(lines.slice(deeper), level + 1)\n };\n blocks.push(quote);\n }\n return blocks;\n};\n\n// A node as the end-of-group pass reads the tree: mdast and the groups recognition builds.\ninterface GroupTreeNode {\n type: string;\n children?: GroupTreeNode[];\n position?: Paragraph[\"position\"];\n data?: unknown;\n}\n\n/** Blocks whose lines carry one more `>` marker than the block around them: a blockquote (or an alert, Sätteri's node for one) and a tab panel or step body. */\nexport const MARKED_BLOCKS: ReadonlySet<string> = new Set([\n `blockquote`,\n `alert`,\n `tabsItem`,\n `stepsItem`\n]);\n\n/** Blocks a line can lazily continue into by its indentation rather than its markers: a list item or a definition. */\nexport const INDENTED_BLOCKS: ReadonlySet<string> = new Set([\n `listItem`,\n `defListDescription`,\n `descriptionDetails`\n]);\n\n/**\n * A paragraph split before its first line (after its first) that `opens` a group, written at the paragraph's level (`quotes` `>` markers), as markdown-it's block rules interrupt a paragraph; `null` when there's none. Attributes ending the paragraph go with the part they end.\n */\nexport const splitAtOpeningLine = (\n para: Paragraph,\n sourceLines: readonly string[],\n quotes: number,\n opens: (text: string) => boolean\n): Paragraph[] | null => {\n const start = para.position?.start.line;\n if (start === undefined) return null;\n const lines = paraToLines(para, sourceLines);\n const at = lines.findIndex((line, index) => {\n const first = line[0];\n return (\n index > 0 &&\n first?.type === `text` &&\n opens(first.value) &&\n markerCount(sourceLines[start - 1 + index] ?? ``) === quotes\n );\n });\n if (at === -1) return null;\n const head = linesToParagraph(lines.slice(0, at));\n const tail = linesToParagraph(lines.slice(at));\n if (!head || !tail) return null;\n if (para.data) tail.data = para.data;\n return [head, tail];\n};\n\n// The paragraph a lazily continued line can end up in: the deepest last block, through lists, items and quotes.\nconst lastParagraph = (\n node: GroupTreeNode | undefined\n): Paragraph | undefined => {\n const last = node?.children?.at(-1);\n if (!last) return undefined;\n // A paragraph of the tree, which the loose node shape doesn't name.\n // oxlint-disable-next-line typescript/no-unsafe-type-assertion\n if (last.type === `paragraph`) return last as unknown as Paragraph;\n return lastParagraph(last);\n};\n\n/**\n * End each group of `listType` (tab groups or steps) where its last panel's `>` markers stop, as markdown-it reads a panel: a line CommonMark lazily continued into the panel's last paragraph, written with fewer markers than the panel's own lines, starts a paragraph after the group, with the lines after it. Groups nested in a panel are ended first, so a line that leaves an outer panel too moves on past its group. The paragraph's attributes (Sätteri reads them off its end) go with its last line.\n */\nexport const endGroupsAtMarkers = (\n root: { children: unknown[] },\n sourceLines: readonly string[],\n listType: `tabsList` | `stepsList`\n): void => {\n const visit = (node: GroupTreeNode, quotes: number): void => {\n const children = node.children;\n if (!children) return;\n for (let i = 0; i < children.length; i++) {\n const child = children[i]!;\n visit(child, quotes + (MARKED_BLOCKS.has(child.type) ? 1 : 0));\n if (child.type !== listType) continue;\n const para = lastParagraph(child.children?.at(-1));\n const start = para?.position?.start.line;\n if (!para || start === undefined) continue;\n const lines = paraToLines(para, sourceLines);\n // The panel's lines carry one more marker than the blocks around the group.\n const outside = lines.findIndex(\n (_, index) =>\n index > 0 &&\n markerCount(sourceLines[start - 1 + index] ?? ``) < quotes + 1\n );\n if (outside === -1) continue;\n const kept = linesToParagraph(lines.slice(0, outside));\n const moved = linesToParagraph(lines.slice(outside));\n if (!kept || !moved) continue;\n para.children = kept.children;\n const data: { hProperties?: Properties } | undefined = para.data;\n if (data?.hProperties) {\n const { hProperties, ...rest } = data;\n const movedData: { hProperties?: Properties } = { hProperties };\n moved.data = movedData;\n para.data = rest;\n }\n // An mdast paragraph, in the loose node shape the pass walks.\n // oxlint-disable-next-line typescript/no-unsafe-type-assertion\n children.splice(i + 1, 0, moved as unknown as GroupTreeNode);\n }\n };\n // The tree, in the loose node shape the pass walks.\n // oxlint-disable-next-line typescript/no-unsafe-type-assertion\n visit(root as GroupTreeNode, 0);\n};\n","// Which blocks a line is written in, by its source prefix: a line that lazily continues a paragraph has fewer `>` markers, or less indentation, than the blocks around that paragraph. The same rule as mdit-attrs' and remd-attrs' own-line attributes, for the plugins in this module's callers.\n\n/**\n * A block a line can be written in, outermost first: a blockquote (or another block written with `>` markers, such as a tab panel), by how many `>` markers lead up to its own, or a list item (or a definition), by the column its content starts at.\n */\nexport type LineContainer =\n | { kind: `quote`; markers: number }\n | { kind: `item`; column: number };\n\n/**\n * How many of `containers`, outermost first, a line is written in. Tabs count as one column.\n */\nexport const containersKept = (\n line: string,\n containers: readonly LineContainer[]\n): number => {\n const prefix = /^[ \\t>]*/.exec(line)?.[0] ?? ``;\n const markers = prefix.split(`>`).length - 1;\n let kept = 0;\n for (const container of containers) {\n if (\n container.kind === `quote`\n ? markers < container.markers\n : prefix.length < container.column\n )\n break;\n kept++;\n }\n return kept;\n};\n\n/**\n * The columns the content of the list items opened on a line starts at, in the order they open, as CommonMark reads a list marker: up to four spaces after it belong to the marker, more start indented content one column after.\n */\nexport const itemColumns = (line: string): number[] => {\n const columns: number[] = [];\n let pos = 0;\n for (;;) {\n while (line[pos] === ` ` || line[pos] === `\\t`) pos++;\n if (line[pos] === `>`) {\n pos++;\n continue;\n }\n const marker = /^(?:[-+*]|\\d{1,9}[.)])(?=[ \\t]|$)/.exec(line.slice(pos));\n if (!marker) return columns;\n const end = pos + marker[0].length;\n let spaces = 0;\n while (line[end + spaces] === ` ` || line[end + spaces] === `\\t`) spaces++;\n const column =\n end + spaces === line.length || spaces > 4 ? end + 1 : end + spaces;\n columns.push(column);\n if (spaces > 4) return columns;\n pos = column;\n }\n};\n","// Captions (`~: caption` on the line right after a block), shared by the markdown-it, remark and Sätteri plugins. CommonMark parses a caption line differently depending on what it follows: after a fence it starts a paragraph of its own; after an image, or lazily after a blockquote or list, it continues the paragraph before it; after a table it's a row. So the plugins find caption lines by their source, and the `>` markers and indentation a line is written with decide which block it captions, as attrs places a block on a line of its own. `processCaptions` does this for an mdast tree (remark, and Sätteri through `editableTree`); markdown-it shares the line rules.\n// Recognition walks mdast and the custom nodes other plugins build (tab groups, steps, alerts) through one loose node shape; the assertions bridging it and mdast's types are reviewed and intentional.\n/* oxlint-disable typescript/no-unsafe-type-assertion */\nimport type { PhrasingContent, Root } from \"mdast\";\nimport type { Properties } from \"hast\";\nimport { isAlertMarkerLine } from \"./github-alerts/index.js\";\nimport { linesToParagraph, paraToLines } from \"./lazy.js\";\nimport { containersKept, type LineContainer } from \"./line-containers.js\";\n\n/** The class of the `<figure>` a caption wraps its block in. */\nexport const CAPTION_CLASS = \"markdown-caption\";\n\n/** Whether a source line is a caption line: `~:`, whitespace and the caption's first word after its `>` markers and indentation. An escaped `\\~:` isn't one, nor is a marker with nothing after it. */\nexport const isCaptionLine = (line: string): boolean =>\n /^~:[ \\t]+\\S/.test(line.replace(/^[ \\t>]*/, ``));\n\n/** Whether text starts with a caption marker, as a parser gives a caption line's text (inline markdown may follow in other nodes). */\nexport const startsCaption = (text: string): boolean =>\n /^~:(?:[ \\t]|$)/.test(text);\n\n/** The text after a caption marker. */\nexport const stripCaptionMarker = (text: string): string =>\n text.replace(/^~:[ \\t]*/, ``);\n\n/**\n * Blocks a caption doesn't attach to, by mdast (and custom node) type: a caption after them stays text. Headings, thematic breaks, raw HTML, definitions and front matter, another caption's figure, and the parts of containers that aren't blocks of their own (titles, labels, terms).\n */\nconst UNCAPTIONED = new Set([\n `heading`,\n `thematicBreak`,\n `html`,\n `definition`,\n `footnoteDefinition`,\n `yaml`,\n `toml`,\n `figure`,\n `alertTitle`,\n `stepsTitle`,\n `tabsLabel`,\n `tabsLabels`,\n `tabsInput`,\n `defListTerm`,\n `descriptionTerm`\n]);\n\n/** The properties of a caption's `<figure>`: its class, then the attributes written at the end of the caption (a class joins it). */\nexport const figureProperties = (author?: Properties): Properties => {\n const {\n class: extraClass,\n className: extraClassName,\n ...rest\n } = author ?? {};\n const extra = [extraClass, extraClassName]\n .flat()\n .flatMap((value) => (typeof value === `string` ? value.split(` `) : []))\n .filter((value) => value !== ``);\n return { className: [CAPTION_CLASS, ...extra], ...rest };\n};\n\ninterface Point {\n line: number;\n column: number;\n}\ninterface Node {\n type: string;\n children?: Node[];\n position?: { start: Point; end: Point };\n data?: { hProperties?: Properties } & Record<string, unknown>;\n value?: string;\n}\n\nconst WHITESPACE = /^\\s*$/;\n\n// Only images (each possibly inside a link) and whitespace: the figure holds them directly, as an image alone in its paragraph is the figure.\n// A lightbox's `!` marker (what `!![alt](src)` leaves before its image) counts as part of the image, so a lightbox's trigger is the figure's content too.\nconst onlyImages = (children: readonly Node[]): boolean =>\n children.some((child) => child.type !== `text`) &&\n children.every(\n (child, index) =>\n child.type === `image` ||\n (child.type === `text` &&\n (WHITESPACE.test(child.value ?? ``) ||\n (/^\\s*!$/.test(child.value ?? ``) &&\n children[index + 1]?.type === `image`))) ||\n (child.type === `link` &&\n (child.children ?? []).length > 0 &&\n (child.children ?? []).every((inner) => inner.type === `image`))\n );\n\nconst figure = (\n content: Node[],\n caption: PhrasingContent[],\n author: Properties | undefined\n): Node => ({\n type: `figure`,\n data: { hName: `figure`, hProperties: figureProperties(author) },\n children: [\n ...content,\n {\n type: `figcaption`,\n data: { hName: `figcaption` },\n children: caption as unknown as Node[]\n }\n ]\n});\n\n// A caption's lines as phrasing content, without the marker on the first.\nconst captionContent = (lines: PhrasingContent[][]): PhrasingContent[] => {\n const first = lines[0]?.[0];\n if (first?.type === `text`) {\n const value = stripCaptionMarker(first.value);\n lines[0] = value\n ? [{ ...first, value }, ...lines[0]!.slice(1)]\n : lines[0]!.slice(1);\n }\n return linesToParagraph(lines)?.children ?? [];\n};\n\n// The attributes a node carries, removed from it: those written at the end of a caption go on its figure.\nconst takeProperties = (node: Node): Properties | undefined => {\n const data = node.data;\n if (!data?.hProperties) return undefined;\n const { hProperties, ...rest } = data;\n node.data = rest;\n return hProperties;\n};\n\n/**\n * Wrap each captioned block of an mdast tree, with its caption, in a `figure` node (`hName: \"figure\"`, class `markdown-caption`) whose last child is a `figcaption` node. `source` is the document the tree was parsed from: caption lines are found, and placed, by their source lines.\n */\nexport const processCaptions = (root: Root, source: string): void => {\n if (!source.includes(`~:`)) return;\n const sourceLines = source.split(/\\r?\\n/);\n const parents = new Map<Node, Node>();\n const paragraphs: Node[] = [];\n const tables: Node[] = [];\n const walk = (node: Node): void => {\n if (node.type === `paragraph`) paragraphs.push(node);\n else if (node.type === `table`) tables.push(node);\n for (const child of node.children ?? []) {\n parents.set(child, node);\n walk(child);\n }\n };\n walk(root as unknown as Node);\n\n const replace = (node: Node, replacement: Node | null): void => {\n const parent = parents.get(node);\n const siblings = parent?.children;\n if (!parent || !siblings) return;\n const index = siblings.indexOf(node);\n if (index === -1) return;\n if (replacement) {\n siblings.splice(index, 1, replacement);\n parents.set(replacement, parent);\n parents.set(node, replacement);\n } else siblings.splice(index, 1);\n };\n const captioned = (node: Node): boolean =>\n parents.get(node)?.type === `figure`;\n\n const ancestorsOf = (node: Node): Node[] => {\n const ancestors: Node[] = [];\n for (let p = parents.get(node); p; p = parents.get(p)) ancestors.unshift(p);\n return ancestors;\n };\n\n // The blocks around a node a line can be written outside of, outermost first, with the block a caption written outside each goes on: a blockquote or alert itself, a tab panel's group, a step body's steps, a list item's list, a definition's list. `undefined` when a list item's content has no position to measure.\n const containersOf = (\n ancestors: readonly Node[]\n ): Array<{ target: Node; line: LineContainer }> | undefined => {\n const containers: Array<{ target: Node; line: LineContainer }> = [];\n const nearest = (index: number, type: string): Node | undefined =>\n ancestors\n .slice(0, index)\n .reverse()\n .find((a) => a.type === type);\n let quotes = 0;\n for (const [index, ancestor] of ancestors.entries()) {\n const quote = (target: Node | undefined): void => {\n containers.push({\n target: target ?? ancestor,\n line: { kind: `quote`, markers: ++quotes }\n });\n };\n switch (ancestor.type) {\n case `blockquote`:\n case `alert`:\n quote(ancestor);\n break;\n // A tab panel (remark builds `tabsItem`, Sätteri renders `tabsPanel`).\n case `tabsItem`:\n case `tabsPanel`:\n quote(nearest(index, `tabsList`));\n break;\n // A step body (Sätteri renders it as `stepsBody` inside its item).\n case `stepsItem`:\n if (!(ancestor.children ?? []).some((c) => c.type === `stepsBody`))\n quote(nearest(index, `stepsList`));\n break;\n case `stepsBody`:\n quote(nearest(index, `stepsList`));\n break;\n case `listItem`:\n case `defListDescription`:\n case `descriptionDetails`: {\n const column = ancestor.children?.[0]?.position?.start.column;\n if (column === undefined) return undefined;\n containers.push({\n target: ancestors[index - 1] ?? ancestor,\n line: { kind: `item`, column: column - 1 }\n });\n break;\n }\n default:\n }\n }\n return containers;\n };\n\n // Tables: a caption line is a row of its own; it and the rows after it are the caption.\n for (const table of tables) {\n const rows = table.children ?? [];\n const first = rows.findIndex((row, index) => {\n const line = row.position?.start.line;\n const text = row.children?.[0]?.children?.[0];\n return (\n index > 0 &&\n line !== undefined &&\n isCaptionLine(sourceLines[line - 1] ?? ``) &&\n text?.type === `text` &&\n startsCaption(text.value ?? ``)\n );\n });\n if (first === -1) continue;\n const captionRows = rows.slice(first);\n const lastCell = captionRows.at(-1)?.children?.[0];\n const author = lastCell ? takeProperties(lastCell) : undefined;\n const caption = captionContent(\n captionRows.map(\n (row) =>\n (row.children?.[0]?.children ?? []) as unknown as PhrasingContent[]\n )\n );\n table.children = rows.slice(0, first);\n replace(table, figure([table], caption, author));\n }\n\n // Paragraphs, innermost and last first, so a figure made inside a block is in place before the block is wrapped.\n for (const para of paragraphs.reverse()) {\n const first = para.position?.start.line;\n if (first === undefined) continue;\n const lines = paraToLines(\n para as unknown as Parameters<typeof paraToLines>[0],\n sourceLines\n );\n // Each line is one source line. An alert's first paragraph lost its marker line (`> [!NOTE]`) to the alert, which leaves its start there.\n const parent = parents.get(para);\n const alert =\n parent?.type === `alert` ||\n (parent?.type === `blockquote` && parent.data?.alertType !== undefined);\n const start =\n alert && isAlertMarkerLine(sourceLines[first - 1] ?? ``)\n ? first + 1\n : first;\n const isCaptionAt = (index: number): boolean => {\n const text = lines[index]?.[0];\n return (\n isCaptionLine(sourceLines[start + index - 1] ?? ``) &&\n text?.type === `text` &&\n startsCaption(text.value)\n );\n };\n\n // A paragraph that is a caption: it captions the block right before it, on the line above.\n if (isCaptionAt(0)) {\n const parent = parents.get(para);\n const siblings = parent?.children ?? [];\n const before = siblings[siblings.indexOf(para) - 1];\n const above = sourceLines[start - 2];\n if (\n !before ||\n UNCAPTIONED.has(before.type) ||\n above === undefined ||\n above.replace(/^[ \\t>]*/, ``) === ``\n )\n continue;\n const author = takeProperties(para);\n replace(para, null);\n replace(before, figure([before], captionContent(lines), author));\n continue;\n }\n\n // A caption line inside the paragraph: the paragraph, or a block around it the line is written outside of.\n let containers: Array<{ target: Node; line: LineContainer }> | undefined;\n const segments: Array<{ index: number; kept: number; target: Node }> = [];\n for (let index = 1; index < lines.length; index++) {\n if (!isCaptionAt(index)) continue;\n containers ??= containersOf(ancestorsOf(para));\n if (!containers) break;\n const kept = containersKept(\n sourceLines[start + index - 1] ?? ``,\n containers.map((c) => c.line)\n );\n // A caption line at the same level or deeper continues the caption; one written outside more blocks starts the caption of the one it leaves.\n const previous = segments.at(-1);\n if (previous && kept >= previous.kept) continue;\n const target = containers[kept]?.target ?? para;\n if (captioned(target)) continue;\n segments.push({ index, kept, target });\n }\n if (segments.length === 0) continue;\n\n const head = lines.slice(0, segments[0]!.index);\n // A hard break ending the line before a caption ends the paragraph instead.\n const lastLine = head.at(-1);\n if (lastLine?.at(-1)?.type === `break`)\n head[head.length - 1] = lastLine.slice(0, -1);\n para.children = (linesToParagraph(head)?.children ??\n []) as unknown as Node[];\n const author = takeProperties(para);\n for (const [i, segment] of segments.entries()) {\n const caption = captionContent(\n lines.slice(segment.index, segments[i + 1]?.index)\n );\n // Attributes ending the paragraph end its last caption.\n const properties = i === segments.length - 1 ? author : undefined;\n const { target } = segment;\n if (target === para && onlyImages(para.children ?? []))\n replace(para, figure(para.children ?? [], caption, properties));\n else replace(target, figure([target], caption, properties));\n }\n }\n};\n","// Logic shared by the rehype and Sätteri hast plugins, so both compute the same result: which paragraphs are empty or hold only images, how headings divide a document into sections, and the lightbox's marker, ids and markup. The plugins apply it with their own tree operations.\n\nimport { CAPTION_CLASS } from \"./caption.js\";\n\n/** The shape of a hast node this module reads and builds. */\nexport interface HastLike {\n type: string;\n tagName?: string;\n value?: string;\n properties?: Record<string, unknown>;\n children?: readonly HastLike[];\n}\n\n/** A hast element as this module builds it; its properties fit hast's `Properties`. */\nexport interface HastElementLike<C> {\n type: `element`;\n tagName: string;\n properties: Record<string, string | string[]>;\n children: C[];\n}\n\n// hast-util-whitespace: only the inter-element whitespace characters.\nconst WHITESPACE = /^[ \\t\\n\\f\\r]*$/;\nconst isWhitespaceText = (node: HastLike): boolean =>\n node.type === `text` && WHITESPACE.test(node.value ?? ``);\n\n/** A `<p>` with no children, or only whitespace text: squeeze-paragraphs removes it. */\nexport const isEmptyParagraph = (node: HastLike): boolean =>\n node.tagName === `p` && (node.children ?? []).every(isWhitespaceText);\n\n/**\n * A `<p>` whose content is only images (each possibly inside a link or a lightbox button) and whitespace: unwrap-images replaces it with its children.\n */\nexport const isImageParagraph = (node: HastLike): boolean => {\n // `image`: an image was found; `empty`: nothing but whitespace yet; `other`: anything else.\n const scan = (\n parent: HastLike,\n inLink: boolean\n ): `image` | `empty` | `other` => {\n let result: `image` | `empty` = `empty`;\n for (const child of parent.children ?? []) {\n if (isWhitespaceText(child)) continue;\n if (child.type !== `element`) return `other`;\n if (child.tagName === `img`) {\n result = `image`;\n continue;\n }\n if (!inLink && (child.tagName === `a` || child.tagName === `button`)) {\n const inner = scan(child, true);\n if (inner === `other`) return `other`;\n if (inner === `image`) result = `image`;\n continue;\n }\n return `other`;\n }\n return result;\n };\n return node.tagName === `p` && scan(node, false) === `image`;\n};\n\n/** The rank of an `h1`–`h6` element, or `undefined`. */\nexport const headingRank = (node: HastLike): number | undefined => {\n if (node.type !== `element`) return undefined;\n const match = /^h([1-6])$/i.exec(node.tagName ?? ``);\n return match ? Number(match[1]) : undefined;\n};\n\n/**\n * Wrap heading-delimited runs of `nodes` into `<section data-depth>` elements, nesting deeper headings inside shallower ones. Content before the first heading stays unwrapped.\n */\nexport const sectionize = <N extends HastLike>(\n nodes: readonly N[],\n section: (depth: number, children: N[]) => N,\n floor = 0\n): N[] => {\n // Shallowest heading rank deeper than the floor.\n let minRank = Infinity;\n for (const node of nodes) {\n const rank = headingRank(node);\n if (rank !== undefined && rank > floor && rank < minRank) minRank = rank;\n }\n if (minRank === Infinity) return [...nodes];\n\n const result: N[] = [];\n let i = 0;\n // Preamble: everything before the first heading of the shallowest rank.\n for (; i < nodes.length; i++) {\n const node = nodes[i];\n if (!node || headingRank(node) === minRank) break;\n result.push(node);\n }\n // Each shallowest heading starts a section that runs until the next peer.\n while (i < nodes.length) {\n const start = i;\n for (i++; i < nodes.length; i++) {\n const node = nodes[i];\n if (!node || headingRank(node) === minRank) break;\n }\n result.push(\n section(minRank, sectionize(nodes.slice(start, i), section, minRank))\n );\n }\n return result;\n};\n\n/**\n * The lightbox opt-in: an image directly after a text run that ends in a `!` at a boundary (start of the run or after whitespace), which is what `!![alt](src)` leaves behind.\n */\nexport const LIGHTBOX_MARKER = /(?:^|\\s)!$/;\n\n/**\n * A short, stable lightbox id from an image src (FNV-1a, base36): the same image always gets the same id, so repeated references share one dialog.\n */\nexport const lightboxId = (src: string): string => {\n let hash = 2166136261;\n for (let i = 0; i < src.length; i += 1) {\n hash ^= src.charCodeAt(i);\n hash = Math.imul(hash, 16777619);\n }\n return `markdown-lightbox-${(hash >>> 0).toString(36)}`;\n};\n\n/** The button that replaces an opted-in image and opens its dialog. */\nexport const lightboxTrigger = <C>(\n id: string,\n image: C\n): HastElementLike<C> => ({\n type: `element`,\n tagName: `button`,\n properties: {\n type: `button`,\n className: [`markdown-lightbox-trigger`],\n command: `show-modal`,\n commandfor: id\n },\n children: [image]\n});\n\n/** The modal dialog, appended at the document end, showing the image full size, and its caption under it when one is given. */\nexport const lightboxDialog = <C>(\n id: string,\n image: C,\n caption?: C[]\n): HastElementLike<HastElementLike<C>> => ({\n type: `element`,\n tagName: `dialog`,\n properties: { id, className: [`markdown-lightbox`], closedby: `any` },\n children: [\n {\n type: `element`,\n tagName: `button`,\n properties: {\n type: `button`,\n className: [`markdown-lightbox-close`],\n command: `close`,\n commandfor: id,\n ariaLabel: `Close image`\n },\n children: [image]\n },\n ...(caption\n ? [\n {\n type: `element` as const,\n tagName: `p`,\n properties: { className: [`markdown-lightbox-caption`] },\n children: caption\n }\n ]\n : [])\n ]\n});\n\n/** Whether a node is a caption's figure (`<figure class=\"markdown-caption\">`, as the caption plugins make): an image that is its content shows the figure's caption in its lightbox dialog, with the `caption` option. */\nexport const isCaptionFigure = (node: HastLike | undefined): boolean => {\n const className = node?.properties?.className;\n return (\n node?.tagName === `figure` &&\n Array.isArray(className) &&\n className.includes(CAPTION_CLASS)\n );\n};\n","// Abbreviation rules shared by the remark and Sätteri plugins: which paragraphs define abbreviations, and how a text value splits around the defined terms.\n\nconst DEFINITION = /^\\*\\[([^[\\]]+)\\]:\\s*(.+)$/;\nconst REGEX_SPECIAL = /[.*+?^${}()|[\\]\\\\]/g;\n\n/**\n * The `[term, title]` pairs a paragraph's text defines, when every line of it is a `*[term]: title` definition; otherwise `undefined` (the paragraph is ordinary text).\n */\nexport const parseAbbreviations = (\n text: string\n): Array<[string, string]> | undefined => {\n const definitions: Array<[string, string]> = [];\n for (const line of text.split(`\\n`)) {\n const match = DEFINITION.exec(line);\n if (!match) return undefined;\n definitions.push([match[1] ?? ``, (match[2] ?? ``).trim()]);\n }\n return definitions;\n};\n\n/** A piece of text: plain, or a defined term with its title. */\nexport type AbbreviationPart =\n | { text: string }\n | { term: string; title: string };\n\n/**\n * Build the scan for a document's abbreviations. Terms match on word boundaries, longest first; the scan returns the pieces of a text value, or `undefined` when it holds no term.\n */\nexport const createAbbreviationScan = (\n abbreviations: ReadonlyMap<string, string>\n): ((value: string) => AbbreviationPart[] | undefined) => {\n const terms = [...abbreviations.keys()]\n .sort((a, b) => b.length - a.length)\n .map((term) => term.replace(REGEX_SPECIAL, `\\\\$&`));\n const pattern = new RegExp(`\\\\b(${terms.join(`|`)})\\\\b`, `g`);\n return (value) => {\n const parts: AbbreviationPart[] = [];\n let last = 0;\n for (const match of value.matchAll(pattern)) {\n const term = match[1] ?? ``;\n if (match.index > last)\n parts.push({ text: value.slice(last, match.index) });\n parts.push({ term, title: abbreviations.get(term) ?? `` });\n last = match.index + term.length;\n }\n if (parts.length === 0) return undefined;\n if (last < value.length) parts.push({ text: value.slice(last) });\n return parts;\n };\n};\n","// Recognition for numbered step sequences, shared by the remark and Sätteri plugins: header lines (`@1. Title`) and their `>` bodies become `stepsList`/`stepsItem` nodes, which each engine then renders. It rewrites mdast in place, so a read-only engine runs it on a copy.\n// This module performs heavy tree-rewriting across mdast/hast types that don't unify cleanly; type assertions bridging those boundaries are reviewed and intentional, so the rule is disabled file-wide rather than per-cast. Defensive optional chains on array[i] accesses are also kept because TS doesn't model index access as fallible.\n/* oxlint-disable typescript/no-unsafe-type-assertion */\n/* oxlint-disable typescript/no-unnecessary-condition */\nimport type {\n Root,\n Paragraph,\n Blockquote,\n PhrasingContent,\n BlockContent,\n DefinitionContent\n} from \"mdast\";\nimport type { Properties } from \"hast\";\nimport {\n blockquoteMarkers,\n endGroupsAtMarkers,\n INDENTED_BLOCKS,\n MARKED_BLOCKS,\n splitAtOpeningLine,\n linesToParagraph,\n markerCount,\n paragraphProperties,\n paraToLines,\n rebuildLazyLines,\n type MarkedLine\n} from \"./lazy.js\";\nimport { isAlertMarkerLine } from \"./github-alerts/index.js\";\n\n// Groups: 1=@ string (depth), 2=number, 3=rest of line (may be empty or title text)\nconst STEP_HEADER_RE = /^(@{1,6})(\\d+)\\. ?(.*)/s;\n\n// ── MDAST node types ──────────────────────────────────────────────────────────\n\n/** A list of steps at one depth, rendered as an `<ol>`. */\nexport interface StepsListNode {\n type: \"stepsList\";\n depth: number;\n containerClass?: string;\n /** A group written in a step's body (`@1.` with the body's `>`), which renders in the body, rather than the step's `@@` sub-steps. */\n inBody?: boolean;\n children: StepsItemNode[];\n data?: { attrsRole?: string; hProperties?: Properties };\n}\n\n/** A step's title, rendered as its title `<p>` unless it is empty. */\nexport interface StepsTitleNode {\n type: \"stepsTitle\";\n children: PhrasingContent[];\n}\n\n/** One step: its title (always the first child, so transforms that walk children reach it), body and nested steps, rendered as an `<li>`. */\nexport interface StepsItemNode {\n type: \"stepsItem\";\n depth: number;\n number: number;\n children: Array<\n StepsTitleNode | BlockContent | DefinitionContent | StepsListNode\n >;\n data?: {\n attrsRole?: string;\n attrsTitle?: PhrasingContent[];\n hProperties?: Properties;\n };\n}\n\n// ── Parser helpers ────────────────────────────────────────────────────────────\n\ninterface ParsedHeader {\n depth: number;\n number: number;\n rest: string;\n}\n\nconst parseHeaderPrefix = (text: string): ParsedHeader | null => {\n const m = STEP_HEADER_RE.exec(text);\n if (!m) return null;\n const [, hashes = \"\", digits = \"\", rest = \"\"] = m;\n return { depth: hashes.length, number: parseInt(digits, 10), rest };\n};\n\n// ── Raw step types ────────────────────────────────────────────────────────────\n\ninterface RawStep {\n depth: number;\n number: number;\n titleNodes: PhrasingContent[];\n body: Array<BlockContent | DefinitionContent>;\n // Attributes the parser read off the end of the header's paragraph, when the header ended it (Sätteri).\n hProperties?: Properties | undefined;\n}\n\n// ── Paragraph line splitting ──────────────────────────────────────────────────\n\n// ── Header paragraph extraction ───────────────────────────────────────────────\n\n// Extract step headers from a paragraph where every line is an @N. header.\n// Mutates `counters` in place so call sites share counter state across siblings.\n// A depth-skipping or non-header line ends the group: the steps before it are\n// returned with that line and the ones after it as `rest`, to be rendered as an\n// ordinary paragraph after the list.\n// requireDepthOne: first header must be depth 1.\ninterface HeaderPara {\n steps: RawStep[];\n rest: PhrasingContent[][];\n restLine: number;\n}\n\nconst extractHeaderPara = (\n para: Paragraph,\n counters: Map<number, number>,\n requireDepthOne = true,\n prevDepth = 0\n): HeaderPara | null => {\n const lines = paraToLines(para);\n const steps: RawStep[] = [];\n let currentDepth = prevDepth;\n const stop = (index: number): HeaderPara | null =>\n steps.length > 0\n ? {\n steps,\n rest: lines.slice(index),\n restLine: (para.position?.start.line ?? 1) + index\n }\n : null;\n\n for (const [index, lineSegs] of lines.entries()) {\n const first = lineSegs[0];\n if (first?.type !== \"text\") return stop(index);\n\n const header = parseHeaderPrefix(first.value);\n if (!header) return stop(index);\n\n const { depth } = header;\n if (steps.length === 0 && requireDepthOne && depth !== 1) return null;\n if (depth > currentDepth + 1) return stop(index);\n\n for (const k of counters.keys()) if (k > depth) counters.delete(k);\n const number = (counters.get(depth) ?? 0) + 1;\n counters.set(depth, number);\n currentDepth = depth;\n\n const titleNodes: PhrasingContent[] = header.rest\n ? [{ type: \"text\", value: header.rest }, ...lineSegs.slice(1)]\n : lineSegs.slice(1);\n\n steps.push({\n depth,\n number,\n titleNodes,\n body: [],\n ...(index === lines.length - 1\n ? { hProperties: paragraphProperties(para) }\n : {})\n });\n }\n\n return stop(lines.length);\n};\n\n// Lines left over after a group ends become ordinary paragraphs, split before\n// every line that opens a new group (a depth-1 header), so the main loop can\n// start that group. Positions follow the source lines (paragraph lines map 1:1\n// to source lines) because group ids hash the start line.\nconst splitAtGroupStarts = (\n lines: PhrasingContent[][],\n firstLine: number\n): Paragraph[] => {\n const paragraphs: Paragraph[] = [];\n let start = 0;\n const flush = (end: number): void => {\n const para = linesToParagraph(lines.slice(start, end));\n if (!para) return;\n para.position = {\n start: { line: firstLine + start, column: 1 },\n end: { line: firstLine + end - 1, column: 1 }\n };\n paragraphs.push(para);\n };\n lines.forEach((line, index) => {\n const first = line[0];\n const opens =\n first?.type === \"text\" && parseHeaderPrefix(first.value)?.depth === 1;\n if (opens && index > start) {\n flush(index);\n start = index;\n }\n });\n flush(lines.length);\n return paragraphs;\n};\n\n// ── Blockquote splitting ──────────────────────────────────────────────────────\n\n// Remark absorbs adjacent non-blank lines after the first @paragraph into one\n// blockquote. We split that blockquote on any embedded @N. step header lines.\ninterface BQSegment {\n header: Omit<RawStep, \"body\"> | null; // null = pre-header content (goes to previous step)\n body: Array<BlockContent | DefinitionContent>;\n}\n\ninterface ParentLike {\n type: string;\n children?: ParentLike[];\n}\n\n// CommonMark lets a line without a blockquote's `>` markers continue the paragraph before it, so lines meant for the next step can end up in a paragraph nested in a step's body (in a deeper blockquote or a list item), where markdown-it reads them by their markers instead. From the deepest last paragraph of `node`, take the lines from the first one written outside the step body (with fewer markers than the body's own, `base`) that `isHeader` accepts; the paragraph is cut before it, in place.\nconst takeLazyLines = (\n node: BlockContent | DefinitionContent,\n sourceLines: readonly string[],\n base: number,\n isHeader: (segs: PhrasingContent[]) => boolean\n): MarkedLine[] | null => {\n let parent = node as unknown as ParentLike;\n let last = parent.children?.at(-1);\n while (last?.type !== \"paragraph\") {\n if (!last?.children?.length) return null;\n parent = last;\n last = parent.children?.at(-1);\n }\n const para = last as unknown as Paragraph;\n const start = para.position?.start.line;\n if (start === undefined || !parent.children) return null;\n const lines = paraToLines(para, sourceLines).map(\n (segs, index): MarkedLine => ({\n segs,\n markers: markerCount(sourceLines[start - 1 + index] ?? \"\")\n })\n );\n const at = lines.findIndex(\n ({ segs, markers }, index) => index > 0 && markers < base && isHeader(segs)\n );\n if (at === -1) return null;\n const kept = linesToParagraph(lines.slice(0, at).map(({ segs }) => segs));\n parent.children.splice(\n -1,\n 1,\n ...(kept ? [kept as unknown as ParentLike] : [])\n );\n return lines.slice(at);\n};\n\nconst splitBlockquote = (\n bq: Blockquote,\n counters: Map<number, number>,\n currentDepth: number,\n sourceLines?: readonly string[]\n): BQSegment[] => {\n const segments: BQSegment[] = [];\n let currentSegment: BQSegment = { header: null, body: [] };\n // The `>` markers of the step body's own lines.\n const base = sourceLines ? blockquoteMarkers(bq, sourceLines) : undefined;\n\n // A line's step header, if it has one that fits the group's depth.\n const stepHeader = (lineSegs: PhrasingContent[]): ParsedHeader | null => {\n const first = lineSegs[0];\n if (first?.type !== \"text\") return null;\n const header = parseHeaderPrefix(first.value);\n return header && header.depth <= currentDepth + 1 ? header : null;\n };\n\n const startStep = (\n header: ParsedHeader,\n lineSegs: PhrasingContent[],\n hProperties?: Properties\n ): void => {\n segments.push(currentSegment);\n\n // Update counter tracking\n for (const k of counters.keys()) if (k > header.depth) counters.delete(k);\n const number = (counters.get(header.depth) ?? 0) + 1;\n counters.set(header.depth, number);\n currentDepth = header.depth;\n\n const titleNodes: PhrasingContent[] = header.rest\n ? [{ type: \"text\", value: header.rest }, ...lineSegs.slice(1)]\n : lineSegs.slice(1);\n\n currentSegment = {\n header: { depth: header.depth, number, titleNodes, hProperties },\n body: []\n };\n };\n\n for (const child of bq.children) {\n if (child.type !== \"paragraph\") {\n currentSegment.body.push(child);\n if (!sourceLines || base === undefined) continue;\n const lazy = takeLazyLines(\n child,\n sourceLines,\n base,\n (segs) => stepHeader(segs) !== null\n );\n if (!lazy) continue;\n // The header and the lines after it: the steps they start, and those steps' bodies.\n let pending: MarkedLine[] = [];\n const flush = (): void => {\n const relative = pending.map((line) => ({\n ...line,\n markers: line.markers - base\n }));\n currentSegment.body.push(...rebuildLazyLines(relative, 0));\n pending = [];\n };\n for (const line of lazy) {\n const header = line.markers < base ? stepHeader(line.segs) : null;\n if (header) {\n flush();\n startStep(header, line.segs);\n } else {\n pending.push(line);\n }\n }\n flush();\n continue;\n }\n\n let bodyLines: PhrasingContent[][] = [];\n const lines = paraToLines(child, sourceLines);\n const first = child.position?.start.line;\n // A header written with the body's own `>` markers is the body's content (it can start a group of its own there), as markdown-it reads the body; only one written outside the body starts the next step.\n const outsideBody = (index: number): boolean =>\n !sourceLines ||\n base === undefined ||\n first === undefined ||\n markerCount(sourceLines[first - 1 + index] ?? \"\") < base;\n for (const [index, lineSegs] of lines.entries()) {\n const header = outsideBody(index) ? stepHeader(lineSegs) : null;\n if (header) {\n // Flush accumulated body lines\n const bodyPara = linesToParagraph(bodyLines);\n if (bodyPara) currentSegment.body.push(bodyPara);\n bodyLines = [];\n startStep(\n header,\n lineSegs,\n index === lines.length - 1 ? paragraphProperties(child) : undefined\n );\n continue;\n }\n bodyLines.push(lineSegs);\n }\n\n // These lines end the paragraph, so they keep its data: attributes the\n // parser read from its end (Sätteri's run before steps).\n const bodyPara = linesToParagraph(bodyLines);\n if (bodyPara && child.data) bodyPara.data = child.data;\n if (bodyPara) currentSegment.body.push(bodyPara);\n }\n\n segments.push(currentSegment);\n return segments;\n};\n\n// ── Tree builder ──────────────────────────────────────────────────────────────\n\nconst buildTree = (\n steps: RawStep[],\n targetDepth: number,\n start: number,\n end: number\n): StepsListNode => {\n const items: StepsItemNode[] = [];\n let i = start;\n\n while (i < end) {\n const s = steps[i];\n if (s?.depth !== targetDepth) {\n i++;\n continue;\n }\n\n let childEnd = i + 1;\n while (childEnd < end && (steps[childEnd]?.depth ?? 0) > targetDepth)\n childEnd++;\n\n // The title node shares `titleNodes` with `attrsTitle`, so attrs trimming one trims the other.\n const bodyChildren: StepsItemNode[\"children\"] = [\n { type: \"stepsTitle\", children: s.titleNodes },\n ...s.body\n ] as StepsItemNode[\"children\"];\n const hasDeeper = steps\n .slice(i + 1, childEnd)\n .some((ss) => ss.depth === targetDepth + 1);\n if (hasDeeper) {\n const nested = buildTree(steps, targetDepth + 1, i + 1, childEnd);\n bodyChildren.push(nested);\n }\n\n items.push({\n type: \"stepsItem\",\n depth: targetDepth,\n number: s.number,\n children: bodyChildren,\n data: {\n attrsRole: \"containerItem\",\n attrsTitle: s.titleNodes,\n ...(s.hProperties ? { hProperties: { ...s.hProperties } } : {})\n }\n });\n\n i = childEnd;\n }\n\n return {\n type: \"stepsList\",\n depth: targetDepth,\n children: items,\n data: { attrsRole: \"container\" }\n };\n};\n\n// ── Remark plugin ─────────────────────────────────────────────────────────────\n\n// Process all step groups found in a children array in-place.\n// Used at root level and recursively inside any parent node's children.\nexport const processStepsInChildren = (\n children: Array<BlockContent | DefinitionContent | Root[\"children\"][number]>,\n containerClass: string,\n sourceLines?: readonly string[],\n quotes = 0,\n parentType = \"root\"\n): void => {\n const newChildren: typeof children = [];\n let i = 0;\n\n while (i < children.length) {\n const node = children[i];\n if (!node) break;\n\n // A step header interrupts the paragraph before it, as markdown-it's block rule does, when it's written at the paragraph's own level (its `>` markers). In a list item or definition, a header line may instead be one CommonMark lazily continued, so those are left as they are.\n if (\n node.type === \"paragraph\" &&\n sourceLines &&\n !INDENTED_BLOCKS.has(parentType)\n ) {\n const split = splitAtOpeningLine(\n node,\n sourceLines,\n quotes,\n (text) => parseHeaderPrefix(text)?.depth === 1\n );\n if (split) {\n children.splice(i, 1, ...split);\n continue;\n }\n }\n\n if (node.type === \"paragraph\") {\n const counters = new Map<number, number>();\n const headerPara = extractHeaderPara(node, counters);\n\n if (headerPara) {\n const rawSteps: RawStep[] = [...headerPara.steps];\n // Lines left over after a depth-skipping or non-header line end the group.\n let rest = headerPara.rest;\n let restLine = headerPara.restLine;\n let j = i + 1;\n // A group always starts with at least one step.\n const lastStep = (): RawStep => rawSteps[rawSteps.length - 1]!;\n let currentStepIdx = rawSteps.length - 1;\n let currentDepth = lastStep().depth;\n\n while (rest.length === 0 && j < children.length) {\n const sibling = children[j];\n if (!sibling) break;\n\n if (sibling.type === \"blockquote\") {\n // An alert after a blank line is a block of its own, not more of the step's body.\n const line = sibling.position?.start.line;\n if (\n sourceLines &&\n line !== undefined &&\n isAlertMarkerLine(sourceLines[line - 1] ?? \"\")\n )\n break;\n const segments = splitBlockquote(\n sibling,\n counters,\n currentDepth,\n sourceLines\n );\n\n const firstSeg = segments[0];\n if (firstSeg?.header === null) {\n rawSteps[currentStepIdx]?.body.push(...firstSeg.body);\n }\n\n for (let s = 1; s < segments.length; s++) {\n const seg = segments[s];\n if (seg?.header) {\n rawSteps.push({ ...seg.header, body: seg.body });\n currentStepIdx = rawSteps.length - 1;\n currentDepth = seg.header.depth;\n }\n }\n\n j++;\n } else if (sibling.type === \"paragraph\") {\n const prevDepth = lastStep().depth;\n const contHeaders = extractHeaderPara(\n sibling,\n counters,\n false,\n prevDepth\n );\n if (contHeaders) {\n rawSteps.push(...contHeaders.steps);\n rest = contHeaders.rest;\n restLine = contHeaders.restLine;\n currentStepIdx = rawSteps.length - 1;\n currentDepth = lastStep().depth;\n j++;\n continue;\n }\n break;\n } else {\n break;\n }\n }\n\n const list = buildTree(rawSteps, 1, 0, rawSteps.length);\n list.containerClass = containerClass;\n if (parentType === \"stepsItem\") list.inBody = true;\n newChildren.push(list as unknown as Root[\"children\"][number]);\n children.splice(j, 0, ...splitAtGroupStarts(rest, restLine));\n i = j;\n continue;\n }\n }\n\n newChildren.push(node);\n i++;\n }\n\n children.splice(0, children.length, ...newChildren);\n};\n\ninterface Container {\n type?: string;\n children?: unknown[];\n}\n\n/**\n * Turn every step sequence in `root` into `stepsList` nodes, at the top level and inside any container (blockquotes, list items, tab panels…), walking into the lists it builds so nested sequences are found too. With the document's `source`, a step header that CommonMark lazily continued into a nested paragraph is recognized too, as markdown-it reads it.\n */\nexport const processSteps = (\n root: Root,\n containerClass: string,\n source?: string\n): void => {\n const sourceLines = source?.split(/\\r?\\n/);\n const walk = (node: Container, quotes: number): void => {\n if (!Array.isArray(node.children) || node.children.length === 0) return;\n const inner = quotes + (MARKED_BLOCKS.has(node.type ?? \"\") ? 1 : 0);\n processStepsInChildren(\n node.children as Array<BlockContent | DefinitionContent>,\n containerClass,\n sourceLines,\n inner,\n node.type\n );\n for (const child of node.children) walk(child as Container, inner);\n };\n processStepsInChildren(root.children, containerClass, sourceLines);\n for (const child of root.children) walk(child, 0);\n if (sourceLines) endGroupsAtMarkers(root, sourceLines, `stepsList`);\n};\n","// Recognition for tabbed content blocks, shared by the remark and Sätteri plugins: header lines (`% Label`) and their `>` bodies become `tabsList`/`tabsItem` nodes, which each engine then renders. It rewrites mdast in place, so a read-only engine runs it on a copy.\n// This module performs heavy tree-rewriting across mdast/unist types that don't unify cleanly; type assertions bridging those boundaries are reviewed and intentional, so the rule is disabled file-wide rather than per-cast. Defensive optional chains on array[i] accesses are also kept because TS doesn't model index access as fallible.\n/* oxlint-disable typescript/no-unsafe-type-assertion */\n/* oxlint-disable typescript/no-unnecessary-condition */\nimport type {\n Root,\n Paragraph,\n Blockquote,\n PhrasingContent,\n BlockContent,\n DefinitionContent,\n RootContent\n} from \"mdast\";\nimport type { Properties } from \"hast\";\nimport {\n blockquoteMarkers,\n endGroupsAtMarkers,\n INDENTED_BLOCKS,\n MARKED_BLOCKS,\n splitAtOpeningLine,\n linesToParagraph,\n markerCount,\n paragraphProperties,\n paraToLines,\n rebuildLazyLines,\n type MarkedLine\n} from \"./lazy.js\";\n\n// ── MDAST node types ──────────────────────────────────────────────────────────\n\n/** A group of tabs at one depth, rendered as the tabs container. */\nexport interface TabsListNode {\n type: \"tabsList\";\n depth: number;\n containerClass?: string;\n groupId: string;\n children: TabsItemNode[];\n data?: { attrsRole?: string; hProperties?: Properties };\n}\n\n/** A tab's label, rendered as its `<label>`. */\nexport interface TabsLabelNode {\n type: \"tabsLabel\";\n children: PhrasingContent[];\n}\n\n/** One tab: its label (always the first child, so transforms that walk children reach it), panel body and nested tabs. */\nexport interface TabsItemNode {\n type: \"tabsItem\";\n depth: number;\n labelText: string; // plain text of the label as recognized, for the group id\n open: boolean;\n children: Array<\n TabsLabelNode | BlockContent | DefinitionContent | TabsListNode\n >;\n data?: {\n attrsRole?: string;\n attrsTitle?: PhrasingContent[];\n attrsItemTitle?: boolean;\n hProperties?: Properties;\n };\n}\n\n// ── Header and ids ────────────────────────────────────────────────────────────\n\n// Matches: %{1,6}+? label text (prefix-plus form: %+ Label)\n// Groups: 1=% string (depth), 2=+ (open marker, optional), 3=label text\nconst TAB_HEADER_RE = /^(%{1,6})(\\+)? (.*)/;\n\ninterface ParsedTabHeader {\n depth: number;\n open: boolean;\n label: string;\n}\n\nconst parseTabHeader = (line: string): ParsedTabHeader | null => {\n const m = TAB_HEADER_RE.exec(line);\n if (!m) return null;\n const [, percents = \"\", plus, label = \"\"] = m;\n return { depth: percents.length, open: plus === \"+\", label };\n};\n\n// djb2 hash — returns an unsigned 32-bit integer\nconst djb2 = (str: string): number => {\n let h = 5381;\n for (let i = 0; i < str.length; i++) {\n h = ((h << 5) + h + str.charCodeAt(i)) >>> 0;\n }\n return h;\n};\n\n/** Strip a trailing attrs block like `{.class #id}` from plain label text, so attrs-consumed markers don't leak into `aria-label`. */\nexport const stripAttrs = (text: string): string =>\n text.replace(/\\s*\\{[^}]*\\}\\s*$/, \"\").trimEnd();\n\nconst slugify = (text: string): string =>\n text\n .toLowerCase()\n .trim()\n .replace(/[^\\w\\s-]/g, \"\")\n .replace(/[\\s_]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n\n// content-based: same label set → same id regardless of page position\nconst groupId = (labels: string[]): string => {\n const key = [...labels].map(slugify).sort().join(\"-\");\n return djb2(key).toString(16);\n};\n\n/**\n * A group's block id, unique on the page even when label sets match: its group id with the group's index among the document's tab groups, counted in the order they open (each nested group after the group around it), so every engine counts the same groups the same way.\n */\nexport const tabsBlockId = (index: number, groupId: string): string =>\n \"tabs-\" + djb2(`${index}:${groupId}`).toString(16);\n\n// ── Raw extraction types ──────────────────────────────────────────────────────\n\ninterface RawTab {\n depth: number;\n open: boolean;\n labelNodes: PhrasingContent[]; // inline nodes for the label\n labelText: string; // plain text for aria-label / data-tab\n body: Array<BlockContent | DefinitionContent>; // blockquote contents\n // Content after the tab's nested groups: headers in its explicit `> %` body that skip a level, kept as written.\n after?: Array<BlockContent | DefinitionContent>;\n // Attributes the parser read off the end of the header's paragraph, when the header ended it (Sätteri).\n hProperties?: Properties | undefined;\n}\n\n// ── Paragraph line splitting ──────────────────────────────────────────────────\n\n/** The plain text of a tab label (text and inline code; other markup contributes its text, images nothing), for its group id and `aria-label`. */\nexport const tabLabelText = (nodes: PhrasingContent[]): string =>\n nodes\n .map((n) => {\n if (n.type === \"text\" || n.type === \"inlineCode\")\n return \"value\" in n ? n.value : \"\";\n if (\"children\" in n) return tabLabelText(n.children);\n return \"\";\n })\n .join(\"\");\n\n// ── Tab group extraction ──────────────────────────────────────────────────────\n\n// Parse a paragraph node that consists entirely of % tab headers (no body\n// content). Returns null if the paragraph isn't all headers. A header that\n// skips a depth level ends the group: it and the lines after it are returned\n// as `rest`, to be rendered as an ordinary paragraph after the tabs.\n// requireDepthOne: if true, the first header must be depth 1 (top-level group start).\n// If false, allows any starting depth (for continuation paragraphs).\nconst extractHeaderPara = (\n para: Paragraph,\n requireDepthOne = true,\n prevDepth = 0\n): { tabs: RawTab[]; rest: PhrasingContent[][]; restLine: number } | null => {\n const lines = paraToLines(para);\n const tabs: RawTab[] = [];\n let currentDepth = prevDepth;\n\n for (const [index, lineSegs] of lines.entries()) {\n const first = lineSegs[0];\n if (first?.type !== \"text\") return null;\n\n const header = parseTabHeader(first.value);\n if (!header) return null;\n\n const { depth, open } = header;\n if (tabs.length === 0 && requireDepthOne && depth !== 1) return null;\n if (depth > currentDepth + 1) {\n return tabs.length > 0\n ? {\n tabs,\n rest: lines.slice(index),\n restLine: (para.position?.start.line ?? 1) + index\n }\n : null;\n }\n currentDepth = depth;\n\n const labelText = header.label;\n const labelNodes: PhrasingContent[] = labelText\n ? [{ type: \"text\", value: labelText }, ...lineSegs.slice(1)]\n : lineSegs.slice(1);\n\n tabs.push({\n depth,\n open,\n labelNodes,\n labelText: tabLabelText(labelNodes),\n body: [],\n ...(index === lines.length - 1\n ? { hProperties: paragraphProperties(para) }\n : {})\n });\n }\n\n return tabs.length > 0 ? { tabs, rest: [], restLine: 0 } : null;\n};\n\n// Lines left over after a group ends become ordinary paragraphs, split before\n// every line that opens a new group (a depth-1 header), so the main loop can\n// start that group. Positions follow the source lines (paragraph lines map 1:1\n// to source lines) because a group at the root ends at a blank line.\nconst splitAtGroupStarts = (\n lines: PhrasingContent[][],\n firstLine: number\n): Paragraph[] => {\n const paragraphs: Paragraph[] = [];\n let start = 0;\n const flush = (end: number): void => {\n const para = linesToParagraph(lines.slice(start, end));\n if (!para) return;\n para.position = {\n start: { line: firstLine + start, column: 1 },\n end: { line: firstLine + end - 1, column: 1 }\n };\n paragraphs.push(para);\n };\n lines.forEach((line, index) => {\n const first = line[0];\n const opens =\n first?.type === \"text\" && parseTabHeader(first.value)?.depth === 1;\n if (opens && index > start) {\n flush(index);\n start = index;\n }\n });\n flush(lines.length);\n return paragraphs;\n};\n\n// Split a blockquote node into segments separated by % tab header lines.\n// Each segment is { header: RawTab | null, body: blockquote-like children }.\n//\n// Remark absorbs adjacent non-blank lines into a blockquote, so:\n// % Tab One\n// > Content for tab one.\n// % Tab Two\n// > Content for tab two.\n//\n// Produces: paragraph(\"% Tab One\") + blockquote containing:\n// paragraph(\"Content for tab one.\\n% Tab Two\\nContent for tab two.\")\n//\n// We need to split that paragraph on lines matching tab headers, then\n// reconstruct the body content for each segment.\ninterface BQSegment {\n header: RawTab | null; // null means pre-header content (goes to prev tab)\n body: Array<BlockContent | DefinitionContent>;\n // true when this blockquote was written with explicit `> %` nesting (multiple\n // block children) rather than being the standard absorbed-tabs pattern where\n // remark collapses consecutive `% Tab\\n> body` lines into one blockquote.\n // Used to apply a depth offset and to unwrap nested blockquote bodies.\n explicit: boolean;\n // With the source: the `>` markers of the header's line, and the body lines after it with theirs, for headers lazily continued into a nested paragraph.\n markers?: number;\n lines: MarkedLine[];\n // The header's line as written, for a header that skips a level and stays text.\n line?: PhrasingContent[];\n}\n\n// A blockquote is \"explicit\" (`> % Label` nesting) when at least one of its\n// direct paragraph children starts with a tab header. The absorbed pattern\n// (remark collapsing consecutive `% Tab\\n> body` lines into one blockquote)\n// never produces standalone header paragraphs — headers are only embedded\n// inside multi-line text nodes.\nconst isExplicitBQ = (bq: Blockquote): boolean =>\n bq.children.some((child) => {\n if (child.type !== \"paragraph\") return false;\n const first = child.children[0];\n return (\n first?.type === \"text\" &&\n parseTabHeader(first.value.split(\"\\n\")[0] ?? \"\") !== null\n );\n });\n\n// Walk to the deepest last child of a node and return its paragraph if one of\n// its lines is a tab header: the first such header, the paragraph truncated\n// before it, and the lines after it (which belong to the new tab, and may hold\n// further headers). Returns null if the paragraph has no tab header line.\n// This handles cases where remark plugins (e.g. remarkDefinitionList) transform\n// absorbed paragraphs into custom nodes — the trailing \"% Code\" line ends up\n// inside a nested paragraph rather than at the blockquote's top level.\nconst extractTrailingTabHeader = (\n node: BlockContent | DefinitionContent,\n sourceLines?: readonly string[]\n): {\n header: RawTab;\n truncatedPara: Paragraph | null;\n rest: PhrasingContent[][];\n path: Array<BlockContent | DefinitionContent>;\n start: number | undefined;\n at: number;\n line: PhrasingContent[];\n} | null => {\n // Walk to the deepest last child that is a paragraph\n const path: Array<BlockContent | DefinitionContent> = [];\n let current: BlockContent | DefinitionContent = node;\n while (\"children\" in current && current.children.length > 0) {\n const last = current.children[current.children.length - 1] as\n | BlockContent\n | DefinitionContent;\n if (last.type === \"paragraph\") {\n path.push(current);\n // Find the first line of this paragraph that is a tab header. A nested\n // blockquote can lazily absorb a header line and the body lines after it.\n const lines = paraToLines(last, sourceLines);\n const at = lines.findIndex(\n (line) => line[0]?.type === \"text\" && parseTabHeader(line[0].value)\n );\n if (at === -1) return null;\n const headerLine = lines[at] ?? [];\n const first = headerLine[0];\n const header =\n first?.type === \"text\" ? parseTabHeader(first.value) : null;\n if (!header) return null;\n const labelText = header.label;\n const labelNodes: PhrasingContent[] = labelText\n ? [{ type: \"text\", value: labelText }, ...headerLine.slice(1)]\n : headerLine.slice(1);\n const rawTab: RawTab = {\n depth: header.depth,\n open: header.open,\n labelNodes,\n labelText: tabLabelText(labelNodes),\n body: [],\n ...(at === lines.length - 1\n ? { hProperties: paragraphProperties(last) }\n : {})\n };\n const truncatedPara = linesToParagraph(lines.slice(0, at));\n return {\n header: rawTab,\n truncatedPara,\n rest: lines.slice(at + 1),\n path,\n start: last.position?.start.line,\n at,\n line: headerLine\n };\n }\n if (!(\"children\" in last)) break;\n path.push(current);\n current = last;\n }\n return null;\n};\n\nconst splitBlockquote = (\n bq: Blockquote,\n explicit: boolean,\n sourceLines?: readonly string[]\n): BQSegment[] => {\n const segments: BQSegment[] = [];\n let currentSegment: BQSegment = {\n header: null,\n body: [],\n explicit,\n lines: []\n };\n // The `>` markers of a plain panel's own lines: a header written with them is the panel's content (it can start a group of its own there), as markdown-it reads the panel; only one written outside the panel starts the next tab. An explicit panel (`> % Label`) places its headers by their markers itself.\n const base =\n sourceLines && !explicit ? blockquoteMarkers(bq, sourceLines) : undefined;\n\n // Split paragraph lines on tab header lines: body lines accumulate into the\n // current segment, and each header starts a new one. `markersOf` gives a\n // line's `>` markers when the source is known.\n const splitLines = (\n lines: PhrasingContent[][],\n markersOf?: (index: number) => number,\n para?: Paragraph\n ): void => {\n let bodyLines: PhrasingContent[][] = [];\n\n for (const [index, lineSegs] of lines.entries()) {\n const first = lineSegs[0];\n const outsidePanel =\n !markersOf || base === undefined || markersOf(index) < base;\n if (first?.type === \"text\" && outsidePanel) {\n const header = parseTabHeader(first.value);\n if (header) {\n // Flush accumulated body lines into current segment\n if (bodyLines.length > 0) {\n const bodyPara = linesToParagraph(bodyLines);\n if (bodyPara) currentSegment.body.push(bodyPara);\n bodyLines = [];\n }\n\n // Save current segment, start a new one\n segments.push(currentSegment);\n\n const labelText = header.label;\n const labelNodes: PhrasingContent[] = labelText\n ? [{ type: \"text\", value: labelText }, ...lineSegs.slice(1)]\n : lineSegs.slice(1);\n\n currentSegment = {\n header: {\n depth: header.depth,\n open: header.open,\n labelNodes,\n labelText: tabLabelText(labelNodes),\n body: [],\n ...(para && index === lines.length - 1\n ? { hProperties: paragraphProperties(para) }\n : {})\n },\n body: [],\n explicit,\n lines: [],\n line: lineSegs,\n ...(markersOf ? { markers: markersOf(index) } : {})\n };\n continue;\n }\n }\n bodyLines.push(lineSegs);\n if (markersOf) {\n currentSegment.lines.push({\n segs: lineSegs,\n markers: markersOf(index)\n });\n }\n }\n\n // Flush remaining body lines. They end the paragraph, so they keep its\n // data: attributes the parser read from its end (Sätteri's run before tabs).\n if (bodyLines.length > 0) {\n const bodyPara = linesToParagraph(bodyLines);\n if (bodyPara && para?.data) bodyPara.data = para.data;\n if (bodyPara) currentSegment.body.push(bodyPara);\n }\n };\n\n for (const child of bq.children) {\n if (child.type !== \"paragraph\") {\n // For non-paragraph children (e.g. defList from remarkDefinitionList),\n // check if the deepest last-child paragraph has a trailing tab header.\n // Remark may have absorbed a \"% NextTab\" line into that nested paragraph.\n const extracted = extractTrailingTabHeader(child, sourceLines);\n if (extracted) {\n // Clone the child with the trailing header line removed from its nested paragraph\n const cloned = JSON.parse(JSON.stringify(child)) as\n | BlockContent\n | DefinitionContent;\n // Navigate to the deepest last child and replace the paragraph.\n // Tree walking through heterogeneous mdast Parent shapes — no narrow\n // type fits all the intermediate nodes we descend through.\n interface ParentLike {\n children: ParentLike[];\n }\n let target: ParentLike = cloned as unknown as ParentLike;\n for (let pi = 1; pi < extracted.path.length; pi++) {\n target = target.children[target.children.length - 1]!;\n }\n const deepestParent = target as unknown as { children: unknown[] };\n if (extracted.truncatedPara) {\n deepestParent.children[deepestParent.children.length - 1] =\n extracted.truncatedPara;\n } else {\n deepestParent.children.splice(deepestParent.children.length - 1, 1);\n }\n currentSegment.body.push(cloned);\n // Start a new segment for the extracted tab header\n segments.push(currentSegment);\n const { start, at } = extracted;\n const markersOf =\n sourceLines && start !== undefined\n ? (index: number): number =>\n markerCount(sourceLines[start - 1 + index] ?? \"\")\n : undefined;\n currentSegment = {\n header: extracted.header,\n body: [],\n explicit,\n lines: [],\n line: extracted.line,\n ...(markersOf ? { markers: markersOf(at) } : {})\n };\n splitLines(\n extracted.rest,\n markersOf ? (index): number => markersOf(at + 1 + index) : undefined\n );\n } else {\n currentSegment.body.push(child);\n }\n continue;\n }\n\n // Check if this paragraph contains tab headers mixed with body text\n const start = child.position?.start.line;\n splitLines(\n paraToLines(child, sourceLines),\n sourceLines && start !== undefined\n ? (index): number => markerCount(sourceLines[start - 1 + index] ?? \"\")\n : undefined,\n child\n );\n }\n\n segments.push(currentSegment);\n return segments;\n};\n\n// The content that a header which skips a level, and what follows it, stand for\n// once they are not tabs: the header line and the lines and blocks after it, as\n// markdown-it reads them. CommonMark lazily continued them into a paragraph; with\n// the source, their `>` markers (relative to `level`, the markers of the content\n// they belong to) rebuild the blockquotes they were written in. Their other\n// blocks follow: in the last quote when they were inside a blockquote the header\n// line is outside of (`quoted`), else beside the rest.\nconst afterSkip = (\n segments: BQSegment[],\n level: number | undefined,\n quoted: boolean\n): Array<BlockContent | DefinitionContent> => {\n const lines: MarkedLine[] = [];\n const blocks: Array<BlockContent | DefinitionContent> = [];\n for (const seg of segments) {\n if (level === undefined || seg.markers === undefined) {\n // Without the source: the header line, then the segment's body quoted.\n if (seg.line) lines.push({ segs: seg.line, markers: 0 });\n blocks.push(...seg.body);\n continue;\n }\n if (seg.line) lines.push({ segs: seg.line, markers: seg.markers - level });\n lines.push(\n ...seg.lines.map((line) => ({ ...line, markers: line.markers - level }))\n );\n blocks.push(...seg.body.filter((block) => block.type !== \"paragraph\"));\n }\n const content = rebuildLazyLines(lines, 0);\n if (blocks.length > 0 && !quoted) {\n content.push(...blocks);\n } else if (blocks.length > 0) {\n const last = content.at(-1);\n if (last?.type === \"blockquote\") last.children.push(...blocks);\n else\n content.push({\n type: \"blockquote\",\n children: blocks\n });\n }\n return content;\n};\n\n// ── Tree builder ──────────────────────────────────────────────────────────────\n\nconst buildTree = (\n rawTabs: RawTab[],\n targetDepth: number,\n start: number,\n end: number,\n containerClass: string\n): TabsListNode => {\n const depthLabels = rawTabs\n .slice(start, end)\n .filter((t) => t.depth === targetDepth)\n .map((t) => stripAttrs(t.labelText));\n\n const gId = groupId(depthLabels);\n\n // Absolute index of the first %+ tab at this depth (-1 if none)\n const explicitOpenIdx = rawTabs\n .slice(start, end)\n .findIndex((t) => t.depth === targetDepth && t.open);\n const explicitOpenAbsIdx =\n explicitOpenIdx >= 0 ? start + explicitOpenIdx : -1;\n\n const items: TabsItemNode[] = [];\n let tabCounter = 0;\n let i = start;\n\n while (i < end) {\n const raw = rawTabs[i];\n if (!raw) break;\n if (raw.depth !== targetDepth) {\n i++;\n continue;\n }\n\n let childEnd = i + 1;\n while (childEnd < end && (rawTabs[childEnd]?.depth ?? 0) > targetDepth)\n childEnd++;\n\n // First %+ wins; if none, first tab is open\n const isOpen =\n explicitOpenAbsIdx >= 0 ? i === explicitOpenAbsIdx : tabCounter === 0;\n // The label node shares `labelNodes` with `attrsTitle`, so attrs trimming one trims the other.\n const bodyChildren: TabsItemNode[\"children\"] = [\n { type: \"tabsLabel\", children: raw.labelNodes },\n ...raw.body\n ];\n\n const hasDeeper = rawTabs\n .slice(i + 1, childEnd)\n .some((t) => t.depth === targetDepth + 1);\n\n if (hasDeeper) {\n const nested = buildTree(\n rawTabs,\n targetDepth + 1,\n i + 1,\n childEnd,\n containerClass\n );\n nested.containerClass = containerClass;\n bodyChildren.push(nested);\n }\n bodyChildren.push(...(raw.after ?? []));\n\n items.push({\n type: \"tabsItem\",\n depth: targetDepth,\n labelText: raw.labelText,\n open: isOpen,\n children: bodyChildren,\n data: {\n attrsRole: \"containerItem\",\n attrsTitle: raw.labelNodes,\n attrsItemTitle: true,\n hProperties: { ...raw.hProperties }\n }\n });\n\n tabCounter++;\n i = childEnd;\n }\n\n return {\n type: \"tabsList\",\n depth: targetDepth,\n groupId: gId,\n children: items,\n data: { attrsRole: \"container\", hProperties: {} }\n };\n};\n\n// ── Remark plugin ─────────────────────────────────────────────────────────────\n\n// Process all tab groups found in a children array in-place.\n// Used at root level and recursively inside any parent node's children.\n// checkBlankLines: when false, skip the line-gap termination check (for nested contexts\n// where blank lines inside blockquotes produce position gaps but are still part of the group).\nexport const processTabsInChildren = (\n children: Array<BlockContent | DefinitionContent | RootContent>,\n containerClass: string,\n checkBlankLines = true,\n sourceLines?: readonly string[],\n quotes = 0,\n parentType = \"root\"\n): void => {\n const newChildren: typeof children = [];\n let i = 0;\n\n while (i < children.length) {\n const node = children[i];\n if (!node) break;\n\n // A tab header interrupts the paragraph before it, as markdown-it's block rule does, when it's written at the paragraph's own level (its `>` markers). In a list item or definition, a header line may instead be one CommonMark lazily continued, so those are left as they are.\n if (\n node.type === \"paragraph\" &&\n sourceLines &&\n !INDENTED_BLOCKS.has(parentType)\n ) {\n const split = splitAtOpeningLine(\n node,\n sourceLines,\n quotes,\n (text) => parseTabHeader(text)?.depth === 1\n );\n if (split) {\n children.splice(i, 1, ...split);\n continue;\n }\n }\n\n if (node.type === \"paragraph\") {\n const headerPara = extractHeaderPara(node);\n\n if (headerPara) {\n const rawTabs: RawTab[] = [...headerPara.tabs];\n // A group always starts with at least one tab.\n const lastTab = (): RawTab => rawTabs[rawTabs.length - 1]!;\n // Lines left over after a depth-skipping header end the group.\n let rest = headerPara.rest;\n let restLine = headerPara.restLine;\n let j = i + 1;\n let currentTabIdx = rawTabs.length - 1;\n let prevEndLine = node.position?.end.line ?? 0;\n\n while (rest.length === 0 && j < children.length) {\n const sibling = children[j];\n if (!sibling) break;\n const siblingStartLine =\n (sibling as { position?: { start: { line: number } } }).position\n ?.start.line ?? prevEndLine + 1;\n\n if (checkBlankLines && siblingStartLine > prevEndLine + 1) break;\n\n if (sibling.type === \"blockquote\") {\n const bq = sibling;\n const explicit = isExplicitBQ(bq);\n const segments = splitBlockquote(bq, explicit, sourceLines);\n // The `>` markers of the owning tab's body lines: an inner header written with fewer belongs outside it.\n const base =\n explicit && sourceLines\n ? blockquoteMarkers(bq, sourceLines)\n : undefined;\n\n const firstSeg = segments[0];\n if (firstSeg?.header === null) {\n rawTabs[currentTabIdx]?.body.push(...firstSeg.body);\n }\n\n // Explicit blockquotes (`> % Label` nesting) have their headers\n // implicitly one level deeper than the owning tab. Apply a depth\n // offset so they nest correctly.\n // Absorbed blockquotes (standard `% Tab\\n> body` pattern) keep\n // literal depths — remark collapses them into a single paragraph child.\n const depthOffset = explicit ? lastTab().depth : 0;\n // The tab whose body this blockquote is.\n const owner = lastTab();\n // Content after the group when a header ends it.\n let ending: Array<BlockContent | DefinitionContent> | null = null;\n\n for (const [index, seg] of segments.slice(1).entries()) {\n if (!seg.header) continue;\n\n // A header remark absorbed into this body from outside it (its line has\n // fewer `>` markers than the body's) is an outer-level tab: it keeps the\n // depth it was written with, its absorbed lines are its body, rebuilt\n // from their markers, and the blocks after them are its body as written.\n const markers = seg.markers;\n if (\n explicit &&\n markers !== undefined &&\n base !== undefined &&\n markers < base\n ) {\n if (seg.header.depth > lastTab().depth + 1) continue;\n const relative = seg.lines.map((line) => ({\n ...line,\n markers: line.markers - (markers + 1)\n }));\n seg.header.body.push(\n ...rebuildLazyLines(relative, 0),\n ...seg.body.slice(seg.lines.length > 0 ? 1 : 0)\n );\n rawTabs.push(seg.header);\n currentTabIdx = rawTabs.length - 1;\n continue;\n }\n\n const adjustedDepth = depthOffset + seg.header.depth;\n const prevDepth = lastTab().depth;\n if (adjustedDepth > prevDepth + 1) {\n if (explicit) {\n // In an explicit `> %` body, a header that skips a level is not a tab: it\n // and its body stay in the owning tab's panel as written, after any group\n // nested there, as markdown-it renders them.\n owner.after = [\n ...(owner.after ?? []),\n ...afterSkip([seg], base, false)\n ];\n continue;\n }\n // In a group of plain `>` bodies, a header that skips a level ends the\n // group: it and everything after it in this blockquote follow the group as\n // ordinary content.\n // The header line is outside the blockquote, one `>` short of its own.\n const quoteMarkers = sourceLines\n ? blockquoteMarkers(bq, sourceLines)\n : undefined;\n ending = afterSkip(\n segments.slice(index + 1),\n quoteMarkers === undefined ? undefined : quoteMarkers - 1,\n true\n );\n break;\n }\n\n seg.header.depth = adjustedDepth;\n\n if (explicit) {\n // For explicit `> %` blockquotes, body items are wrapped in a\n // nested `> >` blockquote. Unwrap each nested blockquote:\n // - Non-explicit (absorbed) inner BQs are re-split to extract\n // tab headers that remark collapsed into a single paragraph.\n // - Explicit inner BQs use their children directly.\n //\n // \"Escaped\" segments: when remark absorbs an outer-level tab header\n // (e.g. `% Code` at root depth) into an inner BQ paragraph, the tab's\n // body node (code fence etc.) is hoisted to the outer BQ as a direct\n // child after that inner BQ. Re-split segments with an empty body had\n // their body hoisted — they are outer-level siblings, not inner children.\n // Subsequent non-blockquote nodes in seg.body belong to those escaped tabs.\n const deferredInnerSegs: BQSegment[] = [];\n // Tracks which re-split segments have empty bodies (body hoisted to outer BQ)\n const escapedSegs: RawTab[] = [];\n\n for (const b of seg.body) {\n if (b.type !== \"blockquote\") {\n // Non-BQ outer sibling — belongs to the first escaped seg's body\n const escaped = escapedSegs.at(-1);\n if (escaped) {\n escaped.body.push(b);\n } else {\n seg.header.body.push(b);\n }\n continue;\n }\n const innerBq = b;\n if (!isExplicitBQ(innerBq)) {\n // Re-split absorbed inner blockquote to extract sibling headers\n const innerSegs = splitBlockquote(\n innerBq,\n false,\n sourceLines\n );\n const innerFirst = innerSegs[0];\n if (innerFirst?.header === null) {\n seg.header.body.push(...innerFirst.body);\n }\n for (const innerSeg of innerSegs.slice(1)) {\n if (!innerSeg.header) continue;\n // An outer-level header that remark absorbed into this inner BQ is an\n // escaped tab. With the source, its line has fewer `>` markers than the\n // owning tab's body: it keeps the depth it was written with, and the\n // lines absorbed after it are its body, rebuilt from their markers.\n // Without, a re-split segment with no body is taken as escaped (its\n // body was hoisted to the outer BQ as a direct child) at depthOffset.\n const markers = innerSeg.markers;\n if (markers !== undefined && base !== undefined) {\n if (markers < base) {\n const relative = innerSeg.lines.map((line) => ({\n ...line,\n markers: line.markers - (markers + 1)\n }));\n innerSeg.header.body.push(\n ...rebuildLazyLines(relative, 0)\n );\n escapedSegs.push(innerSeg.header);\n deferredInnerSegs.push(innerSeg);\n continue;\n }\n } else if (innerSeg.body.length === 0) {\n innerSeg.header.depth = depthOffset;\n escapedSegs.push(innerSeg.header);\n deferredInnerSegs.push(innerSeg);\n continue;\n }\n const tentativeDepth =\n depthOffset + innerSeg.header.depth;\n const innerPrevDepth = lastTab().depth;\n if (tentativeDepth > innerPrevDepth + 1) continue;\n innerSeg.header.depth = tentativeDepth;\n innerSeg.header.body.push(...innerSeg.body);\n deferredInnerSegs.push(innerSeg);\n }\n } else {\n // Explicit inner blockquote — use children directly\n seg.header.body.push(...innerBq.children);\n }\n }\n // Push the current seg first, then any deferred inner siblings\n rawTabs.push(seg.header);\n currentTabIdx = rawTabs.length - 1;\n for (const innerSeg of deferredInnerSegs) {\n if (!innerSeg.header) continue;\n rawTabs.push(innerSeg.header);\n currentTabIdx = rawTabs.length - 1;\n }\n } else {\n seg.header.body.push(...seg.body);\n rawTabs.push(seg.header);\n currentTabIdx = rawTabs.length - 1;\n }\n }\n\n prevEndLine = sibling.position?.end.line ?? prevEndLine;\n j++;\n if (ending) {\n children.splice(j, 0, ...ending);\n break;\n }\n } else if (sibling.type === \"paragraph\") {\n const prevDepth = lastTab().depth;\n const contHeaders = extractHeaderPara(sibling, false, prevDepth);\n if (contHeaders) {\n rawTabs.push(...contHeaders.tabs);\n rest = contHeaders.rest;\n restLine = contHeaders.restLine;\n currentTabIdx = rawTabs.length - 1;\n prevEndLine = sibling.position?.end.line ?? prevEndLine;\n j++;\n continue;\n }\n break;\n } else {\n break;\n }\n }\n\n const list = buildTree(rawTabs, 1, 0, rawTabs.length, containerClass);\n list.containerClass = containerClass;\n newChildren.push(list as unknown as RootContent);\n children.splice(j, 0, ...splitAtGroupStarts(rest, restLine));\n i = j;\n continue;\n }\n }\n\n newChildren.push(node);\n i++;\n }\n\n children.splice(0, children.length, ...newChildren);\n};\n\ninterface Container {\n type?: string;\n children?: unknown[];\n}\n\n/**\n * Recognize every tab group in the tree: at the root, then inside every container (step bodies, list items, other tabs' panels). Blank-line checks only apply at the root: blank lines inside a blockquote leave position gaps that would wrongly end a group once its content has been lifted out of the blockquote. With the document's `source`, a tab header that CommonMark lazily continued into a nested panel is placed by its `>` markers, as markdown-it reads it.\n */\nexport const processTabs = (\n root: Root,\n containerClass: string,\n source?: string\n): void => {\n const sourceLines = source?.split(/\\r?\\n/);\n const walk = (node: Container, quotes: number): void => {\n if (!Array.isArray(node.children) || node.children.length === 0) return;\n const inner = quotes + (MARKED_BLOCKS.has(node.type ?? \"\") ? 1 : 0);\n processTabsInChildren(\n node.children as Array<BlockContent | DefinitionContent>,\n containerClass,\n false,\n sourceLines,\n inner,\n node.type\n );\n for (const child of node.children) walk(child as Container, inner);\n };\n processTabsInChildren(root.children, containerClass, true, sourceLines);\n for (const child of root.children) walk(child, 0);\n if (sourceLines) endGroupsAtMarkers(root, sourceLines, `tabsList`);\n};\n","// A mutable copy of a read-only tree, for engines whose nodes can't be rewritten in place (Sätteri), so they can run the same recognition as remark.\n// A node's children are its own node type; `TreeNode` can't say so, so the two reads of them are asserted.\n/* oxlint-disable typescript/no-unsafe-type-assertion */\n\n/** The part of a node the copy reads: its children, if it has any. */\nexport interface TreeNode {\n type: string;\n children?: readonly TreeNode[];\n data?: unknown;\n}\n\n/** A copy of a tree, and how to write the changes made to it back. */\nexport interface EditableTree<N extends TreeNode> {\n /** A plain, mutable copy of the tree, for recognition to rewrite. */\n tree: N;\n /**\n * Write a node of the (rewritten) copy back: a node recognition left alone becomes the engine's own node again, so it keeps what the engine tracks for it (such as its source position, which later plugins read), and `setChildren` is called only where a children list changed, `setData` only where its `data` was replaced. `build` converts a node recognition created, writing back any copied nodes inside it.\n */\n writeBack: (node: N) => N;\n}\n\nexport const editableTree = <N extends TreeNode>(\n root: N,\n build: (node: N, writeBack: (node: N) => N) => N,\n setChildren: (node: N, children: N[]) => void,\n setData?: (node: N, data: unknown) => void\n): EditableTree<N> => {\n const originals = new Map<N, { node: N; children: readonly N[] }>();\n\n const copy = (node: N): N => {\n const children = node.children as readonly N[] | undefined;\n if (!children) {\n const leaf = { ...node };\n originals.set(leaf, { node, children: [] });\n return leaf;\n }\n const branch = { ...node, children: children.map(copy) };\n originals.set(branch, { node, children });\n return branch;\n };\n\n const writeBack = (node: N): N => {\n const original = originals.get(node);\n if (!original) return build(node, writeBack);\n if (setData && node.data !== original.node.data)\n setData(original.node, node.data);\n if (!node.children) return original.node;\n const children = (node.children as readonly N[]).map(writeBack);\n const changed =\n children.length !== original.children.length ||\n children.some((child, index) => child !== original.children[index]);\n if (changed) setChildren(original.node, children);\n return original.node;\n };\n\n return { tree: copy(root), writeBack };\n};\n","// Inlining referenced `.svg` images, shared by the markdown-it, rehype and Sätteri plugins: whether an SVG's occurrences are inlined, and the markup each becomes. Reading files, optimizing them and resolving paths stay in the plugins, so this module does no I/O.\n\n/** The limits and mode that decide how an SVG's occurrences are inlined. */\nexport interface InlineSvgLimits {\n /** Skip inlining SVGs larger than this many characters. */\n maxImageSize: number;\n /** Skip inlining an SVG referenced more than this many times. */\n maxOccurrences: number;\n /** Skip inlining an SVG whose occurrences add up to more than this many characters. */\n maxTotalSize: number;\n /** Reuse a repeated SVG through a hidden `<symbol>` and `<use>`. */\n deduplication: boolean;\n}\n\nconst hash = (str: string): string => {\n let h = 2166136261;\n for (let i = 0; i < str.length; i++) {\n h = Math.imul(h ^ str.charCodeAt(i), 16777619) >>> 0;\n }\n return h.toString(36);\n};\n\n/**\n * The id of a deduplicated SVG's sprite: a hash of its path relative to the document, with `/` separators, so the same document renders the same ids on any machine or OS (an absolute path would leak the build machine into the HTML).\n */\nexport const svgSpriteId = (relativePath: string): string =>\n `svg-sprite-${hash(relativePath)}`;\n\nconst extractSvgParts = (\n content: string\n): { viewBox: string; width: string; height: string; inner: string } => {\n const openTag = /<svg([^>]*?)>/i.exec(content)?.[1] ?? ``;\n return {\n viewBox: /viewBox=\"([^\"]*)\"/i.exec(openTag)?.[1] ?? ``,\n width: /\\bwidth=\"([^\"]*)\"/i.exec(openTag)?.[1] ?? ``,\n height: /\\bheight=\"([^\"]*)\"/i.exec(openTag)?.[1] ?? ``,\n inner: /<svg[^>]*>([\\s\\S]*?)<\\/svg\\s*>/i.exec(content)?.[1]?.trim() ?? ``\n };\n};\n\nconst escAttr = (s: string): string =>\n s.replace(/&/g, `&amp;`).replace(/\"/g, `&quot;`);\n\n// The image's alt text is the SVG's accessible name.\nconst buildFullInline = (content: string, alt: string): string => {\n if (!alt) return content;\n return content.replace(\n /<svg([^>]*)>/i,\n `<svg$1 aria-label=\"${escAttr(alt)}\">`\n );\n};\n\nconst buildSpriteHtml = (id: string, viewBox: string, inner: string): string =>\n `<svg aria-hidden=\"true\" style=\"display:none\" xmlns=\"http://www.w3.org/2000/svg\">` +\n `<defs><symbol id=\"${id}\" viewBox=\"${escAttr(viewBox)}\">${inner}</symbol></defs>` +\n `</svg>`;\n\nconst buildUseHtml = (\n id: string,\n viewBox: string,\n width: string,\n height: string,\n alt: string\n): string => {\n const attrs = [\n viewBox && `viewBox=\"${escAttr(viewBox)}\"`,\n width && `width=\"${escAttr(width)}\"`,\n height && `height=\"${escAttr(height)}\"`,\n alt && `aria-label=\"${escAttr(alt)}\"`\n ]\n .filter(Boolean)\n .join(` `);\n return `<svg ${attrs}><use href=\"#${id}\"></use></svg>`;\n};\n\n/**\n * The markup for every occurrence of one SVG file, given each occurrence's alt text in document order: the SVG itself, or, with deduplication and more than one occurrence, a hidden sprite on the first and a `<use>` of it on each. `null` when the limits leave the images as they are. `relativePath` is the file's path relative to the document, with `/` separators, for the sprite id.\n */\nexport const inlineSvgMarkup = (\n content: string,\n alts: readonly string[],\n relativePath: string,\n limits: InlineSvgLimits\n): string[] | null => {\n if (content.length > limits.maxImageSize) return null;\n if (alts.length > limits.maxOccurrences) return null;\n if (alts.length * content.length > limits.maxTotalSize) return null;\n if (!limits.deduplication || alts.length < 2) {\n return alts.map((alt) => buildFullInline(content, alt));\n }\n const { viewBox, width, height, inner } = extractSvgParts(content);\n const id = svgSpriteId(relativePath);\n const sprite = buildSpriteHtml(id, viewBox, inner);\n return alts.map((alt, index) => {\n const use = buildUseHtml(id, viewBox, width, height, alt);\n return index === 0 ? sprite + use : use;\n });\n};\n","// Rendering mermaid diagrams with Pele, shared by the markdown-it, rehype and Sätteri plugins: which elements hold a diagram, each diagram's id prefix, the attributes its `<svg>` takes, and the error a failed diagram throws. Rendering itself stays in the plugins, which depend on Pele, so this module has no dependencies.\n\nimport type { HastLike } from \"./hast.js\";\n\n/** An HTML attribute, as markdown-it's tokens hold them. */\nexport type MermaidAttribute = [name: string, value: string];\n\n/** The class a fenced `mermaid` block's `<code>` takes. */\nconst MERMAID_LANGUAGE_CLASS = `language-mermaid`;\n/** The class a `<pre>` holding a diagram written as HTML takes, as Mermaid reads it in the browser. */\nconst MERMAID_PRE_CLASS = `mermaid`;\n\nconst hash = (str: string): string => {\n let h = 2166136261;\n for (let i = 0; i < str.length; i++) {\n h = Math.imul(h ^ str.charCodeAt(i), 16777619) >>> 0;\n }\n return h.toString(36);\n};\n\n/** A diagram's source as Pele reads it: line endings normalized, as markdown-it already has them. */\nexport const mermaidSource = (text: string): string =>\n text.replace(/\\r\\n?/g, `\\n`);\n\n/**\n * A document's id prefixes, one per diagram in document order: `prefix`, then a hash of the diagram's source, so a diagram's ids don't change when others are edited, with `-2`, `-3`… for repeats of one diagram. Pele namespaces every id it writes (an accessible title, a gradient) under it. Create one per document.\n */\nexport const mermaidIdPrefixes = (\n prefix: string\n): ((source: string) => string) => {\n const seen = new Map<string, number>();\n return (source) => {\n const id = `${prefix}-${hash(source)}`;\n const count = (seen.get(id) ?? 0) + 1;\n seen.set(id, count);\n return count === 1 ? id : `${id}-${count}`;\n };\n};\n\nconst escapeAttribute = (value: string): string =>\n value.replace(/&/g, `&amp;`).replace(/\"/g, `&quot;`);\n\nconst classes = (value: string): string[] =>\n value\n .split(/\\s+/)\n .filter(\n (name) =>\n name !== `` &&\n name !== MERMAID_LANGUAGE_CLASS &&\n name !== MERMAID_PRE_CLASS\n );\n\n/**\n * Pele's `<svg>` with the attributes the diagram's element had (from an attribute block such as `{#id .class}`): classes are added after Pele's, a style after Pele's (whose theme variables the diagram needs), and anything else is set, replacing Pele's value. The class that marked the element as a diagram is dropped.\n */\nexport const mermaidSvg = (\n svg: string,\n attributes: readonly MermaidAttribute[]\n): string => {\n const open = /^<svg\\b[^>]*>/.exec(svg)?.[0];\n if (!open || attributes.length === 0) return svg;\n const own = [...open.slice(4, -1).matchAll(/\\s([^\\s=]+)=\"([^\"]*)\"/g)].map(\n ([, name = ``, value = ``]): MermaidAttribute => [name, value]\n );\n const merged = new Map<string, string>(own);\n for (const [name, value] of attributes) {\n const escaped = escapeAttribute(value);\n const current = merged.get(name);\n if (name === `class`) {\n const added = classes(value).map(escapeAttribute).join(` `);\n if (added) merged.set(name, current ? `${current} ${added}` : added);\n } else if (name === `style` && current) {\n merged.set(name, `${current.replace(/;$/, ``)};${escaped}`);\n } else {\n merged.set(name, escaped);\n }\n }\n const tag = [...merged]\n .map(([name, value]) => ` ${name}=\"${value}\"`)\n .join(``);\n return `<svg${tag}>${svg.slice(open.length)}`;\n};\n\n/** A hast element's properties as attributes; `className` becomes `class`, and other names are kept as the attribute plugins write them. */\nexport const hastAttributes = (\n properties: Record<string, unknown> | undefined\n): MermaidAttribute[] => {\n // hast's property values: a string, a number, a boolean (present or absent) or a list.\n const text = (value: unknown): string | undefined =>\n typeof value === `string`\n ? value\n : typeof value === `number`\n ? String(value)\n : value === true\n ? ``\n : Array.isArray(value)\n ? value.map((item) => text(item) ?? ``).join(` `)\n : undefined;\n const attributes: MermaidAttribute[] = [];\n for (const [key, value] of Object.entries(properties ?? {})) {\n const written = text(value);\n if (written !== undefined)\n attributes.push([key === `className` ? `class` : key, written]);\n }\n return attributes;\n};\n\nconst hasClass = (node: HastLike, name: string): boolean => {\n const value = node.properties?.className;\n return Array.isArray(value)\n ? value.includes(name)\n : typeof value === `string` && value.split(/\\s+/).includes(name);\n};\n\nconst textOf = (node: HastLike): string =>\n node.type === `text`\n ? (node.value ?? ``)\n : (node.children ?? []).map(textOf).join(``);\n\n/**\n * The diagram a `<pre>` holds, as rehype-mermaid finds them: a `<pre>` whose only content (besides whitespace) is a `<code class=\"language-mermaid\">`, which is how a fenced `mermaid` block renders, or a `<pre class=\"mermaid\">`. `element` is the one whose attributes the `<svg>` takes. `undefined` for anything else.\n */\nexport const mermaidDiagram = (\n pre: HastLike\n): { source: string; element: HastLike } | undefined => {\n if (pre.tagName !== `pre`) return undefined;\n if (hasClass(pre, MERMAID_PRE_CLASS))\n return { source: mermaidSource(textOf(pre)), element: pre };\n let code: HastLike | undefined;\n for (const child of pre.children ?? []) {\n if (child.type === `text` && /^\\s*$/.test(child.value ?? ``)) continue;\n if (code || child.tagName !== `code`) return undefined;\n code = child;\n }\n return code && hasClass(code, MERMAID_LANGUAGE_CLASS)\n ? { source: mermaidSource(textOf(code)), element: code }\n : undefined;\n};\n\n/**\n * The error a diagram that failed to render throws: Pele's message, at the document line Pele located the problem on (counting from `line`, the line the diagram's element starts on), or at `line` itself when Pele has no location. The original error is the `cause`.\n */\nexport const mermaidFailure = (\n error: unknown,\n line: number | undefined\n): Error => {\n const reason = error instanceof Error ? error.message : String(error);\n const within =\n error instanceof Error &&\n `line` in error &&\n typeof error.line === `number` &&\n error.line > 0\n ? error.line\n : 0;\n const at = line === undefined ? `` : ` on line ${String(line + within)}`;\n return new Error(`Could not render the mermaid diagram${at}: ${reason}`, {\n cause: error\n });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["icon","WHITESPACE","PUNCTUATION","classify","WHITESPACE","WHITESPACE","extractHeaderPara","splitAtGroupStarts","splitBlockquote","buildTree"],"sources":["../src/escapes.ts","../src/github-alerts/types.ts","../src/github-alerts/icons.ts","../src/github-alerts/index.ts","../src/spans.ts","../src/delimited.ts","../src/kbd.ts","../src/scripts.ts","../src/cut-attributes.ts","../src/lazy.ts","../src/line-containers.ts","../src/caption.ts","../src/hast.ts","../src/abbr.ts","../src/steps.ts","../src/tabs.ts","../src/editable.ts","../src/inline-svg.ts","../src/copy-code.ts"],"sourcesContent":["// Parsers resolve backslash escapes before any post-parse transform runs, so a\n// plugin that scans text nodes for delimiters sees `\\==x==` as `==x==`. These\n// helpers recover which characters of a text node were escaped, by aligning its\n// value with the source it came from, and mask them while a plugin scans.\n\n// Only ASCII punctuation can be backslash-escaped (CommonMark §2.4).\nconst ASCII_PUNCTUATION = /^[!-/:-@[-`{-~]$/;\nconst ENTITY = /^&(?:#\\d+|#x[\\da-f]+|[a-z][\\da-z]*);/i;\n\n// Masked characters move into Supplementary Private Use Area-A, where no\n// delimiter pattern can match them; every escapable character maps into\n// U+F0021–U+F007E.\nconst MASK_BASE = 0xf0000;\nconst MASKED = /[\\u{F0021}-\\u{F007E}]/gu;\n\n/**\n * Indices of `value` whose character was backslash-escaped in `source`, where\n * `start`–`end` is the source range the text came from. Characters the parser\n * dropped (backslashes, container prefixes such as `> `, trailing spaces) are\n * skipped, and a character reference stands for the character it decodes to.\n */\nexport const escapedIndices = (\n value: string,\n source: string,\n start: number,\n end: number\n): Set<number> => {\n const escaped = new Set<number>();\n let j = start;\n for (let i = 0; i < value.length && j < end; i++) {\n const char = value.charAt(i);\n let entity: RegExpExecArray | null = null;\n while (j < end && source[j] !== char) {\n entity = source[j] === `&` ? ENTITY.exec(source.slice(j, end)) : null;\n if (entity) break;\n j++;\n }\n if (j >= end) break;\n if (entity) {\n j += entity[0].length;\n continue;\n }\n let slashes = 0;\n for (let k = j - 1; k >= start && source[k] === `\\\\`; k--) slashes++;\n if (slashes % 2 === 1 && ASCII_PUNCTUATION.test(char)) escaped.add(i);\n j++;\n }\n return escaped;\n};\n\n/** Replace the characters at `escaped` with stand-ins no delimiter matches. */\nexport const maskEscaped = (value: string, escaped: Set<number>): string => {\n if (escaped.size === 0) return value;\n let out = ``;\n for (let i = 0; i < value.length; i++) {\n out += escaped.has(i)\n ? String.fromCodePoint(MASK_BASE + value.charCodeAt(i))\n : value[i];\n }\n return out;\n};\n\n/** Restore characters replaced by {@link maskEscaped}. */\nexport const unmaskEscaped = (value: string): string =>\n value.replace(MASKED, (c) =>\n String.fromCharCode(c.codePointAt(0)! - MASK_BASE)\n );\n\n/** The shape of a unist text node this module reads and writes. */\nexport interface TextLikeNode {\n type: string;\n value?: unknown;\n position?:\n | {\n start: { offset?: number | undefined };\n end: { offset?: number | undefined };\n }\n | undefined;\n children?: TextLikeNode[] | undefined;\n}\n\n/**\n * Mask escaped characters in every positioned `text` node of a unist tree, so\n * a delimiter scan skips them. Returns a function that restores them in every\n * node afterwards, including nodes the scan created from masked text.\n */\nexport const maskTreeEscapes = (\n tree: TextLikeNode,\n source: string\n): (() => void) => {\n const walk = (node: TextLikeNode, visit: (n: TextLikeNode) => void): void => {\n visit(node);\n node.children?.forEach((child) => walk(child, visit));\n };\n walk(tree, (node) => {\n const start = node.position?.start.offset;\n const end = node.position?.end.offset;\n if (node.type !== `text` || typeof node.value !== `string`) return;\n if (start === undefined || end === undefined) return;\n node.value = maskEscaped(\n node.value,\n escapedIndices(node.value, source, start, end)\n );\n });\n return () =>\n walk(tree, (node) => {\n if (typeof node.value === `string`)\n node.value = unmaskEscaped(node.value);\n });\n};\n","/** A recognized alert keyword (e.g. `note`, `warning`, `caution`). */\nexport type AlertType =\n | \"note\"\n | \"tip\"\n | \"important\"\n | \"warning\"\n | \"caution\"\n | \"abstract\"\n | \"info\"\n | \"todo\"\n | \"success\"\n | \"question\"\n | \"failure\"\n | \"danger\"\n | \"bug\"\n | \"example\"\n | \"quote\";\n\n// Maps every recognized keyword (lowercase) to its canonical AlertType.\n// Aliases collapse so CSS only needs one selector per canonical type.\n/** Maps every recognized alert keyword (lowercase) to its canonical {@link AlertType}. */\nexport const ALERT_ALIASES: Record<string, AlertType> = {\n // GitHub 5\n note: \"note\",\n tip: \"tip\",\n important: \"important\",\n warning: \"warning\",\n caution: \"caution\",\n // Obsidian extended\n abstract: \"abstract\",\n summary: \"abstract\",\n tldr: \"abstract\",\n info: \"info\",\n todo: \"todo\",\n hint: \"tip\",\n success: \"success\",\n check: \"success\",\n done: \"success\",\n question: \"question\",\n help: \"question\",\n faq: \"question\",\n attention: \"warning\",\n failure: \"failure\",\n fail: \"failure\",\n missing: \"failure\",\n danger: \"danger\",\n error: \"danger\",\n bug: \"bug\",\n example: \"example\",\n quote: \"quote\",\n cite: \"quote\"\n};\n\n/** Default display title for each {@link AlertType}. */\nexport const DEFAULT_TITLE: Record<AlertType, string> = {\n note: \"Note\",\n tip: \"Tip\",\n important: \"Important\",\n warning: \"Warning\",\n caution: \"Caution\",\n abstract: \"Abstract\",\n info: \"Info\",\n todo: \"Todo\",\n success: \"Success\",\n question: \"Question\",\n failure: \"Failure\",\n danger: \"Danger\",\n bug: \"Bug\",\n example: \"Example\",\n quote: \"Quote\"\n};\n\n/** Options shared by the GitHub alerts plugins for every engine. */\nexport interface AlertOptions {\n /**\n * Extra alert types beyond the built-in set. Keys are lowercase keywords\n * (including any aliases you want), values are the canonical type string\n * that appears in the data-alert attribute and CSS class.\n */\n types?: Record<string, string>;\n /** Default display titles, keyed by canonical type. */\n titles?: Partial<Record<AlertType, string>>;\n /** Set false to require exact case on the [!TYPE] keyword. Default: true. */\n matchCaseInsensitive?: boolean;\n /** Set false to suppress the SVG icon in the title. Default: true. */\n icons?: boolean;\n /** CSS class applied to the alert container. Default: \"markdown-alert\". */\n containerClass?: string;\n}\n","import type { AlertType } from \"./types.js\";\n\n// All icons are Lucide SVGs (lucide.dev), stroke=\"currentColor\", 24×24 viewBox.\n// They inherit their color from the --_alert-color CSS variable via `color`.\n\nconst icon = (path: string): string =>\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${path}</svg>`;\n\n/** Inline SVG icon markup for each {@link AlertType}. */\nexport const ICONS: Record<AlertType, string> = {\n // GitHub alert types — Lucide equivalents of the GitHub Octicons\n note: icon(\n '<path d=\"M12 20h9\"></path><path d=\"M16.376 3.622a1 1 0 0 1 3.002 3.002L7.368 18.635a2 2 0 0 1-.855.506l-2.872.838a.5.5 0 0 1-.62-.62l.838-2.872a2 2 0 0 1 .506-.854z\"></path>'\n ),\n tip: icon(\n '<path d=\"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5\"></path><path d=\"M9 18h6\"></path><path d=\"M10 22h4\"></path>'\n ),\n important: icon('<path d=\"M7.9 20A9 9 0 1 0 4 16.1L2 22z\"></path>'),\n warning: icon(\n '<path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"></path><path d=\"M12 9v4\"></path><path d=\"M12 17h.01\"></path>'\n ),\n caution: icon(\n '<circle cx=\"12\" cy=\"12\" r=\"10\"></circle><path d=\"m4.9 4.9 14.2 14.2\"></path><path d=\"M12 8v4\"></path><path d=\"M12 16h.01\"></path>'\n ),\n // Obsidian extended types\n abstract: icon(\n '<rect width=\"8\" height=\"4\" x=\"8\" y=\"2\" rx=\"1\" ry=\"1\"></rect><path d=\"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2\"></path><path d=\"M12 11h4\"></path><path d=\"M12 16h4\"></path><path d=\"M8 11h.01\"></path><path d=\"M8 16h.01\"></path>'\n ),\n info: icon(\n '<circle cx=\"12\" cy=\"12\" r=\"10\"></circle><path d=\"M12 16v-4\"></path><path d=\"M12 8h.01\"></path>'\n ),\n todo: icon(\n '<path d=\"M8 6h13\"></path><path d=\"M8 12h13\"></path><path d=\"M8 18h13\"></path><path d=\"M3 6h.01\"></path><path d=\"M3 12h.01\"></path><path d=\"M3 18h.01\"></path>'\n ),\n success: icon(\n '<path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\"></path><path d=\"m9 11 3 3L22 4\"></path>'\n ),\n question: icon(\n '<circle cx=\"12\" cy=\"12\" r=\"10\"></circle><path d=\"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\"></path><path d=\"M12 17h.01\"></path>'\n ),\n failure: icon(\n '<circle cx=\"12\" cy=\"12\" r=\"10\"></circle><path d=\"m15 9-6 6\"></path><path d=\"m9 9 6 6\"></path>'\n ),\n danger: icon('<path d=\"M13 2 3 14h9l-1 8 10-12h-9l1-8z\"></path>'),\n bug: icon(\n '<path d=\"m8 2 1.88 1.88\"></path><path d=\"M14.12 3.88 16 2\"></path><path d=\"M9 7.13v-1a3.003 3.003 0 1 1 6 0v1\"></path><path d=\"M12 20c-3.3 0-6-2.7-6-6v-3a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v3c0 3.3-2.7 6-6 6\"></path><path d=\"M12 20v-9\"></path><path d=\"M6.53 9C4.6 8.8 3 7.1 3 5\"></path><path d=\"M6 13H2\"></path><path d=\"M3 21c0-2.1 1.7-3.9 3.8-4\"></path><path d=\"M20.97 5c0 2.1-1.6 3.8-3.5 4\"></path><path d=\"M22 13h-4\"></path><path d=\"M17.2 17c2.1.1 3.8 1.9 3.8 4\"></path>'\n ),\n example: icon(\n '<path d=\"M8 6h13\"></path><path d=\"M8 12h13\"></path><path d=\"M8 18h13\"></path><path d=\"M3 6 4 5l1 1-1 1z\"></path><path d=\"M3 12 4 11l1 1-1 1z\"></path><path d=\"M3 18 4 17l1 1-1 1z\"></path>'\n ),\n quote: icon(\n '<path d=\"M3 21c3 0 7-1 7-8V5c0-1.25-.756-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V20c0 1 0 1 1 1z\"></path><path d=\"M15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z\"></path>'\n )\n};\n","import {\n ALERT_ALIASES,\n DEFAULT_TITLE,\n type AlertOptions,\n type AlertType\n} from \"./types.js\";\nimport { ICONS } from \"./icons.js\";\n\nexport { ALERT_ALIASES, DEFAULT_TITLE, ICONS };\nexport type { AlertOptions, AlertType };\n\n// Groups: 1=type keyword, 2=foldable marker (+/-)\nconst MARKER_RE = /^\\[!([^\\]]+)\\]([+-])?/;\n\n/** Whether a source line opens an alert (`> [!NOTE]`), after its `>` markers and indentation, whether or not the alerts plugin reads it: a block that takes the quote after it as more of its content (a step body) leaves an alert be. */\nexport const isAlertMarkerLine = (line: string): boolean =>\n MARKER_RE.test(line.replace(/^[ \t>]*/, ``));\n\nconst capitalize = (s: string): string =>\n s.charAt(0).toUpperCase() + s.slice(1);\n\n/** How an alert keyword resolves under a plugin's options. */\nexport interface AlertResolver {\n /** The canonical type for a `[!KEYWORD]`, or `undefined` if it is not an alert. */\n resolve: (keyword: string) => string | undefined;\n /** The title shown when the alert has no custom title. */\n titleFor: (type: string) => string;\n /** The icon SVG for the title, or `\"\"` when icons are off. */\n iconFor: (type: string) => string;\n /** The alert container's CSS class. */\n containerClass: string;\n}\n\n/** Resolve alert keywords, titles and icons the same way in every engine. */\nexport const createAlertResolver = (\n options: AlertOptions = {}\n): AlertResolver => {\n const {\n types: extraTypes = {},\n titles = {},\n matchCaseInsensitive = true,\n icons = true,\n containerClass = `markdown-alert`\n } = options;\n const aliasMap: Record<string, string> = { ...ALERT_ALIASES, ...extraTypes };\n // Titles may name user-defined types from `options.types` too.\n const customTitles: Partial<Record<string, string>> = titles;\n const isAlertType = (type: string): type is AlertType =>\n type in DEFAULT_TITLE;\n return {\n resolve: (keyword) =>\n aliasMap[matchCaseInsensitive ? keyword.toLowerCase() : keyword],\n // A user-defined type may have no default title; capitalize the keyword as a last resort.\n titleFor: (type) =>\n customTitles[type] ??\n (isAlertType(type) ? DEFAULT_TITLE[type] : undefined) ??\n capitalize(type),\n iconFor: (type) => (icons && isAlertType(type) ? ICONS[type] : ``),\n containerClass\n };\n};\n\n/** The shape of an mdast phrasing node this module reads and builds. */\nexport interface PhrasingLike {\n type: string;\n value?: string;\n alt?: string | null | undefined;\n children?: readonly PhrasingLike[];\n}\n\n/** A paragraph that opens with an alert marker, split into its parts. */\nexport interface AlertParagraph<N extends PhrasingLike> {\n /** The `[!KEYWORD]` text, before alias resolution. */\n keyword: string;\n /** `+` (open) or `-` (closed) for a foldable alert, else `undefined`. */\n fold: `+` | `-` | undefined;\n /** The first line after the marker: the custom title, formatting included. */\n titleNodes: N[];\n /** The title's plain text (text, inline code and image alt), for `aria-label`. */\n titleText: string;\n /** Everything after the first line break (soft or hard): the paragraph's body. */\n bodyNodes: N[];\n}\n\n/** Plain text of inline content: text, inline code and image alt count; raw HTML does not. */\nexport const plainText = (nodes: readonly PhrasingLike[]): string =>\n nodes\n .map((n) =>\n n.type === `text` || n.type === `inlineCode`\n ? (n.value ?? ``)\n : n.type === `image`\n ? (n.alt ?? ``)\n : n.children\n ? plainText(n.children)\n : ``\n )\n .join(``);\n\nconst withValue = <N extends PhrasingLike>(node: N, value: string): N => ({\n ...node,\n value\n});\n\n/**\n * Split an alert's first paragraph (an mdast `paragraph`'s children) into its marker, title and body, or return `null` when it does not open with a `[!KEYWORD]` marker in plain text. The first line is the marker plus an optional title; everything after the first line break — a newline inside a text node (soft) or a `break` node (hard) — is the body. Nothing is dropped. Text nodes are copied; other nodes are reused as they are.\n */\nexport const splitAlertParagraph = <N extends PhrasingLike>(\n children: readonly N[]\n): AlertParagraph<N> | null => {\n const [first, ...rest] = children;\n if (first?.type !== `text` || first.value === undefined) return null;\n const opening = first.value.trimStart();\n const match = MARKER_RE.exec(opening);\n if (!match) return null;\n const [marker, keyword = ``, fold] = match;\n\n const line: N[] = [];\n const body: N[] = [];\n for (const child of [\n withValue(first, opening.slice(marker.length)),\n ...rest\n ]) {\n if (body.length > 0 || line.at(-1)?.type === `break`) {\n body.push(child);\n } else if (child.type === `text` && child.value?.includes(`\\n`)) {\n const at = child.value.indexOf(`\\n`);\n line.push(withValue(child, child.value.slice(0, at)));\n body.push(withValue(child, child.value.slice(at + 1)));\n } else {\n line.push(child);\n }\n }\n if (line.at(-1)?.type === `break`) line.pop();\n\n const trimmed = line.map((n, i) =>\n n.type !== `text`\n ? n\n : withValue(\n n,\n i === 0 && i === line.length - 1\n ? (n.value ?? ``).trim()\n : i === 0\n ? (n.value ?? ``).trimStart()\n : i === line.length - 1\n ? (n.value ?? ``).trimEnd()\n : (n.value ?? ``)\n )\n );\n const titleNodes = trimmed.filter((n) => n.type !== `text` || n.value !== ``);\n const lastTitle = titleNodes.at(-1);\n if (lastTitle?.type === `text`) {\n titleNodes[titleNodes.length - 1] = withValue(\n lastTitle,\n (lastTitle.value ?? ``).trimEnd()\n );\n }\n\n return {\n keyword,\n fold: fold === `+` || fold === `-` ? fold : undefined,\n titleNodes,\n titleText: plainText(titleNodes).trim(),\n bodyNodes: body.filter((n) => n.type !== `text` || n.value !== ``)\n };\n};\n","import { escapedIndices, maskEscaped, unmaskEscaped } from \"./escapes.js\";\nimport type { PhrasingLike } from \"./github-alerts/index.js\";\n\n// The plumbing shared by core's inline span scans (`delimited.ts`, `kbd.ts`): tracking the nodes a scan builds, and masking escaped characters for engines whose nodes are read-only.\n\n/** How a scanned span becomes nodes. */\nexport interface SpanNodes<N extends PhrasingLike> {\n /** A text node with the given value. */\n text: (value: string) => N;\n /** The node a span's content is wrapped in (e.g. an mdast `mark`). */\n wrap: (children: N[]) => N;\n}\n\n/** A node's source range, as unist positions carry it. */\nexport interface Positioned {\n position?:\n | {\n start: { offset?: number | undefined };\n end: { offset?: number | undefined };\n }\n | undefined;\n}\n\n/** A scan over one parent's children, and the nodes it created. */\nexport interface SpanTransform<N extends PhrasingLike> {\n /** Scan `children`, the children of a node of type `parentType`. Returns `children` itself when no span forms. */\n (children: readonly N[], parentType?: string): readonly N[];\n /** Whether `node` was built by this transform (a wrapper or a text node). */\n built: (node: object) => boolean;\n /**\n * The transform for engines whose text values have escapes resolved and whose nodes are read-only, such as Sätteri: escaped characters are masked by aligning each positioned text node with `source`, using copies, and restored in the result. Returns the new children, or `undefined` when no span forms.\n */\n withSource: (\n children: ReadonlyArray<N & Positioned>,\n parentType: string,\n source: string\n ) => N[] | undefined;\n}\n\n/** A scan, given node builders that record what they build. */\nexport type SpanScan<N extends PhrasingLike> = (\n children: readonly N[],\n parentType: string,\n nodes: SpanNodes<N>\n) => readonly N[];\n\n/** Wrap a scan with built-node tracking and source-based escape masking. */\nexport const createSpanTransform = <N extends PhrasingLike>(\n nodes: SpanNodes<N>,\n scan: SpanScan<N>\n): SpanTransform<N> => {\n const built = new WeakSet<object>();\n // Each wrapper's content, kept typed for restoring masked escapes.\n const contents = new WeakMap<object, N[]>();\n const tracked: SpanNodes<N> = {\n text: (value) => {\n const node = nodes.text(value);\n built.add(node);\n return node;\n },\n wrap: (children) => {\n const node = nodes.wrap(children);\n built.add(node);\n contents.set(node, children);\n return node;\n }\n };\n\n const transform = (children: readonly N[], parentType = ``): readonly N[] =>\n scan(children, parentType, tracked);\n\n const restore = (list: readonly N[]): void => {\n for (const node of list) {\n if (!built.has(node)) continue;\n if (node.type === `text` && node.value !== undefined) {\n node.value = unmaskEscaped(node.value);\n } else {\n restore(contents.get(node) ?? []);\n }\n }\n };\n\n const withSource = (\n children: ReadonlyArray<N & Positioned>,\n parentType: string,\n source: string\n ): N[] | undefined => {\n const masked = children.map((node): N => {\n const start = node.position?.start.offset;\n const end = node.position?.end.offset;\n if (\n node.type !== `text` ||\n node.value === undefined ||\n start === undefined ||\n end === undefined\n )\n return node;\n const escaped = escapedIndices(node.value, source, start, end);\n return escaped.size === 0\n ? node\n : tracked.text(maskEscaped(node.value, escaped));\n });\n const next = transform(masked, parentType);\n if (next === masked) return undefined;\n restore(next);\n return [...next];\n };\n\n return Object.assign(transform, {\n built: (node: object) => built.has(node),\n withSource\n });\n};\n","import type { PhrasingLike } from \"./github-alerts/index.js\";\nimport {\n createSpanTransform,\n type SpanNodes,\n type SpanTransform\n} from \"./spans.js\";\n\n// The scan behind `==mark==`, `++ins++`, `--del--` and `||spoiler||`, shared by the remark and Sätteri plugins. It ports markdown-it's delimiter algorithm (the one markdown-it-mark and markdown-it-ins use), so all three engines pair delimiters the same way: runs of the marker split into two-character delimiters that open or close by emphasis-style flanking, each closer pairs with the nearest open opener, pairs nest, and the odd marker of an odd-length run stays outside the tag. It works on one parent's children: text is scanned, other nodes are opaque. It is pure; remark runs it on mutable nodes, Sätteri on read-only ones (it builds new nodes and reuses the rest).\n\n/** A marker whose doubled form delimits a span: `==`, `++`, `--` or `||`. */\nexport type DelimiterMarker = `=` | `+` | `-` | `|`;\n\n// What markdown-it sees beside a run at the edge of a text node: inside an inline parent, that parent's own delimiter (`*`, `[`, `~`…), which is punctuation; at the edge of a block's inline content, the space markdown-it assumes there.\nconst INLINE_PARENTS = new Set([\n `delete`,\n `emphasis`,\n `insert`,\n `link`,\n `linkReference`,\n `mark`,\n `spoiler`,\n `spoilerContent`,\n `strong`,\n `subscript`,\n `superscript`\n]);\n\ntype CharClass = `space` | `punct` | `other`;\n\n// markdown-it's isWhiteSpace, and isMdAsciiPunct || isPunctChar (Unicode P and S).\nconst WHITESPACE =\n /^[\\t\\n\\v\\f\\r \\u00a0\\u1680\\u2000-\\u200a\\u202f\\u205f\\u3000]$/u;\nconst PUNCTUATION = /^[\\p{P}\\p{S}]$/u;\nconst classify = (char: string): CharClass =>\n WHITESPACE.test(char) ? `space` : PUNCTUATION.test(char) ? `punct` : `other`;\n\ninterface Delimiter {\n open: boolean;\n close: boolean;\n /** Index of the paired closer in the delimiter list, or -1. */\n end: number;\n /** Index among the items; consecutive values are delimiters of one run. */\n item: number;\n}\n\ntype Item<N> =\n | { kind: `text`; value: string }\n | { kind: `node`; node: N }\n | { kind: `delimiter` }\n | { kind: `opening` }\n | { kind: `closing` };\n\n/**\n * markdown-it's `balance_pairs` for a single marker. Every delimiter has `length: 0`, as in markdown-it-mark, so the emphasis \"rule of 3\" never applies.\n */\nconst balancePairs = (delimiters: Delimiter[]): void => {\n const jumps: number[] = [];\n const openersBottom = [-1, -1, -1, -1, -1, -1];\n let headerIdx = 0;\n let lastItem = -2;\n delimiters.forEach((closer, closerIdx) => {\n jumps.push(0);\n if (lastItem !== closer.item - 1) headerIdx = closerIdx;\n lastItem = closer.item;\n if (!closer.close) return;\n const bottom = closer.open ? 3 : 0;\n const minOpenerIdx = openersBottom[bottom] ?? -1;\n let openerIdx = headerIdx - (jumps[headerIdx] ?? 0) - 1;\n let newMinOpenerIdx = openerIdx;\n for (; openerIdx > minOpenerIdx; openerIdx -= (jumps[openerIdx] ?? 0) + 1) {\n const opener = delimiters[openerIdx];\n if (!opener?.open || opener.end >= 0) continue;\n const lastJump =\n openerIdx > 0 && delimiters[openerIdx - 1]?.open === false\n ? (jumps[openerIdx - 1] ?? 0) + 1\n : 0;\n jumps[closerIdx] = closerIdx - openerIdx + lastJump;\n jumps[openerIdx] = lastJump;\n closer.open = false;\n opener.end = closerIdx;\n opener.close = false;\n newMinOpenerIdx = -1;\n lastItem = -2;\n break;\n }\n if (newMinOpenerIdx !== -1) openersBottom[bottom] = newMinOpenerIdx;\n });\n};\n\n/** Build the delimiter scan for one marker: `=` (mark), `+` (ins), `-` (del) or `|` (spoiler). */\nexport const createDelimitedTransform = <N extends PhrasingLike>(\n marker: DelimiterMarker,\n nodes: SpanNodes<N>\n): SpanTransform<N> =>\n createSpanTransform(nodes, (children, parentType, { text, wrap }) => {\n const edge: CharClass = INLINE_PARENTS.has(parentType) ? `punct` : `space`;\n // The character class beside a text node, from its sibling: a break is a line ending; any other node ends in its own delimiter or markup.\n const beside = (\n node: N | undefined,\n side: `before` | `after`\n ): CharClass => {\n if (!node) return edge;\n if (node.type === `text` && node.value) {\n return classify(\n side === `before` ? node.value.slice(-1) : node.value.charAt(0)\n );\n }\n return node.type === `break` ? `space` : `punct`;\n };\n\n // markdown-it-mark's tokenizer: text between runs is one item, as markdown-it's pending text becomes one token.\n const items: Array<Item<N>> = [];\n const delimiters: Delimiter[] = [];\n children.forEach((child, index) => {\n const value = child.type === `text` ? child.value : undefined;\n if (value === undefined) {\n items.push({ kind: `node`, node: child });\n return;\n }\n let pending = ``;\n const flush = (): void => {\n if (pending) items.push({ kind: `text`, value: pending });\n pending = ``;\n };\n let i = 0;\n while (i < value.length) {\n let end = i;\n while (value.charAt(end) === marker) end++;\n if (end - i < 2) {\n pending += value.slice(i, Math.max(end, i + 1));\n i = Math.max(end, i + 1);\n continue;\n }\n const last =\n i > 0\n ? classify(value.charAt(i - 1))\n : beside(children[index - 1], `before`);\n const next =\n end < value.length\n ? classify(value.charAt(end))\n : beside(children[index + 1], `after`);\n const open = next !== `space` && (next !== `punct` || last !== `other`);\n const close =\n last !== `space` && (last !== `punct` || next !== `other`);\n flush();\n let length = end - i;\n if (length % 2) {\n items.push({ kind: `text`, value: marker });\n length--;\n }\n for (let pair = 0; pair < length; pair += 2) {\n if (open || close) {\n delimiters.push({ open, close, end: -1, item: items.length });\n items.push({ kind: `delimiter` });\n } else {\n items.push({ kind: `text`, value: marker + marker });\n }\n }\n i = end;\n }\n flush();\n });\n\n balancePairs(delimiters);\n if (!delimiters.some(({ end }) => end >= 0)) return children;\n\n // markdown-it-mark's postProcess: paired delimiters become tags, and the odd marker of an odd-length closing run moves after the closing tags.\n const lone: number[] = [];\n for (const delimiter of delimiters) {\n const closer = delimiters[delimiter.end];\n if (!closer) continue;\n items[delimiter.item] = { kind: `opening` };\n items[closer.item] = { kind: `closing` };\n const previous = items[closer.item - 1];\n if (previous?.kind === `text` && previous.value === marker) {\n lone.push(closer.item - 1);\n }\n }\n for (const i of lone.reverse()) {\n let j = i + 1;\n while (items[j]?.kind === `closing`) j++;\n j--;\n const moved = items[i];\n const target = items[j];\n if (i !== j && moved && target) {\n items[i] = target;\n items[j] = moved;\n }\n }\n\n // Fold the flat items into nested wrappers, merging adjacent text.\n const root: N[] = [];\n const stack: N[][] = [root];\n let buffer = ``;\n const append = (node: N): void => {\n (stack.at(-1) ?? root).push(node);\n };\n const flushText = (): void => {\n if (!buffer) return;\n append(text(buffer));\n buffer = ``;\n };\n for (const item of items) {\n if (item.kind === `text`) {\n buffer += item.value;\n } else if (item.kind === `delimiter`) {\n buffer += marker + marker;\n } else if (item.kind === `node`) {\n flushText();\n append(item.node);\n } else if (item.kind === `opening`) {\n flushText();\n stack.push([]);\n } else {\n flushText();\n append(wrap(stack.pop() ?? []));\n }\n }\n flushText();\n return root;\n });\n","import type { PhrasingLike } from \"./github-alerts/index.js\";\nimport {\n createSpanTransform,\n type SpanNodes,\n type SpanTransform\n} from \"./spans.js\";\n\n// The scan behind `[[key]]`, shared by the remark and Sätteri plugins. It ports markdown-it-kbd's tokenizer: from a `[[`, it walks forward counting nested `[[` and `]]` until the depth returns to zero, gives up at a line ending, and parses the content again for nested keys. It works on one parent's children: text is scanned character by character, other nodes are opaque. One difference is inherent: markdown-it-kbd scans source text, so it claims `[[*a]]*` before emphasis is resolved, while remark and Sätteri have parsed the emphasis before a plugin runs.\n\ntype Unit<N> = { char: string } | { node: N };\n\nconst isChar = (unit: Unit<PhrasingLike> | undefined, char: string): boolean =>\n unit !== undefined && `char` in unit && unit.char === char;\n\n/**\n * The index of the `]]` that closes the `[[` at `start`, or -1. This mirrors markdown-it-kbd's loop, which looks at each character with the one after it, starting from the opener's second `[`, and skips the second character of every pair it consumes.\n */\nconst findClose = <N extends PhrasingLike>(\n units: ReadonlyArray<Unit<N>>,\n start: number\n): number => {\n let depth = 1;\n let skipNext = false;\n for (let i = start + 1; i < units.length; i++) {\n if (skipNext) {\n skipNext = false;\n continue;\n }\n const unit = units[i];\n const next = units[i + 1];\n if (isChar(unit, `]`) && isChar(next, `]`)) {\n depth--;\n if (depth === 0) return i;\n skipNext = true;\n } else if (isChar(unit, `[`) && isChar(next, `[`)) {\n depth++;\n skipNext = true;\n } else if (\n isChar(unit, `\\n`) ||\n (unit && `node` in unit && unit.node.type === `break`)\n ) {\n return -1;\n }\n }\n return -1;\n};\n\n/** Build the `[[key]]` scan. */\nexport const createKbdTransform = <N extends PhrasingLike>(\n nodes: SpanNodes<N>\n): SpanTransform<N> =>\n createSpanTransform(nodes, (children, _parentType, { text, wrap }) => {\n const units: Array<Unit<N>> = children.flatMap((child): Array<Unit<N>> => {\n const value = child.type === `text` ? child.value : undefined;\n return value === undefined\n ? [{ node: child }]\n : Array.from(value, (char) => ({ char }));\n });\n\n // Scan a stretch of units into nodes; a key's content is scanned again, as markdown-it-kbd tokenizes it.\n const scan = (\n list: ReadonlyArray<Unit<N>>\n ): { nodes: N[]; keyed: boolean } => {\n const out: N[] = [];\n let keyed = false;\n let buffer = ``;\n const flushText = (): void => {\n if (buffer) out.push(text(buffer));\n buffer = ``;\n };\n for (let i = 0; i < list.length;) {\n const unit = list[i];\n if (isChar(unit, `[`) && isChar(list[i + 1], `[`)) {\n const end = findClose(list, i);\n if (end >= 0) {\n keyed = true;\n flushText();\n out.push(wrap(scan(list.slice(i + 2, end)).nodes));\n i = end + 2;\n continue;\n }\n }\n if (unit && `char` in unit) buffer += unit.char;\n else if (unit) {\n flushText();\n out.push(unit.node);\n }\n i++;\n }\n flushText();\n return { nodes: out, keyed };\n };\n\n const { nodes: result, keyed } = scan(units);\n return keyed ? result : children;\n });\n","import type {\n Code,\n Construct,\n Event,\n Resolver,\n State,\n TokenizeContext,\n TokenType,\n Effects\n} from \"micromark-util-types\";\n\n// micromark syntax for `~subscript~` and `^superscript^`, shared by remd-sub and remd-sup. Each marker is a single-character delimiter run with emphasis-style flanking. One resolver pairs both markers: it takes closers left to right and pairs each with the nearest opener of the same marker, so crossing runs (`^a~b^c~`) resolve leftmost-first and the two nest, as in markdown-it and Sätteri. It runs once however many of the two constructs a document uses, because micromark calls each `resolveAll` function once.\n\n/** The marker characters, and the micromark token types each produces. */\nconst SCRIPTS = {\n \"~\": { code: 126, type: `subscript` },\n \"^\": { code: 94, type: `superscript` }\n} as const;\n\ntype Marker = keyof typeof SCRIPTS;\n\n// Extensions register their token types by augmenting micromark's TokenTypeMap, which JSR rejects; this one assertion stands in for it.\n// oxlint-disable-next-line typescript/no-unsafe-type-assertion\nconst tokenType = (type: string): TokenType => type as TokenType;\nconst temporary = (type: string): TokenType =>\n tokenType(`${type}SequenceTemporary`);\nconst scriptOf = (tokenType: string): (typeof SCRIPTS)[Marker] | undefined =>\n Object.values(SCRIPTS).find(({ type }) => temporary(type) === tokenType);\n\n// micromark-util-classify-character, inlined: 1 = whitespace, 2 = punctuation.\nconst PUNCTUATION = /\\p{P}|\\p{S}/u;\nconst WHITESPACE = /\\s/;\nconst classify = (code: Code): 1 | 2 | undefined =>\n code === null ||\n code < 0 ||\n code === 32 ||\n WHITESPACE.test(String.fromCharCode(code))\n ? 1\n : PUNCTUATION.test(String.fromCharCode(code))\n ? 2\n : undefined;\n\n// micromark-util-chunked's `splice`, inlined: spreading a long list into Array#splice can overflow the stack.\nconst splice = <T>(\n list: T[],\n start: number,\n remove: number,\n items: T[]\n): void => {\n list.splice(start, remove);\n for (let i = 0; i < items.length; i += 10_000) {\n list.splice(start + i, 0, ...items.slice(i, i + 10_000));\n }\n};\n\n// micromark-util-resolve-all, inlined: run each distinct resolver once.\nconst resolveAll = (\n constructs: ReadonlyArray<Pick<Construct, \"resolveAll\">>,\n events: Event[],\n context: TokenizeContext\n): Event[] => {\n const called: Resolver[] = [];\n let result = events;\n for (const { resolveAll: resolve } of constructs) {\n if (resolve && !called.includes(resolve)) {\n result = resolve(result, context);\n called.push(resolve);\n }\n }\n return result;\n};\n\nconst resolveScripts: Resolver = (events, context) => {\n for (let index = 0; index < events.length; index++) {\n const [kind, closer] = events.at(index) ?? [];\n const script = closer && scriptOf(closer.type);\n if (kind !== `enter` || !closer || !script || !closer._close) continue;\n\n for (let open = index - 1; open >= 0; open--) {\n const [openKind, opener] = events.at(open) ?? [];\n if (\n openKind !== `exit` ||\n !opener ||\n opener.type !== closer.type ||\n !opener._open\n )\n continue;\n\n opener.type = tokenType(`${script.type}Sequence`);\n closer.type = tokenType(`${script.type}Sequence`);\n const span = {\n type: tokenType(script.type),\n start: { ...opener.start },\n end: { ...closer.end }\n };\n const text = {\n type: tokenType(`${script.type}Text`),\n start: { ...opener.end },\n end: { ...closer.start }\n };\n const next: Event[] = [\n [`enter`, span, context],\n [`enter`, opener, context],\n [`exit`, opener, context],\n [`enter`, text, context],\n // Resolve what is between first: runs that open inside the span close inside it or not at all.\n ...resolveAll(\n context.parser.constructs.insideSpan.null ?? [],\n events.slice(open + 1, index),\n context\n ),\n [`exit`, text, context],\n [`enter`, closer, context],\n [`exit`, closer, context],\n [`exit`, span, context]\n ];\n splice(events, open - 1, index - open + 3, next);\n index = open + next.length - 2;\n break;\n }\n }\n // Runs left unpaired are plain text.\n for (const [, token] of events) {\n if (scriptOf(token.type)) token.type = `data`;\n }\n return events;\n};\n\nfunction tokenize(\n this: TokenizeContext,\n effects: Effects,\n ok: State,\n nok: State\n): State {\n const { previous, events } = this;\n return (start: Code) => {\n const script = Object.values(SCRIPTS).find((s) => s.code === start);\n if (!script) return nok(start);\n // Only the start of a run: the rest of a longer run stays text.\n if (\n previous === script.code &&\n events.at(-1)?.[1].type !== `characterEscape`\n )\n return nok(start);\n effects.enter(temporary(script.type));\n effects.consume(start);\n return (after: Code) => {\n // A run of two or more is not a delimiter (`~~` is strikethrough's).\n if (after === script.code) return nok(after);\n const token = effects.exit(temporary(script.type));\n const before = classify(previous);\n const next = classify(after);\n token._open = !next || (next === 2 && Boolean(before));\n token._close = !before || (before === 2 && Boolean(next));\n return ok(after);\n };\n };\n}\n\n/** The shape of a micromark syntax extension this module builds. */\nexport interface ScriptSyntax {\n text: Record<number, unknown>;\n insideSpan: { null: unknown[] };\n}\n\n/**\n * The micromark syntax extension for one of the two markers: `~` (subscript, `subscript` tokens) or `^` (superscript, `superscript` tokens). The constructs of both markers resolve together.\n */\nexport const scriptSyntax = (marker: Marker): ScriptSyntax => {\n const construct: Construct = {\n name: SCRIPTS[marker].type,\n tokenize,\n resolveAll: resolveScripts\n };\n return {\n text: { [SCRIPTS[marker].code]: construct },\n insideSpan: { null: [construct] }\n };\n};\n","// Attribute blocks a lazily continued header hid: a tab or step header right after a body's last paragraph continues it in CommonMark, so a parser that reads attribute blocks before recognition (Sätteri) finds the paragraph's last block mid-paragraph and keeps it as text. Recognition cuts the paragraph before the header; these blocks then end it, and go where the parser would have put them, as markdown-it and remark (whose attrs run after recognition) do.\nimport type { Paragraph, PhrasingContent, Root, RootContent } from \"mdast\";\nimport type { Properties } from \"hast\";\n\n/** Paragraphs recognition rebuilt from lines, as it does where a tab or step header lazily continued them. */\nexport const rebuiltParagraphs = new WeakSet<Paragraph>();\n\n/** The properties an attribute block written after text gives the text's paragraph, as the parser reads them, or `undefined` if it isn't one. */\nexport type ReadAttributes = (block: string) => Properties | undefined;\n\ntype Node = Root | RootContent;\ntype Parent = Extract<Node, { children: unknown }>;\n\n/** A tab or step item recognition built, whose title nodes it shares with its label. */\ninterface TitledItem {\n data: {\n attrsRole: string;\n attrsTitle: PhrasingContent[];\n hProperties?: Properties;\n };\n}\n\n/** Joins `added` into `properties`: classes accumulate, other attributes replace. */\nconst mergeProperties = (\n properties: Properties | undefined,\n added: Properties\n): Properties => {\n const merged: Properties = { ...properties };\n for (const [key, value] of Object.entries(added)) {\n const existing = merged[key];\n merged[key] =\n key === \"className\" && Array.isArray(existing) && Array.isArray(value)\n ? [...existing, ...value]\n : value;\n }\n return merged;\n};\n\n// Whether mdast-util-to-hast wraps the list's paragraphs in `<p>`, as it does in a loose list.\nconst listLoose = (list: Node | undefined): boolean =>\n list?.type !== \"list\" ||\n Boolean(list.spread) ||\n list.children.some((item) => item.spread ?? item.children.length > 1);\n\n/**\n * Places the attribute block now ending each paragraph recognition rebuilt (one a header was cut from), as the parser places one: a block on a line of its own goes on the block it's written after, at the level its `>` markers and indentation put it (the paragraph, its list item in a tight list, or the outermost blockquote or list item it's written outside of, a list item giving its list); a block after text goes on the paragraph, or its list item from the item's first paragraph.\n */\nexport const placeCutAttributes = (\n root: Root,\n sourceLines: readonly string[],\n read: ReadAttributes\n): void => {\n const parents = new Map<Node, Parent>();\n const cut: Paragraph[] = [];\n const items: TitledItem[] = [];\n const walk = (node: Node): void => {\n if (node.type === \"paragraph\" && rebuiltParagraphs.has(node))\n cut.push(node);\n const data: unknown = node.data;\n if (\n typeof data === \"object\" &&\n data !== null &&\n \"attrsRole\" in data &&\n data.attrsRole === \"containerItem\" &&\n \"attrsTitle\" in data &&\n Array.isArray(data.attrsTitle)\n )\n // Recognition's own item nodes, which mdast's types don't name.\n // oxlint-disable-next-line typescript/no-unsafe-type-assertion\n items.push(node as unknown as TitledItem);\n if (!(\"children\" in node)) return;\n for (const child of node.children) {\n parents.set(child, node);\n walk(child);\n }\n };\n walk(root);\n\n for (const para of cut) {\n const children: PhrasingContent[] = para.children;\n const last = children.at(-1);\n if (last?.type !== \"text\") continue;\n const value = last.value.trimEnd();\n const lineStart = value.lastIndexOf(\"\\n\");\n const line = value.slice(lineStart + 1);\n const open = line.lastIndexOf(\"{\");\n if (open === -1) continue;\n const properties = read(line.slice(open));\n if (!properties) continue;\n const before = line.slice(0, open);\n const ownLine =\n before.trim() === \"\" &&\n (lineStart !== -1 || children.at(-2)?.type === \"break\");\n // A block after an element on its line was the element's to take.\n if (before === \"\" && !ownLine) continue;\n\n const ancestors: Parent[] = [];\n for (let p = parents.get(para); p; p = parents.get(p)) ancestors.unshift(p);\n const parent = ancestors.at(-1);\n\n let target: Node = para;\n if (ownLine) {\n const end = last.position?.end;\n const written = end ? (sourceLines[end.line - 1] ?? \"\") : \"\";\n const prefix = /^[ \\t>]*/.exec(written)?.[0] ?? \"\";\n const markers = prefix.split(\">\").length - 1;\n const outside = end\n ? ancestors.findIndex((ancestor) => {\n const start = ancestor.position?.start;\n if (ancestor.type === \"blockquote\" && start) {\n const own = (sourceLines[start.line - 1] ?? \"\").slice(\n 0,\n start.column - 1\n );\n return markers < own.split(\">\").length;\n }\n const first =\n ancestor.type === \"listItem\"\n ? ancestor.children[0]?.position?.start\n : undefined;\n return first !== undefined && prefix.length < first.column - 1;\n })\n : -1;\n const container = ancestors[outside];\n if (container)\n target =\n container.type === \"listItem\"\n ? (ancestors[outside - 1] ?? container)\n : container;\n else if (parent?.type === \"listItem\" && !listLoose(ancestors.at(-2)))\n target = parent;\n } else if (parent?.type === \"listItem\" && parent.children[0] === para) {\n target = parent;\n }\n\n const data: { hProperties?: Properties } | undefined = target.data;\n target.data = {\n ...data,\n hProperties: mergeProperties(data?.hProperties, properties)\n };\n const kept = ownLine\n ? value.slice(0, Math.max(lineStart, 0))\n : value.slice(0, lineStart + 1) + before;\n if (kept.trimEnd() === \"\") children.pop();\n else last.value = kept.trimEnd();\n }\n\n // A header in the middle of its paragraph kept its block as text, which now\n // ends its title: it goes on the item, as mdit-attrs and remd-attrs put a\n // title's block. (A header that ended its paragraph brought the attributes\n // the parser read off it.)\n for (const item of items) {\n const title = item.data.attrsTitle;\n const last = title.at(-1);\n if (last?.type !== \"text\") continue;\n const value = last.value.trimEnd();\n const open = value.lastIndexOf(\"{\");\n if (open === -1) continue;\n const properties = read(value.slice(open));\n if (!properties) continue;\n item.data.hProperties = mergeProperties(item.data.hProperties, properties);\n last.value = value.slice(0, open).trimEnd();\n if (last.value === \"\" && title.length > 1) title.pop();\n }\n};\n","// Lazy continuation, shared by the steps and tabs recognition: CommonMark lets a line without a blockquote's `>` markers continue the paragraph before it, so a header meant for an outer group, and the lines after it, can end up in a paragraph nested in a body. markdown-it reads such lines by their markers instead; with the document's source, so does recognition.\nimport type {\n Blockquote,\n BlockContent,\n DefinitionContent,\n Paragraph,\n PhrasingContent,\n Text\n} from \"mdast\";\nimport type { Properties } from \"hast\";\nimport { rebuiltParagraphs } from \"./cut-attributes.js\";\n\n/** The `>` markers a source line starts with. */\nexport const markerCount = (line: string): number =>\n (/^[ \\t>]*/.exec(line)?.[0] ?? \"\").split(\">\").length - 1;\n\n/** The `>` markers of a blockquote's own lines: those before it on its first line, and its own (that line can open nested blockquotes too). */\nexport const blockquoteMarkers = (\n bq: Blockquote,\n sourceLines: readonly string[]\n): number | undefined => {\n const start = bq.position?.start;\n if (!start) return undefined;\n return (\n markerCount(\n (sourceLines[start.line - 1] ?? \"\").slice(0, start.column - 1)\n ) + 1\n );\n};\n\n/** A paragraph line, with the `>` markers its source line starts with. */\nexport interface MarkedLine {\n segs: PhrasingContent[];\n markers: number;\n}\n\n/**\n * A paragraph's phrasing content split into its lines: text at each line ending, and after a hard break, which stays at the end of its line. With the source, the text on each line keeps its place in it, as remark would give it: from after the line's container prefix to its last non-space character.\n */\nexport const paraToLines = (\n para: Paragraph,\n sourceLines?: readonly string[]\n): PhrasingContent[][] => {\n const lines: PhrasingContent[][] = [[]];\n for (const child of para.children) {\n if (child.type === \"break\") {\n lines.at(-1)?.push(child);\n lines.push([]);\n } else if (child.type === \"text\") {\n const parts = child.value.split(\"\\n\");\n for (const [p, part] of parts.entries()) {\n if (p > 0) lines.push([]);\n if (part === \"\") continue;\n const text: Text = { type: \"text\", value: part };\n const position = child.position;\n if (position) {\n const line = position.start.line + p;\n const source = sourceLines?.[line - 1];\n const start =\n p === 0\n ? position.start\n : source === undefined\n ? undefined\n : {\n line,\n column: (/^[ \\t>]*/.exec(source)?.[0].length ?? 0) + 1\n };\n const end =\n p === parts.length - 1\n ? position.end\n : source === undefined\n ? undefined\n : { line, column: source.trimEnd().length + 1 };\n if (start && end) text.position = { start, end };\n }\n lines.at(-1)?.push(text);\n }\n } else {\n lines.at(-1)?.push(child);\n }\n }\n return lines;\n};\n\n/** The attributes a paragraph carries, which a parser that reads attribute blocks before recognition (Sätteri) read off its end: they belong to its last line. */\nexport const paragraphProperties = (\n para: Paragraph\n): Properties | undefined => {\n const data: { hProperties?: Properties } | undefined = para.data;\n return data?.hProperties;\n};\n\n/** Appends `node` to `children`, merging text into the text before it, as remark keeps a run of text in one node. */\nconst pushPhrasing = (\n children: PhrasingContent[],\n node: PhrasingContent\n): void => {\n const last = children.at(-1);\n if (node.type !== \"text\" || last?.type !== \"text\") {\n children.push(node);\n return;\n }\n // A line ending with no position of its own takes the next line's start.\n const start =\n last.position?.start ??\n (last.value.trim() === \"\" ? node.position?.start : undefined);\n const end = node.position?.end ?? last.position?.end;\n const merged: Text = { type: \"text\", value: last.value + node.value };\n if (start && end) merged.position = { start, end };\n children[children.length - 1] = merged;\n};\n\n/** A paragraph from lines of phrasing content, or `null` for none. Lines join with a line ending, except after a hard break, which is one. */\nexport const linesToParagraph = (\n lines: PhrasingContent[][]\n): Paragraph | null => {\n const children: PhrasingContent[] = [];\n for (const [i, line] of lines.entries()) {\n if (i > 0 && lines[i - 1]?.at(-1)?.type !== \"break\")\n pushPhrasing(children, { type: \"text\", value: \"\\n\" });\n for (const node of line) pushPhrasing(children, node);\n }\n if (children.length === 0) return null;\n const para: Paragraph = { type: \"paragraph\", children };\n const start = children[0]?.position?.start;\n const end = children.at(-1)?.position?.end;\n if (start && end) para.position = { start, end };\n rebuiltParagraphs.add(para);\n return para;\n};\n\n/**\n * The blocks lazily continued lines stand for, from their markers relative to the body they belong to (`level` deep): as such lines go on CommonMark only nests deeper, so a line with more markers opens blockquotes and a new paragraph, and a line with fewer continues the paragraph it follows.\n */\nexport const rebuildLazyLines = (\n lines: MarkedLine[],\n level: number\n): Array<BlockContent | DefinitionContent> => {\n const deeper = lines.findIndex(({ markers }) => markers > level);\n const own = deeper === -1 ? lines : lines.slice(0, deeper);\n const para = linesToParagraph(own.map(({ segs }) => segs));\n const blocks: Array<BlockContent | DefinitionContent> = para ? [para] : [];\n if (deeper !== -1) {\n const quote: Blockquote = {\n type: \"blockquote\",\n children: rebuildLazyLines(lines.slice(deeper), level + 1)\n };\n blocks.push(quote);\n }\n return blocks;\n};\n\n// A node as the end-of-group pass reads the tree: mdast and the groups recognition builds.\ninterface GroupTreeNode {\n type: string;\n children?: GroupTreeNode[];\n position?: Paragraph[\"position\"];\n data?: unknown;\n}\n\n/** Blocks whose lines carry one more `>` marker than the block around them: a blockquote (or an alert, Sätteri's node for one) and a tab panel or step body. */\nexport const MARKED_BLOCKS: ReadonlySet<string> = new Set([\n `blockquote`,\n `alert`,\n `tabsItem`,\n `stepsItem`\n]);\n\n/** Blocks a line can lazily continue into by its indentation rather than its markers: a list item or a definition. */\nexport const INDENTED_BLOCKS: ReadonlySet<string> = new Set([\n `listItem`,\n `defListDescription`,\n `descriptionDetails`\n]);\n\n/**\n * A paragraph split before its first line (after its first) that `opens` a group, written at the paragraph's level (`quotes` `>` markers), as markdown-it's block rules interrupt a paragraph; `null` when there's none. Attributes ending the paragraph go with the part they end.\n */\nexport const splitAtOpeningLine = (\n para: Paragraph,\n sourceLines: readonly string[],\n quotes: number,\n opens: (text: string) => boolean\n): Paragraph[] | null => {\n const start = para.position?.start.line;\n if (start === undefined) return null;\n const lines = paraToLines(para, sourceLines);\n const at = lines.findIndex((line, index) => {\n const first = line[0];\n return (\n index > 0 &&\n first?.type === `text` &&\n opens(first.value) &&\n markerCount(sourceLines[start - 1 + index] ?? ``) === quotes\n );\n });\n if (at === -1) return null;\n const head = linesToParagraph(lines.slice(0, at));\n const tail = linesToParagraph(lines.slice(at));\n if (!head || !tail) return null;\n if (para.data) tail.data = para.data;\n return [head, tail];\n};\n\n// The paragraph a lazily continued line can end up in: the deepest last block, through lists, items and quotes.\nconst lastParagraph = (\n node: GroupTreeNode | undefined\n): Paragraph | undefined => {\n const last = node?.children?.at(-1);\n if (!last) return undefined;\n // A paragraph of the tree, which the loose node shape doesn't name.\n // oxlint-disable-next-line typescript/no-unsafe-type-assertion\n if (last.type === `paragraph`) return last as unknown as Paragraph;\n return lastParagraph(last);\n};\n\n/**\n * End each group of `listType` (tab groups or steps) where its last panel's `>` markers stop, as markdown-it reads a panel: a line CommonMark lazily continued into the panel's last paragraph, written with fewer markers than the panel's own lines, starts a paragraph after the group, with the lines after it. Groups nested in a panel are ended first, so a line that leaves an outer panel too moves on past its group. The paragraph's attributes (Sätteri reads them off its end) go with its last line.\n */\nexport const endGroupsAtMarkers = (\n root: { children: unknown[] },\n sourceLines: readonly string[],\n listType: `tabsList` | `stepsList`\n): void => {\n const visit = (node: GroupTreeNode, quotes: number): void => {\n const children = node.children;\n if (!children) return;\n for (let i = 0; i < children.length; i++) {\n const child = children[i]!;\n visit(child, quotes + (MARKED_BLOCKS.has(child.type) ? 1 : 0));\n if (child.type !== listType) continue;\n const para = lastParagraph(child.children?.at(-1));\n const start = para?.position?.start.line;\n if (!para || start === undefined) continue;\n const lines = paraToLines(para, sourceLines);\n // The panel's lines carry one more marker than the blocks around the group.\n const outside = lines.findIndex(\n (_, index) =>\n index > 0 &&\n markerCount(sourceLines[start - 1 + index] ?? ``) < quotes + 1\n );\n if (outside === -1) continue;\n const kept = linesToParagraph(lines.slice(0, outside));\n const moved = linesToParagraph(lines.slice(outside));\n if (!kept || !moved) continue;\n para.children = kept.children;\n const data: { hProperties?: Properties } | undefined = para.data;\n if (data?.hProperties) {\n const { hProperties, ...rest } = data;\n const movedData: { hProperties?: Properties } = { hProperties };\n moved.data = movedData;\n para.data = rest;\n }\n // An mdast paragraph, in the loose node shape the pass walks.\n // oxlint-disable-next-line typescript/no-unsafe-type-assertion\n children.splice(i + 1, 0, moved as unknown as GroupTreeNode);\n }\n };\n // The tree, in the loose node shape the pass walks.\n // oxlint-disable-next-line typescript/no-unsafe-type-assertion\n visit(root as GroupTreeNode, 0);\n};\n","// Which blocks a line is written in, by its source prefix: a line that lazily continues a paragraph has fewer `>` markers, or less indentation, than the blocks around that paragraph. The same rule as mdit-attrs' and remd-attrs' own-line attributes, for the plugins in this module's callers.\n\n/**\n * A block a line can be written in, outermost first: a blockquote (or another block written with `>` markers, such as a tab panel), by how many `>` markers lead up to its own, or a list item (or a definition), by the column its content starts at.\n */\nexport type LineContainer =\n | { kind: `quote`; markers: number }\n | { kind: `item`; column: number };\n\n/**\n * How many of `containers`, outermost first, a line is written in. Tabs count as one column.\n */\nexport const containersKept = (\n line: string,\n containers: readonly LineContainer[]\n): number => {\n const prefix = /^[ \\t>]*/.exec(line)?.[0] ?? ``;\n const markers = prefix.split(`>`).length - 1;\n let kept = 0;\n for (const container of containers) {\n if (\n container.kind === `quote`\n ? markers < container.markers\n : prefix.length < container.column\n )\n break;\n kept++;\n }\n return kept;\n};\n\n/**\n * The columns the content of the list items opened on a line starts at, in the order they open, as CommonMark reads a list marker: up to four spaces after it belong to the marker, more start indented content one column after.\n */\nexport const itemColumns = (line: string): number[] => {\n const columns: number[] = [];\n let pos = 0;\n for (;;) {\n while (line[pos] === ` ` || line[pos] === `\\t`) pos++;\n if (line[pos] === `>`) {\n pos++;\n continue;\n }\n const marker = /^(?:[-+*]|\\d{1,9}[.)])(?=[ \\t]|$)/.exec(line.slice(pos));\n if (!marker) return columns;\n const end = pos + marker[0].length;\n let spaces = 0;\n while (line[end + spaces] === ` ` || line[end + spaces] === `\\t`) spaces++;\n const column =\n end + spaces === line.length || spaces > 4 ? end + 1 : end + spaces;\n columns.push(column);\n if (spaces > 4) return columns;\n pos = column;\n }\n};\n","// Captions (`~: caption` on the line right after a block), shared by the markdown-it, remark and Sätteri plugins. CommonMark parses a caption line differently depending on what it follows: after a fence it starts a paragraph of its own; after an image, or lazily after a blockquote or list, it continues the paragraph before it; after a table it's a row. So the plugins find caption lines by their source, and the `>` markers and indentation a line is written with decide which block it captions, as attrs places a block on a line of its own. `processCaptions` does this for an mdast tree (remark, and Sätteri through `editableTree`); markdown-it shares the line rules.\n// Recognition walks mdast and the custom nodes other plugins build (tab groups, steps, alerts) through one loose node shape; the assertions bridging it and mdast's types are reviewed and intentional.\n/* oxlint-disable typescript/no-unsafe-type-assertion */\nimport type { PhrasingContent, Root } from \"mdast\";\nimport type { Properties } from \"hast\";\nimport { isAlertMarkerLine } from \"./github-alerts/index.js\";\nimport { linesToParagraph, paraToLines } from \"./lazy.js\";\nimport { containersKept, type LineContainer } from \"./line-containers.js\";\n\n/** The class of the `<figure>` a caption wraps its block in. */\nexport const CAPTION_CLASS = \"markdown-caption\";\n\n/** Whether a source line is a caption line: `~:`, whitespace and the caption's first word after its `>` markers and indentation. An escaped `\\~:` isn't one, nor is a marker with nothing after it. */\nexport const isCaptionLine = (line: string): boolean =>\n /^~:[ \\t]+\\S/.test(line.replace(/^[ \\t>]*/, ``));\n\n/** Whether text starts with a caption marker, as a parser gives a caption line's text (inline markdown may follow in other nodes). */\nexport const startsCaption = (text: string): boolean =>\n /^~:(?:[ \\t]|$)/.test(text);\n\n/** The text after a caption marker. */\nexport const stripCaptionMarker = (text: string): string =>\n text.replace(/^~:[ \\t]*/, ``);\n\n/**\n * Blocks a caption doesn't attach to, by mdast (and custom node) type: a caption after them stays text. Headings, thematic breaks, raw HTML, definitions and front matter, another caption's figure, and the parts of containers that aren't blocks of their own (titles, labels, terms).\n */\nconst UNCAPTIONED = new Set([\n `heading`,\n `thematicBreak`,\n `html`,\n `definition`,\n `footnoteDefinition`,\n `yaml`,\n `toml`,\n `figure`,\n `alertTitle`,\n `stepsTitle`,\n `tabsLabel`,\n `tabsLabels`,\n `tabsInput`,\n `defListTerm`,\n `descriptionTerm`\n]);\n\n/** The properties of a caption's `<figure>`: its class, then the attributes written at the end of the caption (a class joins it). */\nexport const figureProperties = (author?: Properties): Properties => {\n const {\n class: extraClass,\n className: extraClassName,\n ...rest\n } = author ?? {};\n const extra = [extraClass, extraClassName]\n .flat()\n .flatMap((value) => (typeof value === `string` ? value.split(` `) : []))\n .filter((value) => value !== ``);\n return { className: [CAPTION_CLASS, ...extra], ...rest };\n};\n\ninterface Point {\n line: number;\n column: number;\n}\ninterface Node {\n type: string;\n children?: Node[];\n position?: { start: Point; end: Point };\n data?: { hProperties?: Properties } & Record<string, unknown>;\n value?: string;\n}\n\nconst WHITESPACE = /^\\s*$/;\n\n// Only images (each possibly inside a link) and whitespace: the figure holds them directly, as an image alone in its paragraph is the figure.\n// A lightbox's `!` marker (what `!![alt](src)` leaves before its image) counts as part of the image, so a lightbox's trigger is the figure's content too.\nconst onlyImages = (children: readonly Node[]): boolean =>\n children.some((child) => child.type !== `text`) &&\n children.every(\n (child, index) =>\n child.type === `image` ||\n (child.type === `text` &&\n (WHITESPACE.test(child.value ?? ``) ||\n (/^\\s*!$/.test(child.value ?? ``) &&\n children[index + 1]?.type === `image`))) ||\n (child.type === `link` &&\n (child.children ?? []).length > 0 &&\n (child.children ?? []).every((inner) => inner.type === `image`))\n );\n\nconst figure = (\n content: Node[],\n caption: PhrasingContent[],\n author: Properties | undefined\n): Node => ({\n type: `figure`,\n data: { hName: `figure`, hProperties: figureProperties(author) },\n children: [\n ...content,\n {\n type: `figcaption`,\n data: { hName: `figcaption` },\n children: caption as unknown as Node[]\n }\n ]\n});\n\n// A caption's lines as phrasing content, without the marker on the first.\nconst captionContent = (lines: PhrasingContent[][]): PhrasingContent[] => {\n const first = lines[0]?.[0];\n if (first?.type === `text`) {\n const value = stripCaptionMarker(first.value);\n lines[0] = value\n ? [{ ...first, value }, ...lines[0]!.slice(1)]\n : lines[0]!.slice(1);\n }\n return linesToParagraph(lines)?.children ?? [];\n};\n\n// The attributes a node carries, removed from it: those written at the end of a caption go on its figure.\nconst takeProperties = (node: Node): Properties | undefined => {\n const data = node.data;\n if (!data?.hProperties) return undefined;\n const { hProperties, ...rest } = data;\n node.data = rest;\n return hProperties;\n};\n\n/**\n * Wrap each captioned block of an mdast tree, with its caption, in a `figure` node (`hName: \"figure\"`, class `markdown-caption`) whose last child is a `figcaption` node. `source` is the document the tree was parsed from: caption lines are found, and placed, by their source lines.\n */\nexport const processCaptions = (root: Root, source: string): void => {\n if (!source.includes(`~:`)) return;\n const sourceLines = source.split(/\\r?\\n/);\n const parents = new Map<Node, Node>();\n const paragraphs: Node[] = [];\n const tables: Node[] = [];\n const walk = (node: Node): void => {\n if (node.type === `paragraph`) paragraphs.push(node);\n else if (node.type === `table`) tables.push(node);\n for (const child of node.children ?? []) {\n parents.set(child, node);\n walk(child);\n }\n };\n walk(root as unknown as Node);\n\n const replace = (node: Node, replacement: Node | null): void => {\n const parent = parents.get(node);\n const siblings = parent?.children;\n if (!parent || !siblings) return;\n const index = siblings.indexOf(node);\n if (index === -1) return;\n if (replacement) {\n siblings.splice(index, 1, replacement);\n parents.set(replacement, parent);\n parents.set(node, replacement);\n } else siblings.splice(index, 1);\n };\n const captioned = (node: Node): boolean =>\n parents.get(node)?.type === `figure`;\n\n const ancestorsOf = (node: Node): Node[] => {\n const ancestors: Node[] = [];\n for (let p = parents.get(node); p; p = parents.get(p)) ancestors.unshift(p);\n return ancestors;\n };\n\n // The blocks around a node a line can be written outside of, outermost first, with the block a caption written outside each goes on: a blockquote or alert itself, a tab panel's group, a step body's steps, a list item's list, a definition's list. `undefined` when a list item's content has no position to measure.\n const containersOf = (\n ancestors: readonly Node[]\n ): Array<{ target: Node; line: LineContainer }> | undefined => {\n const containers: Array<{ target: Node; line: LineContainer }> = [];\n const nearest = (index: number, type: string): Node | undefined =>\n ancestors\n .slice(0, index)\n .reverse()\n .find((a) => a.type === type);\n let quotes = 0;\n for (const [index, ancestor] of ancestors.entries()) {\n const quote = (target: Node | undefined): void => {\n containers.push({\n target: target ?? ancestor,\n line: { kind: `quote`, markers: ++quotes }\n });\n };\n switch (ancestor.type) {\n case `blockquote`:\n case `alert`:\n quote(ancestor);\n break;\n // A tab panel (remark builds `tabsItem`, Sätteri renders `tabsPanel`).\n case `tabsItem`:\n case `tabsPanel`:\n quote(nearest(index, `tabsList`));\n break;\n // A step body (Sätteri renders it as `stepsBody` inside its item).\n case `stepsItem`:\n if (!(ancestor.children ?? []).some((c) => c.type === `stepsBody`))\n quote(nearest(index, `stepsList`));\n break;\n case `stepsBody`:\n quote(nearest(index, `stepsList`));\n break;\n case `listItem`:\n case `defListDescription`:\n case `descriptionDetails`: {\n const column = ancestor.children?.[0]?.position?.start.column;\n if (column === undefined) return undefined;\n containers.push({\n target: ancestors[index - 1] ?? ancestor,\n line: { kind: `item`, column: column - 1 }\n });\n break;\n }\n default:\n }\n }\n return containers;\n };\n\n // Tables: a caption line is a row of its own; it and the rows after it are the caption.\n for (const table of tables) {\n const rows = table.children ?? [];\n const first = rows.findIndex((row, index) => {\n const line = row.position?.start.line;\n const text = row.children?.[0]?.children?.[0];\n return (\n index > 0 &&\n line !== undefined &&\n isCaptionLine(sourceLines[line - 1] ?? ``) &&\n text?.type === `text` &&\n startsCaption(text.value ?? ``)\n );\n });\n if (first === -1) continue;\n const captionRows = rows.slice(first);\n const lastCell = captionRows.at(-1)?.children?.[0];\n const author = lastCell ? takeProperties(lastCell) : undefined;\n const caption = captionContent(\n captionRows.map(\n (row) =>\n (row.children?.[0]?.children ?? []) as unknown as PhrasingContent[]\n )\n );\n table.children = rows.slice(0, first);\n replace(table, figure([table], caption, author));\n }\n\n // Paragraphs, innermost and last first, so a figure made inside a block is in place before the block is wrapped.\n for (const para of paragraphs.reverse()) {\n const first = para.position?.start.line;\n if (first === undefined) continue;\n const lines = paraToLines(\n para as unknown as Parameters<typeof paraToLines>[0],\n sourceLines\n );\n // Each line is one source line. An alert's first paragraph lost its marker line (`> [!NOTE]`) to the alert, which leaves its start there.\n const parent = parents.get(para);\n const alert =\n parent?.type === `alert` ||\n (parent?.type === `blockquote` && parent.data?.alertType !== undefined);\n const start =\n alert && isAlertMarkerLine(sourceLines[first - 1] ?? ``)\n ? first + 1\n : first;\n const isCaptionAt = (index: number): boolean => {\n const text = lines[index]?.[0];\n return (\n isCaptionLine(sourceLines[start + index - 1] ?? ``) &&\n text?.type === `text` &&\n startsCaption(text.value)\n );\n };\n\n // A paragraph that is a caption: it captions the block right before it, on the line above.\n if (isCaptionAt(0)) {\n const parent = parents.get(para);\n const siblings = parent?.children ?? [];\n const before = siblings[siblings.indexOf(para) - 1];\n const above = sourceLines[start - 2];\n if (\n !before ||\n UNCAPTIONED.has(before.type) ||\n above === undefined ||\n above.replace(/^[ \\t>]*/, ``) === ``\n )\n continue;\n const author = takeProperties(para);\n replace(para, null);\n replace(before, figure([before], captionContent(lines), author));\n continue;\n }\n\n // A caption line inside the paragraph: the paragraph, or a block around it the line is written outside of.\n let containers: Array<{ target: Node; line: LineContainer }> | undefined;\n const segments: Array<{ index: number; kept: number; target: Node }> = [];\n for (let index = 1; index < lines.length; index++) {\n if (!isCaptionAt(index)) continue;\n containers ??= containersOf(ancestorsOf(para));\n if (!containers) break;\n const kept = containersKept(\n sourceLines[start + index - 1] ?? ``,\n containers.map((c) => c.line)\n );\n // A caption line at the same level or deeper continues the caption; one written outside more blocks starts the caption of the one it leaves.\n const previous = segments.at(-1);\n if (previous && kept >= previous.kept) continue;\n const target = containers[kept]?.target ?? para;\n if (captioned(target)) continue;\n segments.push({ index, kept, target });\n }\n if (segments.length === 0) continue;\n\n const head = lines.slice(0, segments[0]!.index);\n // A hard break ending the line before a caption ends the paragraph instead.\n const lastLine = head.at(-1);\n if (lastLine?.at(-1)?.type === `break`)\n head[head.length - 1] = lastLine.slice(0, -1);\n para.children = (linesToParagraph(head)?.children ??\n []) as unknown as Node[];\n const author = takeProperties(para);\n for (const [i, segment] of segments.entries()) {\n const caption = captionContent(\n lines.slice(segment.index, segments[i + 1]?.index)\n );\n // Attributes ending the paragraph end its last caption.\n const properties = i === segments.length - 1 ? author : undefined;\n const { target } = segment;\n if (target === para && onlyImages(para.children ?? []))\n replace(para, figure(para.children ?? [], caption, properties));\n else replace(target, figure([target], caption, properties));\n }\n }\n};\n","// Logic shared by the rehype and Sätteri hast plugins, so both compute the same result: which paragraphs are empty or hold only images, how headings divide a document into sections, and the lightbox's marker, ids and markup. The plugins apply it with their own tree operations.\n\nimport { CAPTION_CLASS } from \"./caption.js\";\n\n/** The shape of a hast node this module reads and builds. */\nexport interface HastLike {\n type: string;\n tagName?: string;\n value?: string;\n properties?: Record<string, unknown>;\n children?: readonly HastLike[];\n}\n\n/** A hast element as this module builds it; its properties fit hast's `Properties`. */\nexport interface HastElementLike<C> {\n type: `element`;\n tagName: string;\n properties: Record<string, string | string[]>;\n children: C[];\n}\n\n// hast-util-whitespace: only the inter-element whitespace characters.\nconst WHITESPACE = /^[ \\t\\n\\f\\r]*$/;\nconst isWhitespaceText = (node: HastLike): boolean =>\n node.type === `text` && WHITESPACE.test(node.value ?? ``);\n\n/** A `<p>` with no children, or only whitespace text: squeeze-paragraphs removes it. */\nexport const isEmptyParagraph = (node: HastLike): boolean =>\n node.tagName === `p` && (node.children ?? []).every(isWhitespaceText);\n\n/**\n * A `<p>` whose content is only images (each possibly inside a link or a lightbox button) and whitespace: unwrap-images replaces it with its children.\n */\nexport const isImageParagraph = (node: HastLike): boolean => {\n // `image`: an image was found; `empty`: nothing but whitespace yet; `other`: anything else.\n const scan = (\n parent: HastLike,\n inLink: boolean\n ): `image` | `empty` | `other` => {\n let result: `image` | `empty` = `empty`;\n for (const child of parent.children ?? []) {\n if (isWhitespaceText(child)) continue;\n if (child.type !== `element`) return `other`;\n if (child.tagName === `img`) {\n result = `image`;\n continue;\n }\n if (!inLink && (child.tagName === `a` || child.tagName === `button`)) {\n const inner = scan(child, true);\n if (inner === `other`) return `other`;\n if (inner === `image`) result = `image`;\n continue;\n }\n return `other`;\n }\n return result;\n };\n return node.tagName === `p` && scan(node, false) === `image`;\n};\n\n/** The rank of an `h1`–`h6` element, or `undefined`. */\nexport const headingRank = (node: HastLike): number | undefined => {\n if (node.type !== `element`) return undefined;\n const match = /^h([1-6])$/i.exec(node.tagName ?? ``);\n return match ? Number(match[1]) : undefined;\n};\n\n/**\n * Wrap heading-delimited runs of `nodes` into `<section data-depth>` elements, nesting deeper headings inside shallower ones. Content before the first heading stays unwrapped.\n */\nexport const sectionize = <N extends HastLike>(\n nodes: readonly N[],\n section: (depth: number, children: N[]) => N,\n floor = 0\n): N[] => {\n // Shallowest heading rank deeper than the floor.\n let minRank = Infinity;\n for (const node of nodes) {\n const rank = headingRank(node);\n if (rank !== undefined && rank > floor && rank < minRank) minRank = rank;\n }\n if (minRank === Infinity) return [...nodes];\n\n const result: N[] = [];\n let i = 0;\n // Preamble: everything before the first heading of the shallowest rank.\n for (; i < nodes.length; i++) {\n const node = nodes[i];\n if (!node || headingRank(node) === minRank) break;\n result.push(node);\n }\n // Each shallowest heading starts a section that runs until the next peer.\n while (i < nodes.length) {\n const start = i;\n for (i++; i < nodes.length; i++) {\n const node = nodes[i];\n if (!node || headingRank(node) === minRank) break;\n }\n result.push(\n section(minRank, sectionize(nodes.slice(start, i), section, minRank))\n );\n }\n return result;\n};\n\n/**\n * The lightbox opt-in: an image directly after a text run that ends in a `!` at a boundary (start of the run or after whitespace), which is what `!![alt](src)` leaves behind.\n */\nexport const LIGHTBOX_MARKER = /(?:^|\\s)!$/;\n\n/**\n * A short, stable lightbox id from an image src (FNV-1a, base36): the same image always gets the same id, so repeated references share one dialog.\n */\nexport const lightboxId = (src: string): string => {\n let hash = 2166136261;\n for (let i = 0; i < src.length; i += 1) {\n hash ^= src.charCodeAt(i);\n hash = Math.imul(hash, 16777619);\n }\n return `markdown-lightbox-${(hash >>> 0).toString(36)}`;\n};\n\n/** The button that replaces an opted-in image and opens its dialog. */\nexport const lightboxTrigger = <C>(\n id: string,\n image: C\n): HastElementLike<C> => ({\n type: `element`,\n tagName: `button`,\n properties: {\n type: `button`,\n className: [`markdown-lightbox-trigger`],\n command: `show-modal`,\n commandfor: id\n },\n children: [image]\n});\n\n/** The modal dialog, appended at the document end, showing the image full size, and its caption under it when one is given. */\nexport const lightboxDialog = <C>(\n id: string,\n image: C,\n caption?: C[]\n): HastElementLike<HastElementLike<C>> => ({\n type: `element`,\n tagName: `dialog`,\n properties: { id, className: [`markdown-lightbox`], closedby: `any` },\n children: [\n {\n type: `element`,\n tagName: `button`,\n properties: {\n type: `button`,\n className: [`markdown-lightbox-close`],\n command: `close`,\n commandfor: id,\n ariaLabel: `Close image`\n },\n children: [image]\n },\n ...(caption\n ? [\n {\n type: `element` as const,\n tagName: `p`,\n properties: { className: [`markdown-lightbox-caption`] },\n children: caption\n }\n ]\n : [])\n ]\n});\n\n/** Whether a node is a caption's figure (`<figure class=\"markdown-caption\">`, as the caption plugins make): an image that is its content shows the figure's caption in its lightbox dialog, with the `caption` option. */\nexport const isCaptionFigure = (node: HastLike | undefined): boolean => {\n const className = node?.properties?.className;\n return (\n node?.tagName === `figure` &&\n Array.isArray(className) &&\n className.includes(CAPTION_CLASS)\n );\n};\n","// Abbreviation rules shared by the remark and Sätteri plugins: which paragraphs define abbreviations, and how a text value splits around the defined terms.\n\nconst DEFINITION = /^\\*\\[([^[\\]]+)\\]:\\s*(.+)$/;\nconst REGEX_SPECIAL = /[.*+?^${}()|[\\]\\\\]/g;\n\n/**\n * The `[term, title]` pairs a paragraph's text defines, when every line of it is a `*[term]: title` definition; otherwise `undefined` (the paragraph is ordinary text).\n */\nexport const parseAbbreviations = (\n text: string\n): Array<[string, string]> | undefined => {\n const definitions: Array<[string, string]> = [];\n for (const line of text.split(`\\n`)) {\n const match = DEFINITION.exec(line);\n if (!match) return undefined;\n definitions.push([match[1] ?? ``, (match[2] ?? ``).trim()]);\n }\n return definitions;\n};\n\n/** A piece of text: plain, or a defined term with its title. */\nexport type AbbreviationPart =\n | { text: string }\n | { term: string; title: string };\n\n/**\n * Build the scan for a document's abbreviations. Terms match on word boundaries, longest first; the scan returns the pieces of a text value, or `undefined` when it holds no term.\n */\nexport const createAbbreviationScan = (\n abbreviations: ReadonlyMap<string, string>\n): ((value: string) => AbbreviationPart[] | undefined) => {\n const terms = [...abbreviations.keys()]\n .sort((a, b) => b.length - a.length)\n .map((term) => term.replace(REGEX_SPECIAL, `\\\\$&`));\n const pattern = new RegExp(`\\\\b(${terms.join(`|`)})\\\\b`, `g`);\n return (value) => {\n const parts: AbbreviationPart[] = [];\n let last = 0;\n for (const match of value.matchAll(pattern)) {\n const term = match[1] ?? ``;\n if (match.index > last)\n parts.push({ text: value.slice(last, match.index) });\n parts.push({ term, title: abbreviations.get(term) ?? `` });\n last = match.index + term.length;\n }\n if (parts.length === 0) return undefined;\n if (last < value.length) parts.push({ text: value.slice(last) });\n return parts;\n };\n};\n","// Recognition for numbered step sequences, shared by the remark and Sätteri plugins: header lines (`@1. Title`) and their `>` bodies become `stepsList`/`stepsItem` nodes, which each engine then renders. It rewrites mdast in place, so a read-only engine runs it on a copy.\n// This module performs heavy tree-rewriting across mdast/hast types that don't unify cleanly; type assertions bridging those boundaries are reviewed and intentional, so the rule is disabled file-wide rather than per-cast. Defensive optional chains on array[i] accesses are also kept because TS doesn't model index access as fallible.\n/* oxlint-disable typescript/no-unsafe-type-assertion */\n/* oxlint-disable typescript/no-unnecessary-condition */\nimport type {\n Root,\n Paragraph,\n Blockquote,\n PhrasingContent,\n BlockContent,\n DefinitionContent\n} from \"mdast\";\nimport type { Properties } from \"hast\";\nimport {\n blockquoteMarkers,\n endGroupsAtMarkers,\n INDENTED_BLOCKS,\n MARKED_BLOCKS,\n splitAtOpeningLine,\n linesToParagraph,\n markerCount,\n paragraphProperties,\n paraToLines,\n rebuildLazyLines,\n type MarkedLine\n} from \"./lazy.js\";\nimport { isAlertMarkerLine } from \"./github-alerts/index.js\";\n\n// Groups: 1=@ string (depth), 2=number, 3=rest of line (may be empty or title text)\nconst STEP_HEADER_RE = /^(@{1,6})(\\d+)\\. ?(.*)/s;\n\n// ── MDAST node types ──────────────────────────────────────────────────────────\n\n/** A list of steps at one depth, rendered as an `<ol>`. */\nexport interface StepsListNode {\n type: \"stepsList\";\n depth: number;\n containerClass?: string;\n /** A group written in a step's body (`@1.` with the body's `>`), which renders in the body, rather than the step's `@@` sub-steps. */\n inBody?: boolean;\n children: StepsItemNode[];\n data?: { attrsRole?: string; hProperties?: Properties };\n}\n\n/** A step's title, rendered as its title `<p>` unless it is empty. */\nexport interface StepsTitleNode {\n type: \"stepsTitle\";\n children: PhrasingContent[];\n}\n\n/** One step: its title (always the first child, so transforms that walk children reach it), body and nested steps, rendered as an `<li>`. */\nexport interface StepsItemNode {\n type: \"stepsItem\";\n depth: number;\n number: number;\n children: Array<\n StepsTitleNode | BlockContent | DefinitionContent | StepsListNode\n >;\n data?: {\n attrsRole?: string;\n attrsTitle?: PhrasingContent[];\n hProperties?: Properties;\n };\n}\n\n// ── Parser helpers ────────────────────────────────────────────────────────────\n\ninterface ParsedHeader {\n depth: number;\n number: number;\n rest: string;\n}\n\nconst parseHeaderPrefix = (text: string): ParsedHeader | null => {\n const m = STEP_HEADER_RE.exec(text);\n if (!m) return null;\n const [, hashes = \"\", digits = \"\", rest = \"\"] = m;\n return { depth: hashes.length, number: parseInt(digits, 10), rest };\n};\n\n// ── Raw step types ────────────────────────────────────────────────────────────\n\ninterface RawStep {\n depth: number;\n number: number;\n titleNodes: PhrasingContent[];\n body: Array<BlockContent | DefinitionContent>;\n // Attributes the parser read off the end of the header's paragraph, when the header ended it (Sätteri).\n hProperties?: Properties | undefined;\n}\n\n// ── Paragraph line splitting ──────────────────────────────────────────────────\n\n// ── Header paragraph extraction ───────────────────────────────────────────────\n\n// Extract step headers from a paragraph where every line is an @N. header.\n// Mutates `counters` in place so call sites share counter state across siblings.\n// A depth-skipping or non-header line ends the group: the steps before it are\n// returned with that line and the ones after it as `rest`, to be rendered as an\n// ordinary paragraph after the list.\n// requireDepthOne: first header must be depth 1.\ninterface HeaderPara {\n steps: RawStep[];\n rest: PhrasingContent[][];\n restLine: number;\n}\n\nconst extractHeaderPara = (\n para: Paragraph,\n counters: Map<number, number>,\n requireDepthOne = true,\n prevDepth = 0\n): HeaderPara | null => {\n const lines = paraToLines(para);\n const steps: RawStep[] = [];\n let currentDepth = prevDepth;\n const stop = (index: number): HeaderPara | null =>\n steps.length > 0\n ? {\n steps,\n rest: lines.slice(index),\n restLine: (para.position?.start.line ?? 1) + index\n }\n : null;\n\n for (const [index, lineSegs] of lines.entries()) {\n const first = lineSegs[0];\n if (first?.type !== \"text\") return stop(index);\n\n const header = parseHeaderPrefix(first.value);\n if (!header) return stop(index);\n\n const { depth } = header;\n if (steps.length === 0 && requireDepthOne && depth !== 1) return null;\n if (depth > currentDepth + 1) return stop(index);\n\n for (const k of counters.keys()) if (k > depth) counters.delete(k);\n const number = (counters.get(depth) ?? 0) + 1;\n counters.set(depth, number);\n currentDepth = depth;\n\n const titleNodes: PhrasingContent[] = header.rest\n ? [{ type: \"text\", value: header.rest }, ...lineSegs.slice(1)]\n : lineSegs.slice(1);\n\n steps.push({\n depth,\n number,\n titleNodes,\n body: [],\n ...(index === lines.length - 1\n ? { hProperties: paragraphProperties(para) }\n : {})\n });\n }\n\n return stop(lines.length);\n};\n\n// Lines left over after a group ends become ordinary paragraphs, split before\n// every line that opens a new group (a depth-1 header), so the main loop can\n// start that group. Positions follow the source lines (paragraph lines map 1:1\n// to source lines) because group ids hash the start line.\nconst splitAtGroupStarts = (\n lines: PhrasingContent[][],\n firstLine: number\n): Paragraph[] => {\n const paragraphs: Paragraph[] = [];\n let start = 0;\n const flush = (end: number): void => {\n const para = linesToParagraph(lines.slice(start, end));\n if (!para) return;\n para.position = {\n start: { line: firstLine + start, column: 1 },\n end: { line: firstLine + end - 1, column: 1 }\n };\n paragraphs.push(para);\n };\n lines.forEach((line, index) => {\n const first = line[0];\n const opens =\n first?.type === \"text\" && parseHeaderPrefix(first.value)?.depth === 1;\n if (opens && index > start) {\n flush(index);\n start = index;\n }\n });\n flush(lines.length);\n return paragraphs;\n};\n\n// ── Blockquote splitting ──────────────────────────────────────────────────────\n\n// Remark absorbs adjacent non-blank lines after the first @paragraph into one\n// blockquote. We split that blockquote on any embedded @N. step header lines.\ninterface BQSegment {\n header: Omit<RawStep, \"body\"> | null; // null = pre-header content (goes to previous step)\n body: Array<BlockContent | DefinitionContent>;\n}\n\ninterface ParentLike {\n type: string;\n children?: ParentLike[];\n}\n\n// CommonMark lets a line without a blockquote's `>` markers continue the paragraph before it, so lines meant for the next step can end up in a paragraph nested in a step's body (in a deeper blockquote or a list item), where markdown-it reads them by their markers instead. From the deepest last paragraph of `node`, take the lines from the first one written outside the step body (with fewer markers than the body's own, `base`) that `isHeader` accepts; the paragraph is cut before it, in place.\nconst takeLazyLines = (\n node: BlockContent | DefinitionContent,\n sourceLines: readonly string[],\n base: number,\n isHeader: (segs: PhrasingContent[]) => boolean\n): MarkedLine[] | null => {\n let parent = node as unknown as ParentLike;\n let last = parent.children?.at(-1);\n while (last?.type !== \"paragraph\") {\n if (!last?.children?.length) return null;\n parent = last;\n last = parent.children?.at(-1);\n }\n const para = last as unknown as Paragraph;\n const start = para.position?.start.line;\n if (start === undefined || !parent.children) return null;\n const lines = paraToLines(para, sourceLines).map(\n (segs, index): MarkedLine => ({\n segs,\n markers: markerCount(sourceLines[start - 1 + index] ?? \"\")\n })\n );\n const at = lines.findIndex(\n ({ segs, markers }, index) => index > 0 && markers < base && isHeader(segs)\n );\n if (at === -1) return null;\n const kept = linesToParagraph(lines.slice(0, at).map(({ segs }) => segs));\n parent.children.splice(\n -1,\n 1,\n ...(kept ? [kept as unknown as ParentLike] : [])\n );\n return lines.slice(at);\n};\n\nconst splitBlockquote = (\n bq: Blockquote,\n counters: Map<number, number>,\n currentDepth: number,\n sourceLines?: readonly string[]\n): BQSegment[] => {\n const segments: BQSegment[] = [];\n let currentSegment: BQSegment = { header: null, body: [] };\n // The `>` markers of the step body's own lines.\n const base = sourceLines ? blockquoteMarkers(bq, sourceLines) : undefined;\n\n // A line's step header, if it has one that fits the group's depth.\n const stepHeader = (lineSegs: PhrasingContent[]): ParsedHeader | null => {\n const first = lineSegs[0];\n if (first?.type !== \"text\") return null;\n const header = parseHeaderPrefix(first.value);\n return header && header.depth <= currentDepth + 1 ? header : null;\n };\n\n const startStep = (\n header: ParsedHeader,\n lineSegs: PhrasingContent[],\n hProperties?: Properties\n ): void => {\n segments.push(currentSegment);\n\n // Update counter tracking\n for (const k of counters.keys()) if (k > header.depth) counters.delete(k);\n const number = (counters.get(header.depth) ?? 0) + 1;\n counters.set(header.depth, number);\n currentDepth = header.depth;\n\n const titleNodes: PhrasingContent[] = header.rest\n ? [{ type: \"text\", value: header.rest }, ...lineSegs.slice(1)]\n : lineSegs.slice(1);\n\n currentSegment = {\n header: { depth: header.depth, number, titleNodes, hProperties },\n body: []\n };\n };\n\n for (const child of bq.children) {\n if (child.type !== \"paragraph\") {\n currentSegment.body.push(child);\n if (!sourceLines || base === undefined) continue;\n const lazy = takeLazyLines(\n child,\n sourceLines,\n base,\n (segs) => stepHeader(segs) !== null\n );\n if (!lazy) continue;\n // The header and the lines after it: the steps they start, and those steps' bodies.\n let pending: MarkedLine[] = [];\n const flush = (): void => {\n const relative = pending.map((line) => ({\n ...line,\n markers: line.markers - base\n }));\n currentSegment.body.push(...rebuildLazyLines(relative, 0));\n pending = [];\n };\n for (const line of lazy) {\n const header = line.markers < base ? stepHeader(line.segs) : null;\n if (header) {\n flush();\n startStep(header, line.segs);\n } else {\n pending.push(line);\n }\n }\n flush();\n continue;\n }\n\n let bodyLines: PhrasingContent[][] = [];\n const lines = paraToLines(child, sourceLines);\n const first = child.position?.start.line;\n // A header written with the body's own `>` markers is the body's content (it can start a group of its own there), as markdown-it reads the body; only one written outside the body starts the next step.\n const outsideBody = (index: number): boolean =>\n !sourceLines ||\n base === undefined ||\n first === undefined ||\n markerCount(sourceLines[first - 1 + index] ?? \"\") < base;\n for (const [index, lineSegs] of lines.entries()) {\n const header = outsideBody(index) ? stepHeader(lineSegs) : null;\n if (header) {\n // Flush accumulated body lines\n const bodyPara = linesToParagraph(bodyLines);\n if (bodyPara) currentSegment.body.push(bodyPara);\n bodyLines = [];\n startStep(\n header,\n lineSegs,\n index === lines.length - 1 ? paragraphProperties(child) : undefined\n );\n continue;\n }\n bodyLines.push(lineSegs);\n }\n\n // These lines end the paragraph, so they keep its data: attributes the\n // parser read from its end (Sätteri's run before steps).\n const bodyPara = linesToParagraph(bodyLines);\n if (bodyPara && child.data) bodyPara.data = child.data;\n if (bodyPara) currentSegment.body.push(bodyPara);\n }\n\n segments.push(currentSegment);\n return segments;\n};\n\n// ── Tree builder ──────────────────────────────────────────────────────────────\n\nconst buildTree = (\n steps: RawStep[],\n targetDepth: number,\n start: number,\n end: number\n): StepsListNode => {\n const items: StepsItemNode[] = [];\n let i = start;\n\n while (i < end) {\n const s = steps[i];\n if (s?.depth !== targetDepth) {\n i++;\n continue;\n }\n\n let childEnd = i + 1;\n while (childEnd < end && (steps[childEnd]?.depth ?? 0) > targetDepth)\n childEnd++;\n\n // The title node shares `titleNodes` with `attrsTitle`, so attrs trimming one trims the other.\n const bodyChildren: StepsItemNode[\"children\"] = [\n { type: \"stepsTitle\", children: s.titleNodes },\n ...s.body\n ] as StepsItemNode[\"children\"];\n const hasDeeper = steps\n .slice(i + 1, childEnd)\n .some((ss) => ss.depth === targetDepth + 1);\n if (hasDeeper) {\n const nested = buildTree(steps, targetDepth + 1, i + 1, childEnd);\n bodyChildren.push(nested);\n }\n\n items.push({\n type: \"stepsItem\",\n depth: targetDepth,\n number: s.number,\n children: bodyChildren,\n data: {\n attrsRole: \"containerItem\",\n attrsTitle: s.titleNodes,\n ...(s.hProperties ? { hProperties: { ...s.hProperties } } : {})\n }\n });\n\n i = childEnd;\n }\n\n return {\n type: \"stepsList\",\n depth: targetDepth,\n children: items,\n data: { attrsRole: \"container\" }\n };\n};\n\n// ── Remark plugin ─────────────────────────────────────────────────────────────\n\n// Process all step groups found in a children array in-place.\n// Used at root level and recursively inside any parent node's children.\nexport const processStepsInChildren = (\n children: Array<BlockContent | DefinitionContent | Root[\"children\"][number]>,\n containerClass: string,\n sourceLines?: readonly string[],\n quotes = 0,\n parentType = \"root\"\n): void => {\n const newChildren: typeof children = [];\n let i = 0;\n\n while (i < children.length) {\n const node = children[i];\n if (!node) break;\n\n // A step header interrupts the paragraph before it, as markdown-it's block rule does, when it's written at the paragraph's own level (its `>` markers). In a list item or definition, a header line may instead be one CommonMark lazily continued, so those are left as they are.\n if (\n node.type === \"paragraph\" &&\n sourceLines &&\n !INDENTED_BLOCKS.has(parentType)\n ) {\n const split = splitAtOpeningLine(\n node,\n sourceLines,\n quotes,\n (text) => parseHeaderPrefix(text)?.depth === 1\n );\n if (split) {\n children.splice(i, 1, ...split);\n continue;\n }\n }\n\n if (node.type === \"paragraph\") {\n const counters = new Map<number, number>();\n const headerPara = extractHeaderPara(node, counters);\n\n if (headerPara) {\n const rawSteps: RawStep[] = [...headerPara.steps];\n // Lines left over after a depth-skipping or non-header line end the group.\n let rest = headerPara.rest;\n let restLine = headerPara.restLine;\n let j = i + 1;\n // A group always starts with at least one step.\n const lastStep = (): RawStep => rawSteps[rawSteps.length - 1]!;\n let currentStepIdx = rawSteps.length - 1;\n let currentDepth = lastStep().depth;\n\n while (rest.length === 0 && j < children.length) {\n const sibling = children[j];\n if (!sibling) break;\n\n if (sibling.type === \"blockquote\") {\n // An alert after a blank line is a block of its own, not more of the step's body.\n const line = sibling.position?.start.line;\n if (\n sourceLines &&\n line !== undefined &&\n isAlertMarkerLine(sourceLines[line - 1] ?? \"\")\n )\n break;\n const segments = splitBlockquote(\n sibling,\n counters,\n currentDepth,\n sourceLines\n );\n\n const firstSeg = segments[0];\n if (firstSeg?.header === null) {\n rawSteps[currentStepIdx]?.body.push(...firstSeg.body);\n }\n\n for (let s = 1; s < segments.length; s++) {\n const seg = segments[s];\n if (seg?.header) {\n rawSteps.push({ ...seg.header, body: seg.body });\n currentStepIdx = rawSteps.length - 1;\n currentDepth = seg.header.depth;\n }\n }\n\n j++;\n } else if (sibling.type === \"paragraph\") {\n const prevDepth = lastStep().depth;\n const contHeaders = extractHeaderPara(\n sibling,\n counters,\n false,\n prevDepth\n );\n if (contHeaders) {\n rawSteps.push(...contHeaders.steps);\n rest = contHeaders.rest;\n restLine = contHeaders.restLine;\n currentStepIdx = rawSteps.length - 1;\n currentDepth = lastStep().depth;\n j++;\n continue;\n }\n break;\n } else {\n break;\n }\n }\n\n const list = buildTree(rawSteps, 1, 0, rawSteps.length);\n list.containerClass = containerClass;\n if (parentType === \"stepsItem\") list.inBody = true;\n newChildren.push(list as unknown as Root[\"children\"][number]);\n children.splice(j, 0, ...splitAtGroupStarts(rest, restLine));\n i = j;\n continue;\n }\n }\n\n newChildren.push(node);\n i++;\n }\n\n children.splice(0, children.length, ...newChildren);\n};\n\ninterface Container {\n type?: string;\n children?: unknown[];\n}\n\n/**\n * Turn every step sequence in `root` into `stepsList` nodes, at the top level and inside any container (blockquotes, list items, tab panels…), walking into the lists it builds so nested sequences are found too. With the document's `source`, a step header that CommonMark lazily continued into a nested paragraph is recognized too, as markdown-it reads it.\n */\nexport const processSteps = (\n root: Root,\n containerClass: string,\n source?: string\n): void => {\n const sourceLines = source?.split(/\\r?\\n/);\n const walk = (node: Container, quotes: number): void => {\n if (!Array.isArray(node.children) || node.children.length === 0) return;\n const inner = quotes + (MARKED_BLOCKS.has(node.type ?? \"\") ? 1 : 0);\n processStepsInChildren(\n node.children as Array<BlockContent | DefinitionContent>,\n containerClass,\n sourceLines,\n inner,\n node.type\n );\n for (const child of node.children) walk(child as Container, inner);\n };\n processStepsInChildren(root.children, containerClass, sourceLines);\n for (const child of root.children) walk(child, 0);\n if (sourceLines) endGroupsAtMarkers(root, sourceLines, `stepsList`);\n};\n","// Recognition for tabbed content blocks, shared by the remark and Sätteri plugins: header lines (`% Label`) and their `>` bodies become `tabsList`/`tabsItem` nodes, which each engine then renders. It rewrites mdast in place, so a read-only engine runs it on a copy.\n// This module performs heavy tree-rewriting across mdast/unist types that don't unify cleanly; type assertions bridging those boundaries are reviewed and intentional, so the rule is disabled file-wide rather than per-cast. Defensive optional chains on array[i] accesses are also kept because TS doesn't model index access as fallible.\n/* oxlint-disable typescript/no-unsafe-type-assertion */\n/* oxlint-disable typescript/no-unnecessary-condition */\nimport type {\n Root,\n Paragraph,\n Blockquote,\n PhrasingContent,\n BlockContent,\n DefinitionContent,\n RootContent\n} from \"mdast\";\nimport type { Properties } from \"hast\";\nimport {\n blockquoteMarkers,\n endGroupsAtMarkers,\n INDENTED_BLOCKS,\n MARKED_BLOCKS,\n splitAtOpeningLine,\n linesToParagraph,\n markerCount,\n paragraphProperties,\n paraToLines,\n rebuildLazyLines,\n type MarkedLine\n} from \"./lazy.js\";\n\n// ── MDAST node types ──────────────────────────────────────────────────────────\n\n/** A group of tabs at one depth, rendered as the tabs container. */\nexport interface TabsListNode {\n type: \"tabsList\";\n depth: number;\n containerClass?: string;\n groupId: string;\n children: TabsItemNode[];\n data?: { attrsRole?: string; hProperties?: Properties };\n}\n\n/** A tab's label, rendered as its `<label>`. */\nexport interface TabsLabelNode {\n type: \"tabsLabel\";\n children: PhrasingContent[];\n}\n\n/** One tab: its label (always the first child, so transforms that walk children reach it), panel body and nested tabs. */\nexport interface TabsItemNode {\n type: \"tabsItem\";\n depth: number;\n labelText: string; // plain text of the label as recognized, for the group id\n open: boolean;\n children: Array<\n TabsLabelNode | BlockContent | DefinitionContent | TabsListNode\n >;\n data?: {\n attrsRole?: string;\n attrsTitle?: PhrasingContent[];\n attrsItemTitle?: boolean;\n hProperties?: Properties;\n };\n}\n\n// ── Header and ids ────────────────────────────────────────────────────────────\n\n// Matches: %{1,6}+? label text (prefix-plus form: %+ Label)\n// Groups: 1=% string (depth), 2=+ (open marker, optional), 3=label text\nconst TAB_HEADER_RE = /^(%{1,6})(\\+)? (.*)/;\n\ninterface ParsedTabHeader {\n depth: number;\n open: boolean;\n label: string;\n}\n\nconst parseTabHeader = (line: string): ParsedTabHeader | null => {\n const m = TAB_HEADER_RE.exec(line);\n if (!m) return null;\n const [, percents = \"\", plus, label = \"\"] = m;\n return { depth: percents.length, open: plus === \"+\", label };\n};\n\n// djb2 hash — returns an unsigned 32-bit integer\nconst djb2 = (str: string): number => {\n let h = 5381;\n for (let i = 0; i < str.length; i++) {\n h = ((h << 5) + h + str.charCodeAt(i)) >>> 0;\n }\n return h;\n};\n\n/** Strip a trailing attrs block like `{.class #id}` from plain label text, so attrs-consumed markers don't leak into `aria-label`. */\nexport const stripAttrs = (text: string): string =>\n text.replace(/\\s*\\{[^}]*\\}\\s*$/, \"\").trimEnd();\n\nconst slugify = (text: string): string =>\n text\n .toLowerCase()\n .trim()\n .replace(/[^\\w\\s-]/g, \"\")\n .replace(/[\\s_]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n\n// content-based: same label set → same id regardless of page position\nconst groupId = (labels: string[]): string => {\n const key = [...labels].map(slugify).sort().join(\"-\");\n return djb2(key).toString(16);\n};\n\n/**\n * A group's block id, unique on the page even when label sets match: its group id with the group's index among the document's tab groups, counted in the order they open (each nested group after the group around it), so every engine counts the same groups the same way.\n */\nexport const tabsBlockId = (index: number, groupId: string): string =>\n \"tabs-\" + djb2(`${index}:${groupId}`).toString(16);\n\n// ── Raw extraction types ──────────────────────────────────────────────────────\n\ninterface RawTab {\n depth: number;\n open: boolean;\n labelNodes: PhrasingContent[]; // inline nodes for the label\n labelText: string; // plain text for aria-label / data-tab\n body: Array<BlockContent | DefinitionContent>; // blockquote contents\n // Content after the tab's nested groups: headers in its explicit `> %` body that skip a level, kept as written.\n after?: Array<BlockContent | DefinitionContent>;\n // Attributes the parser read off the end of the header's paragraph, when the header ended it (Sätteri).\n hProperties?: Properties | undefined;\n}\n\n// ── Paragraph line splitting ──────────────────────────────────────────────────\n\n/** The plain text of a tab label (text and inline code; other markup contributes its text, images nothing), for its group id and `aria-label`. */\nexport const tabLabelText = (nodes: PhrasingContent[]): string =>\n nodes\n .map((n) => {\n if (n.type === \"text\" || n.type === \"inlineCode\")\n return \"value\" in n ? n.value : \"\";\n if (\"children\" in n) return tabLabelText(n.children);\n return \"\";\n })\n .join(\"\");\n\n// ── Tab group extraction ──────────────────────────────────────────────────────\n\n// Parse a paragraph node that consists entirely of % tab headers (no body\n// content). Returns null if the paragraph isn't all headers. A header that\n// skips a depth level ends the group: it and the lines after it are returned\n// as `rest`, to be rendered as an ordinary paragraph after the tabs.\n// requireDepthOne: if true, the first header must be depth 1 (top-level group start).\n// If false, allows any starting depth (for continuation paragraphs).\nconst extractHeaderPara = (\n para: Paragraph,\n requireDepthOne = true,\n prevDepth = 0\n): { tabs: RawTab[]; rest: PhrasingContent[][]; restLine: number } | null => {\n const lines = paraToLines(para);\n const tabs: RawTab[] = [];\n let currentDepth = prevDepth;\n\n for (const [index, lineSegs] of lines.entries()) {\n const first = lineSegs[0];\n if (first?.type !== \"text\") return null;\n\n const header = parseTabHeader(first.value);\n if (!header) return null;\n\n const { depth, open } = header;\n if (tabs.length === 0 && requireDepthOne && depth !== 1) return null;\n if (depth > currentDepth + 1) {\n return tabs.length > 0\n ? {\n tabs,\n rest: lines.slice(index),\n restLine: (para.position?.start.line ?? 1) + index\n }\n : null;\n }\n currentDepth = depth;\n\n const labelText = header.label;\n const labelNodes: PhrasingContent[] = labelText\n ? [{ type: \"text\", value: labelText }, ...lineSegs.slice(1)]\n : lineSegs.slice(1);\n\n tabs.push({\n depth,\n open,\n labelNodes,\n labelText: tabLabelText(labelNodes),\n body: [],\n ...(index === lines.length - 1\n ? { hProperties: paragraphProperties(para) }\n : {})\n });\n }\n\n return tabs.length > 0 ? { tabs, rest: [], restLine: 0 } : null;\n};\n\n// Lines left over after a group ends become ordinary paragraphs, split before\n// every line that opens a new group (a depth-1 header), so the main loop can\n// start that group. Positions follow the source lines (paragraph lines map 1:1\n// to source lines) because a group at the root ends at a blank line.\nconst splitAtGroupStarts = (\n lines: PhrasingContent[][],\n firstLine: number\n): Paragraph[] => {\n const paragraphs: Paragraph[] = [];\n let start = 0;\n const flush = (end: number): void => {\n const para = linesToParagraph(lines.slice(start, end));\n if (!para) return;\n para.position = {\n start: { line: firstLine + start, column: 1 },\n end: { line: firstLine + end - 1, column: 1 }\n };\n paragraphs.push(para);\n };\n lines.forEach((line, index) => {\n const first = line[0];\n const opens =\n first?.type === \"text\" && parseTabHeader(first.value)?.depth === 1;\n if (opens && index > start) {\n flush(index);\n start = index;\n }\n });\n flush(lines.length);\n return paragraphs;\n};\n\n// Split a blockquote node into segments separated by % tab header lines.\n// Each segment is { header: RawTab | null, body: blockquote-like children }.\n//\n// Remark absorbs adjacent non-blank lines into a blockquote, so:\n// % Tab One\n// > Content for tab one.\n// % Tab Two\n// > Content for tab two.\n//\n// Produces: paragraph(\"% Tab One\") + blockquote containing:\n// paragraph(\"Content for tab one.\\n% Tab Two\\nContent for tab two.\")\n//\n// We need to split that paragraph on lines matching tab headers, then\n// reconstruct the body content for each segment.\ninterface BQSegment {\n header: RawTab | null; // null means pre-header content (goes to prev tab)\n body: Array<BlockContent | DefinitionContent>;\n // true when this blockquote was written with explicit `> %` nesting (multiple\n // block children) rather than being the standard absorbed-tabs pattern where\n // remark collapses consecutive `% Tab\\n> body` lines into one blockquote.\n // Used to apply a depth offset and to unwrap nested blockquote bodies.\n explicit: boolean;\n // With the source: the `>` markers of the header's line, and the body lines after it with theirs, for headers lazily continued into a nested paragraph.\n markers?: number;\n lines: MarkedLine[];\n // The header's line as written, for a header that skips a level and stays text.\n line?: PhrasingContent[];\n}\n\n// A blockquote is \"explicit\" (`> % Label` nesting) when at least one of its\n// direct paragraph children starts with a tab header. The absorbed pattern\n// (remark collapsing consecutive `% Tab\\n> body` lines into one blockquote)\n// never produces standalone header paragraphs — headers are only embedded\n// inside multi-line text nodes.\nconst isExplicitBQ = (bq: Blockquote): boolean =>\n bq.children.some((child) => {\n if (child.type !== \"paragraph\") return false;\n const first = child.children[0];\n return (\n first?.type === \"text\" &&\n parseTabHeader(first.value.split(\"\\n\")[0] ?? \"\") !== null\n );\n });\n\n// Walk to the deepest last child of a node and return its paragraph if one of\n// its lines is a tab header: the first such header, the paragraph truncated\n// before it, and the lines after it (which belong to the new tab, and may hold\n// further headers). Returns null if the paragraph has no tab header line.\n// This handles cases where remark plugins (e.g. remarkDefinitionList) transform\n// absorbed paragraphs into custom nodes — the trailing \"% Code\" line ends up\n// inside a nested paragraph rather than at the blockquote's top level.\nconst extractTrailingTabHeader = (\n node: BlockContent | DefinitionContent,\n sourceLines?: readonly string[]\n): {\n header: RawTab;\n truncatedPara: Paragraph | null;\n rest: PhrasingContent[][];\n path: Array<BlockContent | DefinitionContent>;\n start: number | undefined;\n at: number;\n line: PhrasingContent[];\n} | null => {\n // Walk to the deepest last child that is a paragraph\n const path: Array<BlockContent | DefinitionContent> = [];\n let current: BlockContent | DefinitionContent = node;\n while (\"children\" in current && current.children.length > 0) {\n const last = current.children[current.children.length - 1] as\n | BlockContent\n | DefinitionContent;\n if (last.type === \"paragraph\") {\n path.push(current);\n // Find the first line of this paragraph that is a tab header. A nested\n // blockquote can lazily absorb a header line and the body lines after it.\n const lines = paraToLines(last, sourceLines);\n const at = lines.findIndex(\n (line) => line[0]?.type === \"text\" && parseTabHeader(line[0].value)\n );\n if (at === -1) return null;\n const headerLine = lines[at] ?? [];\n const first = headerLine[0];\n const header =\n first?.type === \"text\" ? parseTabHeader(first.value) : null;\n if (!header) return null;\n const labelText = header.label;\n const labelNodes: PhrasingContent[] = labelText\n ? [{ type: \"text\", value: labelText }, ...headerLine.slice(1)]\n : headerLine.slice(1);\n const rawTab: RawTab = {\n depth: header.depth,\n open: header.open,\n labelNodes,\n labelText: tabLabelText(labelNodes),\n body: [],\n ...(at === lines.length - 1\n ? { hProperties: paragraphProperties(last) }\n : {})\n };\n const truncatedPara = linesToParagraph(lines.slice(0, at));\n return {\n header: rawTab,\n truncatedPara,\n rest: lines.slice(at + 1),\n path,\n start: last.position?.start.line,\n at,\n line: headerLine\n };\n }\n if (!(\"children\" in last)) break;\n path.push(current);\n current = last;\n }\n return null;\n};\n\nconst splitBlockquote = (\n bq: Blockquote,\n explicit: boolean,\n sourceLines?: readonly string[]\n): BQSegment[] => {\n const segments: BQSegment[] = [];\n let currentSegment: BQSegment = {\n header: null,\n body: [],\n explicit,\n lines: []\n };\n // The `>` markers of a plain panel's own lines: a header written with them is the panel's content (it can start a group of its own there), as markdown-it reads the panel; only one written outside the panel starts the next tab. An explicit panel (`> % Label`) places its headers by their markers itself.\n const base =\n sourceLines && !explicit ? blockquoteMarkers(bq, sourceLines) : undefined;\n\n // Split paragraph lines on tab header lines: body lines accumulate into the\n // current segment, and each header starts a new one. `markersOf` gives a\n // line's `>` markers when the source is known.\n const splitLines = (\n lines: PhrasingContent[][],\n markersOf?: (index: number) => number,\n para?: Paragraph\n ): void => {\n let bodyLines: PhrasingContent[][] = [];\n\n for (const [index, lineSegs] of lines.entries()) {\n const first = lineSegs[0];\n const outsidePanel =\n !markersOf || base === undefined || markersOf(index) < base;\n if (first?.type === \"text\" && outsidePanel) {\n const header = parseTabHeader(first.value);\n if (header) {\n // Flush accumulated body lines into current segment\n if (bodyLines.length > 0) {\n const bodyPara = linesToParagraph(bodyLines);\n if (bodyPara) currentSegment.body.push(bodyPara);\n bodyLines = [];\n }\n\n // Save current segment, start a new one\n segments.push(currentSegment);\n\n const labelText = header.label;\n const labelNodes: PhrasingContent[] = labelText\n ? [{ type: \"text\", value: labelText }, ...lineSegs.slice(1)]\n : lineSegs.slice(1);\n\n currentSegment = {\n header: {\n depth: header.depth,\n open: header.open,\n labelNodes,\n labelText: tabLabelText(labelNodes),\n body: [],\n ...(para && index === lines.length - 1\n ? { hProperties: paragraphProperties(para) }\n : {})\n },\n body: [],\n explicit,\n lines: [],\n line: lineSegs,\n ...(markersOf ? { markers: markersOf(index) } : {})\n };\n continue;\n }\n }\n bodyLines.push(lineSegs);\n if (markersOf) {\n currentSegment.lines.push({\n segs: lineSegs,\n markers: markersOf(index)\n });\n }\n }\n\n // Flush remaining body lines. They end the paragraph, so they keep its\n // data: attributes the parser read from its end (Sätteri's run before tabs).\n if (bodyLines.length > 0) {\n const bodyPara = linesToParagraph(bodyLines);\n if (bodyPara && para?.data) bodyPara.data = para.data;\n if (bodyPara) currentSegment.body.push(bodyPara);\n }\n };\n\n for (const child of bq.children) {\n if (child.type !== \"paragraph\") {\n // For non-paragraph children (e.g. defList from remarkDefinitionList),\n // check if the deepest last-child paragraph has a trailing tab header.\n // Remark may have absorbed a \"% NextTab\" line into that nested paragraph.\n const extracted = extractTrailingTabHeader(child, sourceLines);\n if (extracted) {\n // Clone the child with the trailing header line removed from its nested paragraph\n const cloned = JSON.parse(JSON.stringify(child)) as\n | BlockContent\n | DefinitionContent;\n // Navigate to the deepest last child and replace the paragraph.\n // Tree walking through heterogeneous mdast Parent shapes — no narrow\n // type fits all the intermediate nodes we descend through.\n interface ParentLike {\n children: ParentLike[];\n }\n let target: ParentLike = cloned as unknown as ParentLike;\n for (let pi = 1; pi < extracted.path.length; pi++) {\n target = target.children[target.children.length - 1]!;\n }\n const deepestParent = target as unknown as { children: unknown[] };\n if (extracted.truncatedPara) {\n deepestParent.children[deepestParent.children.length - 1] =\n extracted.truncatedPara;\n } else {\n deepestParent.children.splice(deepestParent.children.length - 1, 1);\n }\n currentSegment.body.push(cloned);\n // Start a new segment for the extracted tab header\n segments.push(currentSegment);\n const { start, at } = extracted;\n const markersOf =\n sourceLines && start !== undefined\n ? (index: number): number =>\n markerCount(sourceLines[start - 1 + index] ?? \"\")\n : undefined;\n currentSegment = {\n header: extracted.header,\n body: [],\n explicit,\n lines: [],\n line: extracted.line,\n ...(markersOf ? { markers: markersOf(at) } : {})\n };\n splitLines(\n extracted.rest,\n markersOf ? (index): number => markersOf(at + 1 + index) : undefined\n );\n } else {\n currentSegment.body.push(child);\n }\n continue;\n }\n\n // Check if this paragraph contains tab headers mixed with body text\n const start = child.position?.start.line;\n splitLines(\n paraToLines(child, sourceLines),\n sourceLines && start !== undefined\n ? (index): number => markerCount(sourceLines[start - 1 + index] ?? \"\")\n : undefined,\n child\n );\n }\n\n segments.push(currentSegment);\n return segments;\n};\n\n// The content that a header which skips a level, and what follows it, stand for\n// once they are not tabs: the header line and the lines and blocks after it, as\n// markdown-it reads them. CommonMark lazily continued them into a paragraph; with\n// the source, their `>` markers (relative to `level`, the markers of the content\n// they belong to) rebuild the blockquotes they were written in. Their other\n// blocks follow: in the last quote when they were inside a blockquote the header\n// line is outside of (`quoted`), else beside the rest.\nconst afterSkip = (\n segments: BQSegment[],\n level: number | undefined,\n quoted: boolean\n): Array<BlockContent | DefinitionContent> => {\n const lines: MarkedLine[] = [];\n const blocks: Array<BlockContent | DefinitionContent> = [];\n for (const seg of segments) {\n if (level === undefined || seg.markers === undefined) {\n // Without the source: the header line, then the segment's body quoted.\n if (seg.line) lines.push({ segs: seg.line, markers: 0 });\n blocks.push(...seg.body);\n continue;\n }\n if (seg.line) lines.push({ segs: seg.line, markers: seg.markers - level });\n lines.push(\n ...seg.lines.map((line) => ({ ...line, markers: line.markers - level }))\n );\n blocks.push(...seg.body.filter((block) => block.type !== \"paragraph\"));\n }\n const content = rebuildLazyLines(lines, 0);\n if (blocks.length > 0 && !quoted) {\n content.push(...blocks);\n } else if (blocks.length > 0) {\n const last = content.at(-1);\n if (last?.type === \"blockquote\") last.children.push(...blocks);\n else\n content.push({\n type: \"blockquote\",\n children: blocks\n });\n }\n return content;\n};\n\n// ── Tree builder ──────────────────────────────────────────────────────────────\n\nconst buildTree = (\n rawTabs: RawTab[],\n targetDepth: number,\n start: number,\n end: number,\n containerClass: string\n): TabsListNode => {\n const depthLabels = rawTabs\n .slice(start, end)\n .filter((t) => t.depth === targetDepth)\n .map((t) => stripAttrs(t.labelText));\n\n const gId = groupId(depthLabels);\n\n // Absolute index of the first %+ tab at this depth (-1 if none)\n const explicitOpenIdx = rawTabs\n .slice(start, end)\n .findIndex((t) => t.depth === targetDepth && t.open);\n const explicitOpenAbsIdx =\n explicitOpenIdx >= 0 ? start + explicitOpenIdx : -1;\n\n const items: TabsItemNode[] = [];\n let tabCounter = 0;\n let i = start;\n\n while (i < end) {\n const raw = rawTabs[i];\n if (!raw) break;\n if (raw.depth !== targetDepth) {\n i++;\n continue;\n }\n\n let childEnd = i + 1;\n while (childEnd < end && (rawTabs[childEnd]?.depth ?? 0) > targetDepth)\n childEnd++;\n\n // First %+ wins; if none, first tab is open\n const isOpen =\n explicitOpenAbsIdx >= 0 ? i === explicitOpenAbsIdx : tabCounter === 0;\n // The label node shares `labelNodes` with `attrsTitle`, so attrs trimming one trims the other.\n const bodyChildren: TabsItemNode[\"children\"] = [\n { type: \"tabsLabel\", children: raw.labelNodes },\n ...raw.body\n ];\n\n const hasDeeper = rawTabs\n .slice(i + 1, childEnd)\n .some((t) => t.depth === targetDepth + 1);\n\n if (hasDeeper) {\n const nested = buildTree(\n rawTabs,\n targetDepth + 1,\n i + 1,\n childEnd,\n containerClass\n );\n nested.containerClass = containerClass;\n bodyChildren.push(nested);\n }\n bodyChildren.push(...(raw.after ?? []));\n\n items.push({\n type: \"tabsItem\",\n depth: targetDepth,\n labelText: raw.labelText,\n open: isOpen,\n children: bodyChildren,\n data: {\n attrsRole: \"containerItem\",\n attrsTitle: raw.labelNodes,\n attrsItemTitle: true,\n hProperties: { ...raw.hProperties }\n }\n });\n\n tabCounter++;\n i = childEnd;\n }\n\n return {\n type: \"tabsList\",\n depth: targetDepth,\n groupId: gId,\n children: items,\n data: { attrsRole: \"container\", hProperties: {} }\n };\n};\n\n// ── Remark plugin ─────────────────────────────────────────────────────────────\n\n// Process all tab groups found in a children array in-place.\n// Used at root level and recursively inside any parent node's children.\n// checkBlankLines: when false, skip the line-gap termination check (for nested contexts\n// where blank lines inside blockquotes produce position gaps but are still part of the group).\nexport const processTabsInChildren = (\n children: Array<BlockContent | DefinitionContent | RootContent>,\n containerClass: string,\n checkBlankLines = true,\n sourceLines?: readonly string[],\n quotes = 0,\n parentType = \"root\"\n): void => {\n const newChildren: typeof children = [];\n let i = 0;\n\n while (i < children.length) {\n const node = children[i];\n if (!node) break;\n\n // A tab header interrupts the paragraph before it, as markdown-it's block rule does, when it's written at the paragraph's own level (its `>` markers). In a list item or definition, a header line may instead be one CommonMark lazily continued, so those are left as they are.\n if (\n node.type === \"paragraph\" &&\n sourceLines &&\n !INDENTED_BLOCKS.has(parentType)\n ) {\n const split = splitAtOpeningLine(\n node,\n sourceLines,\n quotes,\n (text) => parseTabHeader(text)?.depth === 1\n );\n if (split) {\n children.splice(i, 1, ...split);\n continue;\n }\n }\n\n if (node.type === \"paragraph\") {\n const headerPara = extractHeaderPara(node);\n\n if (headerPara) {\n const rawTabs: RawTab[] = [...headerPara.tabs];\n // A group always starts with at least one tab.\n const lastTab = (): RawTab => rawTabs[rawTabs.length - 1]!;\n // Lines left over after a depth-skipping header end the group.\n let rest = headerPara.rest;\n let restLine = headerPara.restLine;\n let j = i + 1;\n let currentTabIdx = rawTabs.length - 1;\n let prevEndLine = node.position?.end.line ?? 0;\n\n while (rest.length === 0 && j < children.length) {\n const sibling = children[j];\n if (!sibling) break;\n const siblingStartLine =\n (sibling as { position?: { start: { line: number } } }).position\n ?.start.line ?? prevEndLine + 1;\n\n if (checkBlankLines && siblingStartLine > prevEndLine + 1) break;\n\n if (sibling.type === \"blockquote\") {\n const bq = sibling;\n const explicit = isExplicitBQ(bq);\n const segments = splitBlockquote(bq, explicit, sourceLines);\n // The `>` markers of the owning tab's body lines: an inner header written with fewer belongs outside it.\n const base =\n explicit && sourceLines\n ? blockquoteMarkers(bq, sourceLines)\n : undefined;\n\n const firstSeg = segments[0];\n if (firstSeg?.header === null) {\n rawTabs[currentTabIdx]?.body.push(...firstSeg.body);\n }\n\n // Explicit blockquotes (`> % Label` nesting) have their headers\n // implicitly one level deeper than the owning tab. Apply a depth\n // offset so they nest correctly.\n // Absorbed blockquotes (standard `% Tab\\n> body` pattern) keep\n // literal depths — remark collapses them into a single paragraph child.\n const depthOffset = explicit ? lastTab().depth : 0;\n // The tab whose body this blockquote is.\n const owner = lastTab();\n // Content after the group when a header ends it.\n let ending: Array<BlockContent | DefinitionContent> | null = null;\n\n for (const [index, seg] of segments.slice(1).entries()) {\n if (!seg.header) continue;\n\n // A header remark absorbed into this body from outside it (its line has\n // fewer `>` markers than the body's) is an outer-level tab: it keeps the\n // depth it was written with, its absorbed lines are its body, rebuilt\n // from their markers, and the blocks after them are its body as written.\n const markers = seg.markers;\n if (\n explicit &&\n markers !== undefined &&\n base !== undefined &&\n markers < base\n ) {\n if (seg.header.depth > lastTab().depth + 1) continue;\n const relative = seg.lines.map((line) => ({\n ...line,\n markers: line.markers - (markers + 1)\n }));\n seg.header.body.push(\n ...rebuildLazyLines(relative, 0),\n ...seg.body.slice(seg.lines.length > 0 ? 1 : 0)\n );\n rawTabs.push(seg.header);\n currentTabIdx = rawTabs.length - 1;\n continue;\n }\n\n const adjustedDepth = depthOffset + seg.header.depth;\n const prevDepth = lastTab().depth;\n if (adjustedDepth > prevDepth + 1) {\n if (explicit) {\n // In an explicit `> %` body, a header that skips a level is not a tab: it\n // and its body stay in the owning tab's panel as written, after any group\n // nested there, as markdown-it renders them.\n owner.after = [\n ...(owner.after ?? []),\n ...afterSkip([seg], base, false)\n ];\n continue;\n }\n // In a group of plain `>` bodies, a header that skips a level ends the\n // group: it and everything after it in this blockquote follow the group as\n // ordinary content.\n // The header line is outside the blockquote, one `>` short of its own.\n const quoteMarkers = sourceLines\n ? blockquoteMarkers(bq, sourceLines)\n : undefined;\n ending = afterSkip(\n segments.slice(index + 1),\n quoteMarkers === undefined ? undefined : quoteMarkers - 1,\n true\n );\n break;\n }\n\n seg.header.depth = adjustedDepth;\n\n if (explicit) {\n // For explicit `> %` blockquotes, body items are wrapped in a\n // nested `> >` blockquote. Unwrap each nested blockquote:\n // - Non-explicit (absorbed) inner BQs are re-split to extract\n // tab headers that remark collapsed into a single paragraph.\n // - Explicit inner BQs use their children directly.\n //\n // \"Escaped\" segments: when remark absorbs an outer-level tab header\n // (e.g. `% Code` at root depth) into an inner BQ paragraph, the tab's\n // body node (code fence etc.) is hoisted to the outer BQ as a direct\n // child after that inner BQ. Re-split segments with an empty body had\n // their body hoisted — they are outer-level siblings, not inner children.\n // Subsequent non-blockquote nodes in seg.body belong to those escaped tabs.\n const deferredInnerSegs: BQSegment[] = [];\n // Tracks which re-split segments have empty bodies (body hoisted to outer BQ)\n const escapedSegs: RawTab[] = [];\n\n for (const b of seg.body) {\n if (b.type !== \"blockquote\") {\n // Non-BQ outer sibling — belongs to the first escaped seg's body\n const escaped = escapedSegs.at(-1);\n if (escaped) {\n escaped.body.push(b);\n } else {\n seg.header.body.push(b);\n }\n continue;\n }\n const innerBq = b;\n if (!isExplicitBQ(innerBq)) {\n // Re-split absorbed inner blockquote to extract sibling headers\n const innerSegs = splitBlockquote(\n innerBq,\n false,\n sourceLines\n );\n const innerFirst = innerSegs[0];\n if (innerFirst?.header === null) {\n seg.header.body.push(...innerFirst.body);\n }\n for (const innerSeg of innerSegs.slice(1)) {\n if (!innerSeg.header) continue;\n // An outer-level header that remark absorbed into this inner BQ is an\n // escaped tab. With the source, its line has fewer `>` markers than the\n // owning tab's body: it keeps the depth it was written with, and the\n // lines absorbed after it are its body, rebuilt from their markers.\n // Without, a re-split segment with no body is taken as escaped (its\n // body was hoisted to the outer BQ as a direct child) at depthOffset.\n const markers = innerSeg.markers;\n if (markers !== undefined && base !== undefined) {\n if (markers < base) {\n const relative = innerSeg.lines.map((line) => ({\n ...line,\n markers: line.markers - (markers + 1)\n }));\n innerSeg.header.body.push(\n ...rebuildLazyLines(relative, 0)\n );\n escapedSegs.push(innerSeg.header);\n deferredInnerSegs.push(innerSeg);\n continue;\n }\n } else if (innerSeg.body.length === 0) {\n innerSeg.header.depth = depthOffset;\n escapedSegs.push(innerSeg.header);\n deferredInnerSegs.push(innerSeg);\n continue;\n }\n const tentativeDepth =\n depthOffset + innerSeg.header.depth;\n const innerPrevDepth = lastTab().depth;\n if (tentativeDepth > innerPrevDepth + 1) continue;\n innerSeg.header.depth = tentativeDepth;\n innerSeg.header.body.push(...innerSeg.body);\n deferredInnerSegs.push(innerSeg);\n }\n } else {\n // Explicit inner blockquote — use children directly\n seg.header.body.push(...innerBq.children);\n }\n }\n // Push the current seg first, then any deferred inner siblings\n rawTabs.push(seg.header);\n currentTabIdx = rawTabs.length - 1;\n for (const innerSeg of deferredInnerSegs) {\n if (!innerSeg.header) continue;\n rawTabs.push(innerSeg.header);\n currentTabIdx = rawTabs.length - 1;\n }\n } else {\n seg.header.body.push(...seg.body);\n rawTabs.push(seg.header);\n currentTabIdx = rawTabs.length - 1;\n }\n }\n\n prevEndLine = sibling.position?.end.line ?? prevEndLine;\n j++;\n if (ending) {\n children.splice(j, 0, ...ending);\n break;\n }\n } else if (sibling.type === \"paragraph\") {\n const prevDepth = lastTab().depth;\n const contHeaders = extractHeaderPara(sibling, false, prevDepth);\n if (contHeaders) {\n rawTabs.push(...contHeaders.tabs);\n rest = contHeaders.rest;\n restLine = contHeaders.restLine;\n currentTabIdx = rawTabs.length - 1;\n prevEndLine = sibling.position?.end.line ?? prevEndLine;\n j++;\n continue;\n }\n break;\n } else {\n break;\n }\n }\n\n const list = buildTree(rawTabs, 1, 0, rawTabs.length, containerClass);\n list.containerClass = containerClass;\n newChildren.push(list as unknown as RootContent);\n children.splice(j, 0, ...splitAtGroupStarts(rest, restLine));\n i = j;\n continue;\n }\n }\n\n newChildren.push(node);\n i++;\n }\n\n children.splice(0, children.length, ...newChildren);\n};\n\ninterface Container {\n type?: string;\n children?: unknown[];\n}\n\n/**\n * Recognize every tab group in the tree: at the root, then inside every container (step bodies, list items, other tabs' panels). Blank-line checks only apply at the root: blank lines inside a blockquote leave position gaps that would wrongly end a group once its content has been lifted out of the blockquote. With the document's `source`, a tab header that CommonMark lazily continued into a nested panel is placed by its `>` markers, as markdown-it reads it.\n */\nexport const processTabs = (\n root: Root,\n containerClass: string,\n source?: string\n): void => {\n const sourceLines = source?.split(/\\r?\\n/);\n const walk = (node: Container, quotes: number): void => {\n if (!Array.isArray(node.children) || node.children.length === 0) return;\n const inner = quotes + (MARKED_BLOCKS.has(node.type ?? \"\") ? 1 : 0);\n processTabsInChildren(\n node.children as Array<BlockContent | DefinitionContent>,\n containerClass,\n false,\n sourceLines,\n inner,\n node.type\n );\n for (const child of node.children) walk(child as Container, inner);\n };\n processTabsInChildren(root.children, containerClass, true, sourceLines);\n for (const child of root.children) walk(child, 0);\n if (sourceLines) endGroupsAtMarkers(root, sourceLines, `tabsList`);\n};\n","// A mutable copy of a read-only tree, for engines whose nodes can't be rewritten in place (Sätteri), so they can run the same recognition as remark.\n// A node's children are its own node type; `TreeNode` can't say so, so the two reads of them are asserted.\n/* oxlint-disable typescript/no-unsafe-type-assertion */\n\n/** The part of a node the copy reads: its children, if it has any. */\nexport interface TreeNode {\n type: string;\n children?: readonly TreeNode[];\n data?: unknown;\n}\n\n/** A copy of a tree, and how to write the changes made to it back. */\nexport interface EditableTree<N extends TreeNode> {\n /** A plain, mutable copy of the tree, for recognition to rewrite. */\n tree: N;\n /**\n * Write a node of the (rewritten) copy back: a node recognition left alone becomes the engine's own node again, so it keeps what the engine tracks for it (such as its source position, which later plugins read), and `setChildren` is called only where a children list changed, `setData` only where its `data` was replaced. `build` converts a node recognition created, writing back any copied nodes inside it.\n */\n writeBack: (node: N) => N;\n}\n\nexport const editableTree = <N extends TreeNode>(\n root: N,\n build: (node: N, writeBack: (node: N) => N) => N,\n setChildren: (node: N, children: N[]) => void,\n setData?: (node: N, data: unknown) => void\n): EditableTree<N> => {\n const originals = new Map<N, { node: N; children: readonly N[] }>();\n\n const copy = (node: N): N => {\n const children = node.children as readonly N[] | undefined;\n if (!children) {\n const leaf = { ...node };\n originals.set(leaf, { node, children: [] });\n return leaf;\n }\n const branch = { ...node, children: children.map(copy) };\n originals.set(branch, { node, children });\n return branch;\n };\n\n const writeBack = (node: N): N => {\n const original = originals.get(node);\n if (!original) return build(node, writeBack);\n if (setData && node.data !== original.node.data)\n setData(original.node, node.data);\n if (!node.children) return original.node;\n const children = (node.children as readonly N[]).map(writeBack);\n const changed =\n children.length !== original.children.length ||\n children.some((child, index) => child !== original.children[index]);\n if (changed) setChildren(original.node, children);\n return original.node;\n };\n\n return { tree: copy(root), writeBack };\n};\n","// Inlining referenced `.svg` images, shared by the markdown-it, rehype and Sätteri plugins: whether an SVG's occurrences are inlined, and the markup each becomes. Reading files, optimizing them and resolving paths stay in the plugins, so this module does no I/O.\n\n/** The limits and mode that decide how an SVG's occurrences are inlined. */\nexport interface InlineSvgLimits {\n /** Skip inlining SVGs larger than this many characters. */\n maxImageSize: number;\n /** Skip inlining an SVG referenced more than this many times. */\n maxOccurrences: number;\n /** Skip inlining an SVG whose occurrences add up to more than this many characters. */\n maxTotalSize: number;\n /** Reuse a repeated SVG through a hidden `<symbol>` and `<use>`. */\n deduplication: boolean;\n}\n\nconst hash = (str: string): string => {\n let h = 2166136261;\n for (let i = 0; i < str.length; i++) {\n h = Math.imul(h ^ str.charCodeAt(i), 16777619) >>> 0;\n }\n return h.toString(36);\n};\n\n/**\n * The id of a deduplicated SVG's sprite: a hash of its path relative to the document, with `/` separators, so the same document renders the same ids on any machine or OS (an absolute path would leak the build machine into the HTML).\n */\nexport const svgSpriteId = (relativePath: string): string =>\n `svg-sprite-${hash(relativePath)}`;\n\nconst extractSvgParts = (\n content: string\n): { viewBox: string; width: string; height: string; inner: string } => {\n const openTag = /<svg([^>]*?)>/i.exec(content)?.[1] ?? ``;\n return {\n viewBox: /viewBox=\"([^\"]*)\"/i.exec(openTag)?.[1] ?? ``,\n width: /\\bwidth=\"([^\"]*)\"/i.exec(openTag)?.[1] ?? ``,\n height: /\\bheight=\"([^\"]*)\"/i.exec(openTag)?.[1] ?? ``,\n inner: /<svg[^>]*>([\\s\\S]*?)<\\/svg\\s*>/i.exec(content)?.[1]?.trim() ?? ``\n };\n};\n\nconst escAttr = (s: string): string =>\n s.replace(/&/g, `&amp;`).replace(/\"/g, `&quot;`);\n\n// The image's alt text is the SVG's accessible name.\nconst buildFullInline = (content: string, alt: string): string => {\n if (!alt) return content;\n return content.replace(\n /<svg([^>]*)>/i,\n `<svg$1 aria-label=\"${escAttr(alt)}\">`\n );\n};\n\nconst buildSpriteHtml = (id: string, viewBox: string, inner: string): string =>\n `<svg aria-hidden=\"true\" style=\"display:none\" xmlns=\"http://www.w3.org/2000/svg\">` +\n `<defs><symbol id=\"${id}\" viewBox=\"${escAttr(viewBox)}\">${inner}</symbol></defs>` +\n `</svg>`;\n\nconst buildUseHtml = (\n id: string,\n viewBox: string,\n width: string,\n height: string,\n alt: string\n): string => {\n const attrs = [\n viewBox && `viewBox=\"${escAttr(viewBox)}\"`,\n width && `width=\"${escAttr(width)}\"`,\n height && `height=\"${escAttr(height)}\"`,\n alt && `aria-label=\"${escAttr(alt)}\"`\n ]\n .filter(Boolean)\n .join(` `);\n return `<svg ${attrs}><use href=\"#${id}\"></use></svg>`;\n};\n\n/**\n * The markup for every occurrence of one SVG file, given each occurrence's alt text in document order: the SVG itself, or, with deduplication and more than one occurrence, a hidden sprite on the first and a `<use>` of it on each. `null` when the limits leave the images as they are. `relativePath` is the file's path relative to the document, with `/` separators, for the sprite id.\n */\nexport const inlineSvgMarkup = (\n content: string,\n alts: readonly string[],\n relativePath: string,\n limits: InlineSvgLimits\n): string[] | null => {\n if (content.length > limits.maxImageSize) return null;\n if (alts.length > limits.maxOccurrences) return null;\n if (alts.length * content.length > limits.maxTotalSize) return null;\n if (!limits.deduplication || alts.length < 2) {\n return alts.map((alt) => buildFullInline(content, alt));\n }\n const { viewBox, width, height, inner } = extractSvgParts(content);\n const id = svgSpriteId(relativePath);\n const sprite = buildSpriteHtml(id, viewBox, inner);\n return alts.map((alt, index) => {\n const use = buildUseHtml(id, viewBox, width, height, alt);\n return index === 0 ? sprite + use : use;\n });\n};\n","// Copy buttons for code blocks, shared by the markdown-it, rehype and Sätteri plugins: which blocks get one, the id their `<pre>` takes, and the button's markup under the plugins' options. The button goes in the `<pre>`, after its `<code>`, as a `--copy` invoker command aimed at the `<pre>`; the plugins' client script does the copying and shows the button.\n\nimport type { HastLike } from \"./hast.js\";\nimport { mermaidIdPrefixes } from \"./mermaid-pele.js\";\n\n/** The copy button's class. */\nexport const COPY_CODE_CLASS = \"markdown-copy-code\";\n\n/** The invoker command the button sends its code block. */\nexport const COPY_CODE_COMMAND = \"--copy\";\n\n// The word in a fence's meta (```sh nocopy) that leaves its block without a button.\nconst OPT_OUT = `nocopy`;\n\n/** Whether a fence's meta, the info string after its language, turns its block's button off. */\nexport const copyCodeOptedOut = (meta: string | null | undefined): boolean =>\n (meta ?? ``).split(/\\s+/).includes(OPT_OUT);\n\n/** The text a block copies: its code with line endings normalized and without the newline that ends it. */\nexport const copyCodeText = (code: string): string =>\n code.replace(/\\r\\n?/g, `\\n`).replace(/\\n$/, ``);\n\n/**\n * A document's code block ids, one per block in document order: `code-` and a hash of the block's text, so a block's id doesn't change when others are edited, with `-2`, `-3`… for repeats of one block. Create one per document.\n */\nexport const copyCodeIds = (): ((text: string) => string) =>\n mermaidIdPrefixes(`code`);\n\ntype CodeLike = HastLike & { data?: { meta?: unknown } };\n\nconst textOf = (node: HastLike): string =>\n node.type === `text`\n ? (node.value ?? ``)\n : (node.children ?? []).map(textOf).join(``);\n\n/**\n * A hast `<pre>` holding a code block, as markdown renders one: its only element child is a `<code>`. Returns the text the block copies and its fence's meta, or nothing for another `<pre>` or an empty block. The meta is the `<code>`'s, as remark and Sätteri keep it, or else the `<pre>`'s `data-meta` attribute, where a highlighter that rebuilds the block (such as Astro's Shiki) can keep it.\n */\nexport const copyCodeBlock = (\n node: HastLike\n): { text: string; meta: string | undefined } | undefined => {\n if (node.type !== `element` || node.tagName !== `pre`) return undefined;\n const elements = (node.children ?? []).filter(\n (child) => child.type === `element`\n );\n const [code] = elements;\n if (elements.length !== 1 || code?.tagName !== `code`) return undefined;\n const text = copyCodeText(textOf(code));\n if (text === ``) return undefined;\n const meta = (code as CodeLike).data?.meta ?? node.properties?.dataMeta;\n return { text, meta: typeof meta === `string` ? meta : undefined };\n};\n\n/** A copy button's states: before its block is copied, and for a moment after. */\nexport type CopyCodeState = \"copy\" | \"copied\";\n\n/** Options shared by the copy-code plugins for every engine. */\nexport interface CopyCodeOptions {\n /** The button's icon in each state, as SVG markup. An icon can be replaced but not removed, since it's all the button holds: an empty one keeps the default. Defaults: {@link COPY_CODE_ICONS}. */\n icons?: Partial<Record<CopyCodeState, string>>;\n /**\n * Text shown beside the button in each state, and the button's accessible name; `null` or `\"\"` shows none. Defaults: {@link COPY_CODE_TEXT}, none before copying and `Copied!` after. The copy text shows while the button is hovered or focused.\n */\n text?: Partial<Record<CopyCodeState, string | null>>;\n}\n\n// Lucide's copy and check icons (lucide.dev, ISC).\nconst icon = (paths: string): string =>\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">${paths}</svg>`;\n\n/** The button's default icon in each state. */\nexport const COPY_CODE_ICONS: Record<CopyCodeState, string> = {\n copy: icon(\n `<rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"></rect><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"></path>`\n ),\n copied: icon(`<path d=\"M20 6 9 17l-5-5\"></path>`)\n};\n\n/** The button's default text in each state, as GitHub shows it: none before copying, `Copied!` after. */\nexport const COPY_CODE_TEXT: Record<CopyCodeState, string> = {\n copy: ``,\n copied: `Copied!`\n};\n\n// Its accessible name while it has no copy text.\nconst DEFAULT_LABEL = `Copy code`;\n\nconst escape = (value: string): string =>\n value.replace(/&/g, `&amp;`).replace(/</g, `&lt;`).replace(/\"/g, `&quot;`);\n\n/**\n * Builds a document's copy buttons under the plugin's options. A button is for the code block whose `<pre>` has the id, and goes in the `<pre>` after its `<code>`. It starts `hidden`: the client script shows it where it can copy, so a page without the script has no button that does nothing. Each state's icon and text are spans marked `data-state`, which the stylesheet shows by the button's `data-copied`; the client script names the copied button by its copied text.\n */\nexport const createCopyCodeButton = (\n options: CopyCodeOptions = {}\n): ((id: string) => string) => {\n const icons = { ...COPY_CODE_ICONS, ...options.icons };\n const texts = { ...COPY_CODE_TEXT, ...options.text };\n // `null` shows no text, as `\"\"` does.\n const text = (state: CopyCodeState): string => texts[state] ?? ``;\n const states: CopyCodeState[] = [`copy`, `copied`];\n const content = [\n // An empty icon keeps the default, so the button is never empty.\n ...states.map(\n (state) =>\n `<span class=\"${COPY_CODE_CLASS}-icon\" data-state=\"${state}\" aria-hidden=\"true\">${icons[state] || COPY_CODE_ICONS[state]}</span>`\n ),\n ...states.map((state) =>\n text(state)\n ? `<span class=\"${COPY_CODE_CLASS}-text\" data-state=\"${state}\" aria-hidden=\"true\">${escape(text(state))}</span>`\n : ``\n )\n ].join(``);\n const label = escape(text(`copy`) || DEFAULT_LABEL);\n return (id) =>\n `<button type=\"button\" class=\"${COPY_CODE_CLASS}\" command=\"${COPY_CODE_COMMAND}\" commandfor=\"${id}\" aria-label=\"${label}\" hidden>${content}</button>`;\n};\n"],"mappings":";;AAMA,MAAM,oBAAoB;AAC1B,MAAM,SAAS;AAKf,MAAM,YAAY;AAClB,MAAM,SAAS;;;;;;;AAQf,MAAa,kBACX,OACA,QACA,OACA,QACgB;CAChB,MAAM,0BAAU,IAAI,IAAY;CAChC,IAAI,IAAI;CACR,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,UAAU,IAAI,KAAK,KAAK;EAChD,MAAM,OAAO,MAAM,OAAO,CAAC;EAC3B,IAAI,SAAiC;EACrC,OAAO,IAAI,OAAO,OAAO,OAAO,MAAM;GACpC,SAAS,OAAO,OAAO,MAAM,OAAO,KAAK,OAAO,MAAM,GAAG,GAAG,CAAC,IAAI;GACjE,IAAI,QAAQ;GACZ;EACF;EACA,IAAI,KAAK,KAAK;EACd,IAAI,QAAQ;GACV,KAAK,OAAO,EAAE,CAAC;GACf;EACF;EACA,IAAI,UAAU;EACd,KAAK,IAAI,IAAI,IAAI,GAAG,KAAK,SAAS,OAAO,OAAO,MAAM,KAAK;EAC3D,IAAI,UAAU,MAAM,KAAK,kBAAkB,KAAK,IAAI,GAAG,QAAQ,IAAI,CAAC;EACpE;CACF;CACA,OAAO;AACT;;AAGA,MAAa,eAAe,OAAe,YAAiC;CAC1E,IAAI,QAAQ,SAAS,GAAG,OAAO;CAC/B,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAChC,OAAO,QAAQ,IAAI,CAAC,IAChB,OAAO,cAAc,YAAY,MAAM,WAAW,CAAC,CAAC,IACpD,MAAM;CAEZ,OAAO;AACT;;AAGA,MAAa,iBAAiB,UAC5B,MAAM,QAAQ,SAAS,MACrB,OAAO,aAAa,EAAE,YAAY,CAAC,IAAK,SAAS,CACnD;;;;;;AAoBF,MAAa,mBACX,MACA,WACiB;CACjB,MAAM,QAAQ,MAAoB,UAA2C;EAC3E,MAAM,IAAI;EACV,KAAK,UAAU,SAAS,UAAU,KAAK,OAAO,KAAK,CAAC;CACtD;CACA,KAAK,OAAO,SAAS;EACnB,MAAM,QAAQ,KAAK,UAAU,MAAM;EACnC,MAAM,MAAM,KAAK,UAAU,IAAI;EAC/B,IAAI,KAAK,SAAS,UAAU,OAAO,KAAK,UAAU,UAAU;EAC5D,IAAI,UAAU,KAAA,KAAa,QAAQ,KAAA,GAAW;EAC9C,KAAK,QAAQ,YACX,KAAK,OACL,eAAe,KAAK,OAAO,QAAQ,OAAO,GAAG,CAC/C;CACF,CAAC;CACD,aACE,KAAK,OAAO,SAAS;EACnB,IAAI,OAAO,KAAK,UAAU,UACxB,KAAK,QAAQ,cAAc,KAAK,KAAK;CACzC,CAAC;AACL;;;ACxFA,MAAa,gBAA2C;CAEtD,MAAM;CACN,KAAK;CACL,WAAW;CACX,SAAS;CACT,SAAS;CAET,UAAU;CACV,SAAS;CACT,MAAM;CACN,MAAM;CACN,MAAM;CACN,MAAM;CACN,SAAS;CACT,OAAO;CACP,MAAM;CACN,UAAU;CACV,MAAM;CACN,KAAK;CACL,WAAW;CACX,SAAS;CACT,MAAM;CACN,SAAS;CACT,QAAQ;CACR,OAAO;CACP,KAAK;CACL,SAAS;CACT,OAAO;CACP,MAAM;AACR;;AAGA,MAAa,gBAA2C;CACtD,MAAM;CACN,KAAK;CACL,WAAW;CACX,SAAS;CACT,SAAS;CACT,UAAU;CACV,MAAM;CACN,MAAM;CACN,SAAS;CACT,UAAU;CACV,SAAS;CACT,QAAQ;CACR,KAAK;CACL,SAAS;CACT,OAAO;AACT;;ACjEA,MAAMA,UAAQ,SACZ,2MAA2M,KAAK;;AAGlN,MAAa,QAAmC;CAE9C,MAAMA,OACJ,mLACF;CACA,KAAKA,OACH,iLACF;CACA,WAAWA,OAAK,oDAAkD;CAClE,SAASA,OACP,uJACF;CACA,SAASA,OACP,+IACF;CAEA,UAAUA,OACR,wRACF;CACA,MAAMA,OACJ,0GACF;CACA,MAAMA,OACJ,2KACF;CACA,SAASA,OACP,0FACF;CACA,UAAUA,OACR,sIACF;CACA,SAASA,OACP,yGACF;CACA,QAAQA,OAAK,qDAAmD;CAChE,KAAKA,OACH,2eACF;CACA,SAASA,OACP,wMACF;CACA,OAAOA,OACL,oTACF;AACF;;ACzCA,MAAM,YAAY;;AAGlB,MAAa,qBAAqB,SAChC,UAAU,KAAK,KAAK,QAAQ,WAAW,EAAE,CAAC;AAE5C,MAAM,cAAc,MAClB,EAAE,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,EAAE,MAAM,CAAC;;AAevC,MAAa,uBACX,UAAwB,CAAC,MACP;CAClB,MAAM,EACJ,OAAO,aAAa,CAAC,GACrB,SAAS,CAAC,GACV,uBAAuB,MACvB,QAAQ,MACR,iBAAiB,qBACf;CACJ,MAAM,WAAmC;EAAE,GAAG;EAAe,GAAG;CAAW;CAE3E,MAAM,eAAgD;CACtD,MAAM,eAAe,SACnB,QAAQ;CACV,OAAO;EACL,UAAU,YACR,SAAS,uBAAuB,QAAQ,YAAY,IAAI;EAE1D,WAAW,SACT,aAAa,UACZ,YAAY,IAAI,IAAI,cAAc,QAAQ,KAAA,MAC3C,WAAW,IAAI;EACjB,UAAU,SAAU,SAAS,YAAY,IAAI,IAAI,MAAM,QAAQ;EAC/D;CACF;AACF;;AAyBA,MAAa,aAAa,UACxB,MACG,KAAK,MACJ,EAAE,SAAS,UAAU,EAAE,SAAS,eAC3B,EAAE,SAAS,KACZ,EAAE,SAAS,UACR,EAAE,OAAO,KACV,EAAE,WACA,UAAU,EAAE,QAAQ,IACpB,EACV,CAAC,CACA,KAAK,EAAE;AAEZ,MAAM,aAAqC,MAAS,WAAsB;CACxE,GAAG;CACH;AACF;;;;AAKA,MAAa,uBACX,aAC6B;CAC7B,MAAM,CAAC,OAAO,GAAG,QAAQ;CACzB,IAAI,OAAO,SAAS,UAAU,MAAM,UAAU,KAAA,GAAW,OAAO;CAChE,MAAM,UAAU,MAAM,MAAM,UAAU;CACtC,MAAM,QAAQ,UAAU,KAAK,OAAO;CACpC,IAAI,CAAC,OAAO,OAAO;CACnB,MAAM,CAAC,QAAQ,UAAU,IAAI,QAAQ;CAErC,MAAM,OAAY,CAAC;CACnB,MAAM,OAAY,CAAC;CACnB,KAAK,MAAM,SAAS,CAClB,UAAU,OAAO,QAAQ,MAAM,OAAO,MAAM,CAAC,GAC7C,GAAG,IACL,GACE,IAAI,KAAK,SAAS,KAAK,KAAK,GAAG,EAAE,CAAC,EAAE,SAAS,SAC3C,KAAK,KAAK,KAAK;MACV,IAAI,MAAM,SAAS,UAAU,MAAM,OAAO,SAAS,IAAI,GAAG;EAC/D,MAAM,KAAK,MAAM,MAAM,QAAQ,IAAI;EACnC,KAAK,KAAK,UAAU,OAAO,MAAM,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC;EACpD,KAAK,KAAK,UAAU,OAAO,MAAM,MAAM,MAAM,KAAK,CAAC,CAAC,CAAC;CACvD,OACE,KAAK,KAAK,KAAK;CAGnB,IAAI,KAAK,GAAG,EAAE,CAAC,EAAE,SAAS,SAAS,KAAK,IAAI;CAgB5C,MAAM,aAdU,KAAK,KAAK,GAAG,MAC3B,EAAE,SAAS,SACP,IACA,UACE,GACA,MAAM,KAAK,MAAM,KAAK,SAAS,KAC1B,EAAE,SAAS,GAAA,CAAI,KAAK,IACrB,MAAM,KACH,EAAE,SAAS,GAAA,CAAI,UAAU,IAC1B,MAAM,KAAK,SAAS,KACjB,EAAE,SAAS,GAAA,CAAI,QAAQ,IACvB,EAAE,SAAS,EACtB,CAEmB,CAAC,CAAC,QAAQ,MAAM,EAAE,SAAS,UAAU,EAAE,UAAU,EAAE;CAC5E,MAAM,YAAY,WAAW,GAAG,EAAE;CAClC,IAAI,WAAW,SAAS,QACtB,WAAW,WAAW,SAAS,KAAK,UAClC,YACC,UAAU,SAAS,GAAA,CAAI,QAAQ,CAClC;CAGF,OAAO;EACL;EACA,MAAM,SAAS,OAAO,SAAS,MAAM,OAAO,KAAA;EAC5C;EACA,WAAW,UAAU,UAAU,CAAC,CAAC,KAAK;EACtC,WAAW,KAAK,QAAQ,MAAM,EAAE,SAAS,UAAU,EAAE,UAAU,EAAE;CACnE;AACF;;;ACrHA,MAAa,uBACX,OACA,SACqB;CACrB,MAAM,wBAAQ,IAAI,QAAgB;CAElC,MAAM,2BAAW,IAAI,QAAqB;CAC1C,MAAM,UAAwB;EAC5B,OAAO,UAAU;GACf,MAAM,OAAO,MAAM,KAAK,KAAK;GAC7B,MAAM,IAAI,IAAI;GACd,OAAO;EACT;EACA,OAAO,aAAa;GAClB,MAAM,OAAO,MAAM,KAAK,QAAQ;GAChC,MAAM,IAAI,IAAI;GACd,SAAS,IAAI,MAAM,QAAQ;GAC3B,OAAO;EACT;CACF;CAEA,MAAM,aAAa,UAAwB,aAAa,OACtD,KAAK,UAAU,YAAY,OAAO;CAEpC,MAAM,WAAW,SAA6B;EAC5C,KAAK,MAAM,QAAQ,MAAM;GACvB,IAAI,CAAC,MAAM,IAAI,IAAI,GAAG;GACtB,IAAI,KAAK,SAAS,UAAU,KAAK,UAAU,KAAA,GACzC,KAAK,QAAQ,cAAc,KAAK,KAAK;QAErC,QAAQ,SAAS,IAAI,IAAI,KAAK,CAAC,CAAC;EAEpC;CACF;CAEA,MAAM,cACJ,UACA,YACA,WACoB;EACpB,MAAM,SAAS,SAAS,KAAK,SAAY;GACvC,MAAM,QAAQ,KAAK,UAAU,MAAM;GACnC,MAAM,MAAM,KAAK,UAAU,IAAI;GAC/B,IACE,KAAK,SAAS,UACd,KAAK,UAAU,KAAA,KACf,UAAU,KAAA,KACV,QAAQ,KAAA,GAER,OAAO;GACT,MAAM,UAAU,eAAe,KAAK,OAAO,QAAQ,OAAO,GAAG;GAC7D,OAAO,QAAQ,SAAS,IACpB,OACA,QAAQ,KAAK,YAAY,KAAK,OAAO,OAAO,CAAC;EACnD,CAAC;EACD,MAAM,OAAO,UAAU,QAAQ,UAAU;EACzC,IAAI,SAAS,QAAQ,OAAO,KAAA;EAC5B,QAAQ,IAAI;EACZ,OAAO,CAAC,GAAG,IAAI;CACjB;CAEA,OAAO,OAAO,OAAO,WAAW;EAC9B,QAAQ,SAAiB,MAAM,IAAI,IAAI;EACvC;CACF,CAAC;AACH;;ACnGA,MAAM,iCAAiB,IAAI,IAAI;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAKD,MAAMC,eACJ;AACF,MAAMC,gBAAc;AACpB,MAAMC,cAAY,SAChBF,aAAW,KAAK,IAAI,IAAI,UAAUC,cAAY,KAAK,IAAI,IAAI,UAAU;;;;AAqBvE,MAAM,gBAAgB,eAAkC;CACtD,MAAM,QAAkB,CAAC;CACzB,MAAM,gBAAgB;EAAC;EAAI;EAAI;EAAI;EAAI;EAAI;CAAE;CAC7C,IAAI,YAAY;CAChB,IAAI,WAAW;CACf,WAAW,SAAS,QAAQ,cAAc;EACxC,MAAM,KAAK,CAAC;EACZ,IAAI,aAAa,OAAO,OAAO,GAAG,YAAY;EAC9C,WAAW,OAAO;EAClB,IAAI,CAAC,OAAO,OAAO;EACnB,MAAM,SAAS,OAAO,OAAO,IAAI;EACjC,MAAM,eAAe,cAAc,WAAW;EAC9C,IAAI,YAAY,aAAa,MAAM,cAAc,KAAK;EACtD,IAAI,kBAAkB;EACtB,OAAO,YAAY,cAAc,cAAc,MAAM,cAAc,KAAK,GAAG;GACzE,MAAM,SAAS,WAAW;GAC1B,IAAI,CAAC,QAAQ,QAAQ,OAAO,OAAO,GAAG;GACtC,MAAM,WACJ,YAAY,KAAK,WAAW,YAAY,EAAE,EAAE,SAAS,SAChD,MAAM,YAAY,MAAM,KAAK,IAC9B;GACN,MAAM,aAAa,YAAY,YAAY;GAC3C,MAAM,aAAa;GACnB,OAAO,OAAO;GACd,OAAO,MAAM;GACb,OAAO,QAAQ;GACf,kBAAkB;GAClB,WAAW;GACX;EACF;EACA,IAAI,oBAAoB,IAAI,cAAc,UAAU;CACtD,CAAC;AACH;;AAGA,MAAa,4BACX,QACA,UAEA,oBAAoB,QAAQ,UAAU,YAAY,EAAE,MAAM,WAAW;CACnE,MAAM,OAAkB,eAAe,IAAI,UAAU,IAAI,UAAU;CAEnE,MAAM,UACJ,MACA,SACc;EACd,IAAI,CAAC,MAAM,OAAO;EAClB,IAAI,KAAK,SAAS,UAAU,KAAK,OAC/B,OAAOC,WACL,SAAS,WAAW,KAAK,MAAM,MAAM,EAAE,IAAI,KAAK,MAAM,OAAO,CAAC,CAChE;EAEF,OAAO,KAAK,SAAS,UAAU,UAAU;CAC3C;CAGA,MAAM,QAAwB,CAAC;CAC/B,MAAM,aAA0B,CAAC;CACjC,SAAS,SAAS,OAAO,UAAU;EACjC,MAAM,QAAQ,MAAM,SAAS,SAAS,MAAM,QAAQ,KAAA;EACpD,IAAI,UAAU,KAAA,GAAW;GACvB,MAAM,KAAK;IAAE,MAAM;IAAQ,MAAM;GAAM,CAAC;GACxC;EACF;EACA,IAAI,UAAU;EACd,MAAM,cAAoB;GACxB,IAAI,SAAS,MAAM,KAAK;IAAE,MAAM;IAAQ,OAAO;GAAQ,CAAC;GACxD,UAAU;EACZ;EACA,IAAI,IAAI;EACR,OAAO,IAAI,MAAM,QAAQ;GACvB,IAAI,MAAM;GACV,OAAO,MAAM,OAAO,GAAG,MAAM,QAAQ;GACrC,IAAI,MAAM,IAAI,GAAG;IACf,WAAW,MAAM,MAAM,GAAG,KAAK,IAAI,KAAK,IAAI,CAAC,CAAC;IAC9C,IAAI,KAAK,IAAI,KAAK,IAAI,CAAC;IACvB;GACF;GACA,MAAM,OACJ,IAAI,IACAA,WAAS,MAAM,OAAO,IAAI,CAAC,CAAC,IAC5B,OAAO,SAAS,QAAQ,IAAI,QAAQ;GAC1C,MAAM,OACJ,MAAM,MAAM,SACRA,WAAS,MAAM,OAAO,GAAG,CAAC,IAC1B,OAAO,SAAS,QAAQ,IAAI,OAAO;GACzC,MAAM,OAAO,SAAS,YAAY,SAAS,WAAW,SAAS;GAC/D,MAAM,QACJ,SAAS,YAAY,SAAS,WAAW,SAAS;GACpD,MAAM;GACN,IAAI,SAAS,MAAM;GACnB,IAAI,SAAS,GAAG;IACd,MAAM,KAAK;KAAE,MAAM;KAAQ,OAAO;IAAO,CAAC;IAC1C;GACF;GACA,KAAK,IAAI,OAAO,GAAG,OAAO,QAAQ,QAAQ,GACxC,IAAI,QAAQ,OAAO;IACjB,WAAW,KAAK;KAAE;KAAM;KAAO,KAAK;KAAI,MAAM,MAAM;IAAO,CAAC;IAC5D,MAAM,KAAK,EAAE,MAAM,YAAY,CAAC;GAClC,OACE,MAAM,KAAK;IAAE,MAAM;IAAQ,OAAO,SAAS;GAAO,CAAC;GAGvD,IAAI;EACN;EACA,MAAM;CACR,CAAC;CAED,aAAa,UAAU;CACvB,IAAI,CAAC,WAAW,MAAM,EAAE,UAAU,OAAO,CAAC,GAAG,OAAO;CAGpD,MAAM,OAAiB,CAAC;CACxB,KAAK,MAAM,aAAa,YAAY;EAClC,MAAM,SAAS,WAAW,UAAU;EACpC,IAAI,CAAC,QAAQ;EACb,MAAM,UAAU,QAAQ,EAAE,MAAM,UAAU;EAC1C,MAAM,OAAO,QAAQ,EAAE,MAAM,UAAU;EACvC,MAAM,WAAW,MAAM,OAAO,OAAO;EACrC,IAAI,UAAU,SAAS,UAAU,SAAS,UAAU,QAClD,KAAK,KAAK,OAAO,OAAO,CAAC;CAE7B;CACA,KAAK,MAAM,KAAK,KAAK,QAAQ,GAAG;EAC9B,IAAI,IAAI,IAAI;EACZ,OAAO,MAAM,EAAE,EAAE,SAAS,WAAW;EACrC;EACA,MAAM,QAAQ,MAAM;EACpB,MAAM,SAAS,MAAM;EACrB,IAAI,MAAM,KAAK,SAAS,QAAQ;GAC9B,MAAM,KAAK;GACX,MAAM,KAAK;EACb;CACF;CAGA,MAAM,OAAY,CAAC;CACnB,MAAM,QAAe,CAAC,IAAI;CAC1B,IAAI,SAAS;CACb,MAAM,UAAU,SAAkB;EAChC,CAAC,MAAM,GAAG,EAAE,KAAK,KAAA,CAAM,KAAK,IAAI;CAClC;CACA,MAAM,kBAAwB;EAC5B,IAAI,CAAC,QAAQ;EACb,OAAO,KAAK,MAAM,CAAC;EACnB,SAAS;CACX;CACA,KAAK,MAAM,QAAQ,OACjB,IAAI,KAAK,SAAS,QAChB,UAAU,KAAK;MACV,IAAI,KAAK,SAAS,aACvB,UAAU,SAAS;MACd,IAAI,KAAK,SAAS,QAAQ;EAC/B,UAAU;EACV,OAAO,KAAK,IAAI;CAClB,OAAO,IAAI,KAAK,SAAS,WAAW;EAClC,UAAU;EACV,MAAM,KAAK,CAAC,CAAC;CACf,OAAO;EACL,UAAU;EACV,OAAO,KAAK,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC;CAChC;CAEF,UAAU;CACV,OAAO;AACT,CAAC;;ACjNH,MAAM,UAAU,MAAsC,SACpD,SAAS,KAAA,KAAa,UAAU,QAAQ,KAAK,SAAS;;;;AAKxD,MAAM,aACJ,OACA,UACW;CACX,IAAI,QAAQ;CACZ,IAAI,WAAW;CACf,KAAK,IAAI,IAAI,QAAQ,GAAG,IAAI,MAAM,QAAQ,KAAK;EAC7C,IAAI,UAAU;GACZ,WAAW;GACX;EACF;EACA,MAAM,OAAO,MAAM;EACnB,MAAM,OAAO,MAAM,IAAI;EACvB,IAAI,OAAO,MAAM,GAAG,KAAK,OAAO,MAAM,GAAG,GAAG;GAC1C;GACA,IAAI,UAAU,GAAG,OAAO;GACxB,WAAW;EACb,OAAO,IAAI,OAAO,MAAM,GAAG,KAAK,OAAO,MAAM,GAAG,GAAG;GACjD;GACA,WAAW;EACb,OAAO,IACL,OAAO,MAAM,IAAI,KAChB,QAAQ,UAAU,QAAQ,KAAK,KAAK,SAAS,SAE9C,OAAO;CAEX;CACA,OAAO;AACT;;AAGA,MAAa,sBACX,UAEA,oBAAoB,QAAQ,UAAU,aAAa,EAAE,MAAM,WAAW;CACpE,MAAM,QAAwB,SAAS,SAAS,UAA0B;EACxE,MAAM,QAAQ,MAAM,SAAS,SAAS,MAAM,QAAQ,KAAA;EACpD,OAAO,UAAU,KAAA,IACb,CAAC,EAAE,MAAM,MAAM,CAAC,IAChB,MAAM,KAAK,QAAQ,UAAU,EAAE,KAAK,EAAE;CAC5C,CAAC;CAGD,MAAM,QACJ,SACmC;EACnC,MAAM,MAAW,CAAC;EAClB,IAAI,QAAQ;EACZ,IAAI,SAAS;EACb,MAAM,kBAAwB;GAC5B,IAAI,QAAQ,IAAI,KAAK,KAAK,MAAM,CAAC;GACjC,SAAS;EACX;EACA,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,SAAS;GAChC,MAAM,OAAO,KAAK;GAClB,IAAI,OAAO,MAAM,GAAG,KAAK,OAAO,KAAK,IAAI,IAAI,GAAG,GAAG;IACjD,MAAM,MAAM,UAAU,MAAM,CAAC;IAC7B,IAAI,OAAO,GAAG;KACZ,QAAQ;KACR,UAAU;KACV,IAAI,KAAK,KAAK,KAAK,KAAK,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;KACjD,IAAI,MAAM;KACV;IACF;GACF;GACA,IAAI,QAAQ,UAAU,MAAM,UAAU,KAAK;QACtC,IAAI,MAAM;IACb,UAAU;IACV,IAAI,KAAK,KAAK,IAAI;GACpB;GACA;EACF;EACA,UAAU;EACV,OAAO;GAAE,OAAO;GAAK;EAAM;CAC7B;CAEA,MAAM,EAAE,OAAO,QAAQ,UAAU,KAAK,KAAK;CAC3C,OAAO,QAAQ,SAAS;AAC1B,CAAC;;;ACjFH,MAAM,UAAU;CACd,KAAK;EAAE,MAAM;EAAK,MAAM;CAAY;CACpC,KAAK;EAAE,MAAM;EAAI,MAAM;CAAc;AACvC;AAMA,MAAM,aAAa,SAA4B;AAC/C,MAAM,aAAa,SACjB,UAAU,GAAG,KAAK,kBAAkB;AACtC,MAAM,YAAY,cAChB,OAAO,OAAO,OAAO,CAAC,CAAC,MAAM,EAAE,WAAW,UAAU,IAAI,MAAM,SAAS;AAGzE,MAAM,cAAc;AACpB,MAAMC,eAAa;AACnB,MAAM,YAAY,SAChB,SAAS,QACT,OAAO,KACP,SAAS,MACTA,aAAW,KAAK,OAAO,aAAa,IAAI,CAAC,IACrC,IACA,YAAY,KAAK,OAAO,aAAa,IAAI,CAAC,IACxC,IACA,KAAA;AAGR,MAAM,UACJ,MACA,OACA,QACA,UACS;CACT,KAAK,OAAO,OAAO,MAAM;CACzB,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,KACrC,KAAK,OAAO,QAAQ,GAAG,GAAG,GAAG,MAAM,MAAM,GAAG,IAAI,GAAM,CAAC;AAE3D;AAGA,MAAM,cACJ,YACA,QACA,YACY;CACZ,MAAM,SAAqB,CAAC;CAC5B,IAAI,SAAS;CACb,KAAK,MAAM,EAAE,YAAY,aAAa,YACpC,IAAI,WAAW,CAAC,OAAO,SAAS,OAAO,GAAG;EACxC,SAAS,QAAQ,QAAQ,OAAO;EAChC,OAAO,KAAK,OAAO;CACrB;CAEF,OAAO;AACT;AAEA,MAAM,kBAA4B,QAAQ,YAAY;CACpD,KAAK,IAAI,QAAQ,GAAG,QAAQ,OAAO,QAAQ,SAAS;EAClD,MAAM,CAAC,MAAM,UAAU,OAAO,GAAG,KAAK,KAAK,CAAC;EAC5C,MAAM,SAAS,UAAU,SAAS,OAAO,IAAI;EAC7C,IAAI,SAAS,WAAW,CAAC,UAAU,CAAC,UAAU,CAAC,OAAO,QAAQ;EAE9D,KAAK,IAAI,OAAO,QAAQ,GAAG,QAAQ,GAAG,QAAQ;GAC5C,MAAM,CAAC,UAAU,UAAU,OAAO,GAAG,IAAI,KAAK,CAAC;GAC/C,IACE,aAAa,UACb,CAAC,UACD,OAAO,SAAS,OAAO,QACvB,CAAC,OAAO,OAER;GAEF,OAAO,OAAO,UAAU,GAAG,OAAO,KAAK,SAAS;GAChD,OAAO,OAAO,UAAU,GAAG,OAAO,KAAK,SAAS;GAChD,MAAM,OAAO;IACX,MAAM,UAAU,OAAO,IAAI;IAC3B,OAAO,EAAE,GAAG,OAAO,MAAM;IACzB,KAAK,EAAE,GAAG,OAAO,IAAI;GACvB;GACA,MAAM,OAAO;IACX,MAAM,UAAU,GAAG,OAAO,KAAK,KAAK;IACpC,OAAO,EAAE,GAAG,OAAO,IAAI;IACvB,KAAK,EAAE,GAAG,OAAO,MAAM;GACzB;GACA,MAAM,OAAgB;IACpB;KAAC;KAAS;KAAM;IAAO;IACvB;KAAC;KAAS;KAAQ;IAAO;IACzB;KAAC;KAAQ;KAAQ;IAAO;IACxB;KAAC;KAAS;KAAM;IAAO;IAEvB,GAAG,WACD,QAAQ,OAAO,WAAW,WAAW,QAAQ,CAAC,GAC9C,OAAO,MAAM,OAAO,GAAG,KAAK,GAC5B,OACF;IACA;KAAC;KAAQ;KAAM;IAAO;IACtB;KAAC;KAAS;KAAQ;IAAO;IACzB;KAAC;KAAQ;KAAQ;IAAO;IACxB;KAAC;KAAQ;KAAM;IAAO;GACxB;GACA,OAAO,QAAQ,OAAO,GAAG,QAAQ,OAAO,GAAG,IAAI;GAC/C,QAAQ,OAAO,KAAK,SAAS;GAC7B;EACF;CACF;CAEA,KAAK,MAAM,GAAG,UAAU,QACtB,IAAI,SAAS,MAAM,IAAI,GAAG,MAAM,OAAO;CAEzC,OAAO;AACT;AAEA,SAAS,SAEP,SACA,IACA,KACO;CACP,MAAM,EAAE,UAAU,WAAW;CAC7B,QAAQ,UAAgB;EACtB,MAAM,SAAS,OAAO,OAAO,OAAO,CAAC,CAAC,MAAM,MAAM,EAAE,SAAS,KAAK;EAClE,IAAI,CAAC,QAAQ,OAAO,IAAI,KAAK;EAE7B,IACE,aAAa,OAAO,QACpB,OAAO,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,SAAS,mBAE5B,OAAO,IAAI,KAAK;EAClB,QAAQ,MAAM,UAAU,OAAO,IAAI,CAAC;EACpC,QAAQ,QAAQ,KAAK;EACrB,QAAQ,UAAgB;GAEtB,IAAI,UAAU,OAAO,MAAM,OAAO,IAAI,KAAK;GAC3C,MAAM,QAAQ,QAAQ,KAAK,UAAU,OAAO,IAAI,CAAC;GACjD,MAAM,SAAS,SAAS,QAAQ;GAChC,MAAM,OAAO,SAAS,KAAK;GAC3B,MAAM,QAAQ,CAAC,QAAS,SAAS,KAAK,QAAQ,MAAM;GACpD,MAAM,SAAS,CAAC,UAAW,WAAW,KAAK,QAAQ,IAAI;GACvD,OAAO,GAAG,KAAK;EACjB;CACF;AACF;;;;AAWA,MAAa,gBAAgB,WAAiC;CAC5D,MAAM,YAAuB;EAC3B,MAAM,QAAQ,OAAO,CAAC;EACtB;EACA,YAAY;CACd;CACA,OAAO;EACL,MAAM,GAAG,QAAQ,OAAO,CAAC,OAAO,UAAU;EAC1C,YAAY,EAAE,MAAM,CAAC,SAAS,EAAE;CAClC;AACF;;;AC7KA,MAAa,oCAAoB,IAAI,QAAmB;;AAkBxD,MAAM,mBACJ,YACA,UACe;CACf,MAAM,SAAqB,EAAE,GAAG,WAAW;CAC3C,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,GAAG;EAChD,MAAM,WAAW,OAAO;EACxB,OAAO,OACL,QAAQ,eAAe,MAAM,QAAQ,QAAQ,KAAK,MAAM,QAAQ,KAAK,IACjE,CAAC,GAAG,UAAU,GAAG,KAAK,IACtB;CACR;CACA,OAAO;AACT;AAGA,MAAM,aAAa,SACjB,MAAM,SAAS,UACf,QAAQ,KAAK,MAAM,KACnB,KAAK,SAAS,MAAM,SAAS,KAAK,UAAU,KAAK,SAAS,SAAS,CAAC;;;;AAKtE,MAAa,sBACX,MACA,aACA,SACS;CACT,MAAM,0BAAU,IAAI,IAAkB;CACtC,MAAM,MAAmB,CAAC;CAC1B,MAAM,QAAsB,CAAC;CAC7B,MAAM,QAAQ,SAAqB;EACjC,IAAI,KAAK,SAAS,eAAe,kBAAkB,IAAI,IAAI,GACzD,IAAI,KAAK,IAAI;EACf,MAAM,OAAgB,KAAK;EAC3B,IACE,OAAO,SAAS,YAChB,SAAS,QACT,eAAe,QACf,KAAK,cAAc,mBACnB,gBAAgB,QAChB,MAAM,QAAQ,KAAK,UAAU,GAI7B,MAAM,KAAK,IAA6B;EAC1C,IAAI,EAAE,cAAc,OAAO;EAC3B,KAAK,MAAM,SAAS,KAAK,UAAU;GACjC,QAAQ,IAAI,OAAO,IAAI;GACvB,KAAK,KAAK;EACZ;CACF;CACA,KAAK,IAAI;CAET,KAAK,MAAM,QAAQ,KAAK;EACtB,MAAM,WAA8B,KAAK;EACzC,MAAM,OAAO,SAAS,GAAG,EAAE;EAC3B,IAAI,MAAM,SAAS,QAAQ;EAC3B,MAAM,QAAQ,KAAK,MAAM,QAAQ;EACjC,MAAM,YAAY,MAAM,YAAY,IAAI;EACxC,MAAM,OAAO,MAAM,MAAM,YAAY,CAAC;EACtC,MAAM,OAAO,KAAK,YAAY,GAAG;EACjC,IAAI,SAAS,IAAI;EACjB,MAAM,aAAa,KAAK,KAAK,MAAM,IAAI,CAAC;EACxC,IAAI,CAAC,YAAY;EACjB,MAAM,SAAS,KAAK,MAAM,GAAG,IAAI;EACjC,MAAM,UACJ,OAAO,KAAK,MAAM,OACjB,cAAc,MAAM,SAAS,GAAG,EAAE,CAAC,EAAE,SAAS;EAEjD,IAAI,WAAW,MAAM,CAAC,SAAS;EAE/B,MAAM,YAAsB,CAAC;EAC7B,KAAK,IAAI,IAAI,QAAQ,IAAI,IAAI,GAAG,GAAG,IAAI,QAAQ,IAAI,CAAC,GAAG,UAAU,QAAQ,CAAC;EAC1E,MAAM,SAAS,UAAU,GAAG,EAAE;EAE9B,IAAI,SAAe;EACnB,IAAI,SAAS;GACX,MAAM,MAAM,KAAK,UAAU;GAC3B,MAAM,UAAU,MAAO,YAAY,IAAI,OAAO,MAAM,KAAM;GAC1D,MAAM,SAAS,WAAW,KAAK,OAAO,CAAC,GAAG,MAAM;GAChD,MAAM,UAAU,OAAO,MAAM,GAAG,CAAC,CAAC,SAAS;GAC3C,MAAM,UAAU,MACZ,UAAU,WAAW,aAAa;IAChC,MAAM,QAAQ,SAAS,UAAU;IACjC,IAAI,SAAS,SAAS,gBAAgB,OAAO;KAC3C,MAAM,OAAO,YAAY,MAAM,OAAO,MAAM,GAAA,CAAI,MAC9C,GACA,MAAM,SAAS,CACjB;KACA,OAAO,UAAU,IAAI,MAAM,GAAG,CAAC,CAAC;IAClC;IACA,MAAM,QACJ,SAAS,SAAS,aACd,SAAS,SAAS,EAAE,EAAE,UAAU,QAChC,KAAA;IACN,OAAO,UAAU,KAAA,KAAa,OAAO,SAAS,MAAM,SAAS;GAC/D,CAAC,IACD;GACJ,MAAM,YAAY,UAAU;GAC5B,IAAI,WACF,SACE,UAAU,SAAS,aACd,UAAU,UAAU,MAAM,YAC3B;QACH,IAAI,QAAQ,SAAS,cAAc,CAAC,UAAU,UAAU,GAAG,EAAE,CAAC,GACjE,SAAS;EACb,OAAO,IAAI,QAAQ,SAAS,cAAc,OAAO,SAAS,OAAO,MAC/D,SAAS;EAGX,MAAM,OAAiD,OAAO;EAC9D,OAAO,OAAO;GACZ,GAAG;GACH,aAAa,gBAAgB,MAAM,aAAa,UAAU;EAC5D;EACA,MAAM,OAAO,UACT,MAAM,MAAM,GAAG,KAAK,IAAI,WAAW,CAAC,CAAC,IACrC,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI;EACpC,IAAI,KAAK,QAAQ,MAAM,IAAI,SAAS,IAAI;OACnC,KAAK,QAAQ,KAAK,QAAQ;CACjC;CAMA,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,QAAQ,KAAK,KAAK;EACxB,MAAM,OAAO,MAAM,GAAG,EAAE;EACxB,IAAI,MAAM,SAAS,QAAQ;EAC3B,MAAM,QAAQ,KAAK,MAAM,QAAQ;EACjC,MAAM,OAAO,MAAM,YAAY,GAAG;EAClC,IAAI,SAAS,IAAI;EACjB,MAAM,aAAa,KAAK,MAAM,MAAM,IAAI,CAAC;EACzC,IAAI,CAAC,YAAY;EACjB,KAAK,KAAK,cAAc,gBAAgB,KAAK,KAAK,aAAa,UAAU;EACzE,KAAK,QAAQ,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,QAAQ;EAC1C,IAAI,KAAK,UAAU,MAAM,MAAM,SAAS,GAAG,MAAM,IAAI;CACvD;AACF;;;ACvJA,MAAa,eAAe,UACzB,WAAW,KAAK,IAAI,CAAC,GAAG,MAAM,GAAA,CAAI,MAAM,GAAG,CAAC,CAAC,SAAS;;AAGzD,MAAa,qBACX,IACA,gBACuB;CACvB,MAAM,QAAQ,GAAG,UAAU;CAC3B,IAAI,CAAC,OAAO,OAAO,KAAA;CACnB,OACE,aACG,YAAY,MAAM,OAAO,MAAM,GAAA,CAAI,MAAM,GAAG,MAAM,SAAS,CAAC,CAC/D,IAAI;AAER;;;;AAWA,MAAa,eACX,MACA,gBACwB;CACxB,MAAM,QAA6B,CAAC,CAAC,CAAC;CACtC,KAAK,MAAM,SAAS,KAAK,UACvB,IAAI,MAAM,SAAS,SAAS;EAC1B,MAAM,GAAG,EAAE,CAAC,EAAE,KAAK,KAAK;EACxB,MAAM,KAAK,CAAC,CAAC;CACf,OAAO,IAAI,MAAM,SAAS,QAAQ;EAChC,MAAM,QAAQ,MAAM,MAAM,MAAM,IAAI;EACpC,KAAK,MAAM,CAAC,GAAG,SAAS,MAAM,QAAQ,GAAG;GACvC,IAAI,IAAI,GAAG,MAAM,KAAK,CAAC,CAAC;GACxB,IAAI,SAAS,IAAI;GACjB,MAAM,OAAa;IAAE,MAAM;IAAQ,OAAO;GAAK;GAC/C,MAAM,WAAW,MAAM;GACvB,IAAI,UAAU;IACZ,MAAM,OAAO,SAAS,MAAM,OAAO;IACnC,MAAM,SAAS,cAAc,OAAO;IACpC,MAAM,QACJ,MAAM,IACF,SAAS,QACT,WAAW,KAAA,IACT,KAAA,IACA;KACE;KACA,SAAS,WAAW,KAAK,MAAM,CAAC,GAAG,EAAE,CAAC,UAAU,KAAK;IACvD;IACR,MAAM,MACJ,MAAM,MAAM,SAAS,IACjB,SAAS,MACT,WAAW,KAAA,IACT,KAAA,IACA;KAAE;KAAM,QAAQ,OAAO,QAAQ,CAAC,CAAC,SAAS;IAAE;IACpD,IAAI,SAAS,KAAK,KAAK,WAAW;KAAE;KAAO;IAAI;GACjD;GACA,MAAM,GAAG,EAAE,CAAC,EAAE,KAAK,IAAI;EACzB;CACF,OACE,MAAM,GAAG,EAAE,CAAC,EAAE,KAAK,KAAK;CAG5B,OAAO;AACT;;AAGA,MAAa,uBACX,SAC2B;CAE3B,OADuD,KAAK,MAC/C;AACf;;AAGA,MAAM,gBACJ,UACA,SACS;CACT,MAAM,OAAO,SAAS,GAAG,EAAE;CAC3B,IAAI,KAAK,SAAS,UAAU,MAAM,SAAS,QAAQ;EACjD,SAAS,KAAK,IAAI;EAClB;CACF;CAEA,MAAM,QACJ,KAAK,UAAU,UACd,KAAK,MAAM,KAAK,MAAM,KAAK,KAAK,UAAU,QAAQ,KAAA;CACrD,MAAM,MAAM,KAAK,UAAU,OAAO,KAAK,UAAU;CACjD,MAAM,SAAe;EAAE,MAAM;EAAQ,OAAO,KAAK,QAAQ,KAAK;CAAM;CACpE,IAAI,SAAS,KAAK,OAAO,WAAW;EAAE;EAAO;CAAI;CACjD,SAAS,SAAS,SAAS,KAAK;AAClC;;AAGA,MAAa,oBACX,UACqB;CACrB,MAAM,WAA8B,CAAC;CACrC,KAAK,MAAM,CAAC,GAAG,SAAS,MAAM,QAAQ,GAAG;EACvC,IAAI,IAAI,KAAK,MAAM,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,SAAS,SAC1C,aAAa,UAAU;GAAE,MAAM;GAAQ,OAAO;EAAK,CAAC;EACtD,KAAK,MAAM,QAAQ,MAAM,aAAa,UAAU,IAAI;CACtD;CACA,IAAI,SAAS,WAAW,GAAG,OAAO;CAClC,MAAM,OAAkB;EAAE,MAAM;EAAa;CAAS;CACtD,MAAM,QAAQ,SAAS,EAAE,EAAE,UAAU;CACrC,MAAM,MAAM,SAAS,GAAG,EAAE,CAAC,EAAE,UAAU;CACvC,IAAI,SAAS,KAAK,KAAK,WAAW;EAAE;EAAO;CAAI;CAC/C,kBAAkB,IAAI,IAAI;CAC1B,OAAO;AACT;;;;AAKA,MAAa,oBACX,OACA,UAC4C;CAC5C,MAAM,SAAS,MAAM,WAAW,EAAE,cAAc,UAAU,KAAK;CAC/D,MAAM,MAAM,WAAW,KAAK,QAAQ,MAAM,MAAM,GAAG,MAAM;CACzD,MAAM,OAAO,iBAAiB,IAAI,KAAK,EAAE,WAAW,IAAI,CAAC;CACzD,MAAM,SAAkD,OAAO,CAAC,IAAI,IAAI,CAAC;CACzE,IAAI,WAAW,IAAI;EACjB,MAAM,QAAoB;GACxB,MAAM;GACN,UAAU,iBAAiB,MAAM,MAAM,MAAM,GAAG,QAAQ,CAAC;EAC3D;EACA,OAAO,KAAK,KAAK;CACnB;CACA,OAAO;AACT;;AAWA,MAAa,gCAAqC,IAAI,IAAI;CACxD;CACA;CACA;CACA;AACF,CAAC;;AAGD,MAAa,kCAAuC,IAAI,IAAI;CAC1D;CACA;CACA;AACF,CAAC;;;;AAKD,MAAa,sBACX,MACA,aACA,QACA,UACuB;CACvB,MAAM,QAAQ,KAAK,UAAU,MAAM;CACnC,IAAI,UAAU,KAAA,GAAW,OAAO;CAChC,MAAM,QAAQ,YAAY,MAAM,WAAW;CAC3C,MAAM,KAAK,MAAM,WAAW,MAAM,UAAU;EAC1C,MAAM,QAAQ,KAAK;EACnB,OACE,QAAQ,KACR,OAAO,SAAS,UAChB,MAAM,MAAM,KAAK,KACjB,YAAY,YAAY,QAAQ,IAAI,UAAU,EAAE,MAAM;CAE1D,CAAC;CACD,IAAI,OAAO,IAAI,OAAO;CACtB,MAAM,OAAO,iBAAiB,MAAM,MAAM,GAAG,EAAE,CAAC;CAChD,MAAM,OAAO,iBAAiB,MAAM,MAAM,EAAE,CAAC;CAC7C,IAAI,CAAC,QAAQ,CAAC,MAAM,OAAO;CAC3B,IAAI,KAAK,MAAM,KAAK,OAAO,KAAK;CAChC,OAAO,CAAC,MAAM,IAAI;AACpB;AAGA,MAAM,iBACJ,SAC0B;CAC1B,MAAM,OAAO,MAAM,UAAU,GAAG,EAAE;CAClC,IAAI,CAAC,MAAM,OAAO,KAAA;CAGlB,IAAI,KAAK,SAAS,aAAa,OAAO;CACtC,OAAO,cAAc,IAAI;AAC3B;;;;AAKA,MAAa,sBACX,MACA,aACA,aACS;CACT,MAAM,SAAS,MAAqB,WAAyB;EAC3D,MAAM,WAAW,KAAK;EACtB,IAAI,CAAC,UAAU;EACf,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;GACxC,MAAM,QAAQ,SAAS;GACvB,MAAM,OAAO,UAAU,cAAc,IAAI,MAAM,IAAI,IAAI,IAAI,EAAE;GAC7D,IAAI,MAAM,SAAS,UAAU;GAC7B,MAAM,OAAO,cAAc,MAAM,UAAU,GAAG,EAAE,CAAC;GACjD,MAAM,QAAQ,MAAM,UAAU,MAAM;GACpC,IAAI,CAAC,QAAQ,UAAU,KAAA,GAAW;GAClC,MAAM,QAAQ,YAAY,MAAM,WAAW;GAE3C,MAAM,UAAU,MAAM,WACnB,GAAG,UACF,QAAQ,KACR,YAAY,YAAY,QAAQ,IAAI,UAAU,EAAE,IAAI,SAAS,CACjE;GACA,IAAI,YAAY,IAAI;GACpB,MAAM,OAAO,iBAAiB,MAAM,MAAM,GAAG,OAAO,CAAC;GACrD,MAAM,QAAQ,iBAAiB,MAAM,MAAM,OAAO,CAAC;GACnD,IAAI,CAAC,QAAQ,CAAC,OAAO;GACrB,KAAK,WAAW,KAAK;GACrB,MAAM,OAAiD,KAAK;GAC5D,IAAI,MAAM,aAAa;IACrB,MAAM,EAAE,aAAa,GAAG,SAAS;IAEjC,MAAM,OAAO,EADqC,YAC7B;IACrB,KAAK,OAAO;GACd;GAGA,SAAS,OAAO,IAAI,GAAG,GAAG,KAAiC;EAC7D;CACF;CAGA,MAAM,MAAuB,CAAC;AAChC;;;;;ACzPA,MAAa,kBACX,MACA,eACW;CACX,MAAM,SAAS,WAAW,KAAK,IAAI,CAAC,GAAG,MAAM;CAC7C,MAAM,UAAU,OAAO,MAAM,GAAG,CAAC,CAAC,SAAS;CAC3C,IAAI,OAAO;CACX,KAAK,MAAM,aAAa,YAAY;EAClC,IACE,UAAU,SAAS,UACf,UAAU,UAAU,UACpB,OAAO,SAAS,UAAU,QAE9B;EACF;CACF;CACA,OAAO;AACT;;;;AAKA,MAAa,eAAe,SAA2B;CACrD,MAAM,UAAoB,CAAC;CAC3B,IAAI,MAAM;CACV,SAAS;EACP,OAAO,KAAK,SAAS,OAAO,KAAK,SAAS,MAAM;EAChD,IAAI,KAAK,SAAS,KAAK;GACrB;GACA;EACF;EACA,MAAM,SAAS,oCAAoC,KAAK,KAAK,MAAM,GAAG,CAAC;EACvE,IAAI,CAAC,QAAQ,OAAO;EACpB,MAAM,MAAM,MAAM,OAAO,EAAE,CAAC;EAC5B,IAAI,SAAS;EACb,OAAO,KAAK,MAAM,YAAY,OAAO,KAAK,MAAM,YAAY,MAAM;EAClE,MAAM,SACJ,MAAM,WAAW,KAAK,UAAU,SAAS,IAAI,MAAM,IAAI,MAAM;EAC/D,QAAQ,KAAK,MAAM;EACnB,IAAI,SAAS,GAAG,OAAO;EACvB,MAAM;CACR;AACF;;;AC5CA,MAAa,gBAAgB;;AAG7B,MAAa,iBAAiB,SAC5B,cAAc,KAAK,KAAK,QAAQ,YAAY,EAAE,CAAC;;AAGjD,MAAa,iBAAiB,SAC5B,iBAAiB,KAAK,IAAI;;AAG5B,MAAa,sBAAsB,SACjC,KAAK,QAAQ,aAAa,EAAE;;;;AAK9B,MAAM,8BAAc,IAAI,IAAI;CAC1B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;;AAGD,MAAa,oBAAoB,WAAoC;CACnE,MAAM,EACJ,OAAO,YACP,WAAW,gBACX,GAAG,SACD,UAAU,CAAC;CACf,MAAM,QAAQ,CAAC,YAAY,cAAc,CAAC,CACvC,KAAK,CAAC,CACN,SAAS,UAAW,OAAO,UAAU,WAAW,MAAM,MAAM,GAAG,IAAI,CAAC,CAAE,CAAC,CACvE,QAAQ,UAAU,UAAU,EAAE;CACjC,OAAO;EAAE,WAAW,CAAC,eAAe,GAAG,KAAK;EAAG,GAAG;CAAK;AACzD;AAcA,MAAMC,eAAa;AAInB,MAAM,cAAc,aAClB,SAAS,MAAM,UAAU,MAAM,SAAS,MAAM,KAC9C,SAAS,OACN,OAAO,UACN,MAAM,SAAS,WACd,MAAM,SAAS,WACbA,aAAW,KAAK,MAAM,SAAS,EAAE,KAC/B,SAAS,KAAK,MAAM,SAAS,EAAE,KAC9B,SAAS,QAAQ,EAAE,EAAE,SAAS,YACnC,MAAM,SAAS,WACb,MAAM,YAAY,CAAC,EAAA,CAAG,SAAS,MAC/B,MAAM,YAAY,CAAC,EAAA,CAAG,OAAO,UAAU,MAAM,SAAS,OAAO,CACpE;AAEF,MAAM,UACJ,SACA,SACA,YACU;CACV,MAAM;CACN,MAAM;EAAE,OAAO;EAAU,aAAa,iBAAiB,MAAM;CAAE;CAC/D,UAAU,CACR,GAAG,SACH;EACE,MAAM;EACN,MAAM,EAAE,OAAO,aAAa;EAC5B,UAAU;CACZ,CACF;AACF;AAGA,MAAM,kBAAkB,UAAkD;CACxE,MAAM,QAAQ,MAAM,EAAE,GAAG;CACzB,IAAI,OAAO,SAAS,QAAQ;EAC1B,MAAM,QAAQ,mBAAmB,MAAM,KAAK;EAC5C,MAAM,KAAK,QACP,CAAC;GAAE,GAAG;GAAO;EAAM,GAAG,GAAG,MAAM,EAAE,CAAE,MAAM,CAAC,CAAC,IAC3C,MAAM,EAAE,CAAE,MAAM,CAAC;CACvB;CACA,OAAO,iBAAiB,KAAK,CAAC,EAAE,YAAY,CAAC;AAC/C;AAGA,MAAM,kBAAkB,SAAuC;CAC7D,MAAM,OAAO,KAAK;CAClB,IAAI,CAAC,MAAM,aAAa,OAAO,KAAA;CAC/B,MAAM,EAAE,aAAa,GAAG,SAAS;CACjC,KAAK,OAAO;CACZ,OAAO;AACT;;;;AAKA,MAAa,mBAAmB,MAAY,WAAyB;CACnE,IAAI,CAAC,OAAO,SAAS,IAAI,GAAG;CAC5B,MAAM,cAAc,OAAO,MAAM,OAAO;CACxC,MAAM,0BAAU,IAAI,IAAgB;CACpC,MAAM,aAAqB,CAAC;CAC5B,MAAM,SAAiB,CAAC;CACxB,MAAM,QAAQ,SAAqB;EACjC,IAAI,KAAK,SAAS,aAAa,WAAW,KAAK,IAAI;OAC9C,IAAI,KAAK,SAAS,SAAS,OAAO,KAAK,IAAI;EAChD,KAAK,MAAM,SAAS,KAAK,YAAY,CAAC,GAAG;GACvC,QAAQ,IAAI,OAAO,IAAI;GACvB,KAAK,KAAK;EACZ;CACF;CACA,KAAK,IAAuB;CAE5B,MAAM,WAAW,MAAY,gBAAmC;EAC9D,MAAM,SAAS,QAAQ,IAAI,IAAI;EAC/B,MAAM,WAAW,QAAQ;EACzB,IAAI,CAAC,UAAU,CAAC,UAAU;EAC1B,MAAM,QAAQ,SAAS,QAAQ,IAAI;EACnC,IAAI,UAAU,IAAI;EAClB,IAAI,aAAa;GACf,SAAS,OAAO,OAAO,GAAG,WAAW;GACrC,QAAQ,IAAI,aAAa,MAAM;GAC/B,QAAQ,IAAI,MAAM,WAAW;EAC/B,OAAO,SAAS,OAAO,OAAO,CAAC;CACjC;CACA,MAAM,aAAa,SACjB,QAAQ,IAAI,IAAI,CAAC,EAAE,SAAS;CAE9B,MAAM,eAAe,SAAuB;EAC1C,MAAM,YAAoB,CAAC;EAC3B,KAAK,IAAI,IAAI,QAAQ,IAAI,IAAI,GAAG,GAAG,IAAI,QAAQ,IAAI,CAAC,GAAG,UAAU,QAAQ,CAAC;EAC1E,OAAO;CACT;CAGA,MAAM,gBACJ,cAC6D;EAC7D,MAAM,aAA2D,CAAC;EAClE,MAAM,WAAW,OAAe,SAC9B,UACG,MAAM,GAAG,KAAK,CAAC,CACf,QAAQ,CAAC,CACT,MAAM,MAAM,EAAE,SAAS,IAAI;EAChC,IAAI,SAAS;EACb,KAAK,MAAM,CAAC,OAAO,aAAa,UAAU,QAAQ,GAAG;GACnD,MAAM,SAAS,WAAmC;IAChD,WAAW,KAAK;KACd,QAAQ,UAAU;KAClB,MAAM;MAAE,MAAM;MAAS,SAAS,EAAE;KAAO;IAC3C,CAAC;GACH;GACA,QAAQ,SAAS,MAAjB;IACE,KAAK;IACL,KAAK;KACH,MAAM,QAAQ;KACd;IAEF,KAAK;IACL,KAAK;KACH,MAAM,QAAQ,OAAO,UAAU,CAAC;KAChC;IAEF,KAAK;KACH,IAAI,EAAE,SAAS,YAAY,CAAC,EAAA,CAAG,MAAM,MAAM,EAAE,SAAS,WAAW,GAC/D,MAAM,QAAQ,OAAO,WAAW,CAAC;KACnC;IACF,KAAK;KACH,MAAM,QAAQ,OAAO,WAAW,CAAC;KACjC;IACF,KAAK;IACL,KAAK;IACL,KAAK,sBAAsB;KACzB,MAAM,SAAS,SAAS,WAAW,EAAE,EAAE,UAAU,MAAM;KACvD,IAAI,WAAW,KAAA,GAAW,OAAO,KAAA;KACjC,WAAW,KAAK;MACd,QAAQ,UAAU,QAAQ,MAAM;MAChC,MAAM;OAAE,MAAM;OAAQ,QAAQ,SAAS;MAAE;KAC3C,CAAC;KACD;IACF;GAEF;EACF;EACA,OAAO;CACT;CAGA,KAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,OAAO,MAAM,YAAY,CAAC;EAChC,MAAM,QAAQ,KAAK,WAAW,KAAK,UAAU;GAC3C,MAAM,OAAO,IAAI,UAAU,MAAM;GACjC,MAAM,OAAO,IAAI,WAAW,EAAE,EAAE,WAAW;GAC3C,OACE,QAAQ,KACR,SAAS,KAAA,KACT,cAAc,YAAY,OAAO,MAAM,EAAE,KACzC,MAAM,SAAS,UACf,cAAc,KAAK,SAAS,EAAE;EAElC,CAAC;EACD,IAAI,UAAU,IAAI;EAClB,MAAM,cAAc,KAAK,MAAM,KAAK;EACpC,MAAM,WAAW,YAAY,GAAG,EAAE,CAAC,EAAE,WAAW;EAChD,MAAM,SAAS,WAAW,eAAe,QAAQ,IAAI,KAAA;EACrD,MAAM,UAAU,eACd,YAAY,KACT,QACE,IAAI,WAAW,EAAE,EAAE,YAAY,CAAC,CACrC,CACF;EACA,MAAM,WAAW,KAAK,MAAM,GAAG,KAAK;EACpC,QAAQ,OAAO,OAAO,CAAC,KAAK,GAAG,SAAS,MAAM,CAAC;CACjD;CAGA,KAAK,MAAM,QAAQ,WAAW,QAAQ,GAAG;EACvC,MAAM,QAAQ,KAAK,UAAU,MAAM;EACnC,IAAI,UAAU,KAAA,GAAW;EACzB,MAAM,QAAQ,YACZ,MACA,WACF;EAEA,MAAM,SAAS,QAAQ,IAAI,IAAI;EAI/B,MAAM,SAFJ,QAAQ,SAAS,WAChB,QAAQ,SAAS,gBAAgB,OAAO,MAAM,cAAc,KAAA,MAEpD,kBAAkB,YAAY,QAAQ,MAAM,EAAE,IACnD,QAAQ,IACR;EACN,MAAM,eAAe,UAA2B;GAC9C,MAAM,OAAO,MAAM,MAAM,GAAG;GAC5B,OACE,cAAc,YAAY,QAAQ,QAAQ,MAAM,EAAE,KAClD,MAAM,SAAS,UACf,cAAc,KAAK,KAAK;EAE5B;EAGA,IAAI,YAAY,CAAC,GAAG;GAElB,MAAM,WADS,QAAQ,IAAI,IACL,CAAC,EAAE,YAAY,CAAC;GACtC,MAAM,SAAS,SAAS,SAAS,QAAQ,IAAI,IAAI;GACjD,MAAM,QAAQ,YAAY,QAAQ;GAClC,IACE,CAAC,UACD,YAAY,IAAI,OAAO,IAAI,KAC3B,UAAU,KAAA,KACV,MAAM,QAAQ,YAAY,EAAE,MAAM,IAElC;GACF,MAAM,SAAS,eAAe,IAAI;GAClC,QAAQ,MAAM,IAAI;GAClB,QAAQ,QAAQ,OAAO,CAAC,MAAM,GAAG,eAAe,KAAK,GAAG,MAAM,CAAC;GAC/D;EACF;EAGA,IAAI;EACJ,MAAM,WAAiE,CAAC;EACxE,KAAK,IAAI,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS;GACjD,IAAI,CAAC,YAAY,KAAK,GAAG;GACzB,eAAe,aAAa,YAAY,IAAI,CAAC;GAC7C,IAAI,CAAC,YAAY;GACjB,MAAM,OAAO,eACX,YAAY,QAAQ,QAAQ,MAAM,IAClC,WAAW,KAAK,MAAM,EAAE,IAAI,CAC9B;GAEA,MAAM,WAAW,SAAS,GAAG,EAAE;GAC/B,IAAI,YAAY,QAAQ,SAAS,MAAM;GACvC,MAAM,SAAS,WAAW,KAAK,EAAE,UAAU;GAC3C,IAAI,UAAU,MAAM,GAAG;GACvB,SAAS,KAAK;IAAE;IAAO;IAAM;GAAO,CAAC;EACvC;EACA,IAAI,SAAS,WAAW,GAAG;EAE3B,MAAM,OAAO,MAAM,MAAM,GAAG,SAAS,EAAE,CAAE,KAAK;EAE9C,MAAM,WAAW,KAAK,GAAG,EAAE;EAC3B,IAAI,UAAU,GAAG,EAAE,CAAC,EAAE,SAAS,SAC7B,KAAK,KAAK,SAAS,KAAK,SAAS,MAAM,GAAG,EAAE;EAC9C,KAAK,WAAY,iBAAiB,IAAI,CAAC,EAAE,YACvC,CAAC;EACH,MAAM,SAAS,eAAe,IAAI;EAClC,KAAK,MAAM,CAAC,GAAG,YAAY,SAAS,QAAQ,GAAG;GAC7C,MAAM,UAAU,eACd,MAAM,MAAM,QAAQ,OAAO,SAAS,IAAI,EAAE,EAAE,KAAK,CACnD;GAEA,MAAM,aAAa,MAAM,SAAS,SAAS,IAAI,SAAS,KAAA;GACxD,MAAM,EAAE,WAAW;GACnB,IAAI,WAAW,QAAQ,WAAW,KAAK,YAAY,CAAC,CAAC,GACnD,QAAQ,MAAM,OAAO,KAAK,YAAY,CAAC,GAAG,SAAS,UAAU,CAAC;QAC3D,QAAQ,QAAQ,OAAO,CAAC,MAAM,GAAG,SAAS,UAAU,CAAC;EAC5D;CACF;AACF;;ACvTA,MAAM,aAAa;AACnB,MAAM,oBAAoB,SACxB,KAAK,SAAS,UAAU,WAAW,KAAK,KAAK,SAAS,EAAE;;AAG1D,MAAa,oBAAoB,SAC/B,KAAK,YAAY,QAAQ,KAAK,YAAY,CAAC,EAAA,CAAG,MAAM,gBAAgB;;;;AAKtE,MAAa,oBAAoB,SAA4B;CAE3D,MAAM,QACJ,QACA,WACgC;EAChC,IAAI,SAA4B;EAChC,KAAK,MAAM,SAAS,OAAO,YAAY,CAAC,GAAG;GACzC,IAAI,iBAAiB,KAAK,GAAG;GAC7B,IAAI,MAAM,SAAS,WAAW,OAAO;GACrC,IAAI,MAAM,YAAY,OAAO;IAC3B,SAAS;IACT;GACF;GACA,IAAI,CAAC,WAAW,MAAM,YAAY,OAAO,MAAM,YAAY,WAAW;IACpE,MAAM,QAAQ,KAAK,OAAO,IAAI;IAC9B,IAAI,UAAU,SAAS,OAAO;IAC9B,IAAI,UAAU,SAAS,SAAS;IAChC;GACF;GACA,OAAO;EACT;EACA,OAAO;CACT;CACA,OAAO,KAAK,YAAY,OAAO,KAAK,MAAM,KAAK,MAAM;AACvD;;AAGA,MAAa,eAAe,SAAuC;CACjE,IAAI,KAAK,SAAS,WAAW,OAAO,KAAA;CACpC,MAAM,QAAQ,cAAc,KAAK,KAAK,WAAW,EAAE;CACnD,OAAO,QAAQ,OAAO,MAAM,EAAE,IAAI,KAAA;AACpC;;;;AAKA,MAAa,cACX,OACA,SACA,QAAQ,MACA;CAER,IAAI,UAAU;CACd,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,OAAO,YAAY,IAAI;EAC7B,IAAI,SAAS,KAAA,KAAa,OAAO,SAAS,OAAO,SAAS,UAAU;CACtE;CACA,IAAI,YAAY,UAAU,OAAO,CAAC,GAAG,KAAK;CAE1C,MAAM,SAAc,CAAC;CACrB,IAAI,IAAI;CAER,OAAO,IAAI,MAAM,QAAQ,KAAK;EAC5B,MAAM,OAAO,MAAM;EACnB,IAAI,CAAC,QAAQ,YAAY,IAAI,MAAM,SAAS;EAC5C,OAAO,KAAK,IAAI;CAClB;CAEA,OAAO,IAAI,MAAM,QAAQ;EACvB,MAAM,QAAQ;EACd,KAAK,KAAK,IAAI,MAAM,QAAQ,KAAK;GAC/B,MAAM,OAAO,MAAM;GACnB,IAAI,CAAC,QAAQ,YAAY,IAAI,MAAM,SAAS;EAC9C;EACA,OAAO,KACL,QAAQ,SAAS,WAAW,MAAM,MAAM,OAAO,CAAC,GAAG,SAAS,OAAO,CAAC,CACtE;CACF;CACA,OAAO;AACT;;;;AAKA,MAAa,kBAAkB;;;;AAK/B,MAAa,cAAc,QAAwB;CACjD,IAAI,OAAO;CACX,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK,GAAG;EACtC,QAAQ,IAAI,WAAW,CAAC;EACxB,OAAO,KAAK,KAAK,MAAM,QAAQ;CACjC;CACA,OAAO,sBAAsB,SAAS,EAAA,CAAG,SAAS,EAAE;AACtD;;AAGA,MAAa,mBACX,IACA,WACwB;CACxB,MAAM;CACN,SAAS;CACT,YAAY;EACV,MAAM;EACN,WAAW,CAAC,2BAA2B;EACvC,SAAS;EACT,YAAY;CACd;CACA,UAAU,CAAC,KAAK;AAClB;;AAGA,MAAa,kBACX,IACA,OACA,aACyC;CACzC,MAAM;CACN,SAAS;CACT,YAAY;EAAE;EAAI,WAAW,CAAC,mBAAmB;EAAG,UAAU;CAAM;CACpE,UAAU,CACR;EACE,MAAM;EACN,SAAS;EACT,YAAY;GACV,MAAM;GACN,WAAW,CAAC,yBAAyB;GACrC,SAAS;GACT,YAAY;GACZ,WAAW;EACb;EACA,UAAU,CAAC,KAAK;CAClB,GACA,GAAI,UACA,CACE;EACE,MAAM;EACN,SAAS;EACT,YAAY,EAAE,WAAW,CAAC,2BAA2B,EAAE;EACvD,UAAU;CACZ,CACF,IACA,CAAC,CACP;AACF;;AAGA,MAAa,mBAAmB,SAAwC;CACtE,MAAM,YAAY,MAAM,YAAY;CACpC,OACE,MAAM,YAAY,YAClB,MAAM,QAAQ,SAAS,KACvB,UAAU,SAAA,kBAAsB;AAEpC;;ACnLA,MAAM,aAAa;AACnB,MAAM,gBAAgB;;;;AAKtB,MAAa,sBACX,SACwC;CACxC,MAAM,cAAuC,CAAC;CAC9C,KAAK,MAAM,QAAQ,KAAK,MAAM,IAAI,GAAG;EACnC,MAAM,QAAQ,WAAW,KAAK,IAAI;EAClC,IAAI,CAAC,OAAO,OAAO,KAAA;EACnB,YAAY,KAAK,CAAC,MAAM,MAAM,KAAK,MAAM,MAAM,GAAA,CAAI,KAAK,CAAC,CAAC;CAC5D;CACA,OAAO;AACT;;;;AAUA,MAAa,0BACX,kBACwD;CACxD,MAAM,QAAQ,CAAC,GAAG,cAAc,KAAK,CAAC,CAAC,CACpC,MAAM,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,CACnC,KAAK,SAAS,KAAK,QAAQ,eAAe,MAAM,CAAC;CACpD,MAAM,UAAU,IAAI,OAAO,OAAO,MAAM,KAAK,GAAG,EAAE,OAAO,GAAG;CAC5D,QAAQ,UAAU;EAChB,MAAM,QAA4B,CAAC;EACnC,IAAI,OAAO;EACX,KAAK,MAAM,SAAS,MAAM,SAAS,OAAO,GAAG;GAC3C,MAAM,OAAO,MAAM,MAAM;GACzB,IAAI,MAAM,QAAQ,MAChB,MAAM,KAAK,EAAE,MAAM,MAAM,MAAM,MAAM,MAAM,KAAK,EAAE,CAAC;GACrD,MAAM,KAAK;IAAE;IAAM,OAAO,cAAc,IAAI,IAAI,KAAK;GAAG,CAAC;GACzD,OAAO,MAAM,QAAQ,KAAK;EAC5B;EACA,IAAI,MAAM,WAAW,GAAG,OAAO,KAAA;EAC/B,IAAI,OAAO,MAAM,QAAQ,MAAM,KAAK,EAAE,MAAM,MAAM,MAAM,IAAI,EAAE,CAAC;EAC/D,OAAO;CACT;AACF;;ACpBA,MAAM,iBAAiB;AA4CvB,MAAM,qBAAqB,SAAsC;CAC/D,MAAM,IAAI,eAAe,KAAK,IAAI;CAClC,IAAI,CAAC,GAAG,OAAO;CACf,MAAM,GAAG,SAAS,IAAI,SAAS,IAAI,OAAO,MAAM;CAChD,OAAO;EAAE,OAAO,OAAO;EAAQ,QAAQ,SAAS,QAAQ,EAAE;EAAG;CAAK;AACpE;AA6BA,MAAMC,uBACJ,MACA,UACA,kBAAkB,MAClB,YAAY,MACU;CACtB,MAAM,QAAQ,YAAY,IAAI;CAC9B,MAAM,QAAmB,CAAC;CAC1B,IAAI,eAAe;CACnB,MAAM,QAAQ,UACZ,MAAM,SAAS,IACX;EACE;EACA,MAAM,MAAM,MAAM,KAAK;EACvB,WAAW,KAAK,UAAU,MAAM,QAAQ,KAAK;CAC/C,IACA;CAEN,KAAK,MAAM,CAAC,OAAO,aAAa,MAAM,QAAQ,GAAG;EAC/C,MAAM,QAAQ,SAAS;EACvB,IAAI,OAAO,SAAS,QAAQ,OAAO,KAAK,KAAK;EAE7C,MAAM,SAAS,kBAAkB,MAAM,KAAK;EAC5C,IAAI,CAAC,QAAQ,OAAO,KAAK,KAAK;EAE9B,MAAM,EAAE,UAAU;EAClB,IAAI,MAAM,WAAW,KAAK,mBAAmB,UAAU,GAAG,OAAO;EACjE,IAAI,QAAQ,eAAe,GAAG,OAAO,KAAK,KAAK;EAE/C,KAAK,MAAM,KAAK,SAAS,KAAK,GAAG,IAAI,IAAI,OAAO,SAAS,OAAO,CAAC;EACjE,MAAM,UAAU,SAAS,IAAI,KAAK,KAAK,KAAK;EAC5C,SAAS,IAAI,OAAO,MAAM;EAC1B,eAAe;EAEf,MAAM,aAAgC,OAAO,OACzC,CAAC;GAAE,MAAM;GAAQ,OAAO,OAAO;EAAK,GAAG,GAAG,SAAS,MAAM,CAAC,CAAC,IAC3D,SAAS,MAAM,CAAC;EAEpB,MAAM,KAAK;GACT;GACA;GACA;GACA,MAAM,CAAC;GACP,GAAI,UAAU,MAAM,SAAS,IACzB,EAAE,aAAa,oBAAoB,IAAI,EAAE,IACzC,CAAC;EACP,CAAC;CACH;CAEA,OAAO,KAAK,MAAM,MAAM;AAC1B;AAMA,MAAMC,wBACJ,OACA,cACgB;CAChB,MAAM,aAA0B,CAAC;CACjC,IAAI,QAAQ;CACZ,MAAM,SAAS,QAAsB;EACnC,MAAM,OAAO,iBAAiB,MAAM,MAAM,OAAO,GAAG,CAAC;EACrD,IAAI,CAAC,MAAM;EACX,KAAK,WAAW;GACd,OAAO;IAAE,MAAM,YAAY;IAAO,QAAQ;GAAE;GAC5C,KAAK;IAAE,MAAM,YAAY,MAAM;IAAG,QAAQ;GAAE;EAC9C;EACA,WAAW,KAAK,IAAI;CACtB;CACA,MAAM,SAAS,MAAM,UAAU;EAC7B,MAAM,QAAQ,KAAK;EAGnB,IADE,OAAO,SAAS,UAAU,kBAAkB,MAAM,KAAK,CAAC,EAAE,UAAU,KACzD,QAAQ,OAAO;GAC1B,MAAM,KAAK;GACX,QAAQ;EACV;CACF,CAAC;CACD,MAAM,MAAM,MAAM;CAClB,OAAO;AACT;AAiBA,MAAM,iBACJ,MACA,aACA,MACA,aACwB;CACxB,IAAI,SAAS;CACb,IAAI,OAAO,OAAO,UAAU,GAAG,EAAE;CACjC,OAAO,MAAM,SAAS,aAAa;EACjC,IAAI,CAAC,MAAM,UAAU,QAAQ,OAAO;EACpC,SAAS;EACT,OAAO,OAAO,UAAU,GAAG,EAAE;CAC/B;CACA,MAAM,OAAO;CACb,MAAM,QAAQ,KAAK,UAAU,MAAM;CACnC,IAAI,UAAU,KAAA,KAAa,CAAC,OAAO,UAAU,OAAO;CACpD,MAAM,QAAQ,YAAY,MAAM,WAAW,CAAC,CAAC,KAC1C,MAAM,WAAuB;EAC5B;EACA,SAAS,YAAY,YAAY,QAAQ,IAAI,UAAU,EAAE;CAC3D,EACF;CACA,MAAM,KAAK,MAAM,WACd,EAAE,MAAM,WAAW,UAAU,QAAQ,KAAK,UAAU,QAAQ,SAAS,IAAI,CAC5E;CACA,IAAI,OAAO,IAAI,OAAO;CACtB,MAAM,OAAO,iBAAiB,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC,KAAK,EAAE,WAAW,IAAI,CAAC;CACxE,OAAO,SAAS,OACd,IACA,GACA,GAAI,OAAO,CAAC,IAA6B,IAAI,CAAC,CAChD;CACA,OAAO,MAAM,MAAM,EAAE;AACvB;AAEA,MAAMC,qBACJ,IACA,UACA,cACA,gBACgB;CAChB,MAAM,WAAwB,CAAC;CAC/B,IAAI,iBAA4B;EAAE,QAAQ;EAAM,MAAM,CAAC;CAAE;CAEzD,MAAM,OAAO,cAAc,kBAAkB,IAAI,WAAW,IAAI,KAAA;CAGhE,MAAM,cAAc,aAAqD;EACvE,MAAM,QAAQ,SAAS;EACvB,IAAI,OAAO,SAAS,QAAQ,OAAO;EACnC,MAAM,SAAS,kBAAkB,MAAM,KAAK;EAC5C,OAAO,UAAU,OAAO,SAAS,eAAe,IAAI,SAAS;CAC/D;CAEA,MAAM,aACJ,QACA,UACA,gBACS;EACT,SAAS,KAAK,cAAc;EAG5B,KAAK,MAAM,KAAK,SAAS,KAAK,GAAG,IAAI,IAAI,OAAO,OAAO,SAAS,OAAO,CAAC;EACxE,MAAM,UAAU,SAAS,IAAI,OAAO,KAAK,KAAK,KAAK;EACnD,SAAS,IAAI,OAAO,OAAO,MAAM;EACjC,eAAe,OAAO;EAEtB,MAAM,aAAgC,OAAO,OACzC,CAAC;GAAE,MAAM;GAAQ,OAAO,OAAO;EAAK,GAAG,GAAG,SAAS,MAAM,CAAC,CAAC,IAC3D,SAAS,MAAM,CAAC;EAEpB,iBAAiB;GACf,QAAQ;IAAE,OAAO,OAAO;IAAO;IAAQ;IAAY;GAAY;GAC/D,MAAM,CAAC;EACT;CACF;CAEA,KAAK,MAAM,SAAS,GAAG,UAAU;EAC/B,IAAI,MAAM,SAAS,aAAa;GAC9B,eAAe,KAAK,KAAK,KAAK;GAC9B,IAAI,CAAC,eAAe,SAAS,KAAA,GAAW;GACxC,MAAM,OAAO,cACX,OACA,aACA,OACC,SAAS,WAAW,IAAI,MAAM,IACjC;GACA,IAAI,CAAC,MAAM;GAEX,IAAI,UAAwB,CAAC;GAC7B,MAAM,cAAoB;IACxB,MAAM,WAAW,QAAQ,KAAK,UAAU;KACtC,GAAG;KACH,SAAS,KAAK,UAAU;IAC1B,EAAE;IACF,eAAe,KAAK,KAAK,GAAG,iBAAiB,UAAU,CAAC,CAAC;IACzD,UAAU,CAAC;GACb;GACA,KAAK,MAAM,QAAQ,MAAM;IACvB,MAAM,SAAS,KAAK,UAAU,OAAO,WAAW,KAAK,IAAI,IAAI;IAC7D,IAAI,QAAQ;KACV,MAAM;KACN,UAAU,QAAQ,KAAK,IAAI;IAC7B,OACE,QAAQ,KAAK,IAAI;GAErB;GACA,MAAM;GACN;EACF;EAEA,IAAI,YAAiC,CAAC;EACtC,MAAM,QAAQ,YAAY,OAAO,WAAW;EAC5C,MAAM,QAAQ,MAAM,UAAU,MAAM;EAEpC,MAAM,eAAe,UACnB,CAAC,eACD,SAAS,KAAA,KACT,UAAU,KAAA,KACV,YAAY,YAAY,QAAQ,IAAI,UAAU,EAAE,IAAI;EACtD,KAAK,MAAM,CAAC,OAAO,aAAa,MAAM,QAAQ,GAAG;GAC/C,MAAM,SAAS,YAAY,KAAK,IAAI,WAAW,QAAQ,IAAI;GAC3D,IAAI,QAAQ;IAEV,MAAM,WAAW,iBAAiB,SAAS;IAC3C,IAAI,UAAU,eAAe,KAAK,KAAK,QAAQ;IAC/C,YAAY,CAAC;IACb,UACE,QACA,UACA,UAAU,MAAM,SAAS,IAAI,oBAAoB,KAAK,IAAI,KAAA,CAC5D;IACA;GACF;GACA,UAAU,KAAK,QAAQ;EACzB;EAIA,MAAM,WAAW,iBAAiB,SAAS;EAC3C,IAAI,YAAY,MAAM,MAAM,SAAS,OAAO,MAAM;EAClD,IAAI,UAAU,eAAe,KAAK,KAAK,QAAQ;CACjD;CAEA,SAAS,KAAK,cAAc;CAC5B,OAAO;AACT;AAIA,MAAMC,eACJ,OACA,aACA,OACA,QACkB;CAClB,MAAM,QAAyB,CAAC;CAChC,IAAI,IAAI;CAER,OAAO,IAAI,KAAK;EACd,MAAM,IAAI,MAAM;EAChB,IAAI,GAAG,UAAU,aAAa;GAC5B;GACA;EACF;EAEA,IAAI,WAAW,IAAI;EACnB,OAAO,WAAW,QAAQ,MAAM,SAAS,EAAE,SAAS,KAAK,aACvD;EAGF,MAAM,eAA0C,CAC9C;GAAE,MAAM;GAAc,UAAU,EAAE;EAAW,GAC7C,GAAG,EAAE,IACP;EAIA,IAHkB,MACf,MAAM,IAAI,GAAG,QAAQ,CAAC,CACtB,MAAM,OAAO,GAAG,UAAU,cAAc,CAC/B,GAAG;GACb,MAAM,SAASA,YAAU,OAAO,cAAc,GAAG,IAAI,GAAG,QAAQ;GAChE,aAAa,KAAK,MAAM;EAC1B;EAEA,MAAM,KAAK;GACT,MAAM;GACN,OAAO;GACP,QAAQ,EAAE;GACV,UAAU;GACV,MAAM;IACJ,WAAW;IACX,YAAY,EAAE;IACd,GAAI,EAAE,cAAc,EAAE,aAAa,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,CAAC;GAC/D;EACF,CAAC;EAED,IAAI;CACN;CAEA,OAAO;EACL,MAAM;EACN,OAAO;EACP,UAAU;EACV,MAAM,EAAE,WAAW,YAAY;CACjC;AACF;AAMA,MAAa,0BACX,UACA,gBACA,aACA,SAAS,GACT,aAAa,WACJ;CACT,MAAM,cAA+B,CAAC;CACtC,IAAI,IAAI;CAER,OAAO,IAAI,SAAS,QAAQ;EAC1B,MAAM,OAAO,SAAS;EACtB,IAAI,CAAC,MAAM;EAGX,IACE,KAAK,SAAS,eACd,eACA,CAAC,gBAAgB,IAAI,UAAU,GAC/B;GACA,MAAM,QAAQ,mBACZ,MACA,aACA,SACC,SAAS,kBAAkB,IAAI,CAAC,EAAE,UAAU,CAC/C;GACA,IAAI,OAAO;IACT,SAAS,OAAO,GAAG,GAAG,GAAG,KAAK;IAC9B;GACF;EACF;EAEA,IAAI,KAAK,SAAS,aAAa;GAC7B,MAAM,2BAAW,IAAI,IAAoB;GACzC,MAAM,aAAaH,oBAAkB,MAAM,QAAQ;GAEnD,IAAI,YAAY;IACd,MAAM,WAAsB,CAAC,GAAG,WAAW,KAAK;IAEhD,IAAI,OAAO,WAAW;IACtB,IAAI,WAAW,WAAW;IAC1B,IAAI,IAAI,IAAI;IAEZ,MAAM,iBAA0B,SAAS,SAAS,SAAS;IAC3D,IAAI,iBAAiB,SAAS,SAAS;IACvC,IAAI,eAAe,SAAS,CAAC,CAAC;IAE9B,OAAO,KAAK,WAAW,KAAK,IAAI,SAAS,QAAQ;KAC/C,MAAM,UAAU,SAAS;KACzB,IAAI,CAAC,SAAS;KAEd,IAAI,QAAQ,SAAS,cAAc;MAEjC,MAAM,OAAO,QAAQ,UAAU,MAAM;MACrC,IACE,eACA,SAAS,KAAA,KACT,kBAAkB,YAAY,OAAO,MAAM,EAAE,GAE7C;MACF,MAAM,WAAWE,kBACf,SACA,UACA,cACA,WACF;MAEA,MAAM,WAAW,SAAS;MAC1B,IAAI,UAAU,WAAW,MACvB,SAAS,eAAe,EAAE,KAAK,KAAK,GAAG,SAAS,IAAI;MAGtD,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;OACxC,MAAM,MAAM,SAAS;OACrB,IAAI,KAAK,QAAQ;QACf,SAAS,KAAK;SAAE,GAAG,IAAI;SAAQ,MAAM,IAAI;QAAK,CAAC;QAC/C,iBAAiB,SAAS,SAAS;QACnC,eAAe,IAAI,OAAO;OAC5B;MACF;MAEA;KACF,OAAO,IAAI,QAAQ,SAAS,aAAa;MACvC,MAAM,YAAY,SAAS,CAAC,CAAC;MAC7B,MAAM,cAAcF,oBAClB,SACA,UACA,OACA,SACF;MACA,IAAI,aAAa;OACf,SAAS,KAAK,GAAG,YAAY,KAAK;OAClC,OAAO,YAAY;OACnB,WAAW,YAAY;OACvB,iBAAiB,SAAS,SAAS;OACnC,eAAe,SAAS,CAAC,CAAC;OAC1B;OACA;MACF;MACA;KACF,OACE;IAEJ;IAEA,MAAM,OAAOG,YAAU,UAAU,GAAG,GAAG,SAAS,MAAM;IACtD,KAAK,iBAAiB;IACtB,IAAI,eAAe,aAAa,KAAK,SAAS;IAC9C,YAAY,KAAK,IAA2C;IAC5D,SAAS,OAAO,GAAG,GAAG,GAAGF,qBAAmB,MAAM,QAAQ,CAAC;IAC3D,IAAI;IACJ;GACF;EACF;EAEA,YAAY,KAAK,IAAI;EACrB;CACF;CAEA,SAAS,OAAO,GAAG,SAAS,QAAQ,GAAG,WAAW;AACpD;;;;AAUA,MAAa,gBACX,MACA,gBACA,WACS;CACT,MAAM,cAAc,QAAQ,MAAM,OAAO;CACzC,MAAM,QAAQ,MAAiB,WAAyB;EACtD,IAAI,CAAC,MAAM,QAAQ,KAAK,QAAQ,KAAK,KAAK,SAAS,WAAW,GAAG;EACjE,MAAM,QAAQ,UAAU,cAAc,IAAI,KAAK,QAAQ,EAAE,IAAI,IAAI;EACjE,uBACE,KAAK,UACL,gBACA,aACA,OACA,KAAK,IACP;EACA,KAAK,MAAM,SAAS,KAAK,UAAU,KAAK,OAAoB,KAAK;CACnE;CACA,uBAAuB,KAAK,UAAU,gBAAgB,WAAW;CACjE,KAAK,MAAM,SAAS,KAAK,UAAU,KAAK,OAAO,CAAC;CAChD,IAAI,aAAa,mBAAmB,MAAM,aAAa,WAAW;AACpE;;ACpfA,MAAM,gBAAgB;AAQtB,MAAM,kBAAkB,SAAyC;CAC/D,MAAM,IAAI,cAAc,KAAK,IAAI;CACjC,IAAI,CAAC,GAAG,OAAO;CACf,MAAM,GAAG,WAAW,IAAI,MAAM,QAAQ,MAAM;CAC5C,OAAO;EAAE,OAAO,SAAS;EAAQ,MAAM,SAAS;EAAK;CAAM;AAC7D;AAGA,MAAM,QAAQ,QAAwB;CACpC,IAAI,IAAI;CACR,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,KAC9B,KAAM,KAAK,KAAK,IAAI,IAAI,WAAW,CAAC,MAAO;CAE7C,OAAO;AACT;;AAGA,MAAa,cAAc,SACzB,KAAK,QAAQ,oBAAoB,EAAE,CAAC,CAAC,QAAQ;AAE/C,MAAM,WAAW,SACf,KACG,YAAY,CAAC,CACb,KAAK,CAAC,CACN,QAAQ,aAAa,EAAE,CAAC,CACxB,QAAQ,WAAW,GAAG,CAAC,CACvB,QAAQ,YAAY,EAAE;AAG3B,MAAM,WAAW,WAA6B;CAC5C,MAAM,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG;CACpD,OAAO,KAAK,GAAG,CAAC,CAAC,SAAS,EAAE;AAC9B;;;;AAKA,MAAa,eAAe,OAAe,YACzC,UAAU,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC,CAAC,SAAS,EAAE;;AAmBnD,MAAa,gBAAgB,UAC3B,MACG,KAAK,MAAM;CACV,IAAI,EAAE,SAAS,UAAU,EAAE,SAAS,cAClC,OAAO,WAAW,IAAI,EAAE,QAAQ;CAClC,IAAI,cAAc,GAAG,OAAO,aAAa,EAAE,QAAQ;CACnD,OAAO;AACT,CAAC,CAAC,CACD,KAAK,EAAE;AAUZ,MAAM,qBACJ,MACA,kBAAkB,MAClB,YAAY,MAC+D;CAC3E,MAAM,QAAQ,YAAY,IAAI;CAC9B,MAAM,OAAiB,CAAC;CACxB,IAAI,eAAe;CAEnB,KAAK,MAAM,CAAC,OAAO,aAAa,MAAM,QAAQ,GAAG;EAC/C,MAAM,QAAQ,SAAS;EACvB,IAAI,OAAO,SAAS,QAAQ,OAAO;EAEnC,MAAM,SAAS,eAAe,MAAM,KAAK;EACzC,IAAI,CAAC,QAAQ,OAAO;EAEpB,MAAM,EAAE,OAAO,SAAS;EACxB,IAAI,KAAK,WAAW,KAAK,mBAAmB,UAAU,GAAG,OAAO;EAChE,IAAI,QAAQ,eAAe,GACzB,OAAO,KAAK,SAAS,IACjB;GACE;GACA,MAAM,MAAM,MAAM,KAAK;GACvB,WAAW,KAAK,UAAU,MAAM,QAAQ,KAAK;EAC/C,IACA;EAEN,eAAe;EAEf,MAAM,YAAY,OAAO;EACzB,MAAM,aAAgC,YAClC,CAAC;GAAE,MAAM;GAAQ,OAAO;EAAU,GAAG,GAAG,SAAS,MAAM,CAAC,CAAC,IACzD,SAAS,MAAM,CAAC;EAEpB,KAAK,KAAK;GACR;GACA;GACA;GACA,WAAW,aAAa,UAAU;GAClC,MAAM,CAAC;GACP,GAAI,UAAU,MAAM,SAAS,IACzB,EAAE,aAAa,oBAAoB,IAAI,EAAE,IACzC,CAAC;EACP,CAAC;CACH;CAEA,OAAO,KAAK,SAAS,IAAI;EAAE;EAAM,MAAM,CAAC;EAAG,UAAU;CAAE,IAAI;AAC7D;AAMA,MAAM,sBACJ,OACA,cACgB;CAChB,MAAM,aAA0B,CAAC;CACjC,IAAI,QAAQ;CACZ,MAAM,SAAS,QAAsB;EACnC,MAAM,OAAO,iBAAiB,MAAM,MAAM,OAAO,GAAG,CAAC;EACrD,IAAI,CAAC,MAAM;EACX,KAAK,WAAW;GACd,OAAO;IAAE,MAAM,YAAY;IAAO,QAAQ;GAAE;GAC5C,KAAK;IAAE,MAAM,YAAY,MAAM;IAAG,QAAQ;GAAE;EAC9C;EACA,WAAW,KAAK,IAAI;CACtB;CACA,MAAM,SAAS,MAAM,UAAU;EAC7B,MAAM,QAAQ,KAAK;EAGnB,IADE,OAAO,SAAS,UAAU,eAAe,MAAM,KAAK,CAAC,EAAE,UAAU,KACtD,QAAQ,OAAO;GAC1B,MAAM,KAAK;GACX,QAAQ;EACV;CACF,CAAC;CACD,MAAM,MAAM,MAAM;CAClB,OAAO;AACT;AAoCA,MAAM,gBAAgB,OACpB,GAAG,SAAS,MAAM,UAAU;CAC1B,IAAI,MAAM,SAAS,aAAa,OAAO;CACvC,MAAM,QAAQ,MAAM,SAAS;CAC7B,OACE,OAAO,SAAS,UAChB,eAAe,MAAM,MAAM,MAAM,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM;AAEzD,CAAC;AASH,MAAM,4BACJ,MACA,gBASU;CAEV,MAAM,OAAgD,CAAC;CACvD,IAAI,UAA4C;CAChD,OAAO,cAAc,WAAW,QAAQ,SAAS,SAAS,GAAG;EAC3D,MAAM,OAAO,QAAQ,SAAS,QAAQ,SAAS,SAAS;EAGxD,IAAI,KAAK,SAAS,aAAa;GAC7B,KAAK,KAAK,OAAO;GAGjB,MAAM,QAAQ,YAAY,MAAM,WAAW;GAC3C,MAAM,KAAK,MAAM,WACd,SAAS,KAAK,EAAE,EAAE,SAAS,UAAU,eAAe,KAAK,EAAE,CAAC,KAAK,CACpE;GACA,IAAI,OAAO,IAAI,OAAO;GACtB,MAAM,aAAa,MAAM,OAAO,CAAC;GACjC,MAAM,QAAQ,WAAW;GACzB,MAAM,SACJ,OAAO,SAAS,SAAS,eAAe,MAAM,KAAK,IAAI;GACzD,IAAI,CAAC,QAAQ,OAAO;GACpB,MAAM,YAAY,OAAO;GACzB,MAAM,aAAgC,YAClC,CAAC;IAAE,MAAM;IAAQ,OAAO;GAAU,GAAG,GAAG,WAAW,MAAM,CAAC,CAAC,IAC3D,WAAW,MAAM,CAAC;GAYtB,OAAO;IACL,QAAQ;KAXR,OAAO,OAAO;KACd,MAAM,OAAO;KACb;KACA,WAAW,aAAa,UAAU;KAClC,MAAM,CAAC;KACP,GAAI,OAAO,MAAM,SAAS,IACtB,EAAE,aAAa,oBAAoB,IAAI,EAAE,IACzC,CAAC;IAIQ;IACb,eAHoB,iBAAiB,MAAM,MAAM,GAAG,EAAE,CAG1C;IACZ,MAAM,MAAM,MAAM,KAAK,CAAC;IACxB;IACA,OAAO,KAAK,UAAU,MAAM;IAC5B;IACA,MAAM;GACR;EACF;EACA,IAAI,EAAE,cAAc,OAAO;EAC3B,KAAK,KAAK,OAAO;EACjB,UAAU;CACZ;CACA,OAAO;AACT;AAEA,MAAM,mBACJ,IACA,UACA,gBACgB;CAChB,MAAM,WAAwB,CAAC;CAC/B,IAAI,iBAA4B;EAC9B,QAAQ;EACR,MAAM,CAAC;EACP;EACA,OAAO,CAAC;CACV;CAEA,MAAM,OACJ,eAAe,CAAC,WAAW,kBAAkB,IAAI,WAAW,IAAI,KAAA;CAKlE,MAAM,cACJ,OACA,WACA,SACS;EACT,IAAI,YAAiC,CAAC;EAEtC,KAAK,MAAM,CAAC,OAAO,aAAa,MAAM,QAAQ,GAAG;GAC/C,MAAM,QAAQ,SAAS;GACvB,MAAM,eACJ,CAAC,aAAa,SAAS,KAAA,KAAa,UAAU,KAAK,IAAI;GACzD,IAAI,OAAO,SAAS,UAAU,cAAc;IAC1C,MAAM,SAAS,eAAe,MAAM,KAAK;IACzC,IAAI,QAAQ;KAEV,IAAI,UAAU,SAAS,GAAG;MACxB,MAAM,WAAW,iBAAiB,SAAS;MAC3C,IAAI,UAAU,eAAe,KAAK,KAAK,QAAQ;MAC/C,YAAY,CAAC;KACf;KAGA,SAAS,KAAK,cAAc;KAE5B,MAAM,YAAY,OAAO;KACzB,MAAM,aAAgC,YAClC,CAAC;MAAE,MAAM;MAAQ,OAAO;KAAU,GAAG,GAAG,SAAS,MAAM,CAAC,CAAC,IACzD,SAAS,MAAM,CAAC;KAEpB,iBAAiB;MACf,QAAQ;OACN,OAAO,OAAO;OACd,MAAM,OAAO;OACb;OACA,WAAW,aAAa,UAAU;OAClC,MAAM,CAAC;OACP,GAAI,QAAQ,UAAU,MAAM,SAAS,IACjC,EAAE,aAAa,oBAAoB,IAAI,EAAE,IACzC,CAAC;MACP;MACA,MAAM,CAAC;MACP;MACA,OAAO,CAAC;MACR,MAAM;MACN,GAAI,YAAY,EAAE,SAAS,UAAU,KAAK,EAAE,IAAI,CAAC;KACnD;KACA;IACF;GACF;GACA,UAAU,KAAK,QAAQ;GACvB,IAAI,WACF,eAAe,MAAM,KAAK;IACxB,MAAM;IACN,SAAS,UAAU,KAAK;GAC1B,CAAC;EAEL;EAIA,IAAI,UAAU,SAAS,GAAG;GACxB,MAAM,WAAW,iBAAiB,SAAS;GAC3C,IAAI,YAAY,MAAM,MAAM,SAAS,OAAO,KAAK;GACjD,IAAI,UAAU,eAAe,KAAK,KAAK,QAAQ;EACjD;CACF;CAEA,KAAK,MAAM,SAAS,GAAG,UAAU;EAC/B,IAAI,MAAM,SAAS,aAAa;GAI9B,MAAM,YAAY,yBAAyB,OAAO,WAAW;GAC7D,IAAI,WAAW;IAEb,MAAM,SAAS,KAAK,MAAM,KAAK,UAAU,KAAK,CAAC;IAS/C,IAAI,SAAqB;IACzB,KAAK,IAAI,KAAK,GAAG,KAAK,UAAU,KAAK,QAAQ,MAC3C,SAAS,OAAO,SAAS,OAAO,SAAS,SAAS;IAEpD,MAAM,gBAAgB;IACtB,IAAI,UAAU,eACZ,cAAc,SAAS,cAAc,SAAS,SAAS,KACrD,UAAU;SAEZ,cAAc,SAAS,OAAO,cAAc,SAAS,SAAS,GAAG,CAAC;IAEpE,eAAe,KAAK,KAAK,MAAM;IAE/B,SAAS,KAAK,cAAc;IAC5B,MAAM,EAAE,OAAO,OAAO;IACtB,MAAM,YACJ,eAAe,UAAU,KAAA,KACpB,UACC,YAAY,YAAY,QAAQ,IAAI,UAAU,EAAE,IAClD,KAAA;IACN,iBAAiB;KACf,QAAQ,UAAU;KAClB,MAAM,CAAC;KACP;KACA,OAAO,CAAC;KACR,MAAM,UAAU;KAChB,GAAI,YAAY,EAAE,SAAS,UAAU,EAAE,EAAE,IAAI,CAAC;IAChD;IACA,WACE,UAAU,MACV,aAAa,UAAkB,UAAU,KAAK,IAAI,KAAK,IAAI,KAAA,CAC7D;GACF,OACE,eAAe,KAAK,KAAK,KAAK;GAEhC;EACF;EAGA,MAAM,QAAQ,MAAM,UAAU,MAAM;EACpC,WACE,YAAY,OAAO,WAAW,GAC9B,eAAe,UAAU,KAAA,KACpB,UAAkB,YAAY,YAAY,QAAQ,IAAI,UAAU,EAAE,IACnE,KAAA,GACJ,KACF;CACF;CAEA,SAAS,KAAK,cAAc;CAC5B,OAAO;AACT;AASA,MAAM,aACJ,UACA,OACA,WAC4C;CAC5C,MAAM,QAAsB,CAAC;CAC7B,MAAM,SAAkD,CAAC;CACzD,KAAK,MAAM,OAAO,UAAU;EAC1B,IAAI,UAAU,KAAA,KAAa,IAAI,YAAY,KAAA,GAAW;GAEpD,IAAI,IAAI,MAAM,MAAM,KAAK;IAAE,MAAM,IAAI;IAAM,SAAS;GAAE,CAAC;GACvD,OAAO,KAAK,GAAG,IAAI,IAAI;GACvB;EACF;EACA,IAAI,IAAI,MAAM,MAAM,KAAK;GAAE,MAAM,IAAI;GAAM,SAAS,IAAI,UAAU;EAAM,CAAC;EACzE,MAAM,KACJ,GAAG,IAAI,MAAM,KAAK,UAAU;GAAE,GAAG;GAAM,SAAS,KAAK,UAAU;EAAM,EAAE,CACzE;EACA,OAAO,KAAK,GAAG,IAAI,KAAK,QAAQ,UAAU,MAAM,SAAS,WAAW,CAAC;CACvE;CACA,MAAM,UAAU,iBAAiB,OAAO,CAAC;CACzC,IAAI,OAAO,SAAS,KAAK,CAAC,QACxB,QAAQ,KAAK,GAAG,MAAM;MACjB,IAAI,OAAO,SAAS,GAAG;EAC5B,MAAM,OAAO,QAAQ,GAAG,EAAE;EAC1B,IAAI,MAAM,SAAS,cAAc,KAAK,SAAS,KAAK,GAAG,MAAM;OAE3D,QAAQ,KAAK;GACX,MAAM;GACN,UAAU;EACZ,CAAC;CACL;CACA,OAAO;AACT;AAIA,MAAM,aACJ,SACA,aACA,OACA,KACA,mBACiB;CACjB,MAAM,cAAc,QACjB,MAAM,OAAO,GAAG,CAAC,CACjB,QAAQ,MAAM,EAAE,UAAU,WAAW,CAAC,CACtC,KAAK,MAAM,WAAW,EAAE,SAAS,CAAC;CAErC,MAAM,MAAM,QAAQ,WAAW;CAG/B,MAAM,kBAAkB,QACrB,MAAM,OAAO,GAAG,CAAC,CACjB,WAAW,MAAM,EAAE,UAAU,eAAe,EAAE,IAAI;CACrD,MAAM,qBACJ,mBAAmB,IAAI,QAAQ,kBAAkB;CAEnD,MAAM,QAAwB,CAAC;CAC/B,IAAI,aAAa;CACjB,IAAI,IAAI;CAER,OAAO,IAAI,KAAK;EACd,MAAM,MAAM,QAAQ;EACpB,IAAI,CAAC,KAAK;EACV,IAAI,IAAI,UAAU,aAAa;GAC7B;GACA;EACF;EAEA,IAAI,WAAW,IAAI;EACnB,OAAO,WAAW,QAAQ,QAAQ,SAAS,EAAE,SAAS,KAAK,aACzD;EAGF,MAAM,SACJ,sBAAsB,IAAI,MAAM,qBAAqB,eAAe;EAEtE,MAAM,eAAyC,CAC7C;GAAE,MAAM;GAAa,UAAU,IAAI;EAAW,GAC9C,GAAG,IAAI,IACT;EAMA,IAJkB,QACf,MAAM,IAAI,GAAG,QAAQ,CAAC,CACtB,MAAM,MAAM,EAAE,UAAU,cAAc,CAE7B,GAAG;GACb,MAAM,SAAS,UACb,SACA,cAAc,GACd,IAAI,GACJ,UACA,cACF;GACA,OAAO,iBAAiB;GACxB,aAAa,KAAK,MAAM;EAC1B;EACA,aAAa,KAAK,GAAI,IAAI,SAAS,CAAC,CAAE;EAEtC,MAAM,KAAK;GACT,MAAM;GACN,OAAO;GACP,WAAW,IAAI;GACf,MAAM;GACN,UAAU;GACV,MAAM;IACJ,WAAW;IACX,YAAY,IAAI;IAChB,gBAAgB;IAChB,aAAa,EAAE,GAAG,IAAI,YAAY;GACpC;EACF,CAAC;EAED;EACA,IAAI;CACN;CAEA,OAAO;EACL,MAAM;EACN,OAAO;EACP,SAAS;EACT,UAAU;EACV,MAAM;GAAE,WAAW;GAAa,aAAa,CAAC;EAAE;CAClD;AACF;AAQA,MAAa,yBACX,UACA,gBACA,kBAAkB,MAClB,aACA,SAAS,GACT,aAAa,WACJ;CACT,MAAM,cAA+B,CAAC;CACtC,IAAI,IAAI;CAER,OAAO,IAAI,SAAS,QAAQ;EAC1B,MAAM,OAAO,SAAS;EACtB,IAAI,CAAC,MAAM;EAGX,IACE,KAAK,SAAS,eACd,eACA,CAAC,gBAAgB,IAAI,UAAU,GAC/B;GACA,MAAM,QAAQ,mBACZ,MACA,aACA,SACC,SAAS,eAAe,IAAI,CAAC,EAAE,UAAU,CAC5C;GACA,IAAI,OAAO;IACT,SAAS,OAAO,GAAG,GAAG,GAAG,KAAK;IAC9B;GACF;EACF;EAEA,IAAI,KAAK,SAAS,aAAa;GAC7B,MAAM,aAAa,kBAAkB,IAAI;GAEzC,IAAI,YAAY;IACd,MAAM,UAAoB,CAAC,GAAG,WAAW,IAAI;IAE7C,MAAM,gBAAwB,QAAQ,QAAQ,SAAS;IAEvD,IAAI,OAAO,WAAW;IACtB,IAAI,WAAW,WAAW;IAC1B,IAAI,IAAI,IAAI;IACZ,IAAI,gBAAgB,QAAQ,SAAS;IACrC,IAAI,cAAc,KAAK,UAAU,IAAI,QAAQ;IAE7C,OAAO,KAAK,WAAW,KAAK,IAAI,SAAS,QAAQ;KAC/C,MAAM,UAAU,SAAS;KACzB,IAAI,CAAC,SAAS;KACd,MAAM,mBACH,QAAuD,UACpD,MAAM,QAAQ,cAAc;KAElC,IAAI,mBAAmB,mBAAmB,cAAc,GAAG;KAE3D,IAAI,QAAQ,SAAS,cAAc;MACjC,MAAM,KAAK;MACX,MAAM,WAAW,aAAa,EAAE;MAChC,MAAM,WAAW,gBAAgB,IAAI,UAAU,WAAW;MAE1D,MAAM,OACJ,YAAY,cACR,kBAAkB,IAAI,WAAW,IACjC,KAAA;MAEN,MAAM,WAAW,SAAS;MAC1B,IAAI,UAAU,WAAW,MACvB,QAAQ,cAAc,EAAE,KAAK,KAAK,GAAG,SAAS,IAAI;MAQpD,MAAM,cAAc,WAAW,QAAQ,CAAC,CAAC,QAAQ;MAEjD,MAAM,QAAQ,QAAQ;MAEtB,IAAI,SAAyD;MAE7D,KAAK,MAAM,CAAC,OAAO,QAAQ,SAAS,MAAM,CAAC,CAAC,CAAC,QAAQ,GAAG;OACtD,IAAI,CAAC,IAAI,QAAQ;OAMjB,MAAM,UAAU,IAAI;OACpB,IACE,YACA,YAAY,KAAA,KACZ,SAAS,KAAA,KACT,UAAU,MACV;QACA,IAAI,IAAI,OAAO,QAAQ,QAAQ,CAAC,CAAC,QAAQ,GAAG;QAC5C,MAAM,WAAW,IAAI,MAAM,KAAK,UAAU;SACxC,GAAG;SACH,SAAS,KAAK,WAAW,UAAU;QACrC,EAAE;QACF,IAAI,OAAO,KAAK,KACd,GAAG,iBAAiB,UAAU,CAAC,GAC/B,GAAG,IAAI,KAAK,MAAM,IAAI,MAAM,SAAS,IAAI,IAAI,CAAC,CAChD;QACA,QAAQ,KAAK,IAAI,MAAM;QACvB,gBAAgB,QAAQ,SAAS;QACjC;OACF;OAEA,MAAM,gBAAgB,cAAc,IAAI,OAAO;OAE/C,IAAI,gBADc,QAAQ,CAAC,CAAC,QACI,GAAG;QACjC,IAAI,UAAU;SAIZ,MAAM,QAAQ,CACZ,GAAI,MAAM,SAAS,CAAC,GACpB,GAAG,UAAU,CAAC,GAAG,GAAG,MAAM,KAAK,CACjC;SACA;QACF;QAKA,MAAM,eAAe,cACjB,kBAAkB,IAAI,WAAW,IACjC,KAAA;QACJ,SAAS,UACP,SAAS,MAAM,QAAQ,CAAC,GACxB,iBAAiB,KAAA,IAAY,KAAA,IAAY,eAAe,GACxD,IACF;QACA;OACF;OAEA,IAAI,OAAO,QAAQ;OAEnB,IAAI,UAAU;QAaZ,MAAM,oBAAiC,CAAC;QAExC,MAAM,cAAwB,CAAC;QAE/B,KAAK,MAAM,KAAK,IAAI,MAAM;SACxB,IAAI,EAAE,SAAS,cAAc;UAE3B,MAAM,UAAU,YAAY,GAAG,EAAE;UACjC,IAAI,SACF,QAAQ,KAAK,KAAK,CAAC;eAEnB,IAAI,OAAO,KAAK,KAAK,CAAC;UAExB;SACF;SACA,MAAM,UAAU;SAChB,IAAI,CAAC,aAAa,OAAO,GAAG;UAE1B,MAAM,YAAY,gBAChB,SACA,OACA,WACF;UACA,MAAM,aAAa,UAAU;UAC7B,IAAI,YAAY,WAAW,MACzB,IAAI,OAAO,KAAK,KAAK,GAAG,WAAW,IAAI;UAEzC,KAAK,MAAM,YAAY,UAAU,MAAM,CAAC,GAAG;WACzC,IAAI,CAAC,SAAS,QAAQ;WAOtB,MAAM,UAAU,SAAS;WACzB,IAAI,YAAY,KAAA,KAAa,SAAS,KAAA,GAChC;gBAAA,UAAU,MAAM;aAClB,MAAM,WAAW,SAAS,MAAM,KAAK,UAAU;cAC7C,GAAG;cACH,SAAS,KAAK,WAAW,UAAU;aACrC,EAAE;aACF,SAAS,OAAO,KAAK,KACnB,GAAG,iBAAiB,UAAU,CAAC,CACjC;aACA,YAAY,KAAK,SAAS,MAAM;aAChC,kBAAkB,KAAK,QAAQ;aAC/B;YACF;kBACK,IAAI,SAAS,KAAK,WAAW,GAAG;YACrC,SAAS,OAAO,QAAQ;YACxB,YAAY,KAAK,SAAS,MAAM;YAChC,kBAAkB,KAAK,QAAQ;YAC/B;WACF;WACA,MAAM,iBACJ,cAAc,SAAS,OAAO;WAEhC,IAAI,iBADmB,QAAQ,CAAC,CAAC,QACK,GAAG;WACzC,SAAS,OAAO,QAAQ;WACxB,SAAS,OAAO,KAAK,KAAK,GAAG,SAAS,IAAI;WAC1C,kBAAkB,KAAK,QAAQ;UACjC;SACF,OAEE,IAAI,OAAO,KAAK,KAAK,GAAG,QAAQ,QAAQ;QAE5C;QAEA,QAAQ,KAAK,IAAI,MAAM;QACvB,gBAAgB,QAAQ,SAAS;QACjC,KAAK,MAAM,YAAY,mBAAmB;SACxC,IAAI,CAAC,SAAS,QAAQ;SACtB,QAAQ,KAAK,SAAS,MAAM;SAC5B,gBAAgB,QAAQ,SAAS;QACnC;OACF,OAAO;QACL,IAAI,OAAO,KAAK,KAAK,GAAG,IAAI,IAAI;QAChC,QAAQ,KAAK,IAAI,MAAM;QACvB,gBAAgB,QAAQ,SAAS;OACnC;MACF;MAEA,cAAc,QAAQ,UAAU,IAAI,QAAQ;MAC5C;MACA,IAAI,QAAQ;OACV,SAAS,OAAO,GAAG,GAAG,GAAG,MAAM;OAC/B;MACF;KACF,OAAO,IAAI,QAAQ,SAAS,aAAa;MACvC,MAAM,YAAY,QAAQ,CAAC,CAAC;MAC5B,MAAM,cAAc,kBAAkB,SAAS,OAAO,SAAS;MAC/D,IAAI,aAAa;OACf,QAAQ,KAAK,GAAG,YAAY,IAAI;OAChC,OAAO,YAAY;OACnB,WAAW,YAAY;OACvB,gBAAgB,QAAQ,SAAS;OACjC,cAAc,QAAQ,UAAU,IAAI,QAAQ;OAC5C;OACA;MACF;MACA;KACF,OACE;IAEJ;IAEA,MAAM,OAAO,UAAU,SAAS,GAAG,GAAG,QAAQ,QAAQ,cAAc;IACpE,KAAK,iBAAiB;IACtB,YAAY,KAAK,IAA8B;IAC/C,SAAS,OAAO,GAAG,GAAG,GAAG,mBAAmB,MAAM,QAAQ,CAAC;IAC3D,IAAI;IACJ;GACF;EACF;EAEA,YAAY,KAAK,IAAI;EACrB;CACF;CAEA,SAAS,OAAO,GAAG,SAAS,QAAQ,GAAG,WAAW;AACpD;;;;AAUA,MAAa,eACX,MACA,gBACA,WACS;CACT,MAAM,cAAc,QAAQ,MAAM,OAAO;CACzC,MAAM,QAAQ,MAAiB,WAAyB;EACtD,IAAI,CAAC,MAAM,QAAQ,KAAK,QAAQ,KAAK,KAAK,SAAS,WAAW,GAAG;EACjE,MAAM,QAAQ,UAAU,cAAc,IAAI,KAAK,QAAQ,EAAE,IAAI,IAAI;EACjE,sBACE,KAAK,UACL,gBACA,OACA,aACA,OACA,KAAK,IACP;EACA,KAAK,MAAM,SAAS,KAAK,UAAU,KAAK,OAAoB,KAAK;CACnE;CACA,sBAAsB,KAAK,UAAU,gBAAgB,MAAM,WAAW;CACtE,KAAK,MAAM,SAAS,KAAK,UAAU,KAAK,OAAO,CAAC;CAChD,IAAI,aAAa,mBAAmB,MAAM,aAAa,UAAU;AACnE;;ACh6BA,MAAa,gBACX,MACA,OACA,aACA,YACoB;CACpB,MAAM,4BAAY,IAAI,IAA4C;CAElE,MAAM,QAAQ,SAAe;EAC3B,MAAM,WAAW,KAAK;EACtB,IAAI,CAAC,UAAU;GACb,MAAM,OAAO,EAAE,GAAG,KAAK;GACvB,UAAU,IAAI,MAAM;IAAE;IAAM,UAAU,CAAC;GAAE,CAAC;GAC1C,OAAO;EACT;EACA,MAAM,SAAS;GAAE,GAAG;GAAM,UAAU,SAAS,IAAI,IAAI;EAAE;EACvD,UAAU,IAAI,QAAQ;GAAE;GAAM;EAAS,CAAC;EACxC,OAAO;CACT;CAEA,MAAM,aAAa,SAAe;EAChC,MAAM,WAAW,UAAU,IAAI,IAAI;EACnC,IAAI,CAAC,UAAU,OAAO,MAAM,MAAM,SAAS;EAC3C,IAAI,WAAW,KAAK,SAAS,SAAS,KAAK,MACzC,QAAQ,SAAS,MAAM,KAAK,IAAI;EAClC,IAAI,CAAC,KAAK,UAAU,OAAO,SAAS;EACpC,MAAM,WAAY,KAAK,SAA0B,IAAI,SAAS;EAI9D,IAFE,SAAS,WAAW,SAAS,SAAS,UACtC,SAAS,MAAM,OAAO,UAAU,UAAU,SAAS,SAAS,MAAM,GACvD,YAAY,SAAS,MAAM,QAAQ;EAChD,OAAO,SAAS;CAClB;CAEA,OAAO;EAAE,MAAM,KAAK,IAAI;EAAG;CAAU;AACvC;;AC1CA,MAAM,QAAQ,QAAwB;CACpC,IAAI,IAAI;CACR,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,KAC9B,IAAI,KAAK,KAAK,IAAI,IAAI,WAAW,CAAC,GAAG,QAAQ,MAAM;CAErD,OAAO,EAAE,SAAS,EAAE;AACtB;;;;AAKA,MAAa,eAAe,iBAC1B,cAAc,KAAK,YAAY;AAEjC,MAAM,mBACJ,YACsE;CACtE,MAAM,UAAU,iBAAiB,KAAK,OAAO,CAAC,GAAG,MAAM;CACvD,OAAO;EACL,SAAS,qBAAqB,KAAK,OAAO,CAAC,GAAG,MAAM;EACpD,OAAO,qBAAqB,KAAK,OAAO,CAAC,GAAG,MAAM;EAClD,QAAQ,sBAAsB,KAAK,OAAO,CAAC,GAAG,MAAM;EACpD,OAAO,kCAAkC,KAAK,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,KAAK;CACzE;AACF;AAEA,MAAM,WAAW,MACf,EAAE,QAAQ,MAAM,OAAO,CAAC,CAAC,QAAQ,MAAM,QAAQ;AAGjD,MAAM,mBAAmB,SAAiB,QAAwB;CAChE,IAAI,CAAC,KAAK,OAAO;CACjB,OAAO,QAAQ,QACb,iBACA,sBAAsB,QAAQ,GAAG,EAAE,GACrC;AACF;AAEA,MAAM,mBAAmB,IAAY,SAAiB,UACpD,qGACqB,GAAG,aAAa,QAAQ,OAAO,EAAE,IAAI,MAAM;AAGlE,MAAM,gBACJ,IACA,SACA,OACA,QACA,QACW;CASX,OAAO,QARO;EACZ,WAAW,YAAY,QAAQ,OAAO,EAAE;EACxC,SAAS,UAAU,QAAQ,KAAK,EAAE;EAClC,UAAU,WAAW,QAAQ,MAAM,EAAE;EACrC,OAAO,eAAe,QAAQ,GAAG,EAAE;CACrC,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GACW,EAAE,eAAe,GAAG;AACzC;;;;AAKA,MAAa,mBACX,SACA,MACA,cACA,WACoB;CACpB,IAAI,QAAQ,SAAS,OAAO,cAAc,OAAO;CACjD,IAAI,KAAK,SAAS,OAAO,gBAAgB,OAAO;CAChD,IAAI,KAAK,SAAS,QAAQ,SAAS,OAAO,cAAc,OAAO;CAC/D,IAAI,CAAC,OAAO,iBAAiB,KAAK,SAAS,GACzC,OAAO,KAAK,KAAK,QAAQ,gBAAgB,SAAS,GAAG,CAAC;CAExD,MAAM,EAAE,SAAS,OAAO,QAAQ,UAAU,gBAAgB,OAAO;CACjE,MAAM,KAAK,YAAY,YAAY;CACnC,MAAM,SAAS,gBAAgB,IAAI,SAAS,KAAK;CACjD,OAAO,KAAK,KAAK,KAAK,UAAU;EAC9B,MAAM,MAAM,aAAa,IAAI,SAAS,OAAO,QAAQ,GAAG;EACxD,OAAO,UAAU,IAAI,SAAS,MAAM;CACtC,CAAC;AACH;;;AC3FA,MAAa,kBAAkB;;AAG/B,MAAa,oBAAoB;AAGjC,MAAM,UAAU;;AAGhB,MAAa,oBAAoB,UAC9B,QAAQ,GAAA,CAAI,MAAM,KAAK,CAAC,CAAC,SAAS,OAAO;;AAG5C,MAAa,gBAAgB,SAC3B,KAAK,QAAQ,UAAU,IAAI,CAAC,CAAC,QAAQ,OAAO,EAAE;;;;AAKhD,MAAa,oBACX,kBAAkB,MAAM;AAI1B,MAAM,UAAU,SACd,KAAK,SAAS,SACT,KAAK,SAAS,MACd,KAAK,YAAY,CAAC,EAAA,CAAG,IAAI,MAAM,CAAC,CAAC,KAAK,EAAE;;;;AAK/C,MAAa,iBACX,SAC2D;CAC3D,IAAI,KAAK,SAAS,aAAa,KAAK,YAAY,OAAO,OAAO,KAAA;CAC9D,MAAM,YAAY,KAAK,YAAY,CAAC,EAAA,CAAG,QACpC,UAAU,MAAM,SAAS,SAC5B;CACA,MAAM,CAAC,QAAQ;CACf,IAAI,SAAS,WAAW,KAAK,MAAM,YAAY,QAAQ,OAAO,KAAA;CAC9D,MAAM,OAAO,aAAa,OAAO,IAAI,CAAC;CACtC,IAAI,SAAS,IAAI,OAAO,KAAA;CACxB,MAAM,OAAQ,KAAkB,MAAM,QAAQ,KAAK,YAAY;CAC/D,OAAO;EAAE;EAAM,MAAM,OAAO,SAAS,WAAW,OAAO,KAAA;CAAU;AACnE;AAgBA,MAAM,QAAQ,UACZ,wLAAwL,MAAM;;AAGhM,MAAa,kBAAiD;CAC5D,MAAM,KACJ,yIACF;CACA,QAAQ,KAAK,mCAAmC;AAClD;;AAGA,MAAa,iBAAgD;CAC3D,MAAM;CACN,QAAQ;AACV;AAGA,MAAM,gBAAgB;AAEtB,MAAM,UAAU,UACd,MAAM,QAAQ,MAAM,OAAO,CAAC,CAAC,QAAQ,MAAM,MAAM,CAAC,CAAC,QAAQ,MAAM,QAAQ;;;;AAK3E,MAAa,wBACX,UAA2B,CAAC,MACC;CAC7B,MAAM,QAAQ;EAAE,GAAG;EAAiB,GAAG,QAAQ;CAAM;CACrD,MAAM,QAAQ;EAAE,GAAG;EAAgB,GAAG,QAAQ;CAAK;CAEnD,MAAM,QAAQ,UAAiC,MAAM,UAAU;CAC/D,MAAM,SAA0B,CAAC,QAAQ,QAAQ;CACjD,MAAM,UAAU,CAEd,GAAG,OAAO,KACP,UACC,gBAAgB,gBAAgB,qBAAqB,MAAM,uBAAuB,MAAM,UAAU,gBAAgB,OAAO,QAC7H,GACA,GAAG,OAAO,KAAK,UACb,KAAK,KAAK,IACN,gBAAgB,gBAAgB,qBAAqB,MAAM,uBAAuB,OAAO,KAAK,KAAK,CAAC,EAAE,WACtG,EACN,CACF,CAAC,CAAC,KAAK,EAAE;CACT,MAAM,QAAQ,OAAO,KAAK,MAAM,KAAK,aAAa;CAClD,QAAQ,OACN,gCAAgC,gBAAgB,aAAa,kBAAkB,gBAAgB,GAAG,gBAAgB,MAAM,WAAW,QAAQ;AAC/I"}