@mirrordown/core 0.0.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["WHITESPACE","PUNCTUATION","classify","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/hast.ts","../src/abbr.ts","../src/cut-attributes.ts","../src/lazy.ts","../src/steps.ts","../src/tabs.ts","../src/editable.ts","../src/inline-svg.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\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","// 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\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. */\nexport const lightboxDialog = <C>(\n id: string,\n image: 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 ]\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","// 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","// 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 linesToParagraph,\n markerCount,\n paragraphProperties,\n paraToLines,\n rebuildLazyLines,\n type MarkedLine\n} from \"./lazy.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 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 for (const [index, lineSegs] of lines.entries()) {\n const header = stepHeader(lineSegs);\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): 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 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 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 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 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): void => {\n if (!Array.isArray(node.children) || node.children.length === 0) return;\n processStepsInChildren(\n node.children as Array<BlockContent | DefinitionContent>,\n containerClass,\n sourceLines\n );\n for (const child of node.children) walk(child as Container);\n };\n processStepsInChildren(root.children, containerClass, sourceLines);\n for (const child of root.children) walk(child as Container);\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 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\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 if (first?.type === \"text\") {\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): 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 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 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): void => {\n if (!Array.isArray(node.children) || node.children.length === 0) return;\n processTabsInChildren(\n node.children as Array<BlockContent | DefinitionContent>,\n containerClass,\n false,\n sourceLines\n );\n for (const child of node.children) walk(child as Container);\n };\n processTabsInChildren(root.children, containerClass, true, sourceLines);\n for (const child of root.children) walk(child as Container);\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"],"mappings":"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"}
package/package.json CHANGED
@@ -1,11 +1,41 @@
1
1
  {
2
2
  "name": "@mirrordown/core",
3
- "version": "0.0.0",
4
3
  "description": "Shared, engine-agnostic logic for Mirrordown's markdown-it, remark/rehype and Sätteri plugins.",
4
+ "version": "0.1.0",
5
5
  "license": "MIT",
6
6
  "author": "Drake Costa <drake@saeris.io> (https://saeris.gg)",
7
7
  "repository": {
8
8
  "type": "git",
9
9
  "url": "git+https://github.com/mirrordown/mirrordown.git"
10
+ },
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "type": "module",
15
+ "sideEffects": false,
16
+ "exports": {
17
+ ".": {
18
+ "development": "./src/index.ts",
19
+ "types": "./dist/index.d.mts",
20
+ "import": "./dist/index.mjs"
21
+ }
22
+ },
23
+ "engines": {
24
+ "node": ">=24.0.0"
25
+ },
26
+ "bumpy": {
27
+ "publishCommand": [
28
+ "node ../../scripts/sync-jsr-version.mjs",
29
+ "node ../../scripts/npm-publish.mjs",
30
+ "node ../../scripts/jsr-resolve-deps.mjs",
31
+ "node ../../scripts/jsr-publish.mjs"
32
+ ]
33
+ },
34
+ "dependencies": {
35
+ "@types/hast": "^3.0.4",
36
+ "@types/mdast": "^4.0.4"
37
+ },
38
+ "devDependencies": {
39
+ "micromark-util-types": "^2.0.2"
10
40
  }
11
- }
41
+ }