@ngrok/mantle 0.71.0 → 0.72.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/agent.json +76 -0
- package/dist/alert-dialog.d.ts +4 -4
- package/dist/{button-Bq0x5Pv4.d.ts → button-BMgAxAwM.d.ts} +4 -4
- package/dist/button.d.ts +1 -1
- package/dist/code-block.d.ts +2 -2
- package/dist/code-block.js +2 -2
- package/dist/code-block.js.map +1 -1
- package/dist/code-block_highlight-utils.d.ts +2 -2
- package/dist/code-block_highlight-utils.js +1 -1
- package/dist/command.d.ts +2 -2
- package/dist/data-table.d.ts +1 -1
- package/dist/hooks.d.ts +2 -2
- package/dist/llms.txt +77 -0
- package/dist/mantle.css +73 -0
- package/dist/otp-input.d.ts +2 -1
- package/dist/otp-input.js +1 -1
- package/dist/otp-input.js.map +1 -1
- package/dist/progress.js +1 -1
- package/dist/progress.js.map +1 -1
- package/dist/resolve-pre-rendered-props-Bqg41IkV.js +13 -0
- package/dist/resolve-pre-rendered-props-Bqg41IkV.js.map +1 -0
- package/dist/{resolve-pre-rendered-props-CNUnH1fU.d.ts → resolve-pre-rendered-props-CdqAcY5m.d.ts} +153 -5
- package/dist/split-button.d.ts +1 -1
- package/package.json +3 -1
- package/dist/resolve-pre-rendered-props-C-kiaLHj.js +0 -13
- package/dist/resolve-pre-rendered-props-C-kiaLHj.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-pre-rendered-props-Bqg41IkV.js","names":[],"sources":["../src/components/code-block/mantle-code.ts","../src/components/code-block/line-numbers.ts","../src/components/code-block/decorate-highlighted-html.ts","../src/components/code-block/fold-range-utils.ts","../src/components/code-block/compute-json-fold-ranges.ts","../src/components/code-block/compute-fold-ranges.ts","../src/components/code-block/indentation.ts","../src/components/code-block/normalize-indentation.ts","../src/components/code-block/supported-languages.ts","../src/components/code-block/parse-line-options.ts","../src/components/code-block/resolve-pre-rendered-props.ts"],"sourcesContent":["import type { SupportedLanguage } from \"../code-block/supported-languages.js\";\nimport type { LineRange } from \"../code-block/line-numbers.js\";\nimport type { Indentation } from \"../code-block/indentation.js\";\n\n/** Languages that represent shell/terminal commands. */\nconst shellLanguages = new Set<SupportedLanguage>([\"bash\", \"sh\", \"shell\"]);\n\n/** Returns the default `showLineNumbers` value for a given language and code string. Single-line shell snippets default to `false`; everything else defaults to `true`. */\nfunction defaultShowLineNumbers(language: SupportedLanguage, code: string): boolean {\n\tif (shellLanguages.has(language) && !code.trim().includes(\"\\n\")) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nconst mantleCodeBlockValueBrand: unique symbol = Symbol(\"MantleCodeBlockValue\");\n\n/**\n * The value produced by `mantleCode()`. Contains pre-rendered Shiki HTML (injected\n * by the Vite plugin at build time) and the original code string for the copy button.\n *\n * `~preHtml` is required at render time. Runtime syntax highlighting is intentionally\n * unsupported; only placeholder substitution for interpolated values is performed.\n */\ntype MantleCodeBlockValue = {\n\t/**\n\t * Nominal type brand to prevent accidental use of plain objects.\n\t */\n\t[mantleCodeBlockValueBrand]: true;\n\t/**\n\t * The language used for syntax highlighting.\n\t */\n\tlanguage: SupportedLanguage;\n\t/**\n\t * The original code string (used by the copy button).\n\t */\n\tcode: string;\n\t/**\n\t * Fully pre-rendered Shiki HTML injected by the Vite plugin or server highlighter.\n\t * This must be present for rendering.\n\t *\n\t * **Security:** This HTML is injected via `dangerouslySetInnerHTML`. It must\n\t * come from a trusted source (Shiki output from the Vite plugin or\n\t * `createMantleServerSyntaxHighlighter`). Never pass unsanitized user input.\n\t */\n\t\"~preHtml\"?: string | undefined;\n\t/**\n\t * Runtime values used to replace `SHIKI_VAL_N` placeholders in `~preHtml`.\n\t * This enables interpolated template expressions while preserving build-time highlighting.\n\t */\n\t\"~preVals\"?: unknown[] | undefined;\n\t/**\n\t * Placeholder token prefix used by the Vite transform for interpolated values.\n\t * When omitted, CodeBlock falls back to the legacy `SHIKI_VAL_<n>` format.\n\t */\n\t\"~preValToken\"?: string | undefined;\n\t/**\n\t * Optional default for line-number rendering when this value is displayed.\n\t */\n\t\"~showLineNumbers\"?: boolean | undefined;\n\t/**\n\t * Optional default highlighted line numbers/ranges when this value is displayed.\n\t */\n\t\"~highlightLines\"?: (LineRange | number)[] | undefined;\n\t/**\n\t * Optional default start line number when line numbers are displayed.\n\t * @default 1\n\t */\n\t\"~lineNumberStart\"?: number | undefined;\n};\n\n/** Maps each key starting with `OldPrefix` to `NewPrefix`, leaving other keys unchanged. */\ntype ReplacePrefix<T, OldPrefix extends string, NewPrefix extends string> = {\n\t[K in keyof T as K extends `${OldPrefix}${infer Rest}` ? `${NewPrefix}${Rest}` : K]: T[K];\n};\n\n/** Public input shape for `createMantleCodeBlockValue`, with `~`-prefixed keys renamed to unprefixed. */\ntype MantleCodeBlockValueInput = ReplacePrefix<\n\tOmit<MantleCodeBlockValue, typeof mantleCodeBlockValueBrand>,\n\t\"~\",\n\t\"\"\n>;\n\n/** Options for configuring line numbers, highlights, and indentation in `mantleCode()`. */\ntype MantleCodeOptions = {\n\t/** Line numbers or ranges to visually highlight in the code block. */\n\thighlightLines?: (LineRange | number)[] | undefined;\n\t/** The indentation style to use when normalizing the code string. */\n\tindentation?: Indentation | undefined;\n\t/**\n\t * The starting line number when line numbers are displayed.\n\t * @default 1\n\t */\n\tlineNumberStart?: number | undefined;\n\t/**\n\t * Whether to show line numbers in the code block. Defaults to `true` for most\n\t * languages, but `false` for single-line shell snippets (`bash`, `sh`, `shell`).\n\t */\n\tshowLineNumbers?: boolean | undefined;\n};\n\n/**\n * Creates a `MantleCodeBlockValue` for use with `CodeBlock.Code`.\n *\n * **Security:** The `preHtml` field is rendered via `dangerouslySetInnerHTML`.\n * Only pass HTML produced by Shiki (via the Vite plugin or\n * `createMantleServerSyntaxHighlighter`). Never pass unsanitized user input as `preHtml`.\n */\nfunction createMantleCodeBlockValue({\n\tpreHtml,\n\tpreValToken,\n\tpreVals,\n\thighlightLines,\n\tlineNumberStart,\n\tshowLineNumbers,\n\tcode,\n\tlanguage,\n}: MantleCodeBlockValueInput): MantleCodeBlockValue {\n\treturn {\n\t\t[mantleCodeBlockValueBrand]: true,\n\t\tlanguage,\n\t\tcode,\n\t\t\"~preHtml\": preHtml,\n\t\t\"~preValToken\": preValToken,\n\t\t\"~preVals\": preVals,\n\t\t\"~highlightLines\": highlightLines,\n\t\t\"~lineNumberStart\": lineNumberStart,\n\t\t\"~showLineNumbers\": showLineNumbers,\n\t};\n}\n\n/** Joins a `TemplateStringsArray` and its interpolated values into a single code string. */\nfunction buildCodeFromTemplate(strings: TemplateStringsArray, values: unknown[]): string {\n\tlet code = \"\";\n\tfor (let index = 0; index < strings.length; index += 1) {\n\t\tcode += strings[index] ?? \"\";\n\t\tif (index < values.length) {\n\t\t\tcode += String(values[index]);\n\t\t}\n\t}\n\treturn code;\n}\n\n/**\n * Tagged template literal for Shiki syntax highlighting.\n *\n * Returns a `MantleCodeBlockValue` that `CodeBlock.Code` renders.\n * The Vite transform plugin rewrites calls to this function at build time,\n * inlining pre-rendered Shiki HTML so that no highlighting work happens in the browser.\n * Configure it via `mantleCodeBlockPlugins()` in `vite.config.ts`.\n *\n * Interpolated template expressions are supported via placeholder substitution.\n *\n * Line numbers are shown by default (`showLineNumbers` defaults to `true`),\n * except for single-line shell snippets (`bash`, `sh`, `shell`) where they default to `false`.\n *\n * @example\n * ```tsx\n * // Static string (line numbers shown by default)\n * mantleCode(\"typescript\")`const x: string = \"hello\";`\n * // Interpolated string\n * mantleCode(\"typescript\")`const greeting = \"Hello, ${name}!\";`\n * // Disable line numbers\n * mantleCode(\"typescript\", { showLineNumbers: false })`const x = 1;`\n * // Single-line shell — line numbers hidden by default\n * mantleCode(\"bash\")`npm install @ngrok/mantle`\n * ```\n */\nfunction mantleCode(\n\tlanguage: SupportedLanguage,\n\toptions: MantleCodeOptions = {},\n): (strings: TemplateStringsArray, ...values: unknown[]) => MantleCodeBlockValue {\n\tconst { showLineNumbers, highlightLines, lineNumberStart } = options;\n\n\treturn (strings, ...values) => {\n\t\tconst code = buildCodeFromTemplate(strings, values);\n\n\t\treturn createMantleCodeBlockValue({\n\t\t\tlanguage,\n\t\t\tcode,\n\t\t\tpreHtml: undefined,\n\t\t\tpreVals: values.length > 0 ? values : undefined,\n\t\t\thighlightLines,\n\t\t\tlineNumberStart,\n\t\t\tshowLineNumbers: showLineNumbers ?? defaultShowLineNumbers(language, code),\n\t\t});\n\t};\n}\n\nexport { defaultShowLineNumbers, mantleCode };\nexport { createMantleCodeBlockValue };\nexport type { MantleCodeBlockValue, MantleCodeOptions };\n","/**\n * A line range is a string in the format of `start-end` where `start` and `end` are line numbers.\n */\nexport type LineRange = `${number}-${number}`;\n\nconst MAX_EXPANDED_LINE_RANGE_LENGTH = 1_000;\n\n/**\n * Given a list of line ranges and numbers, resolves them into a unique list of line numbers as a set.\n *\n * @example\n * ```tsx\n * const highlightedLines = resolveLineNumbers(1, \"3-5\", 7, \"10-12\");\n * // Returns: Set {1, 3, 4, 5, 7, 10, 11, 12}\n *\n * const singleLine = resolveLineNumbers(42);\n * // Returns: Set {42}\n * ```\n */\nexport function resolveLineNumbers(...items: (LineRange | number)[]): Set<number> {\n\tconst lineNumberSet = new Set<number>();\n\n\tfor (const item of items) {\n\t\tif (typeof item === \"number\") {\n\t\t\tif (!isPositiveLineNumber(item)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// only support integer line numbers\n\t\t\tconst int = Math.floor(item);\n\t\t\tlineNumberSet.add(int);\n\t\t} else {\n\t\t\tconst separatorIndex = item.indexOf(\"-\");\n\t\t\tconst startPart = item.slice(0, separatorIndex);\n\t\t\tconst endPart = item.slice(separatorIndex + 1);\n\t\t\tlet start = Number.parseInt(startPart, 10);\n\t\t\tlet end = Number.parseInt(endPart, 10);\n\n\t\t\t// ignore invalid ranges that don't contain valid line numbers\n\t\t\tif (!isPositiveLineNumber(start) || !isPositiveLineNumber(end)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// swap start and end if they are backwards\n\t\t\tif (start > end) {\n\t\t\t\t[start, end] = [end, start];\n\t\t\t}\n\n\t\t\tif (end - start + 1 > MAX_EXPANDED_LINE_RANGE_LENGTH) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// add all line numbers in the range, inclusive\n\t\t\tfor (let i = start; i <= end; i++) {\n\t\t\t\tlineNumberSet.add(i);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn lineNumberSet;\n}\n\n/**\n * Type Predicate: checks if a value is a positive, finite integer.\n */\nconst isPositiveLineNumber = (value: number | undefined): value is number =>\n\tvalue != null && !Number.isNaN(value) && value > 0 && Number.isFinite(value);\n","import type { LineRange } from \"./line-numbers.js\";\nimport { resolveLineNumbers } from \"./line-numbers.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport type { FoldableRange } from \"./compute-json-fold-ranges.js\";\n\n/** Removes trailing `\\n` and `\\r` characters from the end of a string. */\nfunction trimTrailingNewlines(input: string): string {\n\tlet end = input.length;\n\twhile (end > 0 && (input.charCodeAt(end - 1) === 10 || input.charCodeAt(end - 1) === 13)) {\n\t\tend -= 1;\n\t}\n\treturn end === input.length ? input : input.slice(0, end);\n}\n\n/** Splits Shiki-highlighted HTML into per-line content, unwrapping `<span class=\"line\">` wrappers. */\nfunction splitHighlightedHtmlIntoLines(html: string): string[] {\n\tconst normalizedHtml = trimTrailingNewlines(html).replaceAll(\"\\r\\n\", \"\\n\").replaceAll(\"\\r\", \"\\n\");\n\tconst shikiLines = normalizedHtml.split(\"\\n\");\n\tconst linePrefix = '<span class=\"line\">';\n\tconst lineSuffix = \"</span>\";\n\n\tfor (let i = 0; i < shikiLines.length; i++) {\n\t\tconst line = shikiLines[i] ?? \"\";\n\t\tif (line.startsWith(linePrefix) && line.endsWith(lineSuffix)) {\n\t\t\tshikiLines[i] = line.slice(linePrefix.length, line.length - lineSuffix.length);\n\t\t}\n\t}\n\n\treturn shikiLines;\n}\n\n/** Inline caret SVG used by the fold toggle button. Mirrors `CaretDown` from Phosphor at a small size. */\nconst FOLD_CARET_SVG =\n\t'<svg class=\"mantle-code-fold-caret\" viewBox=\"0 0 16 16\" aria-hidden=\"true\" focusable=\"false\"><path fill=\"currentColor\" fill-rule=\"evenodd\" d=\"M3.22 5.97a.75.75 0 0 1 1.06 0L8 9.69l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L3.22 7.03a.75.75 0 0 1 0-1.06Z\"/></svg>';\n\n/**\n * Encodes public fold IDs for safe HTML attribute storage and for the\n * runtime's space-separated region sets. Built-in strategies use numeric\n * strings, but custom strategies may use descriptive IDs with spaces or\n * quotes.\n */\nfunction encodeFoldRegionId(id: string): string {\n\treturn encodeURIComponent(id);\n}\n\n/** Input for {@link decorateHighlightedHtml}. */\ntype DecorateHighlightedHtmlInput = {\n\t/**\n\t * Optional list of foldable ranges, typically produced by\n\t * {@link import(\"./compute-json-fold-ranges.js\").computeJsonFoldRanges}.\n\t *\n\t * When non-empty, every line gets a fold gutter slot; opener lines render a\n\t * semantic `<button>` toggle, descendant content lines carry\n\t * `data-fold-regions` so the runtime can hide them in O(region size) on\n\t * collapse.\n\t */\n\tfoldableRanges?: FoldableRange[] | undefined;\n\thighlightLines?: (LineRange | number)[] | undefined;\n\thtml: string;\n\tlineNumberStart?: number | undefined;\n\tshowLineNumbers?: boolean | undefined;\n};\n\n/**\n * Wraps each line of Shiki-highlighted HTML in Mantle's line-number, fold,\n * and line-highlight markup, producing the final HTML rendered by `CodeBlock.Code`.\n */\nfunction decorateHighlightedHtml({\n\tfoldableRanges,\n\thighlightLines,\n\thtml,\n\tlineNumberStart = 1,\n\tshowLineNumbers = false,\n}: DecorateHighlightedHtmlInput): string {\n\tconst highlightedLineNumbers = resolveLineNumbers(...(highlightLines ?? []));\n\tconst lines = splitHighlightedHtmlIntoLines(html);\n\n\t// Build per-line fold metadata so each line can announce its parent fold\n\t// regions and opener lines can render a toggle. Indexing up front keeps\n\t// the per-line loop O(1) for fold lookups, even on 1000+ line inputs.\n\t// Fold ranges are *buffer-relative* (1-indexed positions in the original\n\t// code), independent of `lineNumberStart` which only affects display.\n\tconst openerIdByBufferLine = new Map<number, string>();\n\tconst regionsByBufferLine = new Map<number, string[]>();\n\tconst hasFolds = foldableRanges != null && foldableRanges.length > 0;\n\n\tif (hasFolds && foldableRanges != null) {\n\t\tfor (const range of foldableRanges) {\n\t\t\tconst encodedId = encodeFoldRegionId(range.id);\n\t\t\topenerIdByBufferLine.set(range.startLine, encodedId);\n\t\t\tfor (let bufferLine = range.startLine + 1; bufferLine < range.endLine; bufferLine += 1) {\n\t\t\t\tlet regions = regionsByBufferLine.get(bufferLine);\n\t\t\t\tif (regions == null) {\n\t\t\t\t\tregions = [];\n\t\t\t\t\tregionsByBufferLine.set(bufferLine, regions);\n\t\t\t\t}\n\t\t\t\tregions.push(encodedId);\n\t\t\t}\n\t\t}\n\t}\n\n\tlet output = \"\";\n\tfor (let i = 0; i < lines.length; i++) {\n\t\tconst line = lines[i] ?? \"\";\n\t\tconst bufferLineNumber = i + 1;\n\t\tconst displayedLineNumber = lineNumberStart + i;\n\t\tconst lineClassName = cx(\n\t\t\t\"mantle-code-line\",\n\t\t\thighlightedLineNumbers.has(displayedLineNumber) && \"mantle-code-line-highlighted\",\n\t\t);\n\n\t\tconst lineNumberHtml = showLineNumbers\n\t\t\t? `<span class=\"mantle-code-line-number\" data-slot=\"line-number\">${displayedLineNumber}</span>`\n\t\t\t: \"\";\n\n\t\tlet foldGutterHtml = \"\";\n\t\tlet foldRegionsAttribute = \"\";\n\t\tlet trailingEllipsisHtml = \"\";\n\t\tif (hasFolds) {\n\t\t\t// Opener lines render a real semantic <button> in the gutter.\n\t\t\t// Non-opener lines reserve gutter space via CSS — see the\n\t\t\t// `:has(.mantle-code-fold-toggle)` rule in mantle.css. Skipping\n\t\t\t// per-line spacer markup is what keeps HTML overhead near zero\n\t\t\t// for large JSON blocks.\n\t\t\tconst openerId = openerIdByBufferLine.get(bufferLineNumber);\n\t\t\tif (openerId != null) {\n\t\t\t\tfoldGutterHtml = `<button type=\"button\" class=\"mantle-code-fold-toggle\" data-slot=\"fold-toggle\" data-fold-line=\"${openerId}\" aria-expanded=\"true\" aria-label=\"Toggle code folding\">${FOLD_CARET_SVG}</button>`;\n\t\t\t\ttrailingEllipsisHtml =\n\t\t\t\t\t'<span class=\"mantle-code-fold-ellipsis\" data-slot=\"fold-ellipsis\" aria-hidden=\"true\">⋯</span>';\n\t\t\t}\n\n\t\t\tconst regions = regionsByBufferLine.get(bufferLineNumber);\n\t\t\tif (regions != null && regions.length > 0) {\n\t\t\t\tfoldRegionsAttribute = ` data-fold-regions=\"${regions.join(\" \")}\"`;\n\t\t\t}\n\t\t}\n\n\t\tconst renderedContent = line === \"\" ? \" \" : line;\n\t\tconst contentHtml = `<span class=\"mantle-code-line-content\" data-slot=\"line-content\">${renderedContent}${trailingEllipsisHtml}</span>`;\n\n\t\toutput += `<span class=\"${lineClassName}\" data-line-number=\"${displayedLineNumber}\"${foldRegionsAttribute}>${lineNumberHtml}${foldGutterHtml}${contentHtml}</span>`;\n\t}\n\treturn output;\n}\n\nexport { decorateHighlightedHtml };\nexport type { DecorateHighlightedHtmlInput };\n","/**\n * Shared types and helpers used by every fold-range computer\n * (`computeFoldRanges`, `computeJsonFoldRanges`). Kept in its own module so\n * the legacy raw-source parser and the token-driven parser can share a\n * single dedup/finalize pass without taking a dependency on each other.\n */\n\n/**\n * A foldable region in a code block. Lines `startLine + 1` through\n * `endLine - 1` are hidden when the region is collapsed; the opener and\n * closer lines remain visible.\n */\ntype FoldableRange = {\n\t/**\n\t * Stable identifier for the fold region within a code block. Equal to the\n\t * stringified `startLine` (unique by construction after dedup), encoded\n\t * into `data-fold-line` on the toggle button and `data-fold-regions` on\n\t * each descendant line so the runtime delegated handler can resolve\n\t * toggles by attribute lookup. Custom strategies should provide non-empty\n\t * IDs that are unique within the code block; the decorator URI-encodes\n\t * them before rendering so spaces and quotes remain safe.\n\t */\n\tid: string;\n\t/** 1-based line number of the line that contains the opening token. */\n\tstartLine: number;\n\t/** 1-based line number of the line that contains the matching closing token. */\n\tendLine: number;\n};\n\n/**\n * Sorts ranges by `startLine` ascending (with `endLine` descending as a\n * tiebreak so the largest span wins on a shared opener line) and keeps at\n * most one range per opener line. Mutates and returns the input.\n */\nfunction finalizeFoldRanges(ranges: FoldableRange[]): FoldableRange[] {\n\tif (ranges.length <= 1) {\n\t\treturn ranges;\n\t}\n\tranges.sort((a, b) => {\n\t\tif (a.startLine !== b.startLine) {\n\t\t\treturn a.startLine - b.startLine;\n\t\t}\n\t\treturn b.endLine - a.endLine;\n\t});\n\n\tconst filtered: FoldableRange[] = [];\n\tlet lastStartLine = -1;\n\tfor (const range of ranges) {\n\t\tif (range.startLine === lastStartLine) {\n\t\t\tcontinue;\n\t\t}\n\t\tfiltered.push(range);\n\t\tlastStartLine = range.startLine;\n\t}\n\treturn filtered;\n}\n\nexport { finalizeFoldRanges };\nexport type { FoldableRange };\n","import { finalizeFoldRanges, type FoldableRange } from \"./fold-range-utils.js\";\n\ntype JsonBracketStackEntry = {\n\topener: 123 | 91;\n\tline: number;\n};\n\n/**\n * Computes foldable ranges for a JSON source string. Each multi-line `{...}`\n * or `[...]` produces one range whose opener and closer lines remain visible\n * when collapsed (matching VS Code's folding behavior).\n *\n * The parser is intentionally permissive: it skips over unmatched/invalid\n * bracket sequences instead of throwing, so a partially valid JSON snippet\n * still gets the folds it can. Strings, escape sequences, and unicode\n * escapes are handled correctly so brackets inside string literals don't\n * open spurious folds.\n *\n * Runs in a single pass over the source (O(n) chars). At most one fold range\n * per opener line is emitted — when several brackets open on the same line,\n * only the outermost (largest range) survives, so a single click collapses\n * the whole sub-tree without rendering stacked toggles.\n *\n * @example\n * ```ts\n * computeJsonFoldRanges(`{\\n \"a\": [\\n 1\\n ]\\n}`);\n * // => [\n * // { id: \"1\", startLine: 1, endLine: 5 },\n * // { id: \"2\", startLine: 2, endLine: 4 },\n * // ]\n * ```\n */\nfunction computeJsonFoldRanges(code: string): FoldableRange[] {\n\tconst length = code.length;\n\tif (length === 0) {\n\t\treturn [];\n\t}\n\n\tconst stack: JsonBracketStackEntry[] = [];\n\tconst ranges: FoldableRange[] = [];\n\n\tlet line = 1;\n\tlet index = 0;\n\n\twhile (index < length) {\n\t\tconst character = code.charCodeAt(index);\n\n\t\tif (character === 10) {\n\t\t\t// '\\n'\n\t\t\tline += 1;\n\t\t\tindex += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tif (character === 13) {\n\t\t\t// '\\r' — treat \\r\\n and bare \\r as a line break\n\t\t\tline += 1;\n\t\t\tindex += 1;\n\t\t\tif (index < length && code.charCodeAt(index) === 10) {\n\t\t\t\tindex += 1;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (character === 34) {\n\t\t\t// '\"' — skip over string contents (including escaped quotes)\n\t\t\tindex += 1;\n\t\t\twhile (index < length) {\n\t\t\t\tconst stringChar = code.charCodeAt(index);\n\t\t\t\tif (stringChar === 92) {\n\t\t\t\t\t// '\\\\' — skip the next char unconditionally; do not advance line on escaped \\n\n\t\t\t\t\tindex += 2;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (stringChar === 34) {\n\t\t\t\t\tindex += 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (stringChar === 10 || stringChar === 13) {\n\t\t\t\t\t// Unterminated string spanning a line — bail without advancing further into it.\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tindex += 1;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (character === 123 || character === 91) {\n\t\t\t// '{' or '['\n\t\t\tstack.push({ opener: character, line });\n\t\t\tindex += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (character === 125 || character === 93) {\n\t\t\t// '}' or ']'\n\t\t\tconst matchingOpener = character === 125 ? 123 : 91;\n\t\t\tconst top = stack[stack.length - 1];\n\t\t\tif (top?.opener === matchingOpener) {\n\t\t\t\tstack.pop();\n\t\t\t\tif (top.line !== line) {\n\t\t\t\t\tranges.push({ id: String(top.line), startLine: top.line, endLine: line });\n\t\t\t\t}\n\t\t\t} else if (top != null) {\n\t\t\t\t// Mismatched closer: the active bracket sequence is structurally\n\t\t\t\t// invalid, so prevent any containing opener from pairing later.\n\t\t\t\tstack.length = 0;\n\t\t\t}\n\t\t\tindex += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tindex += 1;\n\t}\n\n\treturn finalizeFoldRanges(ranges);\n}\n\nexport { computeJsonFoldRanges };\nexport type { FoldableRange };\n","import { finalizeFoldRanges, type FoldableRange } from \"./fold-range-utils.js\";\nimport type { SupportedLanguage } from \"./supported-languages.js\";\n\n/**\n * A single TextMate scope name attached to part of a {@link FoldToken}.\n *\n * Mirrors the shape produced by Shiki's `includeExplanation: 'scopeName'`\n * option without taking a runtime dependency on Shiki, so this module can be\n * unit-tested with hand-written fixtures.\n */\ntype FoldScope = {\n\tscopeName: string;\n};\n\n/**\n * One sub-explanation within a {@link FoldToken}. A single Shiki token may\n * cover content with several scope sets — for example an interpolation\n * boundary inside a template literal — so its `explanation` is an array.\n */\ntype FoldExplanation = {\n\tcontent: string;\n\tscopes: FoldScope[];\n};\n\n/**\n * Minimal token shape consumed by {@link computeFoldRanges}. Compatible with\n * `ThemedToken` from `@shikijs/types` when `includeExplanation: 'scopeName'`\n * is enabled.\n */\ntype FoldToken = {\n\tcontent: string;\n\texplanation?: FoldExplanation[];\n};\n\n/**\n * One line of {@link FoldToken}s, as returned by Shiki's\n * `codeToTokens`/`tokens` transformer hook.\n */\ntype FoldLine = FoldToken[];\n\n/**\n * Folding strategy applied to a language. Picked by {@link foldStrategyFor}\n * based on how the language naturally delimits blocks:\n *\n * - `bracket` — `{}`/`[]` pairs (C-family, JSON, CSS, Rust, Go, …).\n * - `indentation` — significant whitespace (Python, YAML).\n * - `tag` — element open/close tags (HTML, XML).\n * - `none` — plain text and other languages without a useful folding model.\n */\ntype FoldStrategy = \"bracket\" | \"indentation\" | \"tag\" | \"none\";\n\n/** Returns the {@link FoldStrategy} used for the given supported language. */\nfunction foldStrategyFor(language: SupportedLanguage): FoldStrategy {\n\tswitch (language) {\n\t\tcase \"python\":\n\t\tcase \"py\":\n\t\tcase \"yaml\":\n\t\tcase \"yml\":\n\t\t\treturn \"indentation\";\n\t\tcase \"html\":\n\t\tcase \"xml\":\n\t\t\treturn \"tag\";\n\t\tcase \"bash\":\n\t\tcase \"sh\":\n\t\tcase \"shell\":\n\t\tcase \"plain\":\n\t\tcase \"plaintext\":\n\t\tcase \"text\":\n\t\tcase \"txt\":\n\t\t\t// Shell languages use keyword pairs (`if … fi`, `do … done`, etc.)\n\t\t\t// rather than brackets; folding `{}` would catch only brace\n\t\t\t// expansions, which aren't useful blocks. Until we model the\n\t\t\t// keyword pairs, opt out so we don't pay the per-token scope cost.\n\t\t\treturn \"none\";\n\t\tdefault:\n\t\t\treturn \"bracket\";\n\t}\n}\n\n/** Input for {@link computeFoldRanges}. */\ntype ComputeFoldRangesInput = {\n\t/** Resolved supported language; controls which strategy runs. */\n\tlanguage: SupportedLanguage;\n\t/**\n\t * Tokens produced by Shiki for the same code that will be rendered.\n\t * Must include scope explanations (i.e. tokenized with\n\t * `includeExplanation: 'scopeName'` or `true`) so string and comment\n\t * regions can be ignored.\n\t */\n\ttokens: FoldLine[];\n};\n\n/**\n * Computes foldable ranges for a tokenized code block. Dispatches to the\n * right strategy for the given language, so callers don't need to know how\n * a particular grammar models block boundaries.\n *\n * The bracket strategy uses TextMate scopes to distinguish real punctuation\n * from `{`/`[` characters that appear inside strings, comments, or regular\n * expressions — this is what lets one parser cover JS, TS, Go, Rust, JSON,\n * CSS, and friends without per-language string/comment logic.\n *\n * Returns ranges sorted by `startLine` ascending; at most one range per\n * opener line survives so the gutter renders a single toggle even when\n * multiple constructs open on the same line (`{\"a\":[`).\n */\nfunction computeFoldRanges({ language, tokens }: ComputeFoldRangesInput): FoldableRange[] {\n\tconst strategy = foldStrategyFor(language);\n\tswitch (strategy) {\n\t\tcase \"bracket\":\n\t\t\treturn computeBracketFoldRanges(tokens);\n\t\tcase \"indentation\":\n\t\t\treturn computeIndentationFoldRanges(tokens);\n\t\tcase \"tag\":\n\t\t\treturn computeTagFoldRanges(tokens);\n\t\tcase \"none\":\n\t\t\treturn [];\n\t}\n}\n\n/**\n * Returns true when a token's innermost scope means it represents inert\n * content — string body, comment body, regex body, or character escape —\n * and therefore any `{`/`[`/`<` characters inside it should be ignored.\n *\n * Checking the innermost scope (last entry) keeps template-literal\n * interpolations foldable: `${ ... }` punctuation lives under\n * `punctuation.definition.template-expression.*`, not `string.*`, so the\n * embedded expression isn't filtered out even though `string.template`\n * appears earlier in the scope chain.\n */\nfunction isInertScope(scopes: FoldScope[]): boolean {\n\tif (scopes.length === 0) {\n\t\treturn false;\n\t}\n\tconst innermost = scopes[scopes.length - 1]?.scopeName ?? \"\";\n\treturn (\n\t\tinnermost === \"string\" ||\n\t\tinnermost === \"comment\" ||\n\t\tinnermost.startsWith(\"string.\") ||\n\t\tinnermost.startsWith(\"comment.\") ||\n\t\tinnermost.startsWith(\"constant.character.escape\")\n\t);\n}\n\n/**\n * Yields explanation pieces of a token, or one fallback piece with no\n * scopes when the token wasn't tokenized with `includeExplanation`.\n */\nfunction explanationsOf(token: FoldToken): readonly FoldExplanation[] {\n\tif (token.explanation != null && token.explanation.length > 0) {\n\t\treturn token.explanation;\n\t}\n\treturn [{ content: token.content, scopes: [] }];\n}\n\n/**\n * Reconstructs non-inert line text without losing Shiki-owned whitespace.\n * Explanation pieces can omit leading spaces, so use the full token content\n * whenever every explanation piece is visible.\n */\nfunction visibleTextForLine(line: FoldLine): string {\n\tlet visible = \"\";\n\tfor (const token of line) {\n\t\tconst explanations = explanationsOf(token);\n\t\tlet hasInert = false;\n\t\tfor (const explanation of explanations) {\n\t\t\tif (isInertScope(explanation.scopes)) {\n\t\t\t\thasInert = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!hasInert) {\n\t\t\tvisible += token.content;\n\t\t\tcontinue;\n\t\t}\n\t\tfor (const explanation of explanations) {\n\t\t\tif (isInertScope(explanation.scopes)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvisible += explanation.content;\n\t\t}\n\t}\n\treturn visible;\n}\n\n/**\n * Returns the count of leading whitespace characters on a line, or `-1`\n * for blank lines. Reads only the first token's content — Shiki emits\n * leading whitespace as its own token, so a full-line concat is wasted\n * work for the indentation strategy.\n */\nfunction leadingIndentOfLine(line: FoldLine | undefined): number {\n\tif (line == null || line.length === 0) {\n\t\treturn -1;\n\t}\n\tlet column = 0;\n\tfor (const token of line) {\n\t\tconst content = token.content;\n\t\tfor (let charIndex = 0; charIndex < content.length; charIndex += 1) {\n\t\t\tconst character = content.charCodeAt(charIndex);\n\t\t\tif (character === 32 || character === 9) {\n\t\t\t\tcolumn += 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\treturn column;\n\t\t}\n\t}\n\treturn -1;\n}\n\n/**\n * Bracket-pair folding strategy. Walks every token, skips inert (string,\n * comment, escape) regions, and pairs `{`/`[` openers with `}`/`]` closers\n * via a single stack pass.\n *\n * Parens (`(`/`)`) are intentionally not folded — function call argument\n * lists are usually short and folding them creates more noise than value.\n */\nfunction computeBracketFoldRanges(tokens: FoldLine[]): FoldableRange[] {\n\tconst stack: number[] = [];\n\tconst ranges: FoldableRange[] = [];\n\n\tfor (let lineIndex = 0; lineIndex < tokens.length; lineIndex += 1) {\n\t\tconst line = tokens[lineIndex];\n\t\tif (line == null) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst lineNumber = lineIndex + 1;\n\n\t\tfor (const token of line) {\n\t\t\tif (!hasBracketChar(token.content)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tfor (const explanation of explanationsOf(token)) {\n\t\t\t\tif (isInertScope(explanation.scopes)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst content = explanation.content;\n\t\t\t\tfor (let charIndex = 0; charIndex < content.length; charIndex += 1) {\n\t\t\t\t\tconst character = content.charCodeAt(charIndex);\n\t\t\t\t\tif (character === 123 || character === 91) {\n\t\t\t\t\t\tstack.push(lineNumber);\n\t\t\t\t\t} else if (character === 125 || character === 93) {\n\t\t\t\t\t\tconst startLine = stack.pop();\n\t\t\t\t\t\tif (startLine != null && startLine !== lineNumber) {\n\t\t\t\t\t\t\tranges.push({ id: String(startLine), startLine, endLine: lineNumber });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn finalizeFoldRanges(ranges);\n}\n\n/**\n * Pre-filter: returns true if `content` contains any of `{`, `}`, `[`, `]`.\n * Most tokens in non-JSON code are identifiers/whitespace/operators that\n * never participate in bracket folding, so this collapses ~95% of the per-\n * character scan to a single `String.prototype.indexOf` per token.\n */\nfunction hasBracketChar(content: string): boolean {\n\tfor (let i = 0; i < content.length; i += 1) {\n\t\tconst character = content.charCodeAt(i);\n\t\tif (character === 123 || character === 125 || character === 91 || character === 93) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Indentation-based folding strategy for languages where blocks are defined\n * by leading whitespace (Python, YAML).\n *\n * For each non-blank line, finds the maximal run of following lines that are\n * either blank or more deeply indented than the opener. The opener stays\n * visible; descendant lines collapse. The \"closer\" line (`endLine`) is the\n * first line at or below the opener's indent — purely a sentinel so the\n * decorator's `startLine + 1 .. endLine - 1` hide loop covers the body.\n *\n * A tab is treated as one column. Mixed tabs/spaces compare consistently\n * because we compare the count of leading whitespace characters; if a file\n * mixes the two within a single block, indent comparisons may misfire, but\n * neither Python nor YAML idiomatically mixes them.\n */\nfunction computeIndentationFoldRanges(tokens: FoldLine[]): FoldableRange[] {\n\tconst indents: number[] = new Array(tokens.length);\n\tfor (let i = 0; i < tokens.length; i += 1) {\n\t\tindents[i] = leadingIndentOfLine(tokens[i]);\n\t}\n\n\tconst ranges: FoldableRange[] = [];\n\tfor (let openerIndex = 0; openerIndex < indents.length; openerIndex += 1) {\n\t\tconst indent = indents[openerIndex] ?? -1;\n\t\tif (indent < 0) {\n\t\t\tcontinue;\n\t\t}\n\t\tlet lastChild = -1;\n\t\tlet scan = openerIndex + 1;\n\t\twhile (scan < indents.length) {\n\t\t\tconst next = indents[scan] ?? -1;\n\t\t\tif (next < 0) {\n\t\t\t\tscan += 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (next > indent) {\n\t\t\t\tlastChild = scan;\n\t\t\t\tscan += 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tif (lastChild > openerIndex) {\n\t\t\t// endLine plays the role of the \"closer\": the first line that is\n\t\t\t// not folded. `lastChild + 2` converts the 0-indexed last child\n\t\t\t// to a 1-indexed sentinel one past it.\n\t\t\tranges.push({\n\t\t\t\tid: String(openerIndex + 1),\n\t\t\t\tstartLine: openerIndex + 1,\n\t\t\t\tendLine: lastChild + 2,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn finalizeFoldRanges(ranges);\n}\n\n/**\n * Tag-pair folding strategy for HTML and XML.\n *\n * Reconstructs each line's visible text from non-inert tokens, then scans\n * tag patterns with a small linear scanner. Self-closing tags (`<br/>`, `<img />`)\n * and known void HTML elements (`<br>`, `<img>`, `<input>`, …) don't push\n * onto the stack. Stack-based matching emits one range per line with an\n * unmatched opener and a matching closer on a later line.\n *\n * Multi-line tags (an opener whose `>` is on a different line than the\n * `<`) are deliberately not folded in v1 — they're rare and would require\n * cross-line state.\n */\nfunction computeTagFoldRanges(tokens: FoldLine[]): FoldableRange[] {\n\tconst stack: { name: string; line: number }[] = [];\n\tconst ranges: FoldableRange[] = [];\n\n\tfor (let lineIndex = 0; lineIndex < tokens.length; lineIndex += 1) {\n\t\tconst line = tokens[lineIndex];\n\t\tif (line == null) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst lineNumber = lineIndex + 1;\n\t\tconst visible = visibleTextForLine(line);\n\n\t\tconst matches = extractTagMatches(visible);\n\t\tfor (const match of matches) {\n\t\t\tif (match.kind === \"open\") {\n\t\t\t\tstack.push({ name: match.name, line: lineNumber });\n\t\t\t} else {\n\t\t\t\tconst top = stack.length > 0 ? stack[stack.length - 1] : undefined;\n\t\t\t\tif (top != null && top.name.toLowerCase() === match.name.toLowerCase()) {\n\t\t\t\t\tstack.pop();\n\t\t\t\t\tif (top.line !== lineNumber) {\n\t\t\t\t\t\tranges.push({\n\t\t\t\t\t\t\tid: String(top.line),\n\t\t\t\t\t\t\tstartLine: top.line,\n\t\t\t\t\t\t\tendLine: lineNumber,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn finalizeFoldRanges(ranges);\n}\n\n/** HTML elements whose tags don't have a closing counterpart. */\nconst VOID_HTML_ELEMENTS = new Set<string>([\n\t\"area\",\n\t\"base\",\n\t\"br\",\n\t\"col\",\n\t\"embed\",\n\t\"hr\",\n\t\"img\",\n\t\"input\",\n\t\"link\",\n\t\"meta\",\n\t\"param\",\n\t\"source\",\n\t\"track\",\n\t\"wbr\",\n]);\n\n/**\n * Extracts open/close tag matches from a single line's visible text.\n *\n * Only tags that both open and close on this line are considered; we skip\n * partial tags (an unmatched `<` with no `>`) so multi-line tags don't\n * register as openers.\n */\nfunction extractTagMatches(line: string): { name: string; kind: \"open\" | \"close\" }[] {\n\tconst matches: { name: string; kind: \"open\" | \"close\" }[] = [];\n\tlet index = 0;\n\n\twhile (index < line.length) {\n\t\tconst tagStart = line.indexOf(\"<\", index);\n\t\tif (tagStart === -1) {\n\t\t\tbreak;\n\t\t}\n\n\t\tlet cursor = skipHtmlWhitespace(line, tagStart + 1);\n\t\tconst isClose = line.charCodeAt(cursor) === 47;\n\t\tif (isClose) {\n\t\t\tcursor = skipHtmlWhitespace(line, cursor + 1);\n\t\t}\n\n\t\tif (!isTagNameStart(line.charCodeAt(cursor))) {\n\t\t\tindex = tagStart + 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst nameStart = cursor;\n\t\tcursor += 1;\n\t\twhile (cursor < line.length && isTagNameContinue(line.charCodeAt(cursor))) {\n\t\t\tcursor += 1;\n\t\t}\n\t\tconst name = line.slice(nameStart, cursor);\n\t\tconst tagEnd = findTagEnd(line, cursor);\n\t\tif (tagEnd === -1) {\n\t\t\tindex = tagStart + 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (isClose) {\n\t\t\tmatches.push({ name, kind: \"close\" });\n\t\t\tindex = tagEnd + 1;\n\t\t\tcontinue;\n\t\t}\n\t\tconst selfClosing = tagEndsSelfClosing(line, tagEnd);\n\t\tif (selfClosing || VOID_HTML_ELEMENTS.has(name.toLowerCase())) {\n\t\t\tindex = tagEnd + 1;\n\t\t\tcontinue;\n\t\t}\n\t\tmatches.push({ name, kind: \"open\" });\n\t\tindex = tagEnd + 1;\n\t}\n\treturn matches;\n}\n\n/** Returns true for whitespace accepted inside a tag opener. */\nfunction isHtmlWhitespace(character: number): boolean {\n\treturn (\n\t\tcharacter === 9 ||\n\t\tcharacter === 10 ||\n\t\tcharacter === 11 ||\n\t\tcharacter === 12 ||\n\t\tcharacter === 13 ||\n\t\tcharacter === 32\n\t);\n}\n\n/** Skips HTML whitespace starting at `index`. */\nfunction skipHtmlWhitespace(line: string, index: number): number {\n\tlet cursor = index;\n\twhile (cursor < line.length && isHtmlWhitespace(line.charCodeAt(cursor))) {\n\t\tcursor += 1;\n\t}\n\treturn cursor;\n}\n\n/** Returns true when `character` can start an HTML/XML tag name. */\nfunction isTagNameStart(character: number): boolean {\n\treturn (character >= 65 && character <= 90) || (character >= 97 && character <= 122);\n}\n\n/** Returns true when `character` can continue an HTML/XML tag name. */\nfunction isTagNameContinue(character: number): boolean {\n\treturn (\n\t\tisTagNameStart(character) ||\n\t\t(character >= 48 && character <= 57) ||\n\t\tcharacter === 45 ||\n\t\tcharacter === 58 ||\n\t\tcharacter === 95\n\t);\n}\n\n/** Finds the closing `>` for a tag, ignoring `>` inside quoted attributes. */\nfunction findTagEnd(line: string, index: number): number {\n\tlet quote: number | undefined;\n\tfor (let cursor = index; cursor < line.length; cursor += 1) {\n\t\tconst character = line.charCodeAt(cursor);\n\t\tif (quote != null) {\n\t\t\tif (character === quote) {\n\t\t\t\tquote = undefined;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (character === 34 || character === 39) {\n\t\t\tquote = character;\n\t\t\tcontinue;\n\t\t}\n\t\tif (character === 62) {\n\t\t\treturn cursor;\n\t\t}\n\t}\n\treturn -1;\n}\n\n/** Returns true when the tag ending at `tagEnd` has a trailing `/`. */\nfunction tagEndsSelfClosing(line: string, tagEnd: number): boolean {\n\tlet cursor = tagEnd - 1;\n\twhile (cursor >= 0 && isHtmlWhitespace(line.charCodeAt(cursor))) {\n\t\tcursor -= 1;\n\t}\n\treturn cursor >= 0 && line.charCodeAt(cursor) === 47;\n}\n\nexport {\n\t//,\n\tcomputeFoldRanges,\n\tfoldStrategyFor,\n};\n\nexport type {\n\t//,\n\tComputeFoldRangesInput,\n\tFoldExplanation,\n\tFoldLine,\n\tFoldScope,\n\tFoldStrategy,\n\tFoldToken,\n};\n","import type { SupportedLanguage } from \"./supported-languages.js\";\n\nconst indentations = [\"tabs\", \"spaces\"] as const;\ntype Indentation = (typeof indentations)[number];\n\n/**\n * Type Predicate: checks if the given value is a valid indentation type.\n */\nfunction isIndentation(input: unknown): input is Indentation {\n\treturn indentations.includes(input as Indentation);\n}\n\n/**\n * Infers the indentation type based on the language and preferred indentation.\n *\n * @param language - The language to check.\n * @param preferredIndentation - The preferred indentation type (overrides what is detected).\n */\nfunction inferIndentation(\n\tlanguage: SupportedLanguage,\n\tpreferredIndentation: Indentation | undefined,\n) {\n\t// if the user has a preferred indentation, use that regardless of the language\n\tif (preferredIndentation) {\n\t\treturn preferredIndentation;\n\t}\n\n\tif (isTabIndentedLanguage(language)) {\n\t\treturn \"tabs\";\n\t}\n\n\tif (isSpaceIndentedLanguage(language)) {\n\t\treturn \"spaces\";\n\t}\n\n\treturn \"spaces\";\n}\n\nexport {\n\t//,\n\tindentations,\n\tinferIndentation,\n\tisIndentation,\n};\n\nexport type {\n\t//,\n\tIndentation,\n};\n\n/**\n * Languages that require or strongly prefer tabs\n */\nconst tabIndentedLanguages = [\n\t\"csharp\",\n\t\"css\",\n\t\"go\",\n\t\"html\",\n\t\"java\",\n\t\"javascript\",\n\t\"js\",\n\t\"jsx\",\n\t\"ts\",\n\t\"tsx\",\n\t\"typescript\",\n\t\"xml\",\n] as const satisfies SupportedLanguage[];\n\nconst tabIndentedLanguageSet = new Set<string>(tabIndentedLanguages);\n\n/**\n * Languages that require or strongly prefer spaces\n */\nconst spaceIndentedLanguages = [\n\t\"python\",\n\t\"py\",\n\t\"yaml\",\n\t\"yml\",\n\t\"ruby\",\n\t\"rb\",\n] as const satisfies SupportedLanguage[];\n\nconst spaceIndentedLanguageSet = new Set<string>(spaceIndentedLanguages);\n\ntype TabIndentedLanguage = (typeof tabIndentedLanguages)[number];\ntype SpaceIndentedLanguage = (typeof spaceIndentedLanguages)[number];\n\n/**\n * Type Predicate: checks if the given value is a required/preferred tab-indented language.\n */\nfunction isTabIndentedLanguage(value: SupportedLanguage): value is TabIndentedLanguage {\n\treturn tabIndentedLanguageSet.has(value);\n}\n\n/**\n * Type Predicate: checks if the given value is a required/preferred space-indented language.\n */\nfunction isSpaceIndentedLanguage(value: SupportedLanguage): value is SpaceIndentedLanguage {\n\treturn spaceIndentedLanguageSet.has(value);\n}\n","import type { Indentation } from \"./indentation.js\";\n\ntype Options = {\n\t/**\n\t * The indentation type to use. Can be either \"tabs\" or \"spaces\".\n\t * @default \"spaces\"\n\t */\n\tindentation?: Indentation;\n};\n\n/**\n * Trim any leading and trailing whitespace/empty lines, convert leading\n * indentation to the given options.indentation\n */\nfunction normalizeIndentation(value: string, options?: Options): string {\n\tconst indentation = options?.indentation ?? \"spaces\";\n\tconst normalizedLineEndings = value.replace(/\\r\\n?/g, \"\\n\");\n\tconst trimmed = normalizedLineEndings.trim();\n\n\tif (trimmed === \"\") {\n\t\treturn \"\";\n\t}\n\n\tconst minIndent = findMinIndent(normalizedLineEndings);\n\tconst lines = trimmed.split(\"\\n\");\n\tconst normalizedLines = new Array<string>(lines.length);\n\n\tfor (let i = 0; i < lines.length; i++) {\n\t\tconst line = lines[i];\n\t\tif (line == null) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst dedentedLine = startsWithNonWhitespace(line) ? line : line.slice(minIndent);\n\t\tnormalizedLines[i] = normalizeLeadingIndentation(dedentedLine, indentation);\n\t}\n\n\treturn normalizedLines.join(\"\\n\");\n}\n\nexport {\n\t//,\n\tnormalizeIndentation,\n};\n\n/**\n * Rewrites only the leading indentation of a non-empty line into the requested\n * indentation style, leaving the rest of the line untouched.\n */\nfunction normalizeLeadingIndentation(line: string, indentation: Indentation): string {\n\tlet indentEnd = 0;\n\twhile (indentEnd < line.length) {\n\t\tconst character = line[indentEnd];\n\t\tif (character !== \" \" && character !== \"\\t\") {\n\t\t\tbreak;\n\t\t}\n\t\tindentEnd += 1;\n\t}\n\n\tif (indentEnd === 0 || indentEnd === line.length) {\n\t\treturn line;\n\t}\n\n\tconst leadingWhitespace = line.slice(0, indentEnd);\n\tconst normalizedLeadingWhitespace =\n\t\tindentation === \"spaces\"\n\t\t\t? leadingWhitespace.replace(/\\t/g, \" \")\n\t\t\t: leadingWhitespace.replace(/ {2}/g, \"\\t\");\n\n\treturn normalizedLeadingWhitespace + line.slice(indentEnd);\n}\n\n/**\n * Returns true when a line begins with visible content instead of indentation.\n */\nfunction startsWithNonWhitespace(line: string): boolean {\n\tconst firstCharacter = line[0];\n\treturn firstCharacter != null && firstCharacter !== \" \" && firstCharacter !== \"\\t\";\n}\n\n/**\n * Find the shortest indentation of a multiline string.\n */\nfunction findMinIndent(value: string): number {\n\tlet minIndent = Number.POSITIVE_INFINITY;\n\tlet indent = 0;\n\tlet atLineStart = true;\n\n\tfor (let i = 0; i < value.length; i++) {\n\t\tconst char = value[i];\n\n\t\tif (atLineStart) {\n\t\t\tif (char === \" \" || char === \"\\t\") {\n\t\t\t\tindent += 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (char === \"\\n\" || char === \"\\r\") {\n\t\t\t\tindent = 0;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (indent < minIndent) {\n\t\t\t\tminIndent = indent;\n\t\t\t\tif (minIndent === 0) {\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t}\n\t\t\tatLineStart = false;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"\\n\" || char === \"\\r\") {\n\t\t\tatLineStart = true;\n\t\t\tindent = 0;\n\t\t}\n\t}\n\n\treturn minIndent === Number.POSITIVE_INFINITY ? 0 : minIndent;\n}\n","/**\n * List of supported languages for syntax highlighting.\n * @private\n */\nexport const supportedLanguages = [\n\t\"bash\",\n\t\"cs\",\n\t\"csharp\",\n\t\"css\",\n\t\"go\",\n\t\"html\",\n\t\"java\",\n\t\"javascript\",\n\t\"js\",\n\t\"json\",\n\t\"jsx\",\n\t\"plain\",\n\t\"plaintext\",\n\t\"py\",\n\t\"python\",\n\t\"rb\",\n\t\"ruby\",\n\t\"rust\",\n\t\"sh\",\n\t\"shell\",\n\t\"text\",\n\t\"ts\",\n\t\"tsx\",\n\t\"txt\",\n\t\"typescript\",\n\t\"xml\",\n\t\"yaml\",\n\t\"yml\",\n] as const;\n\n/**\n * Supported languages for syntax highlighting.\n */\ntype SupportedLanguage = (typeof supportedLanguages)[number];\nconst supportedLanguageSet = new Set<SupportedLanguage>(supportedLanguages);\nconst defaultLanguage = \"text\" satisfies SupportedLanguage;\n\n/**\n * Parses a markdown code block (```) language class into a SupportedLanguage.\n * Defaults to \"text\" if no supported language is found.\n */\nfunction parseLanguage(\n\tvalue: `language-${string}` | `lang-${string}` | (string & {}) | undefined,\n): SupportedLanguage {\n\tconst trimmed = value?.trim() ?? \"\";\n\tif (!trimmed) {\n\t\treturn defaultLanguage;\n\t}\n\n\t// remove leading \"language-\" and \"lang-\" prefixes\n\t// find first '-' and slice from there\n\tconst prefixSeparatorIndex = trimmed.indexOf(\"-\");\n\tconst maybeLanguage =\n\t\tprefixSeparatorIndex === -1 ? trimmed : trimmed.slice(prefixSeparatorIndex + 1);\n\n\treturn isSupportedLanguage(maybeLanguage) ? maybeLanguage : defaultLanguage;\n}\n\n/**\n * Type Predicate: checks if an arbitrary value is a supported syntax highlighting language.\n */\nconst isSupportedLanguage = (value: unknown): value is SupportedLanguage => {\n\treturn typeof value === \"string\" && supportedLanguageSet.has(value as SupportedLanguage);\n};\n\nexport {\n\t//,\n\tisSupportedLanguage,\n\tparseLanguage,\n};\n\nexport type { SupportedLanguage };\n","import type { LineRange } from \"./line-numbers.js\";\n\n/** Parses a boolean or `\"true\"`/`\"false\"` string into a boolean. Returns `undefined` for unrecognized values. */\nfunction parseCodeBlockShowLineNumbers(value: unknown): boolean | undefined {\n\tif (typeof value === \"boolean\") {\n\t\treturn value;\n\t}\n\tif (typeof value === \"string\") {\n\t\tif (value === \"true\") {\n\t\t\treturn true;\n\t\t}\n\t\tif (value === \"false\") {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/** Parses a positive integer (or its string representation) for the starting line number. Returns `undefined` for invalid values. */\nfunction parseCodeBlockLineNumberStart(value: unknown): number | undefined {\n\tif (typeof value === \"number\" && Number.isFinite(value) && value > 0) {\n\t\treturn Math.floor(value);\n\t}\n\tif (typeof value === \"string\" && /^\\d+$/.test(value)) {\n\t\tconst parsed = Number.parseInt(value, 10);\n\t\treturn parsed > 0 ? parsed : undefined;\n\t}\n\treturn undefined;\n}\n\n/** Parses highlight line specifications from an array or comma-separated string (e.g. `[1, \"3-5\"]` or `\"1,3-5\"`). Returns `undefined` when no valid entries are found. */\nfunction parseCodeBlockHighlightLines(value: unknown): (LineRange | number)[] | undefined {\n\tconst parseSingle = (item: unknown): LineRange | number | undefined => {\n\t\tif (typeof item === \"number\") {\n\t\t\treturn Number.isFinite(item) && item > 0 ? Math.floor(item) : undefined;\n\t\t}\n\t\tif (typeof item === \"string\") {\n\t\t\tconst trimmed = item.trim();\n\t\t\tif (/^\\d+$/.test(trimmed)) {\n\t\t\t\tconst parsed = Number.parseInt(trimmed, 10);\n\t\t\t\treturn parsed > 0 ? parsed : undefined;\n\t\t\t}\n\t\t\tif (/^\\d+-\\d+$/.test(trimmed)) {\n\t\t\t\tconst [startStr, endStr] = trimmed.split(\"-\");\n\t\t\t\tconst start = Number.parseInt(startStr ?? \"\", 10);\n\t\t\t\tconst end = Number.parseInt(endStr ?? \"\", 10);\n\t\t\t\tif (start > 0 && end > 0) {\n\t\t\t\t\treturn trimmed as LineRange;\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t};\n\n\tif (typeof value === \"string\") {\n\t\tconst parsed: (LineRange | number)[] = [];\n\t\tconst segments = value.split(\",\");\n\t\tfor (const segment of segments) {\n\t\t\tconst maybe = parseSingle(segment);\n\t\t\tif (maybe != null) {\n\t\t\t\tparsed.push(maybe);\n\t\t\t}\n\t\t}\n\t\treturn parsed.length > 0 ? parsed : undefined;\n\t}\n\n\tif (!Array.isArray(value)) {\n\t\treturn undefined;\n\t}\n\tconst parsed: (LineRange | number)[] = [];\n\tfor (const item of value) {\n\t\tconst maybe = parseSingle(item);\n\t\tif (maybe != null) {\n\t\t\tparsed.push(maybe);\n\t\t}\n\t}\n\treturn parsed.length > 0 ? parsed : undefined;\n}\n\nexport {\n\t//,\n\tparseCodeBlockHighlightLines,\n\tparseCodeBlockLineNumberStart,\n\tparseCodeBlockShowLineNumbers,\n};\n","import type { SupportedLanguage } from \"./supported-languages.js\";\nimport { isSupportedLanguage } from \"./supported-languages.js\";\nimport { parseBooleanish } from \"../../types/booleanish.js\";\nimport { type Indentation, isIndentation } from \"./indentation.js\";\nimport {\n\tparseCodeBlockHighlightLines,\n\tparseCodeBlockLineNumberStart,\n\tparseCodeBlockShowLineNumbers,\n} from \"./parse-line-options.js\";\n\nconst modes = [\n\t//,\n\t\"cli\",\n\t\"file\",\n\t\"traffic-policy\",\n] as const;\n/** The visual mode preset for a code block (determines header icon). */\ntype Mode = (typeof modes)[number];\n\n/** User-facing input shape for code block metadata (metastring key-value pairs). */\ntype MetaInput = {\n\tcollapsible?: boolean | undefined;\n\tdisableCopy?: boolean | undefined;\n\tindentation?: Indentation | undefined;\n\tmode?: Mode | undefined;\n\ttitle?: string | undefined;\n};\n\n/** Resolved code block metadata with defaults applied. */\ntype Meta = {\n\tcollapsible: boolean;\n\tdisableCopy: boolean;\n\tindentation?: Indentation | undefined;\n\tmode?: Mode | undefined;\n\ttitle?: string | undefined;\n};\n\nconst defaultMeta = {\n\tcollapsible: false,\n\tdisableCopy: false,\n\tindentation: undefined,\n\tmode: undefined,\n\ttitle: undefined,\n} as const satisfies Meta;\n\n/** The type of the default metadata constant. */\ntype DefaultMeta = typeof defaultMeta;\n\n/** Parses a code fence metastring (e.g. `title=\"example\" collapsible`) into a structured `Meta` object. */\nfunction parseMetastring(input: string | undefined): Meta {\n\tconst metastring = input?.trim() ?? \"\";\n\tif (!metastring) {\n\t\treturn defaultMeta;\n\t}\n\n\tconst metaJson: Record<string, unknown> = {};\n\tconst tokens = tokenizeMetastring(metastring);\n\tfor (const token of tokens) {\n\t\tconst separatorIndex = token.indexOf(\"=\");\n\t\tconst key = separatorIndex === -1 ? token : token.slice(0, separatorIndex);\n\t\tconst value = separatorIndex === -1 ? undefined : token.slice(separatorIndex + 1);\n\n\t\tif (!key) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst normalized = normalizeValue(value);\n\t\tmetaJson[key] = normalized ?? true;\n\t}\n\n\treturn parseMetaJson(metaJson);\n}\n\n/** Strips surrounding double-quotes and trims whitespace from a metastring value. */\nfunction normalizeValue(value: string | undefined) {\n\tif (value == null) {\n\t\treturn undefined;\n\t}\n\tconst trimmed = value.trim();\n\tconst lastIndex = trimmed.length - 1;\n\tif (lastIndex >= 1 && trimmed.charCodeAt(0) === 34 && trimmed.charCodeAt(lastIndex) === 34) {\n\t\treturn trimmed.slice(1, lastIndex);\n\t}\n\treturn trimmed;\n}\n\n/** Splits a metastring into whitespace-delimited tokens, respecting double-quoted segments. */\nfunction tokenizeMetastring(value: string | undefined): string[] {\n\tconst input = value?.trim() ?? \"\";\n\tconst result: string[] = [];\n\n\tlet current = \"\";\n\tlet inQuotes = false;\n\n\tfor (let i = 0; i < input.length; i++) {\n\t\tconst char = input[i] ?? \"\";\n\t\tif (!inQuotes && isMetastringWhitespace(char)) {\n\t\t\tif (current) {\n\t\t\t\tresult.push(current);\n\t\t\t\tcurrent = \"\";\n\t\t\t}\n\t\t} else if (char === '\"') {\n\t\t\tinQuotes = !inQuotes;\n\t\t\tcurrent += char;\n\t\t} else {\n\t\t\tcurrent += char;\n\t\t}\n\t}\n\n\tif (current) {\n\t\tresult.push(current);\n\t}\n\n\treturn result;\n}\n\n/** Returns `true` for the ASCII whitespace characters a metastring may use to separate tokens. */\nfunction isMetastringWhitespace(char: string): boolean {\n\treturn char === \" \" || char === \"\\t\" || char === \"\\n\" || char === \"\\r\";\n}\n\n/** Type predicate: checks if a value is a valid code block `Mode`. */\nfunction isMode(input: unknown): input is Mode {\n\treturn input === \"cli\" || input === \"file\" || input === \"traffic-policy\";\n}\n\n/** Converts a raw key-value record (from tokenized metastring) into a validated `Meta` object. */\nfunction parseMetaJson(input: Record<string, unknown>): Meta {\n\tconst {\n\t\tcollapsible = defaultMeta.collapsible,\n\t\tdisableCopy = defaultMeta.disableCopy,\n\t\tindentation = defaultMeta.indentation,\n\t\tmode = defaultMeta.mode,\n\t\ttitle = defaultMeta.title,\n\t} = input;\n\n\treturn {\n\t\tcollapsible:\n\t\t\ttypeof collapsible === \"string\" || typeof collapsible === \"boolean\"\n\t\t\t\t? parseBooleanish(collapsible)\n\t\t\t\t: defaultMeta.collapsible,\n\t\tdisableCopy:\n\t\t\ttypeof disableCopy === \"string\" || typeof disableCopy === \"boolean\"\n\t\t\t\t? parseBooleanish(disableCopy)\n\t\t\t\t: defaultMeta.disableCopy,\n\t\tindentation: isIndentation(indentation) ? indentation : defaultMeta.indentation,\n\t\tmode: isMode(mode) ? mode : defaultMeta.mode,\n\t\ttitle: typeof title === \"string\" ? title.trim() : defaultMeta.title,\n\t};\n}\n\n/** Props that the rehype plugin attaches to `<pre>` elements for pre-rendered code blocks. */\ntype ResolvePreRenderedCodeBlockPropsInput = {\n\tcollapsible?: unknown;\n\tdisableCopy?: unknown;\n\tmantleCode?: unknown;\n\tmantleCollapsible?: unknown;\n\tmantleDisableCopy?: unknown;\n\tmantleHighlightLines?: unknown;\n\tmantleLanguage?: unknown;\n\tmantleLineNumberStart?: unknown;\n\tmantleMode?: unknown;\n\tmantlePreHtml?: unknown;\n\tmantleShowLineNumbers?: unknown;\n\tmantleTitle?: unknown;\n\tmode?: unknown;\n\ttitle?: unknown;\n};\n\n/** Combined input type for a `<pre>` element that may carry both metastring and pre-rendered props. */\ntype CodeBlockPreElementInput = MetaInput & ResolvePreRenderedCodeBlockPropsInput;\n\ntype PreRenderedCodeBlockPropKey = keyof ResolvePreRenderedCodeBlockPropsInput;\n\n/** Normalized code block props extracted from pre-rendered `<pre>` element attributes. */\ntype ResolvedPreRenderedCodeBlockProps = {\n\tcode: string | undefined;\n\tcollapsible: boolean | undefined;\n\tdisableCopy: boolean | undefined;\n\thighlightLines: (number | `${number}-${number}`)[] | undefined;\n\tlanguage: SupportedLanguage | undefined;\n\tlineNumberStart: number | undefined;\n\tmode: Mode | undefined;\n\tpreHtml: string | undefined;\n\trawLanguage: unknown;\n\tshowLineNumbers: boolean | undefined;\n\ttitle: string | undefined;\n};\n\n/** Result of {@link resolvePreRenderedCodeBlockProps}: extracted Mantle props and remaining pass-through props. */\ntype ResolvePreRenderedCodeBlockPropsResult<T extends Record<string, unknown>> = {\n\tmantleCode: ResolvedPreRenderedCodeBlockProps | undefined;\n\tprops: Omit<T, PreRenderedCodeBlockPropKey>;\n};\n\n/**\n * Extracts and normalizes `mantle*` props from a `<pre>` element's attributes,\n * separating them from pass-through props. Returns `undefined` for the Mantle\n * payload when no pre-rendered attributes are present.\n */\nfunction resolvePreRenderedCodeBlockProps<\n\tT extends ResolvePreRenderedCodeBlockPropsInput & Record<string, unknown>,\n>(input: T): ResolvePreRenderedCodeBlockPropsResult<T> {\n\tconst {\n\t\tcollapsible,\n\t\tdisableCopy,\n\t\tmantleCode,\n\t\tmantleCollapsible,\n\t\tmantleDisableCopy,\n\t\tmantleHighlightLines,\n\t\tmantleLanguage,\n\t\tmantleLineNumberStart,\n\t\tmantleMode,\n\t\tmantlePreHtml,\n\t\tmantleShowLineNumbers,\n\t\tmantleTitle,\n\t\tmode,\n\t\ttitle,\n\t\t...props\n\t} = input;\n\n\tconst hasPayload =\n\t\tmantleLanguage != null ||\n\t\tmantleCode != null ||\n\t\tmantlePreHtml != null ||\n\t\tmantleShowLineNumbers != null ||\n\t\tmantleHighlightLines != null ||\n\t\tmantleLineNumberStart != null ||\n\t\tmantleCollapsible != null ||\n\t\tmantleDisableCopy != null ||\n\t\tmantleMode != null ||\n\t\tmantleTitle != null;\n\n\tif (!hasPayload) {\n\t\treturn {\n\t\t\tmantleCode: undefined,\n\t\t\tprops: props as Omit<T, PreRenderedCodeBlockPropKey>,\n\t\t};\n\t}\n\n\treturn {\n\t\tmantleCode: {\n\t\t\tcode: typeof mantleCode === \"string\" ? mantleCode : undefined,\n\t\t\tcollapsible:\n\t\t\t\t(typeof mantleCollapsible === \"string\" || typeof mantleCollapsible === \"boolean\"\n\t\t\t\t\t? parseBooleanish(mantleCollapsible)\n\t\t\t\t\t: undefined) ??\n\t\t\t\t(typeof collapsible === \"string\" || typeof collapsible === \"boolean\"\n\t\t\t\t\t? parseBooleanish(collapsible)\n\t\t\t\t\t: undefined),\n\t\t\tdisableCopy:\n\t\t\t\ttypeof mantleDisableCopy === \"string\" || typeof mantleDisableCopy === \"boolean\"\n\t\t\t\t\t? parseBooleanish(mantleDisableCopy)\n\t\t\t\t\t: typeof disableCopy === \"string\" || typeof disableCopy === \"boolean\"\n\t\t\t\t\t\t? parseBooleanish(disableCopy)\n\t\t\t\t\t\t: undefined,\n\t\t\thighlightLines: parseCodeBlockHighlightLines(mantleHighlightLines),\n\t\t\tlanguage:\n\t\t\t\ttypeof mantleLanguage === \"string\" && isSupportedLanguage(mantleLanguage)\n\t\t\t\t\t? mantleLanguage\n\t\t\t\t\t: undefined,\n\t\t\tlineNumberStart: parseCodeBlockLineNumberStart(mantleLineNumberStart),\n\t\t\tmode: isMode(mantleMode) ? mantleMode : isMode(mode) ? mode : undefined,\n\t\t\tpreHtml: typeof mantlePreHtml === \"string\" ? mantlePreHtml : undefined,\n\t\t\trawLanguage: mantleLanguage,\n\t\t\tshowLineNumbers: parseCodeBlockShowLineNumbers(mantleShowLineNumbers),\n\t\t\ttitle:\n\t\t\t\ttypeof mantleTitle === \"string\"\n\t\t\t\t\t? mantleTitle.trim()\n\t\t\t\t\t: typeof title === \"string\"\n\t\t\t\t\t\t? title.trim()\n\t\t\t\t\t\t: undefined,\n\t\t},\n\t\tprops: props as Omit<T, PreRenderedCodeBlockPropKey>,\n\t};\n}\n\nexport { resolvePreRenderedCodeBlockProps };\nexport {\n\t//,\n\tdefaultMeta,\n\tnormalizeValue,\n\tparseMetastring,\n\ttokenizeMetastring,\n};\n\nexport type {\n\tCodeBlockPreElementInput,\n\tDefaultMeta,\n\tMeta,\n\tMetaInput,\n\tMode,\n\tResolvePreRenderedCodeBlockPropsInput,\n\tResolvePreRenderedCodeBlockPropsResult,\n\tResolvedPreRenderedCodeBlockProps,\n};\n"],"mappings":"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"}
|
package/dist/{resolve-pre-rendered-props-CNUnH1fU.d.ts → resolve-pre-rendered-props-CdqAcY5m.d.ts}
RENAMED
|
@@ -4,19 +4,91 @@
|
|
|
4
4
|
*/
|
|
5
5
|
type LineRange = `${number}-${number}`;
|
|
6
6
|
//#endregion
|
|
7
|
+
//#region src/components/code-block/fold-range-utils.d.ts
|
|
8
|
+
/**
|
|
9
|
+
* Shared types and helpers used by every fold-range computer
|
|
10
|
+
* (`computeFoldRanges`, `computeJsonFoldRanges`). Kept in its own module so
|
|
11
|
+
* the legacy raw-source parser and the token-driven parser can share a
|
|
12
|
+
* single dedup/finalize pass without taking a dependency on each other.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* A foldable region in a code block. Lines `startLine + 1` through
|
|
16
|
+
* `endLine - 1` are hidden when the region is collapsed; the opener and
|
|
17
|
+
* closer lines remain visible.
|
|
18
|
+
*/
|
|
19
|
+
type FoldableRange = {
|
|
20
|
+
/**
|
|
21
|
+
* Stable identifier for the fold region within a code block. Equal to the
|
|
22
|
+
* stringified `startLine` (unique by construction after dedup), encoded
|
|
23
|
+
* into `data-fold-line` on the toggle button and `data-fold-regions` on
|
|
24
|
+
* each descendant line so the runtime delegated handler can resolve
|
|
25
|
+
* toggles by attribute lookup. Custom strategies should provide non-empty
|
|
26
|
+
* IDs that are unique within the code block; the decorator URI-encodes
|
|
27
|
+
* them before rendering so spaces and quotes remain safe.
|
|
28
|
+
*/
|
|
29
|
+
id: string; /** 1-based line number of the line that contains the opening token. */
|
|
30
|
+
startLine: number; /** 1-based line number of the line that contains the matching closing token. */
|
|
31
|
+
endLine: number;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Sorts ranges by `startLine` ascending (with `endLine` descending as a
|
|
35
|
+
* tiebreak so the largest span wins on a shared opener line) and keeps at
|
|
36
|
+
* most one range per opener line. Mutates and returns the input.
|
|
37
|
+
*/
|
|
38
|
+
declare function finalizeFoldRanges(ranges: FoldableRange[]): FoldableRange[];
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region src/components/code-block/compute-json-fold-ranges.d.ts
|
|
41
|
+
/**
|
|
42
|
+
* Computes foldable ranges for a JSON source string. Each multi-line `{...}`
|
|
43
|
+
* or `[...]` produces one range whose opener and closer lines remain visible
|
|
44
|
+
* when collapsed (matching VS Code's folding behavior).
|
|
45
|
+
*
|
|
46
|
+
* The parser is intentionally permissive: it skips over unmatched/invalid
|
|
47
|
+
* bracket sequences instead of throwing, so a partially valid JSON snippet
|
|
48
|
+
* still gets the folds it can. Strings, escape sequences, and unicode
|
|
49
|
+
* escapes are handled correctly so brackets inside string literals don't
|
|
50
|
+
* open spurious folds.
|
|
51
|
+
*
|
|
52
|
+
* Runs in a single pass over the source (O(n) chars). At most one fold range
|
|
53
|
+
* per opener line is emitted — when several brackets open on the same line,
|
|
54
|
+
* only the outermost (largest range) survives, so a single click collapses
|
|
55
|
+
* the whole sub-tree without rendering stacked toggles.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* computeJsonFoldRanges(`{\n "a": [\n 1\n ]\n}`);
|
|
60
|
+
* // => [
|
|
61
|
+
* // { id: "1", startLine: 1, endLine: 5 },
|
|
62
|
+
* // { id: "2", startLine: 2, endLine: 4 },
|
|
63
|
+
* // ]
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
declare function computeJsonFoldRanges(code: string): FoldableRange[];
|
|
67
|
+
//#endregion
|
|
7
68
|
//#region src/components/code-block/decorate-highlighted-html.d.ts
|
|
8
69
|
/** Input for {@link decorateHighlightedHtml}. */
|
|
9
70
|
type DecorateHighlightedHtmlInput = {
|
|
71
|
+
/**
|
|
72
|
+
* Optional list of foldable ranges, typically produced by
|
|
73
|
+
* {@link import("./compute-json-fold-ranges.js").computeJsonFoldRanges}.
|
|
74
|
+
*
|
|
75
|
+
* When non-empty, every line gets a fold gutter slot; opener lines render a
|
|
76
|
+
* semantic `<button>` toggle, descendant content lines carry
|
|
77
|
+
* `data-fold-regions` so the runtime can hide them in O(region size) on
|
|
78
|
+
* collapse.
|
|
79
|
+
*/
|
|
80
|
+
foldableRanges?: FoldableRange[] | undefined;
|
|
10
81
|
highlightLines?: (LineRange | number)[] | undefined;
|
|
11
82
|
html: string;
|
|
12
83
|
lineNumberStart?: number | undefined;
|
|
13
84
|
showLineNumbers?: boolean | undefined;
|
|
14
85
|
};
|
|
15
86
|
/**
|
|
16
|
-
* Wraps each line of Shiki-highlighted HTML in Mantle's line-number
|
|
17
|
-
* line-highlight markup, producing the final HTML rendered by `CodeBlock.Code`.
|
|
87
|
+
* Wraps each line of Shiki-highlighted HTML in Mantle's line-number, fold,
|
|
88
|
+
* and line-highlight markup, producing the final HTML rendered by `CodeBlock.Code`.
|
|
18
89
|
*/
|
|
19
90
|
declare function decorateHighlightedHtml({
|
|
91
|
+
foldableRanges,
|
|
20
92
|
highlightLines,
|
|
21
93
|
html,
|
|
22
94
|
lineNumberStart,
|
|
@@ -43,6 +115,82 @@ declare function parseLanguage(value: `language-${string}` | `lang-${string}` |
|
|
|
43
115
|
*/
|
|
44
116
|
declare const isSupportedLanguage: (value: unknown) => value is SupportedLanguage;
|
|
45
117
|
//#endregion
|
|
118
|
+
//#region src/components/code-block/compute-fold-ranges.d.ts
|
|
119
|
+
/**
|
|
120
|
+
* A single TextMate scope name attached to part of a {@link FoldToken}.
|
|
121
|
+
*
|
|
122
|
+
* Mirrors the shape produced by Shiki's `includeExplanation: 'scopeName'`
|
|
123
|
+
* option without taking a runtime dependency on Shiki, so this module can be
|
|
124
|
+
* unit-tested with hand-written fixtures.
|
|
125
|
+
*/
|
|
126
|
+
type FoldScope = {
|
|
127
|
+
scopeName: string;
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* One sub-explanation within a {@link FoldToken}. A single Shiki token may
|
|
131
|
+
* cover content with several scope sets — for example an interpolation
|
|
132
|
+
* boundary inside a template literal — so its `explanation` is an array.
|
|
133
|
+
*/
|
|
134
|
+
type FoldExplanation = {
|
|
135
|
+
content: string;
|
|
136
|
+
scopes: FoldScope[];
|
|
137
|
+
};
|
|
138
|
+
/**
|
|
139
|
+
* Minimal token shape consumed by {@link computeFoldRanges}. Compatible with
|
|
140
|
+
* `ThemedToken` from `@shikijs/types` when `includeExplanation: 'scopeName'`
|
|
141
|
+
* is enabled.
|
|
142
|
+
*/
|
|
143
|
+
type FoldToken = {
|
|
144
|
+
content: string;
|
|
145
|
+
explanation?: FoldExplanation[];
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* One line of {@link FoldToken}s, as returned by Shiki's
|
|
149
|
+
* `codeToTokens`/`tokens` transformer hook.
|
|
150
|
+
*/
|
|
151
|
+
type FoldLine = FoldToken[];
|
|
152
|
+
/**
|
|
153
|
+
* Folding strategy applied to a language. Picked by {@link foldStrategyFor}
|
|
154
|
+
* based on how the language naturally delimits blocks:
|
|
155
|
+
*
|
|
156
|
+
* - `bracket` — `{}`/`[]` pairs (C-family, JSON, CSS, Rust, Go, …).
|
|
157
|
+
* - `indentation` — significant whitespace (Python, YAML).
|
|
158
|
+
* - `tag` — element open/close tags (HTML, XML).
|
|
159
|
+
* - `none` — plain text and other languages without a useful folding model.
|
|
160
|
+
*/
|
|
161
|
+
type FoldStrategy = "bracket" | "indentation" | "tag" | "none";
|
|
162
|
+
/** Returns the {@link FoldStrategy} used for the given supported language. */
|
|
163
|
+
declare function foldStrategyFor(language: SupportedLanguage): FoldStrategy;
|
|
164
|
+
/** Input for {@link computeFoldRanges}. */
|
|
165
|
+
type ComputeFoldRangesInput = {
|
|
166
|
+
/** Resolved supported language; controls which strategy runs. */language: SupportedLanguage;
|
|
167
|
+
/**
|
|
168
|
+
* Tokens produced by Shiki for the same code that will be rendered.
|
|
169
|
+
* Must include scope explanations (i.e. tokenized with
|
|
170
|
+
* `includeExplanation: 'scopeName'` or `true`) so string and comment
|
|
171
|
+
* regions can be ignored.
|
|
172
|
+
*/
|
|
173
|
+
tokens: FoldLine[];
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* Computes foldable ranges for a tokenized code block. Dispatches to the
|
|
177
|
+
* right strategy for the given language, so callers don't need to know how
|
|
178
|
+
* a particular grammar models block boundaries.
|
|
179
|
+
*
|
|
180
|
+
* The bracket strategy uses TextMate scopes to distinguish real punctuation
|
|
181
|
+
* from `{`/`[` characters that appear inside strings, comments, or regular
|
|
182
|
+
* expressions — this is what lets one parser cover JS, TS, Go, Rust, JSON,
|
|
183
|
+
* CSS, and friends without per-language string/comment logic.
|
|
184
|
+
*
|
|
185
|
+
* Returns ranges sorted by `startLine` ascending; at most one range per
|
|
186
|
+
* opener line survives so the gutter renders a single toggle even when
|
|
187
|
+
* multiple constructs open on the same line (`{"a":[`).
|
|
188
|
+
*/
|
|
189
|
+
declare function computeFoldRanges({
|
|
190
|
+
language,
|
|
191
|
+
tokens
|
|
192
|
+
}: ComputeFoldRangesInput): FoldableRange[];
|
|
193
|
+
//#endregion
|
|
46
194
|
//#region src/components/code-block/indentation.d.ts
|
|
47
195
|
declare const indentations: readonly ["tabs", "spaces"];
|
|
48
196
|
type Indentation = (typeof indentations)[number];
|
|
@@ -56,7 +204,7 @@ declare function isIndentation(input: unknown): input is Indentation;
|
|
|
56
204
|
* @param language - The language to check.
|
|
57
205
|
* @param preferredIndentation - The preferred indentation type (overrides what is detected).
|
|
58
206
|
*/
|
|
59
|
-
declare function inferIndentation(language: SupportedLanguage, preferredIndentation: Indentation | undefined): "
|
|
207
|
+
declare function inferIndentation(language: SupportedLanguage, preferredIndentation: Indentation | undefined): "tabs" | "spaces";
|
|
60
208
|
//#endregion
|
|
61
209
|
//#region src/components/code-block/normalize-indentation.d.ts
|
|
62
210
|
type Options = {
|
|
@@ -281,5 +429,5 @@ type ResolvePreRenderedCodeBlockPropsResult<T extends Record<string, unknown>> =
|
|
|
281
429
|
*/
|
|
282
430
|
declare function resolvePreRenderedCodeBlockProps<T extends ResolvePreRenderedCodeBlockPropsInput & Record<string, unknown>>(input: T): ResolvePreRenderedCodeBlockPropsResult<T>;
|
|
283
431
|
//#endregion
|
|
284
|
-
export {
|
|
285
|
-
//# sourceMappingURL=resolve-pre-rendered-props-
|
|
432
|
+
export { FoldStrategy as A, computeJsonFoldRanges as B, Indentation as C, FoldExplanation as D, ComputeFoldRangesInput as E, isSupportedLanguage as F, finalizeFoldRanges as H, parseLanguage as I, supportedLanguages as L, computeFoldRanges as M, foldStrategyFor as N, FoldLine as O, SupportedLanguage as P, DecorateHighlightedHtmlInput as R, normalizeIndentation as S, isIndentation as T, LineRange as U, FoldableRange as V, MantleCodeBlockValue as _, Mode as a, defaultShowLineNumbers as b, ResolvedPreRenderedCodeBlockProps as c, parseMetastring as d, resolvePreRenderedCodeBlockProps as f, parseCodeBlockShowLineNumbers as g, parseCodeBlockLineNumberStart as h, MetaInput as i, FoldToken as j, FoldScope as k, defaultMeta as l, parseCodeBlockHighlightLines as m, DefaultMeta as n, ResolvePreRenderedCodeBlockPropsInput as o, tokenizeMetastring as p, Meta as r, ResolvePreRenderedCodeBlockPropsResult as s, CodeBlockPreElementInput as t, normalizeValue as u, MantleCodeOptions as v, inferIndentation as w, mantleCode as x, createMantleCodeBlockValue as y, decorateHighlightedHtml as z };
|
|
433
|
+
//# sourceMappingURL=resolve-pre-rendered-props-CdqAcY5m.d.ts.map
|
package/dist/split-button.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as IconButton } from "./icon-button-BnK4K7YK.js";
|
|
2
|
-
import { t as Button } from "./button-
|
|
2
|
+
import { t as Button } from "./button-BMgAxAwM.js";
|
|
3
3
|
import { t as DropdownMenu } from "./dropdown-menu-CzUNYIfA.js";
|
|
4
4
|
import * as _$react from "react";
|
|
5
5
|
import { ComponentProps, ReactNode } from "react";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ngrok/mantle",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.72.0",
|
|
4
4
|
"description": "mantle is ngrok's UI library and design system.",
|
|
5
5
|
"homepage": "https://mantle.ngrok.com",
|
|
6
6
|
"license": "MIT",
|
|
@@ -48,6 +48,8 @@
|
|
|
48
48
|
"default": "./dist/source-all.css"
|
|
49
49
|
},
|
|
50
50
|
"./package.json": "./package.json",
|
|
51
|
+
"./agent.json": "./dist/agent.json",
|
|
52
|
+
"./llms.txt": "./dist/llms.txt",
|
|
51
53
|
"./accordion": {
|
|
52
54
|
"@ngrok/src-live-types": "./src/components/accordion/index.ts",
|
|
53
55
|
"types": "./dist/accordion.d.ts",
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./cx-D1HYnpvA.js";import{t}from"./booleanish-CBGdPL3Q.js";const n=new Set([`bash`,`sh`,`shell`]);function r(e,t){return!(n.has(e)&&!t.trim().includes(`
|
|
2
|
-
`))}const i=Symbol(`MantleCodeBlockValue`);function a({preHtml:e,preValToken:t,preVals:n,highlightLines:r,lineNumberStart:a,showLineNumbers:o,code:s,language:c}){return{[i]:!0,language:c,code:s,"~preHtml":e,"~preValToken":t,"~preVals":n,"~highlightLines":r,"~lineNumberStart":a,"~showLineNumbers":o}}function o(e,t){let n=``;for(let r=0;r<e.length;r+=1)n+=e[r]??``,r<t.length&&(n+=String(t[r]));return n}function s(e,t={}){let{showLineNumbers:n,highlightLines:i,lineNumberStart:s}=t;return(t,...c)=>{let l=o(t,c);return a({language:e,code:l,preHtml:void 0,preVals:c.length>0?c:void 0,highlightLines:i,lineNumberStart:s,showLineNumbers:n??r(e,l)})}}function c(...e){let t=new Set;for(let n of e)if(typeof n==`number`){if(!l(n))continue;let e=Math.floor(n);t.add(e)}else{let e=n.indexOf(`-`),r=n.slice(0,e),i=n.slice(e+1),a=Number.parseInt(r,10),o=Number.parseInt(i,10);if(!l(a)||!l(o)||(a>o&&([a,o]=[o,a]),o-a+1>1e3))continue;for(let e=a;e<=o;e++)t.add(e)}return t}const l=e=>e!=null&&!Number.isNaN(e)&&e>0&&Number.isFinite(e);function u(e){let t=e.length;for(;t>0&&(e.charCodeAt(t-1)===10||e.charCodeAt(t-1)===13);)--t;return t===e.length?e:e.slice(0,t)}function d(e){let t=u(e).replaceAll(`\r
|
|
3
|
-
`,`
|
|
4
|
-
`).replaceAll(`\r`,`
|
|
5
|
-
`).split(`
|
|
6
|
-
`);for(let e=0;e<t.length;e++){let n=t[e]??``;n.startsWith(`<span class="line">`)&&n.endsWith(`</span>`)&&(t[e]=n.slice(19,n.length-7))}return t}function f({highlightLines:t,html:n,lineNumberStart:r=1,showLineNumbers:i=!1}){let a=c(...t??[]),o=d(n),s=``;for(let t=0;t<o.length;t++){let n=o[t]??``,c=r+t,l=e(`mantle-code-line`,a.has(c)&&`mantle-code-line-highlighted`),u=i?`<span class="mantle-code-line-number" data-slot="line-number">${c}</span>`:``;s+=`<span class="${l}" data-line-number="${c}">${u}<span class="mantle-code-line-content" data-slot="line-content">${n===``?` `:n}</span></span>`}return s}const p=[`tabs`,`spaces`];function m(e){return p.includes(e)}function h(e,t){return t||(v(e)?`tabs`:(y(e),`spaces`))}const g=new Set([`csharp`,`css`,`go`,`html`,`java`,`javascript`,`js`,`jsx`,`ts`,`tsx`,`typescript`,`xml`]),_=new Set([`python`,`py`,`yaml`,`yml`,`ruby`,`rb`]);function v(e){return g.has(e)}function y(e){return _.has(e)}function b(e,t){let n=t?.indentation??`spaces`,r=e.replace(/\r\n?/g,`
|
|
7
|
-
`),i=r.trim();if(i===``)return``;let a=C(r),o=i.split(`
|
|
8
|
-
`),s=Array(o.length);for(let e=0;e<o.length;e++){let t=o[e];t!=null&&(s[e]=x(S(t)?t:t.slice(a),n))}return s.join(`
|
|
9
|
-
`)}function x(e,t){let n=0;for(;n<e.length;){let t=e[n];if(t!==` `&&t!==` `)break;n+=1}if(n===0||n===e.length)return e;let r=e.slice(0,n);return(t===`spaces`?r.replace(/\t/g,` `):r.replace(/ {2}/g,` `))+e.slice(n)}function S(e){let t=e[0];return t!=null&&t!==` `&&t!==` `}function C(e){let t=1/0,n=0,r=!0;for(let i=0;i<e.length;i++){let a=e[i];if(r){if(a===` `||a===` `){n+=1;continue}if(a===`
|
|
10
|
-
`||a===`\r`){n=0;continue}if(n<t&&(t=n,t===0))return 0;r=!1;continue}(a===`
|
|
11
|
-
`||a===`\r`)&&(r=!0,n=0)}return t===1/0?0:t}const w=`bash.cs.csharp.css.go.html.java.javascript.js.json.jsx.plain.plaintext.py.python.rb.ruby.rust.sh.shell.text.ts.tsx.txt.typescript.xml.yaml.yml`.split(`.`),T=new Set(w),E=`text`;function D(e){let t=e?.trim()??``;if(!t)return E;let n=t.indexOf(`-`),r=n===-1?t:t.slice(n+1);return O(r)?r:E}const O=e=>typeof e==`string`&&T.has(e);function k(e){if(typeof e==`boolean`)return e;if(typeof e==`string`){if(e===`true`)return!0;if(e===`false`)return!1}}function A(e){if(typeof e==`number`&&Number.isFinite(e)&&e>0)return Math.floor(e);if(typeof e==`string`&&/^\d+$/.test(e)){let t=Number.parseInt(e,10);return t>0?t:void 0}}function j(e){let t=e=>{if(typeof e==`number`)return Number.isFinite(e)&&e>0?Math.floor(e):void 0;if(typeof e==`string`){let t=e.trim();if(/^\d+$/.test(t)){let e=Number.parseInt(t,10);return e>0?e:void 0}if(/^\d+-\d+$/.test(t)){let[e,n]=t.split(`-`);return Number.parseInt(e??``,10)>0&&Number.parseInt(n??``,10)>0?t:void 0}}};if(typeof e==`string`){let n=[],r=e.split(`,`);for(let e of r){let r=t(e);r!=null&&n.push(r)}return n.length>0?n:void 0}if(!Array.isArray(e))return;let n=[];for(let r of e){let e=t(r);e!=null&&n.push(e)}return n.length>0?n:void 0}const M={collapsible:!1,disableCopy:!1,indentation:void 0,mode:void 0,title:void 0};function N(e){let t=e?.trim()??``;if(!t)return M;let n={},r=F(t);for(let e of r){let t=e.indexOf(`=`),r=t===-1?e:e.slice(0,t),i=t===-1?void 0:e.slice(t+1);r&&(n[r]=P(i)??!0)}return R(n)}function P(e){if(e==null)return;let t=e.trim(),n=t.length-1;return n>=1&&t.charCodeAt(0)===34&&t.charCodeAt(n)===34?t.slice(1,n):t}function F(e){let t=e?.trim()??``,n=[],r=``,i=!1;for(let e=0;e<t.length;e++){let a=t[e]??``;!i&&I(a)?r&&=(n.push(r),``):(a===`"`&&(i=!i),r+=a)}return r&&n.push(r),n}function I(e){return e===` `||e===` `||e===`
|
|
12
|
-
`||e===`\r`}function L(e){return e===`cli`||e===`file`||e===`traffic-policy`}function R(e){let{collapsible:n=M.collapsible,disableCopy:r=M.disableCopy,indentation:i=M.indentation,mode:a=M.mode,title:o=M.title}=e;return{collapsible:typeof n==`string`||typeof n==`boolean`?t(n):M.collapsible,disableCopy:typeof r==`string`||typeof r==`boolean`?t(r):M.disableCopy,indentation:m(i)?i:M.indentation,mode:L(a)?a:M.mode,title:typeof o==`string`?o.trim():M.title}}function z(e){let{collapsible:n,disableCopy:r,mantleCode:i,mantleCollapsible:a,mantleDisableCopy:o,mantleHighlightLines:s,mantleLanguage:c,mantleLineNumberStart:l,mantleMode:u,mantlePreHtml:d,mantleShowLineNumbers:f,mantleTitle:p,mode:m,title:h,...g}=e;return c!=null||i!=null||d!=null||f!=null||s!=null||l!=null||a!=null||o!=null||u!=null||p!=null?{mantleCode:{code:typeof i==`string`?i:void 0,collapsible:(typeof a==`string`||typeof a==`boolean`?t(a):void 0)??(typeof n==`string`||typeof n==`boolean`?t(n):void 0),disableCopy:typeof o==`string`||typeof o==`boolean`?t(o):typeof r==`string`||typeof r==`boolean`?t(r):void 0,highlightLines:j(s),language:typeof c==`string`&&O(c)?c:void 0,lineNumberStart:A(l),mode:L(u)?u:L(m)?m:void 0,preHtml:typeof d==`string`?d:void 0,rawLanguage:c,showLineNumbers:k(f),title:typeof p==`string`?p.trim():typeof h==`string`?h.trim():void 0},props:g}:{mantleCode:void 0,props:g}}export{r as _,F as a,k as c,w as d,b as f,a as g,f as h,z as i,O as l,m,P as n,j as o,h as p,N as r,A as s,M as t,D as u,s as v};
|
|
13
|
-
//# sourceMappingURL=resolve-pre-rendered-props-C-kiaLHj.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-pre-rendered-props-C-kiaLHj.js","names":[],"sources":["../src/components/code-block/mantle-code.ts","../src/components/code-block/line-numbers.ts","../src/components/code-block/decorate-highlighted-html.ts","../src/components/code-block/indentation.ts","../src/components/code-block/normalize-indentation.ts","../src/components/code-block/supported-languages.ts","../src/components/code-block/parse-line-options.ts","../src/components/code-block/resolve-pre-rendered-props.ts"],"sourcesContent":["import type { SupportedLanguage } from \"../code-block/supported-languages.js\";\nimport type { LineRange } from \"../code-block/line-numbers.js\";\nimport type { Indentation } from \"../code-block/indentation.js\";\n\n/** Languages that represent shell/terminal commands. */\nconst shellLanguages = new Set<SupportedLanguage>([\"bash\", \"sh\", \"shell\"]);\n\n/** Returns the default `showLineNumbers` value for a given language and code string. Single-line shell snippets default to `false`; everything else defaults to `true`. */\nfunction defaultShowLineNumbers(language: SupportedLanguage, code: string): boolean {\n\tif (shellLanguages.has(language) && !code.trim().includes(\"\\n\")) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nconst mantleCodeBlockValueBrand: unique symbol = Symbol(\"MantleCodeBlockValue\");\n\n/**\n * The value produced by `mantleCode()`. Contains pre-rendered Shiki HTML (injected\n * by the Vite plugin at build time) and the original code string for the copy button.\n *\n * `~preHtml` is required at render time. Runtime syntax highlighting is intentionally\n * unsupported; only placeholder substitution for interpolated values is performed.\n */\ntype MantleCodeBlockValue = {\n\t/**\n\t * Nominal type brand to prevent accidental use of plain objects.\n\t */\n\t[mantleCodeBlockValueBrand]: true;\n\t/**\n\t * The language used for syntax highlighting.\n\t */\n\tlanguage: SupportedLanguage;\n\t/**\n\t * The original code string (used by the copy button).\n\t */\n\tcode: string;\n\t/**\n\t * Fully pre-rendered Shiki HTML injected by the Vite plugin or server highlighter.\n\t * This must be present for rendering.\n\t *\n\t * **Security:** This HTML is injected via `dangerouslySetInnerHTML`. It must\n\t * come from a trusted source (Shiki output from the Vite plugin or\n\t * `createMantleServerSyntaxHighlighter`). Never pass unsanitized user input.\n\t */\n\t\"~preHtml\"?: string | undefined;\n\t/**\n\t * Runtime values used to replace `SHIKI_VAL_N` placeholders in `~preHtml`.\n\t * This enables interpolated template expressions while preserving build-time highlighting.\n\t */\n\t\"~preVals\"?: unknown[] | undefined;\n\t/**\n\t * Placeholder token prefix used by the Vite transform for interpolated values.\n\t * When omitted, CodeBlock falls back to the legacy `SHIKI_VAL_<n>` format.\n\t */\n\t\"~preValToken\"?: string | undefined;\n\t/**\n\t * Optional default for line-number rendering when this value is displayed.\n\t */\n\t\"~showLineNumbers\"?: boolean | undefined;\n\t/**\n\t * Optional default highlighted line numbers/ranges when this value is displayed.\n\t */\n\t\"~highlightLines\"?: (LineRange | number)[] | undefined;\n\t/**\n\t * Optional default start line number when line numbers are displayed.\n\t * @default 1\n\t */\n\t\"~lineNumberStart\"?: number | undefined;\n};\n\n/** Maps each key starting with `OldPrefix` to `NewPrefix`, leaving other keys unchanged. */\ntype ReplacePrefix<T, OldPrefix extends string, NewPrefix extends string> = {\n\t[K in keyof T as K extends `${OldPrefix}${infer Rest}` ? `${NewPrefix}${Rest}` : K]: T[K];\n};\n\n/** Public input shape for `createMantleCodeBlockValue`, with `~`-prefixed keys renamed to unprefixed. */\ntype MantleCodeBlockValueInput = ReplacePrefix<\n\tOmit<MantleCodeBlockValue, typeof mantleCodeBlockValueBrand>,\n\t\"~\",\n\t\"\"\n>;\n\n/** Options for configuring line numbers, highlights, and indentation in `mantleCode()`. */\ntype MantleCodeOptions = {\n\t/** Line numbers or ranges to visually highlight in the code block. */\n\thighlightLines?: (LineRange | number)[] | undefined;\n\t/** The indentation style to use when normalizing the code string. */\n\tindentation?: Indentation | undefined;\n\t/**\n\t * The starting line number when line numbers are displayed.\n\t * @default 1\n\t */\n\tlineNumberStart?: number | undefined;\n\t/**\n\t * Whether to show line numbers in the code block. Defaults to `true` for most\n\t * languages, but `false` for single-line shell snippets (`bash`, `sh`, `shell`).\n\t */\n\tshowLineNumbers?: boolean | undefined;\n};\n\n/**\n * Creates a `MantleCodeBlockValue` for use with `CodeBlock.Code`.\n *\n * **Security:** The `preHtml` field is rendered via `dangerouslySetInnerHTML`.\n * Only pass HTML produced by Shiki (via the Vite plugin or\n * `createMantleServerSyntaxHighlighter`). Never pass unsanitized user input as `preHtml`.\n */\nfunction createMantleCodeBlockValue({\n\tpreHtml,\n\tpreValToken,\n\tpreVals,\n\thighlightLines,\n\tlineNumberStart,\n\tshowLineNumbers,\n\tcode,\n\tlanguage,\n}: MantleCodeBlockValueInput): MantleCodeBlockValue {\n\treturn {\n\t\t[mantleCodeBlockValueBrand]: true,\n\t\tlanguage,\n\t\tcode,\n\t\t\"~preHtml\": preHtml,\n\t\t\"~preValToken\": preValToken,\n\t\t\"~preVals\": preVals,\n\t\t\"~highlightLines\": highlightLines,\n\t\t\"~lineNumberStart\": lineNumberStart,\n\t\t\"~showLineNumbers\": showLineNumbers,\n\t};\n}\n\n/** Joins a `TemplateStringsArray` and its interpolated values into a single code string. */\nfunction buildCodeFromTemplate(strings: TemplateStringsArray, values: unknown[]): string {\n\tlet code = \"\";\n\tfor (let index = 0; index < strings.length; index += 1) {\n\t\tcode += strings[index] ?? \"\";\n\t\tif (index < values.length) {\n\t\t\tcode += String(values[index]);\n\t\t}\n\t}\n\treturn code;\n}\n\n/**\n * Tagged template literal for Shiki syntax highlighting.\n *\n * Returns a `MantleCodeBlockValue` that `CodeBlock.Code` renders.\n * The Vite transform plugin rewrites calls to this function at build time,\n * inlining pre-rendered Shiki HTML so that no highlighting work happens in the browser.\n * Configure it via `mantleCodeBlockPlugins()` in `vite.config.ts`.\n *\n * Interpolated template expressions are supported via placeholder substitution.\n *\n * Line numbers are shown by default (`showLineNumbers` defaults to `true`),\n * except for single-line shell snippets (`bash`, `sh`, `shell`) where they default to `false`.\n *\n * @example\n * ```tsx\n * // Static string (line numbers shown by default)\n * mantleCode(\"typescript\")`const x: string = \"hello\";`\n * // Interpolated string\n * mantleCode(\"typescript\")`const greeting = \"Hello, ${name}!\";`\n * // Disable line numbers\n * mantleCode(\"typescript\", { showLineNumbers: false })`const x = 1;`\n * // Single-line shell — line numbers hidden by default\n * mantleCode(\"bash\")`npm install @ngrok/mantle`\n * ```\n */\nfunction mantleCode(\n\tlanguage: SupportedLanguage,\n\toptions: MantleCodeOptions = {},\n): (strings: TemplateStringsArray, ...values: unknown[]) => MantleCodeBlockValue {\n\tconst { showLineNumbers, highlightLines, lineNumberStart } = options;\n\n\treturn (strings, ...values) => {\n\t\tconst code = buildCodeFromTemplate(strings, values);\n\n\t\treturn createMantleCodeBlockValue({\n\t\t\tlanguage,\n\t\t\tcode,\n\t\t\tpreHtml: undefined,\n\t\t\tpreVals: values.length > 0 ? values : undefined,\n\t\t\thighlightLines,\n\t\t\tlineNumberStart,\n\t\t\tshowLineNumbers: showLineNumbers ?? defaultShowLineNumbers(language, code),\n\t\t});\n\t};\n}\n\nexport { defaultShowLineNumbers, mantleCode };\nexport { createMantleCodeBlockValue };\nexport type { MantleCodeBlockValue, MantleCodeOptions };\n","/**\n * A line range is a string in the format of `start-end` where `start` and `end` are line numbers.\n */\nexport type LineRange = `${number}-${number}`;\n\nconst MAX_EXPANDED_LINE_RANGE_LENGTH = 1_000;\n\n/**\n * Given a list of line ranges and numbers, resolves them into a unique list of line numbers as a set.\n *\n * @example\n * ```tsx\n * const highlightedLines = resolveLineNumbers(1, \"3-5\", 7, \"10-12\");\n * // Returns: Set {1, 3, 4, 5, 7, 10, 11, 12}\n *\n * const singleLine = resolveLineNumbers(42);\n * // Returns: Set {42}\n * ```\n */\nexport function resolveLineNumbers(...items: (LineRange | number)[]): Set<number> {\n\tconst lineNumberSet = new Set<number>();\n\n\tfor (const item of items) {\n\t\tif (typeof item === \"number\") {\n\t\t\tif (!isPositiveLineNumber(item)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// only support integer line numbers\n\t\t\tconst int = Math.floor(item);\n\t\t\tlineNumberSet.add(int);\n\t\t} else {\n\t\t\tconst separatorIndex = item.indexOf(\"-\");\n\t\t\tconst startPart = item.slice(0, separatorIndex);\n\t\t\tconst endPart = item.slice(separatorIndex + 1);\n\t\t\tlet start = Number.parseInt(startPart, 10);\n\t\t\tlet end = Number.parseInt(endPart, 10);\n\n\t\t\t// ignore invalid ranges that don't contain valid line numbers\n\t\t\tif (!isPositiveLineNumber(start) || !isPositiveLineNumber(end)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// swap start and end if they are backwards\n\t\t\tif (start > end) {\n\t\t\t\t[start, end] = [end, start];\n\t\t\t}\n\n\t\t\tif (end - start + 1 > MAX_EXPANDED_LINE_RANGE_LENGTH) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// add all line numbers in the range, inclusive\n\t\t\tfor (let i = start; i <= end; i++) {\n\t\t\t\tlineNumberSet.add(i);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn lineNumberSet;\n}\n\n/**\n * Type Predicate: checks if a value is a positive, finite integer.\n */\nconst isPositiveLineNumber = (value: number | undefined): value is number =>\n\tvalue != null && !Number.isNaN(value) && value > 0 && Number.isFinite(value);\n","import type { LineRange } from \"./line-numbers.js\";\nimport { resolveLineNumbers } from \"./line-numbers.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\n\n/** Removes trailing `\\n` and `\\r` characters from the end of a string. */\nfunction trimTrailingNewlines(input: string): string {\n\tlet end = input.length;\n\twhile (end > 0 && (input.charCodeAt(end - 1) === 10 || input.charCodeAt(end - 1) === 13)) {\n\t\tend -= 1;\n\t}\n\treturn end === input.length ? input : input.slice(0, end);\n}\n\n/** Splits Shiki-highlighted HTML into per-line content, unwrapping `<span class=\"line\">` wrappers. */\nfunction splitHighlightedHtmlIntoLines(html: string): string[] {\n\tconst normalizedHtml = trimTrailingNewlines(html).replaceAll(\"\\r\\n\", \"\\n\").replaceAll(\"\\r\", \"\\n\");\n\tconst shikiLines = normalizedHtml.split(\"\\n\");\n\tconst linePrefix = '<span class=\"line\">';\n\tconst lineSuffix = \"</span>\";\n\n\tfor (let i = 0; i < shikiLines.length; i++) {\n\t\tconst line = shikiLines[i] ?? \"\";\n\t\tif (line.startsWith(linePrefix) && line.endsWith(lineSuffix)) {\n\t\t\tshikiLines[i] = line.slice(linePrefix.length, line.length - lineSuffix.length);\n\t\t}\n\t}\n\n\treturn shikiLines;\n}\n\n/** Input for {@link decorateHighlightedHtml}. */\ntype DecorateHighlightedHtmlInput = {\n\thighlightLines?: (LineRange | number)[] | undefined;\n\thtml: string;\n\tlineNumberStart?: number | undefined;\n\tshowLineNumbers?: boolean | undefined;\n};\n\n/**\n * Wraps each line of Shiki-highlighted HTML in Mantle's line-number and\n * line-highlight markup, producing the final HTML rendered by `CodeBlock.Code`.\n */\nfunction decorateHighlightedHtml({\n\thighlightLines,\n\thtml,\n\tlineNumberStart = 1,\n\tshowLineNumbers = false,\n}: DecorateHighlightedHtmlInput): string {\n\tconst highlightedLineNumbers = resolveLineNumbers(...(highlightLines ?? []));\n\tconst lines = splitHighlightedHtmlIntoLines(html);\n\tlet output = \"\";\n\tfor (let i = 0; i < lines.length; i++) {\n\t\tconst line = lines[i] ?? \"\";\n\t\tconst lineNumber = lineNumberStart + i;\n\t\tconst lineClassName = cx(\n\t\t\t\"mantle-code-line\",\n\t\t\thighlightedLineNumbers.has(lineNumber) && \"mantle-code-line-highlighted\",\n\t\t);\n\n\t\tconst lineNumberHtml = showLineNumbers\n\t\t\t? `<span class=\"mantle-code-line-number\" data-slot=\"line-number\">${lineNumber}</span>`\n\t\t\t: \"\";\n\n\t\toutput += `<span class=\"${lineClassName}\" data-line-number=\"${lineNumber}\">${lineNumberHtml}<span class=\"mantle-code-line-content\" data-slot=\"line-content\">${line === \"\" ? \" \" : line}</span></span>`;\n\t}\n\treturn output;\n}\n\nexport { decorateHighlightedHtml };\nexport type { DecorateHighlightedHtmlInput };\n","import type { SupportedLanguage } from \"./supported-languages.js\";\n\nconst indentations = [\"tabs\", \"spaces\"] as const;\ntype Indentation = (typeof indentations)[number];\n\n/**\n * Type Predicate: checks if the given value is a valid indentation type.\n */\nfunction isIndentation(input: unknown): input is Indentation {\n\treturn indentations.includes(input as Indentation);\n}\n\n/**\n * Infers the indentation type based on the language and preferred indentation.\n *\n * @param language - The language to check.\n * @param preferredIndentation - The preferred indentation type (overrides what is detected).\n */\nfunction inferIndentation(\n\tlanguage: SupportedLanguage,\n\tpreferredIndentation: Indentation | undefined,\n) {\n\t// if the user has a preferred indentation, use that regardless of the language\n\tif (preferredIndentation) {\n\t\treturn preferredIndentation;\n\t}\n\n\tif (isTabIndentedLanguage(language)) {\n\t\treturn \"tabs\";\n\t}\n\n\tif (isSpaceIndentedLanguage(language)) {\n\t\treturn \"spaces\";\n\t}\n\n\treturn \"spaces\";\n}\n\nexport {\n\t//,\n\tindentations,\n\tinferIndentation,\n\tisIndentation,\n};\n\nexport type {\n\t//,\n\tIndentation,\n};\n\n/**\n * Languages that require or strongly prefer tabs\n */\nconst tabIndentedLanguages = [\n\t\"csharp\",\n\t\"css\",\n\t\"go\",\n\t\"html\",\n\t\"java\",\n\t\"javascript\",\n\t\"js\",\n\t\"jsx\",\n\t\"ts\",\n\t\"tsx\",\n\t\"typescript\",\n\t\"xml\",\n] as const satisfies SupportedLanguage[];\n\nconst tabIndentedLanguageSet = new Set<string>(tabIndentedLanguages);\n\n/**\n * Languages that require or strongly prefer spaces\n */\nconst spaceIndentedLanguages = [\n\t\"python\",\n\t\"py\",\n\t\"yaml\",\n\t\"yml\",\n\t\"ruby\",\n\t\"rb\",\n] as const satisfies SupportedLanguage[];\n\nconst spaceIndentedLanguageSet = new Set<string>(spaceIndentedLanguages);\n\ntype TabIndentedLanguage = (typeof tabIndentedLanguages)[number];\ntype SpaceIndentedLanguage = (typeof spaceIndentedLanguages)[number];\n\n/**\n * Type Predicate: checks if the given value is a required/preferred tab-indented language.\n */\nfunction isTabIndentedLanguage(value: SupportedLanguage): value is TabIndentedLanguage {\n\treturn tabIndentedLanguageSet.has(value);\n}\n\n/**\n * Type Predicate: checks if the given value is a required/preferred space-indented language.\n */\nfunction isSpaceIndentedLanguage(value: SupportedLanguage): value is SpaceIndentedLanguage {\n\treturn spaceIndentedLanguageSet.has(value);\n}\n","import type { Indentation } from \"./indentation.js\";\n\ntype Options = {\n\t/**\n\t * The indentation type to use. Can be either \"tabs\" or \"spaces\".\n\t * @default \"spaces\"\n\t */\n\tindentation?: Indentation;\n};\n\n/**\n * Trim any leading and trailing whitespace/empty lines, convert leading\n * indentation to the given options.indentation\n */\nfunction normalizeIndentation(value: string, options?: Options): string {\n\tconst indentation = options?.indentation ?? \"spaces\";\n\tconst normalizedLineEndings = value.replace(/\\r\\n?/g, \"\\n\");\n\tconst trimmed = normalizedLineEndings.trim();\n\n\tif (trimmed === \"\") {\n\t\treturn \"\";\n\t}\n\n\tconst minIndent = findMinIndent(normalizedLineEndings);\n\tconst lines = trimmed.split(\"\\n\");\n\tconst normalizedLines = new Array<string>(lines.length);\n\n\tfor (let i = 0; i < lines.length; i++) {\n\t\tconst line = lines[i];\n\t\tif (line == null) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst dedentedLine = startsWithNonWhitespace(line) ? line : line.slice(minIndent);\n\t\tnormalizedLines[i] = normalizeLeadingIndentation(dedentedLine, indentation);\n\t}\n\n\treturn normalizedLines.join(\"\\n\");\n}\n\nexport {\n\t//,\n\tnormalizeIndentation,\n};\n\n/**\n * Rewrites only the leading indentation of a non-empty line into the requested\n * indentation style, leaving the rest of the line untouched.\n */\nfunction normalizeLeadingIndentation(line: string, indentation: Indentation): string {\n\tlet indentEnd = 0;\n\twhile (indentEnd < line.length) {\n\t\tconst character = line[indentEnd];\n\t\tif (character !== \" \" && character !== \"\\t\") {\n\t\t\tbreak;\n\t\t}\n\t\tindentEnd += 1;\n\t}\n\n\tif (indentEnd === 0 || indentEnd === line.length) {\n\t\treturn line;\n\t}\n\n\tconst leadingWhitespace = line.slice(0, indentEnd);\n\tconst normalizedLeadingWhitespace =\n\t\tindentation === \"spaces\"\n\t\t\t? leadingWhitespace.replace(/\\t/g, \" \")\n\t\t\t: leadingWhitespace.replace(/ {2}/g, \"\\t\");\n\n\treturn normalizedLeadingWhitespace + line.slice(indentEnd);\n}\n\n/**\n * Returns true when a line begins with visible content instead of indentation.\n */\nfunction startsWithNonWhitespace(line: string): boolean {\n\tconst firstCharacter = line[0];\n\treturn firstCharacter != null && firstCharacter !== \" \" && firstCharacter !== \"\\t\";\n}\n\n/**\n * Find the shortest indentation of a multiline string.\n */\nfunction findMinIndent(value: string): number {\n\tlet minIndent = Number.POSITIVE_INFINITY;\n\tlet indent = 0;\n\tlet atLineStart = true;\n\n\tfor (let i = 0; i < value.length; i++) {\n\t\tconst char = value[i];\n\n\t\tif (atLineStart) {\n\t\t\tif (char === \" \" || char === \"\\t\") {\n\t\t\t\tindent += 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (char === \"\\n\" || char === \"\\r\") {\n\t\t\t\tindent = 0;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (indent < minIndent) {\n\t\t\t\tminIndent = indent;\n\t\t\t\tif (minIndent === 0) {\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t}\n\t\t\tatLineStart = false;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"\\n\" || char === \"\\r\") {\n\t\t\tatLineStart = true;\n\t\t\tindent = 0;\n\t\t}\n\t}\n\n\treturn minIndent === Number.POSITIVE_INFINITY ? 0 : minIndent;\n}\n","/**\n * List of supported languages for syntax highlighting.\n * @private\n */\nexport const supportedLanguages = [\n\t\"bash\",\n\t\"cs\",\n\t\"csharp\",\n\t\"css\",\n\t\"go\",\n\t\"html\",\n\t\"java\",\n\t\"javascript\",\n\t\"js\",\n\t\"json\",\n\t\"jsx\",\n\t\"plain\",\n\t\"plaintext\",\n\t\"py\",\n\t\"python\",\n\t\"rb\",\n\t\"ruby\",\n\t\"rust\",\n\t\"sh\",\n\t\"shell\",\n\t\"text\",\n\t\"ts\",\n\t\"tsx\",\n\t\"txt\",\n\t\"typescript\",\n\t\"xml\",\n\t\"yaml\",\n\t\"yml\",\n] as const;\n\n/**\n * Supported languages for syntax highlighting.\n */\ntype SupportedLanguage = (typeof supportedLanguages)[number];\nconst supportedLanguageSet = new Set<SupportedLanguage>(supportedLanguages);\nconst defaultLanguage = \"text\" satisfies SupportedLanguage;\n\n/**\n * Parses a markdown code block (```) language class into a SupportedLanguage.\n * Defaults to \"text\" if no supported language is found.\n */\nfunction parseLanguage(\n\tvalue: `language-${string}` | `lang-${string}` | (string & {}) | undefined,\n): SupportedLanguage {\n\tconst trimmed = value?.trim() ?? \"\";\n\tif (!trimmed) {\n\t\treturn defaultLanguage;\n\t}\n\n\t// remove leading \"language-\" and \"lang-\" prefixes\n\t// find first '-' and slice from there\n\tconst prefixSeparatorIndex = trimmed.indexOf(\"-\");\n\tconst maybeLanguage =\n\t\tprefixSeparatorIndex === -1 ? trimmed : trimmed.slice(prefixSeparatorIndex + 1);\n\n\treturn isSupportedLanguage(maybeLanguage) ? maybeLanguage : defaultLanguage;\n}\n\n/**\n * Type Predicate: checks if an arbitrary value is a supported syntax highlighting language.\n */\nconst isSupportedLanguage = (value: unknown): value is SupportedLanguage => {\n\treturn typeof value === \"string\" && supportedLanguageSet.has(value as SupportedLanguage);\n};\n\nexport {\n\t//,\n\tisSupportedLanguage,\n\tparseLanguage,\n};\n\nexport type { SupportedLanguage };\n","import type { LineRange } from \"./line-numbers.js\";\n\n/** Parses a boolean or `\"true\"`/`\"false\"` string into a boolean. Returns `undefined` for unrecognized values. */\nfunction parseCodeBlockShowLineNumbers(value: unknown): boolean | undefined {\n\tif (typeof value === \"boolean\") {\n\t\treturn value;\n\t}\n\tif (typeof value === \"string\") {\n\t\tif (value === \"true\") {\n\t\t\treturn true;\n\t\t}\n\t\tif (value === \"false\") {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/** Parses a positive integer (or its string representation) for the starting line number. Returns `undefined` for invalid values. */\nfunction parseCodeBlockLineNumberStart(value: unknown): number | undefined {\n\tif (typeof value === \"number\" && Number.isFinite(value) && value > 0) {\n\t\treturn Math.floor(value);\n\t}\n\tif (typeof value === \"string\" && /^\\d+$/.test(value)) {\n\t\tconst parsed = Number.parseInt(value, 10);\n\t\treturn parsed > 0 ? parsed : undefined;\n\t}\n\treturn undefined;\n}\n\n/** Parses highlight line specifications from an array or comma-separated string (e.g. `[1, \"3-5\"]` or `\"1,3-5\"`). Returns `undefined` when no valid entries are found. */\nfunction parseCodeBlockHighlightLines(value: unknown): (LineRange | number)[] | undefined {\n\tconst parseSingle = (item: unknown): LineRange | number | undefined => {\n\t\tif (typeof item === \"number\") {\n\t\t\treturn Number.isFinite(item) && item > 0 ? Math.floor(item) : undefined;\n\t\t}\n\t\tif (typeof item === \"string\") {\n\t\t\tconst trimmed = item.trim();\n\t\t\tif (/^\\d+$/.test(trimmed)) {\n\t\t\t\tconst parsed = Number.parseInt(trimmed, 10);\n\t\t\t\treturn parsed > 0 ? parsed : undefined;\n\t\t\t}\n\t\t\tif (/^\\d+-\\d+$/.test(trimmed)) {\n\t\t\t\tconst [startStr, endStr] = trimmed.split(\"-\");\n\t\t\t\tconst start = Number.parseInt(startStr ?? \"\", 10);\n\t\t\t\tconst end = Number.parseInt(endStr ?? \"\", 10);\n\t\t\t\tif (start > 0 && end > 0) {\n\t\t\t\t\treturn trimmed as LineRange;\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t};\n\n\tif (typeof value === \"string\") {\n\t\tconst parsed: (LineRange | number)[] = [];\n\t\tconst segments = value.split(\",\");\n\t\tfor (const segment of segments) {\n\t\t\tconst maybe = parseSingle(segment);\n\t\t\tif (maybe != null) {\n\t\t\t\tparsed.push(maybe);\n\t\t\t}\n\t\t}\n\t\treturn parsed.length > 0 ? parsed : undefined;\n\t}\n\n\tif (!Array.isArray(value)) {\n\t\treturn undefined;\n\t}\n\tconst parsed: (LineRange | number)[] = [];\n\tfor (const item of value) {\n\t\tconst maybe = parseSingle(item);\n\t\tif (maybe != null) {\n\t\t\tparsed.push(maybe);\n\t\t}\n\t}\n\treturn parsed.length > 0 ? parsed : undefined;\n}\n\nexport {\n\t//,\n\tparseCodeBlockHighlightLines,\n\tparseCodeBlockLineNumberStart,\n\tparseCodeBlockShowLineNumbers,\n};\n","import type { SupportedLanguage } from \"./supported-languages.js\";\nimport { isSupportedLanguage } from \"./supported-languages.js\";\nimport { parseBooleanish } from \"../../types/booleanish.js\";\nimport { type Indentation, isIndentation } from \"./indentation.js\";\nimport {\n\tparseCodeBlockHighlightLines,\n\tparseCodeBlockLineNumberStart,\n\tparseCodeBlockShowLineNumbers,\n} from \"./parse-line-options.js\";\n\nconst modes = [\n\t//,\n\t\"cli\",\n\t\"file\",\n\t\"traffic-policy\",\n] as const;\n/** The visual mode preset for a code block (determines header icon). */\ntype Mode = (typeof modes)[number];\n\n/** User-facing input shape for code block metadata (metastring key-value pairs). */\ntype MetaInput = {\n\tcollapsible?: boolean | undefined;\n\tdisableCopy?: boolean | undefined;\n\tindentation?: Indentation | undefined;\n\tmode?: Mode | undefined;\n\ttitle?: string | undefined;\n};\n\n/** Resolved code block metadata with defaults applied. */\ntype Meta = {\n\tcollapsible: boolean;\n\tdisableCopy: boolean;\n\tindentation?: Indentation | undefined;\n\tmode?: Mode | undefined;\n\ttitle?: string | undefined;\n};\n\nconst defaultMeta = {\n\tcollapsible: false,\n\tdisableCopy: false,\n\tindentation: undefined,\n\tmode: undefined,\n\ttitle: undefined,\n} as const satisfies Meta;\n\n/** The type of the default metadata constant. */\ntype DefaultMeta = typeof defaultMeta;\n\n/** Parses a code fence metastring (e.g. `title=\"example\" collapsible`) into a structured `Meta` object. */\nfunction parseMetastring(input: string | undefined): Meta {\n\tconst metastring = input?.trim() ?? \"\";\n\tif (!metastring) {\n\t\treturn defaultMeta;\n\t}\n\n\tconst metaJson: Record<string, unknown> = {};\n\tconst tokens = tokenizeMetastring(metastring);\n\tfor (const token of tokens) {\n\t\tconst separatorIndex = token.indexOf(\"=\");\n\t\tconst key = separatorIndex === -1 ? token : token.slice(0, separatorIndex);\n\t\tconst value = separatorIndex === -1 ? undefined : token.slice(separatorIndex + 1);\n\n\t\tif (!key) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst normalized = normalizeValue(value);\n\t\tmetaJson[key] = normalized ?? true;\n\t}\n\n\treturn parseMetaJson(metaJson);\n}\n\n/** Strips surrounding double-quotes and trims whitespace from a metastring value. */\nfunction normalizeValue(value: string | undefined) {\n\tif (value == null) {\n\t\treturn undefined;\n\t}\n\tconst trimmed = value.trim();\n\tconst lastIndex = trimmed.length - 1;\n\tif (lastIndex >= 1 && trimmed.charCodeAt(0) === 34 && trimmed.charCodeAt(lastIndex) === 34) {\n\t\treturn trimmed.slice(1, lastIndex);\n\t}\n\treturn trimmed;\n}\n\n/** Splits a metastring into whitespace-delimited tokens, respecting double-quoted segments. */\nfunction tokenizeMetastring(value: string | undefined): string[] {\n\tconst input = value?.trim() ?? \"\";\n\tconst result: string[] = [];\n\n\tlet current = \"\";\n\tlet inQuotes = false;\n\n\tfor (let i = 0; i < input.length; i++) {\n\t\tconst char = input[i] ?? \"\";\n\t\tif (!inQuotes && isMetastringWhitespace(char)) {\n\t\t\tif (current) {\n\t\t\t\tresult.push(current);\n\t\t\t\tcurrent = \"\";\n\t\t\t}\n\t\t} else if (char === '\"') {\n\t\t\tinQuotes = !inQuotes;\n\t\t\tcurrent += char;\n\t\t} else {\n\t\t\tcurrent += char;\n\t\t}\n\t}\n\n\tif (current) {\n\t\tresult.push(current);\n\t}\n\n\treturn result;\n}\n\n/** Returns `true` for the ASCII whitespace characters a metastring may use to separate tokens. */\nfunction isMetastringWhitespace(char: string): boolean {\n\treturn char === \" \" || char === \"\\t\" || char === \"\\n\" || char === \"\\r\";\n}\n\n/** Type predicate: checks if a value is a valid code block `Mode`. */\nfunction isMode(input: unknown): input is Mode {\n\treturn input === \"cli\" || input === \"file\" || input === \"traffic-policy\";\n}\n\n/** Converts a raw key-value record (from tokenized metastring) into a validated `Meta` object. */\nfunction parseMetaJson(input: Record<string, unknown>): Meta {\n\tconst {\n\t\tcollapsible = defaultMeta.collapsible,\n\t\tdisableCopy = defaultMeta.disableCopy,\n\t\tindentation = defaultMeta.indentation,\n\t\tmode = defaultMeta.mode,\n\t\ttitle = defaultMeta.title,\n\t} = input;\n\n\treturn {\n\t\tcollapsible:\n\t\t\ttypeof collapsible === \"string\" || typeof collapsible === \"boolean\"\n\t\t\t\t? parseBooleanish(collapsible)\n\t\t\t\t: defaultMeta.collapsible,\n\t\tdisableCopy:\n\t\t\ttypeof disableCopy === \"string\" || typeof disableCopy === \"boolean\"\n\t\t\t\t? parseBooleanish(disableCopy)\n\t\t\t\t: defaultMeta.disableCopy,\n\t\tindentation: isIndentation(indentation) ? indentation : defaultMeta.indentation,\n\t\tmode: isMode(mode) ? mode : defaultMeta.mode,\n\t\ttitle: typeof title === \"string\" ? title.trim() : defaultMeta.title,\n\t};\n}\n\n/** Props that the rehype plugin attaches to `<pre>` elements for pre-rendered code blocks. */\ntype ResolvePreRenderedCodeBlockPropsInput = {\n\tcollapsible?: unknown;\n\tdisableCopy?: unknown;\n\tmantleCode?: unknown;\n\tmantleCollapsible?: unknown;\n\tmantleDisableCopy?: unknown;\n\tmantleHighlightLines?: unknown;\n\tmantleLanguage?: unknown;\n\tmantleLineNumberStart?: unknown;\n\tmantleMode?: unknown;\n\tmantlePreHtml?: unknown;\n\tmantleShowLineNumbers?: unknown;\n\tmantleTitle?: unknown;\n\tmode?: unknown;\n\ttitle?: unknown;\n};\n\n/** Combined input type for a `<pre>` element that may carry both metastring and pre-rendered props. */\ntype CodeBlockPreElementInput = MetaInput & ResolvePreRenderedCodeBlockPropsInput;\n\ntype PreRenderedCodeBlockPropKey = keyof ResolvePreRenderedCodeBlockPropsInput;\n\n/** Normalized code block props extracted from pre-rendered `<pre>` element attributes. */\ntype ResolvedPreRenderedCodeBlockProps = {\n\tcode: string | undefined;\n\tcollapsible: boolean | undefined;\n\tdisableCopy: boolean | undefined;\n\thighlightLines: (number | `${number}-${number}`)[] | undefined;\n\tlanguage: SupportedLanguage | undefined;\n\tlineNumberStart: number | undefined;\n\tmode: Mode | undefined;\n\tpreHtml: string | undefined;\n\trawLanguage: unknown;\n\tshowLineNumbers: boolean | undefined;\n\ttitle: string | undefined;\n};\n\n/** Result of {@link resolvePreRenderedCodeBlockProps}: extracted Mantle props and remaining pass-through props. */\ntype ResolvePreRenderedCodeBlockPropsResult<T extends Record<string, unknown>> = {\n\tmantleCode: ResolvedPreRenderedCodeBlockProps | undefined;\n\tprops: Omit<T, PreRenderedCodeBlockPropKey>;\n};\n\n/**\n * Extracts and normalizes `mantle*` props from a `<pre>` element's attributes,\n * separating them from pass-through props. Returns `undefined` for the Mantle\n * payload when no pre-rendered attributes are present.\n */\nfunction resolvePreRenderedCodeBlockProps<\n\tT extends ResolvePreRenderedCodeBlockPropsInput & Record<string, unknown>,\n>(input: T): ResolvePreRenderedCodeBlockPropsResult<T> {\n\tconst {\n\t\tcollapsible,\n\t\tdisableCopy,\n\t\tmantleCode,\n\t\tmantleCollapsible,\n\t\tmantleDisableCopy,\n\t\tmantleHighlightLines,\n\t\tmantleLanguage,\n\t\tmantleLineNumberStart,\n\t\tmantleMode,\n\t\tmantlePreHtml,\n\t\tmantleShowLineNumbers,\n\t\tmantleTitle,\n\t\tmode,\n\t\ttitle,\n\t\t...props\n\t} = input;\n\n\tconst hasPayload =\n\t\tmantleLanguage != null ||\n\t\tmantleCode != null ||\n\t\tmantlePreHtml != null ||\n\t\tmantleShowLineNumbers != null ||\n\t\tmantleHighlightLines != null ||\n\t\tmantleLineNumberStart != null ||\n\t\tmantleCollapsible != null ||\n\t\tmantleDisableCopy != null ||\n\t\tmantleMode != null ||\n\t\tmantleTitle != null;\n\n\tif (!hasPayload) {\n\t\treturn {\n\t\t\tmantleCode: undefined,\n\t\t\tprops: props as Omit<T, PreRenderedCodeBlockPropKey>,\n\t\t};\n\t}\n\n\treturn {\n\t\tmantleCode: {\n\t\t\tcode: typeof mantleCode === \"string\" ? mantleCode : undefined,\n\t\t\tcollapsible:\n\t\t\t\t(typeof mantleCollapsible === \"string\" || typeof mantleCollapsible === \"boolean\"\n\t\t\t\t\t? parseBooleanish(mantleCollapsible)\n\t\t\t\t\t: undefined) ??\n\t\t\t\t(typeof collapsible === \"string\" || typeof collapsible === \"boolean\"\n\t\t\t\t\t? parseBooleanish(collapsible)\n\t\t\t\t\t: undefined),\n\t\t\tdisableCopy:\n\t\t\t\ttypeof mantleDisableCopy === \"string\" || typeof mantleDisableCopy === \"boolean\"\n\t\t\t\t\t? parseBooleanish(mantleDisableCopy)\n\t\t\t\t\t: typeof disableCopy === \"string\" || typeof disableCopy === \"boolean\"\n\t\t\t\t\t\t? parseBooleanish(disableCopy)\n\t\t\t\t\t\t: undefined,\n\t\t\thighlightLines: parseCodeBlockHighlightLines(mantleHighlightLines),\n\t\t\tlanguage:\n\t\t\t\ttypeof mantleLanguage === \"string\" && isSupportedLanguage(mantleLanguage)\n\t\t\t\t\t? mantleLanguage\n\t\t\t\t\t: undefined,\n\t\t\tlineNumberStart: parseCodeBlockLineNumberStart(mantleLineNumberStart),\n\t\t\tmode: isMode(mantleMode) ? mantleMode : isMode(mode) ? mode : undefined,\n\t\t\tpreHtml: typeof mantlePreHtml === \"string\" ? mantlePreHtml : undefined,\n\t\t\trawLanguage: mantleLanguage,\n\t\t\tshowLineNumbers: parseCodeBlockShowLineNumbers(mantleShowLineNumbers),\n\t\t\ttitle:\n\t\t\t\ttypeof mantleTitle === \"string\"\n\t\t\t\t\t? mantleTitle.trim()\n\t\t\t\t\t: typeof title === \"string\"\n\t\t\t\t\t\t? title.trim()\n\t\t\t\t\t\t: undefined,\n\t\t},\n\t\tprops: props as Omit<T, PreRenderedCodeBlockPropKey>,\n\t};\n}\n\nexport { resolvePreRenderedCodeBlockProps };\nexport {\n\t//,\n\tdefaultMeta,\n\tnormalizeValue,\n\tparseMetastring,\n\ttokenizeMetastring,\n};\n\nexport type {\n\tCodeBlockPreElementInput,\n\tDefaultMeta,\n\tMeta,\n\tMetaInput,\n\tMode,\n\tResolvePreRenderedCodeBlockPropsInput,\n\tResolvePreRenderedCodeBlockPropsResult,\n\tResolvedPreRenderedCodeBlockProps,\n};\n"],"mappings":"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"}
|