@willbooster/shared-lib 10.19.1 → 10.19.2

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.
Files changed (68) hide show
  1. package/dist/appEnv.cjs.map +1 -1
  2. package/dist/appEnv.js.map +1 -1
  3. package/dist/array.cjs.map +1 -1
  4. package/dist/array.js.map +1 -1
  5. package/dist/assert.cjs.map +1 -1
  6. package/dist/assert.js.map +1 -1
  7. package/dist/concurrency.cjs.map +1 -1
  8. package/dist/concurrency.js.map +1 -1
  9. package/dist/crypto.cjs.map +1 -1
  10. package/dist/crypto.js.map +1 -1
  11. package/dist/error.cjs.map +1 -1
  12. package/dist/error.js.map +1 -1
  13. package/dist/filePath.cjs.map +1 -1
  14. package/dist/filePath.js.map +1 -1
  15. package/dist/foreignCjk.cjs.map +1 -1
  16. package/dist/foreignCjk.js.map +1 -1
  17. package/dist/formatIsoDate.cjs.map +1 -1
  18. package/dist/formatIsoDate.js.map +1 -1
  19. package/dist/github.cjs.map +1 -1
  20. package/dist/github.js.map +1 -1
  21. package/dist/githubTemplates.cjs.map +1 -1
  22. package/dist/githubTemplates.js.map +1 -1
  23. package/dist/http.cjs.map +1 -1
  24. package/dist/http.js.map +1 -1
  25. package/dist/humanize.cjs.map +1 -1
  26. package/dist/humanize.js.map +1 -1
  27. package/dist/mail.cjs.map +1 -1
  28. package/dist/mail.js.map +1 -1
  29. package/dist/markdown.cjs.map +1 -1
  30. package/dist/markdown.js.map +1 -1
  31. package/dist/number.cjs.map +1 -1
  32. package/dist/number.js.map +1 -1
  33. package/dist/object.cjs.map +1 -1
  34. package/dist/object.js.map +1 -1
  35. package/dist/parseCommandLineArgs.cjs.map +1 -1
  36. package/dist/parseCommandLineArgs.js.map +1 -1
  37. package/dist/parseIsoDate.cjs.map +1 -1
  38. package/dist/parseIsoDate.js.map +1 -1
  39. package/dist/prompt.cjs +8 -8
  40. package/dist/prompt.cjs.map +1 -1
  41. package/dist/prompt.js +8 -8
  42. package/dist/prompt.js.map +1 -1
  43. package/dist/promptFormatters.cjs.map +1 -1
  44. package/dist/promptFormatters.js.map +1 -1
  45. package/dist/recoverJson.cjs +2 -2
  46. package/dist/recoverJson.cjs.map +1 -1
  47. package/dist/recoverJson.js +1 -1
  48. package/dist/recoverJson.js.map +1 -1
  49. package/dist/shuffle.cjs.map +1 -1
  50. package/dist/shuffle.js.map +1 -1
  51. package/dist/sleep.cjs.map +1 -1
  52. package/dist/sleep.js.map +1 -1
  53. package/dist/sqlite.cjs.map +1 -1
  54. package/dist/sqlite.js.map +1 -1
  55. package/dist/testingRules.js.map +1 -1
  56. package/dist/text.cjs.map +1 -1
  57. package/dist/text.js.map +1 -1
  58. package/dist/throttledFetch.cjs.map +1 -1
  59. package/dist/throttledFetch.js.map +1 -1
  60. package/dist/timeout.cjs.map +1 -1
  61. package/dist/timeout.js.map +1 -1
  62. package/dist/url.cjs.map +1 -1
  63. package/dist/url.js.map +1 -1
  64. package/dist/yaml.cjs.map +1 -1
  65. package/dist/yaml.js.map +1 -1
  66. package/dist/zenkaku.cjs.map +1 -1
  67. package/dist/zenkaku.js.map +1 -1
  68. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.cjs","names":[],"sources":["../src/markdown.ts"],"sourcesContent":["export interface CodeBlock {\n /** The first word of the info string, lowercased; `undefined` when the fence has none. */\n language?: string;\n code: string;\n /** `false` when the text ends before the closing fence, e.g. because the LLM output was cut off. */\n isClosed: boolean;\n}\n\ninterface Fence {\n char: string;\n length: number;\n indent: number;\n language: string;\n}\n\n/**\n * Extracts the fenced code blocks (backticks or tildes, any fence length) of Markdown text such as an LLM response.\n * A block runs to the first closing fence of the same character that is at least as long as its opening fence,\n * so a longer fence can hold shorter fences. Only fences indented by at most three spaces are recognized; fences\n * inside block quotes, deeply nested list items, and indented code blocks are not.\n */\nexport function extractCodeBlocks(markdown: string): CodeBlock[] {\n const lines = splitLines(markdown);\n const blocks: CodeBlock[] = [];\n for (let index = 0; index < lines.length; index++) {\n const fence = parseOpeningFence(lines[index] ?? '');\n if (!fence) continue;\n const end = findClosingFence(lines, index + 1, fence);\n blocks.push({\n ...(fence.language && { language: fence.language }),\n code: lines\n .slice(index + 1, end)\n .map((line) => stripIndent(line, fence.indent))\n .join('\\n'),\n isClosed: end < lines.length,\n });\n index = end;\n }\n return blocks;\n}\n\n/**\n * Returns the contents of the code block that an LLM wrapped its whole response in, or `text` itself when the\n * response does not start with a fence or the fence's language is not one of a nonempty `languages` list\n * (compared case-insensitively). An omitted or empty list allows any language.\n * When the response also ends with a matching closing fence, everything between its first and last lines is returned,\n * so fences the LLM nested without lengthening the outer fence stay in the contents. Otherwise the first block is\n * returned and text after it is dropped; an unclosed block runs to the end of the text.\n */\nexport function extractIfSingleOutermostCodeBlock(text: string, languages?: readonly string[]): string {\n const block = findOutermostCodeBlock(text);\n if (!block) return text;\n if (languages?.length && !languages.some((language) => language.toLowerCase() === block.language)) return text;\n return block.code;\n}\n\nconst WRAPPED_MARKDOWN_LANGUAGES = new Set(['', 'markdown', 'md']);\n\n/**\n * Returns the trimmed contents of the first closed fenced code block (backticks or tildes) that follows a line holding\n * only `<tagName>` in text such as an LLM response, e.g. `<answer>\\n~~~\\n42\\n~~~`, or `undefined` when there is none.\n * Only blank lines may separate the tag line from the opening fence. Mentions of the tag within prose lines and tag\n * lines inside other fenced blocks (e.g. a format example) are skipped, but a whole-response `markdown`, `md`, or\n * unlabeled wrapper is read inside, as `parseMarkdownSections` does.\n */\nexport function extractTaggedCodeBlock(text: string, tagName: string): string | undefined {\n const tag = `<${tagName}>`;\n const found = findTaggedCodeBlock(splitLines(text), tag);\n if (found !== undefined) return found;\n // Only a real wrapper hides every tag line from the scan above; a leading example block paired with the tagged\n // block's closing fence merely looks like one, so its contents must not be read first.\n const wrapper = findOutermostCodeBlock(text);\n if (wrapper?.isWhole && WRAPPED_MARKDOWN_LANGUAGES.has(wrapper.language)) {\n return findTaggedCodeBlock(splitLines(wrapper.code), tag);\n }\n}\n\nfunction findTaggedCodeBlock(lines: readonly string[], tag: string): string | undefined {\n for (let index = 0; index < lines.length; index++) {\n const line = lines[index] ?? '';\n const enclosingFence = parseOpeningFence(line);\n if (enclosingFence) {\n index = findClosingFence(lines, index + 1, enclosingFence);\n continue;\n }\n if (line.trim() !== tag) continue;\n let fenceIndex = index + 1;\n while (fenceIndex < lines.length && !lines[fenceIndex]?.trim()) fenceIndex++;\n const fence = parseOpeningFence(lines[fenceIndex] ?? '');\n if (!fence) continue;\n const end = findClosingFence(lines, fenceIndex + 1, fence);\n if (end < lines.length) {\n return lines\n .slice(fenceIndex + 1, end)\n .map((contentLine) => stripIndent(contentLine, fence.indent))\n .join('\\n')\n .trim();\n }\n }\n}\n\nexport interface MarkdownSection {\n depth: number;\n /** The heading text with the closing `#` sequence and inline-code backticks removed. */\n heading: string;\n /** The source text up to the next heading at the same or a shallower depth, trimmed; subsections are included. */\n content: string;\n}\n\n/**\n * Extracts the content of the section headed by each of `names` from Markdown text such as an LLM response, keyed by\n * the given names. A heading matches a name when both are equal after removing decorations at their edges (such as\n * `**bold**`, backticks, and quotes), a leading number like `1.` or `2.1`, and a trailing colon, ignoring case and spacing;\n * headings at any depth are candidates.\n * Among matching headings, the shallowest wins, then one equal to the name as written, then the first; each heading\n * serves at most one name. When distinct requested names normalize alike, only exact matches at the shallowest\n * matching depth are returned. Missing, empty, or ambiguous sections are absent from the prototype-free result.\n */\nexport function extractSections<const Name extends string>(\n markdown: string,\n names: readonly Name[]\n): Partial<Record<Name, string>> {\n const candidates = parseMarkdownSections(markdown).map((section) => ({\n ...section,\n key: normalizeHeading(section.heading),\n }));\n const requested = [...new Set(names)].map((name) => ({ name, key: normalizeHeading(name) }));\n const sections: Partial<Record<Name, string>> = Object.create(null);\n for (const { name, key } of requested) {\n let best: (typeof candidates)[number] | undefined;\n for (const candidate of candidates) {\n if (candidate.key !== key) continue;\n if (\n !best ||\n candidate.depth < best.depth ||\n (candidate.depth === best.depth && candidate.heading === name && best.heading !== name)\n ) {\n best = candidate;\n }\n }\n if (!best) continue;\n if (best.heading !== name && requested.some((other) => other.name !== name && other.key === key)) continue;\n if (best.content) sections[name] = best.content;\n }\n return sections;\n}\n\n/**\n * Returns every ATX heading of Markdown text in order, with the source text under it.\n * Only headings starting at the beginning of a line outside fenced code blocks count; setext headings (underlined\n * with `=` or `-`) are ignored. A whole-response `markdown`, `md`, or unlabeled wrapper is read inside as\n * `extractIfSingleOutermostCodeBlock` finds it, preserving nested fences. A leading wrapper followed by prose is\n * also read inside, but only when there are no headings outside fences.\n */\nexport function parseMarkdownSections(markdown: string): MarkdownSection[] {\n const block = findOutermostCodeBlock(markdown);\n const wrapper = block && WRAPPED_MARKDOWN_LANGUAGES.has(block.language) ? block : undefined;\n if (wrapper?.isWhole) return splitSections(wrapper.code);\n const sections = splitSections(markdown);\n return sections.length === 0 && wrapper ? splitSections(wrapper.code) : sections;\n}\n\nfunction normalizeHeading(heading: string): string {\n return stripHeadingEdges(stripHeadingEdges(heading).replace(/^\\d+(?:\\.\\d+)*(?:\\.\\s+|\\)\\s*|\\s+)/u, ''))\n .replaceAll(/\\s+/gu, ' ')\n .toLowerCase();\n}\n\nfunction stripHeadingEdges(text: string): string {\n // Only the edges: `_` and `*` inside a heading belong to names such as `my_file.py`.\n return text.replaceAll(/^[\\s*_`~\"'「」]+|[\\s*_`~\"'「」::]+$/gu, '');\n}\n\nfunction splitSections(markdown: string): MarkdownSection[] {\n const lines = splitLines(markdown);\n const headings = findHeadings(lines);\n return headings.map((heading, index) => {\n let nextIndex = index + 1;\n while (nextIndex < headings.length && (headings[nextIndex]?.depth ?? 0) > heading.depth) nextIndex++;\n return {\n depth: heading.depth,\n heading: heading.text,\n content: lines\n .slice(heading.index + 1, headings[nextIndex]?.index)\n .join('\\n')\n .trim(),\n };\n });\n}\n\nfunction findOutermostCodeBlock(text: string): { language: string; code: string; isWhole: boolean } | undefined {\n // Keep the opening fence's indentation, which is stripped from the contents.\n const lines = splitLines(text.replace(/^\\s*\\n/u, '').trimEnd());\n const fence = parseOpeningFence(lines[0] ?? '');\n if (!fence) return;\n const lastIndex = lines.length - 1;\n const end =\n lastIndex > 0 && isClosingFence(lines[lastIndex] ?? '', fence) ? lastIndex : findClosingFence(lines, 1, fence);\n return {\n language: fence.language,\n code: lines\n .slice(1, end)\n .map((line) => stripIndent(line, fence.indent))\n .join('\\n'),\n isWhole: end >= lastIndex,\n };\n}\n\nfunction findHeadings(lines: readonly string[]): { index: number; depth: number; text: string }[] {\n const headings: { index: number; depth: number; text: string }[] = [];\n for (let index = 0; index < lines.length; index++) {\n const line = lines[index] ?? '';\n const fence = parseOpeningFence(line);\n if (fence) {\n index = findClosingFence(lines, index + 1, fence);\n continue;\n }\n const match = /^(#{1,6})(?:[ \\t]+(.*))?$/u.exec(line);\n if (!match) continue;\n const text = (match[2] ?? '')\n // The closing sequence of an ATX heading needs a space before it, so `# C#` keeps its `#`.\n .replace(/(?:^|[ \\t]+)#+[ \\t]*$/u, '')\n .trim()\n .replaceAll(/(`+)(.+?)\\1/gu, (_match, _delimiter: string, content: string) =>\n content.startsWith(' ') && content.endsWith(' ') ? content.slice(1, -1) : content\n );\n headings.push({ index, depth: match[1]?.length ?? 1, text });\n }\n return headings;\n}\n\nfunction parseOpeningFence(line: string): Fence | undefined {\n const match = /^( {0,3})(`{3,}|~{3,})(.*)$/u.exec(line);\n const fence = match?.[2];\n const info = match?.[3] ?? '';\n // A backtick in the info string makes the line inline code instead of a fence.\n if (!fence || (fence.startsWith('`') && info.includes('`'))) return;\n return {\n char: fence.charAt(0),\n length: fence.length,\n indent: match[1]?.length ?? 0,\n language: info.trim().split(/\\s/u)[0]?.toLowerCase() ?? '',\n };\n}\n\n/** Returns the index of the line closing `fence`, or the number of lines when it is never closed. */\nfunction findClosingFence(lines: readonly string[], start: number, fence: Fence): number {\n let index = start;\n while (index < lines.length && !isClosingFence(lines[index] ?? '', fence)) index++;\n return index;\n}\n\nfunction isClosingFence(line: string, fence: Fence): boolean {\n const closer = /^ {0,3}(`{3,}|~{3,})[ \\t]*$/u.exec(line)?.[1];\n return closer?.charAt(0) === fence.char && closer.length >= fence.length;\n}\n\nfunction stripIndent(line: string, indent: number): string {\n let index = 0;\n while (index < indent && line[index] === ' ') index++;\n return line.slice(index);\n}\n\nfunction splitLines(text: string): string[] {\n return text.split(/\\r?\\n/u);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"markdown.cjs","names":["extractCodeBlocks","lines","splitLines","markdown","blocks","index","fence","parseOpeningFence","end","findClosingFence","stripIndent","line","extractIfSingleOutermostCodeBlock","block","findOutermostCodeBlock","text","languages","language","WRAPPED_MARKDOWN_LANGUAGES","extractTaggedCodeBlock","tag","tagName","found","findTaggedCodeBlock","wrapper","enclosingFence","fenceIndex","contentLine","extractSections","candidates","parseMarkdownSections","section","normalizeHeading","requested","names","name","sections","best","candidate","key","other","splitSections","stripHeadingEdges","heading","headings","findHeadings","nextIndex","lastIndex","isClosingFence","match","content","info","start","closer","indent"],"sources":["../src/markdown.ts"],"sourcesContent":["export interface CodeBlock {\n /** The first word of the info string, lowercased; `undefined` when the fence has none. */\n language?: string;\n code: string;\n /** `false` when the text ends before the closing fence, e.g. because the LLM output was cut off. */\n isClosed: boolean;\n}\n\ninterface Fence {\n char: string;\n length: number;\n indent: number;\n language: string;\n}\n\n/**\n * Extracts the fenced code blocks (backticks or tildes, any fence length) of Markdown text such as an LLM response.\n * A block runs to the first closing fence of the same character that is at least as long as its opening fence,\n * so a longer fence can hold shorter fences. Only fences indented by at most three spaces are recognized; fences\n * inside block quotes, deeply nested list items, and indented code blocks are not.\n */\nexport function extractCodeBlocks(markdown: string): CodeBlock[] {\n const lines = splitLines(markdown);\n const blocks: CodeBlock[] = [];\n for (let index = 0; index < lines.length; index++) {\n const fence = parseOpeningFence(lines[index] ?? '');\n if (!fence) continue;\n const end = findClosingFence(lines, index + 1, fence);\n blocks.push({\n ...(fence.language && { language: fence.language }),\n code: lines\n .slice(index + 1, end)\n .map((line) => stripIndent(line, fence.indent))\n .join('\\n'),\n isClosed: end < lines.length,\n });\n index = end;\n }\n return blocks;\n}\n\n/**\n * Returns the contents of the code block that an LLM wrapped its whole response in, or `text` itself when the\n * response does not start with a fence or the fence's language is not one of a nonempty `languages` list\n * (compared case-insensitively). An omitted or empty list allows any language.\n * When the response also ends with a matching closing fence, everything between its first and last lines is returned,\n * so fences the LLM nested without lengthening the outer fence stay in the contents. Otherwise the first block is\n * returned and text after it is dropped; an unclosed block runs to the end of the text.\n */\nexport function extractIfSingleOutermostCodeBlock(text: string, languages?: readonly string[]): string {\n const block = findOutermostCodeBlock(text);\n if (!block) return text;\n if (languages?.length && !languages.some((language) => language.toLowerCase() === block.language)) return text;\n return block.code;\n}\n\nconst WRAPPED_MARKDOWN_LANGUAGES = new Set(['', 'markdown', 'md']);\n\n/**\n * Returns the trimmed contents of the first closed fenced code block (backticks or tildes) that follows a line holding\n * only `<tagName>` in text such as an LLM response, e.g. `<answer>\\n~~~\\n42\\n~~~`, or `undefined` when there is none.\n * Only blank lines may separate the tag line from the opening fence. Mentions of the tag within prose lines and tag\n * lines inside other fenced blocks (e.g. a format example) are skipped, but a whole-response `markdown`, `md`, or\n * unlabeled wrapper is read inside, as `parseMarkdownSections` does.\n */\nexport function extractTaggedCodeBlock(text: string, tagName: string): string | undefined {\n const tag = `<${tagName}>`;\n const found = findTaggedCodeBlock(splitLines(text), tag);\n if (found !== undefined) return found;\n // Only a real wrapper hides every tag line from the scan above; a leading example block paired with the tagged\n // block's closing fence merely looks like one, so its contents must not be read first.\n const wrapper = findOutermostCodeBlock(text);\n if (wrapper?.isWhole && WRAPPED_MARKDOWN_LANGUAGES.has(wrapper.language)) {\n return findTaggedCodeBlock(splitLines(wrapper.code), tag);\n }\n}\n\nfunction findTaggedCodeBlock(lines: readonly string[], tag: string): string | undefined {\n for (let index = 0; index < lines.length; index++) {\n const line = lines[index] ?? '';\n const enclosingFence = parseOpeningFence(line);\n if (enclosingFence) {\n index = findClosingFence(lines, index + 1, enclosingFence);\n continue;\n }\n if (line.trim() !== tag) continue;\n let fenceIndex = index + 1;\n while (fenceIndex < lines.length && !lines[fenceIndex]?.trim()) fenceIndex++;\n const fence = parseOpeningFence(lines[fenceIndex] ?? '');\n if (!fence) continue;\n const end = findClosingFence(lines, fenceIndex + 1, fence);\n if (end < lines.length) {\n return lines\n .slice(fenceIndex + 1, end)\n .map((contentLine) => stripIndent(contentLine, fence.indent))\n .join('\\n')\n .trim();\n }\n }\n}\n\nexport interface MarkdownSection {\n depth: number;\n /** The heading text with the closing `#` sequence and inline-code backticks removed. */\n heading: string;\n /** The source text up to the next heading at the same or a shallower depth, trimmed; subsections are included. */\n content: string;\n}\n\n/**\n * Extracts the content of the section headed by each of `names` from Markdown text such as an LLM response, keyed by\n * the given names. A heading matches a name when both are equal after removing decorations at their edges (such as\n * `**bold**`, backticks, and quotes), a leading number like `1.` or `2.1`, and a trailing colon, ignoring case and spacing;\n * headings at any depth are candidates.\n * Among matching headings, the shallowest wins, then one equal to the name as written, then the first; each heading\n * serves at most one name. When distinct requested names normalize alike, only exact matches at the shallowest\n * matching depth are returned. Missing, empty, or ambiguous sections are absent from the prototype-free result.\n */\nexport function extractSections<const Name extends string>(\n markdown: string,\n names: readonly Name[]\n): Partial<Record<Name, string>> {\n const candidates = parseMarkdownSections(markdown).map((section) => ({\n ...section,\n key: normalizeHeading(section.heading),\n }));\n const requested = [...new Set(names)].map((name) => ({ name, key: normalizeHeading(name) }));\n const sections: Partial<Record<Name, string>> = Object.create(null);\n for (const { name, key } of requested) {\n let best: (typeof candidates)[number] | undefined;\n for (const candidate of candidates) {\n if (candidate.key !== key) continue;\n if (\n !best ||\n candidate.depth < best.depth ||\n (candidate.depth === best.depth && candidate.heading === name && best.heading !== name)\n ) {\n best = candidate;\n }\n }\n if (!best) continue;\n if (best.heading !== name && requested.some((other) => other.name !== name && other.key === key)) continue;\n if (best.content) sections[name] = best.content;\n }\n return sections;\n}\n\n/**\n * Returns every ATX heading of Markdown text in order, with the source text under it.\n * Only headings starting at the beginning of a line outside fenced code blocks count; setext headings (underlined\n * with `=` or `-`) are ignored. A whole-response `markdown`, `md`, or unlabeled wrapper is read inside as\n * `extractIfSingleOutermostCodeBlock` finds it, preserving nested fences. A leading wrapper followed by prose is\n * also read inside, but only when there are no headings outside fences.\n */\nexport function parseMarkdownSections(markdown: string): MarkdownSection[] {\n const block = findOutermostCodeBlock(markdown);\n const wrapper = block && WRAPPED_MARKDOWN_LANGUAGES.has(block.language) ? block : undefined;\n if (wrapper?.isWhole) return splitSections(wrapper.code);\n const sections = splitSections(markdown);\n return sections.length === 0 && wrapper ? splitSections(wrapper.code) : sections;\n}\n\nfunction normalizeHeading(heading: string): string {\n return stripHeadingEdges(stripHeadingEdges(heading).replace(/^\\d+(?:\\.\\d+)*(?:\\.\\s+|\\)\\s*|\\s+)/u, ''))\n .replaceAll(/\\s+/gu, ' ')\n .toLowerCase();\n}\n\nfunction stripHeadingEdges(text: string): string {\n // Only the edges: `_` and `*` inside a heading belong to names such as `my_file.py`.\n return text.replaceAll(/^[\\s*_`~\"'「」]+|[\\s*_`~\"'「」::]+$/gu, '');\n}\n\nfunction splitSections(markdown: string): MarkdownSection[] {\n const lines = splitLines(markdown);\n const headings = findHeadings(lines);\n return headings.map((heading, index) => {\n let nextIndex = index + 1;\n while (nextIndex < headings.length && (headings[nextIndex]?.depth ?? 0) > heading.depth) nextIndex++;\n return {\n depth: heading.depth,\n heading: heading.text,\n content: lines\n .slice(heading.index + 1, headings[nextIndex]?.index)\n .join('\\n')\n .trim(),\n };\n });\n}\n\nfunction findOutermostCodeBlock(text: string): { language: string; code: string; isWhole: boolean } | undefined {\n // Keep the opening fence's indentation, which is stripped from the contents.\n const lines = splitLines(text.replace(/^\\s*\\n/u, '').trimEnd());\n const fence = parseOpeningFence(lines[0] ?? '');\n if (!fence) return;\n const lastIndex = lines.length - 1;\n const end =\n lastIndex > 0 && isClosingFence(lines[lastIndex] ?? '', fence) ? lastIndex : findClosingFence(lines, 1, fence);\n return {\n language: fence.language,\n code: lines\n .slice(1, end)\n .map((line) => stripIndent(line, fence.indent))\n .join('\\n'),\n isWhole: end >= lastIndex,\n };\n}\n\nfunction findHeadings(lines: readonly string[]): { index: number; depth: number; text: string }[] {\n const headings: { index: number; depth: number; text: string }[] = [];\n for (let index = 0; index < lines.length; index++) {\n const line = lines[index] ?? '';\n const fence = parseOpeningFence(line);\n if (fence) {\n index = findClosingFence(lines, index + 1, fence);\n continue;\n }\n const match = /^(#{1,6})(?:[ \\t]+(.*))?$/u.exec(line);\n if (!match) continue;\n const text = (match[2] ?? '')\n // The closing sequence of an ATX heading needs a space before it, so `# C#` keeps its `#`.\n .replace(/(?:^|[ \\t]+)#+[ \\t]*$/u, '')\n .trim()\n .replaceAll(/(`+)(.+?)\\1/gu, (_match, _delimiter: string, content: string) =>\n content.startsWith(' ') && content.endsWith(' ') ? content.slice(1, -1) : content\n );\n headings.push({ index, depth: match[1]?.length ?? 1, text });\n }\n return headings;\n}\n\nfunction parseOpeningFence(line: string): Fence | undefined {\n const match = /^( {0,3})(`{3,}|~{3,})(.*)$/u.exec(line);\n const fence = match?.[2];\n const info = match?.[3] ?? '';\n // A backtick in the info string makes the line inline code instead of a fence.\n if (!fence || (fence.startsWith('`') && info.includes('`'))) return;\n return {\n char: fence.charAt(0),\n length: fence.length,\n indent: match[1]?.length ?? 0,\n language: info.trim().split(/\\s/u)[0]?.toLowerCase() ?? '',\n };\n}\n\n/** Returns the index of the line closing `fence`, or the number of lines when it is never closed. */\nfunction findClosingFence(lines: readonly string[], start: number, fence: Fence): number {\n let index = start;\n while (index < lines.length && !isClosingFence(lines[index] ?? '', fence)) index++;\n return index;\n}\n\nfunction isClosingFence(line: string, fence: Fence): boolean {\n const closer = /^ {0,3}(`{3,}|~{3,})[ \\t]*$/u.exec(line)?.[1];\n return closer?.charAt(0) === fence.char && closer.length >= fence.length;\n}\n\nfunction stripIndent(line: string, indent: number): string {\n let index = 0;\n while (index < indent && line[index] === ' ') index++;\n return line.slice(index);\n}\n\nfunction splitLines(text: string): string[] {\n return text.split(/\\r?\\n/u);\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.js","names":[],"sources":["../src/markdown.ts"],"sourcesContent":["export interface CodeBlock {\n /** The first word of the info string, lowercased; `undefined` when the fence has none. */\n language?: string;\n code: string;\n /** `false` when the text ends before the closing fence, e.g. because the LLM output was cut off. */\n isClosed: boolean;\n}\n\ninterface Fence {\n char: string;\n length: number;\n indent: number;\n language: string;\n}\n\n/**\n * Extracts the fenced code blocks (backticks or tildes, any fence length) of Markdown text such as an LLM response.\n * A block runs to the first closing fence of the same character that is at least as long as its opening fence,\n * so a longer fence can hold shorter fences. Only fences indented by at most three spaces are recognized; fences\n * inside block quotes, deeply nested list items, and indented code blocks are not.\n */\nexport function extractCodeBlocks(markdown: string): CodeBlock[] {\n const lines = splitLines(markdown);\n const blocks: CodeBlock[] = [];\n for (let index = 0; index < lines.length; index++) {\n const fence = parseOpeningFence(lines[index] ?? '');\n if (!fence) continue;\n const end = findClosingFence(lines, index + 1, fence);\n blocks.push({\n ...(fence.language && { language: fence.language }),\n code: lines\n .slice(index + 1, end)\n .map((line) => stripIndent(line, fence.indent))\n .join('\\n'),\n isClosed: end < lines.length,\n });\n index = end;\n }\n return blocks;\n}\n\n/**\n * Returns the contents of the code block that an LLM wrapped its whole response in, or `text` itself when the\n * response does not start with a fence or the fence's language is not one of a nonempty `languages` list\n * (compared case-insensitively). An omitted or empty list allows any language.\n * When the response also ends with a matching closing fence, everything between its first and last lines is returned,\n * so fences the LLM nested without lengthening the outer fence stay in the contents. Otherwise the first block is\n * returned and text after it is dropped; an unclosed block runs to the end of the text.\n */\nexport function extractIfSingleOutermostCodeBlock(text: string, languages?: readonly string[]): string {\n const block = findOutermostCodeBlock(text);\n if (!block) return text;\n if (languages?.length && !languages.some((language) => language.toLowerCase() === block.language)) return text;\n return block.code;\n}\n\nconst WRAPPED_MARKDOWN_LANGUAGES = new Set(['', 'markdown', 'md']);\n\n/**\n * Returns the trimmed contents of the first closed fenced code block (backticks or tildes) that follows a line holding\n * only `<tagName>` in text such as an LLM response, e.g. `<answer>\\n~~~\\n42\\n~~~`, or `undefined` when there is none.\n * Only blank lines may separate the tag line from the opening fence. Mentions of the tag within prose lines and tag\n * lines inside other fenced blocks (e.g. a format example) are skipped, but a whole-response `markdown`, `md`, or\n * unlabeled wrapper is read inside, as `parseMarkdownSections` does.\n */\nexport function extractTaggedCodeBlock(text: string, tagName: string): string | undefined {\n const tag = `<${tagName}>`;\n const found = findTaggedCodeBlock(splitLines(text), tag);\n if (found !== undefined) return found;\n // Only a real wrapper hides every tag line from the scan above; a leading example block paired with the tagged\n // block's closing fence merely looks like one, so its contents must not be read first.\n const wrapper = findOutermostCodeBlock(text);\n if (wrapper?.isWhole && WRAPPED_MARKDOWN_LANGUAGES.has(wrapper.language)) {\n return findTaggedCodeBlock(splitLines(wrapper.code), tag);\n }\n}\n\nfunction findTaggedCodeBlock(lines: readonly string[], tag: string): string | undefined {\n for (let index = 0; index < lines.length; index++) {\n const line = lines[index] ?? '';\n const enclosingFence = parseOpeningFence(line);\n if (enclosingFence) {\n index = findClosingFence(lines, index + 1, enclosingFence);\n continue;\n }\n if (line.trim() !== tag) continue;\n let fenceIndex = index + 1;\n while (fenceIndex < lines.length && !lines[fenceIndex]?.trim()) fenceIndex++;\n const fence = parseOpeningFence(lines[fenceIndex] ?? '');\n if (!fence) continue;\n const end = findClosingFence(lines, fenceIndex + 1, fence);\n if (end < lines.length) {\n return lines\n .slice(fenceIndex + 1, end)\n .map((contentLine) => stripIndent(contentLine, fence.indent))\n .join('\\n')\n .trim();\n }\n }\n}\n\nexport interface MarkdownSection {\n depth: number;\n /** The heading text with the closing `#` sequence and inline-code backticks removed. */\n heading: string;\n /** The source text up to the next heading at the same or a shallower depth, trimmed; subsections are included. */\n content: string;\n}\n\n/**\n * Extracts the content of the section headed by each of `names` from Markdown text such as an LLM response, keyed by\n * the given names. A heading matches a name when both are equal after removing decorations at their edges (such as\n * `**bold**`, backticks, and quotes), a leading number like `1.` or `2.1`, and a trailing colon, ignoring case and spacing;\n * headings at any depth are candidates.\n * Among matching headings, the shallowest wins, then one equal to the name as written, then the first; each heading\n * serves at most one name. When distinct requested names normalize alike, only exact matches at the shallowest\n * matching depth are returned. Missing, empty, or ambiguous sections are absent from the prototype-free result.\n */\nexport function extractSections<const Name extends string>(\n markdown: string,\n names: readonly Name[]\n): Partial<Record<Name, string>> {\n const candidates = parseMarkdownSections(markdown).map((section) => ({\n ...section,\n key: normalizeHeading(section.heading),\n }));\n const requested = [...new Set(names)].map((name) => ({ name, key: normalizeHeading(name) }));\n const sections: Partial<Record<Name, string>> = Object.create(null);\n for (const { name, key } of requested) {\n let best: (typeof candidates)[number] | undefined;\n for (const candidate of candidates) {\n if (candidate.key !== key) continue;\n if (\n !best ||\n candidate.depth < best.depth ||\n (candidate.depth === best.depth && candidate.heading === name && best.heading !== name)\n ) {\n best = candidate;\n }\n }\n if (!best) continue;\n if (best.heading !== name && requested.some((other) => other.name !== name && other.key === key)) continue;\n if (best.content) sections[name] = best.content;\n }\n return sections;\n}\n\n/**\n * Returns every ATX heading of Markdown text in order, with the source text under it.\n * Only headings starting at the beginning of a line outside fenced code blocks count; setext headings (underlined\n * with `=` or `-`) are ignored. A whole-response `markdown`, `md`, or unlabeled wrapper is read inside as\n * `extractIfSingleOutermostCodeBlock` finds it, preserving nested fences. A leading wrapper followed by prose is\n * also read inside, but only when there are no headings outside fences.\n */\nexport function parseMarkdownSections(markdown: string): MarkdownSection[] {\n const block = findOutermostCodeBlock(markdown);\n const wrapper = block && WRAPPED_MARKDOWN_LANGUAGES.has(block.language) ? block : undefined;\n if (wrapper?.isWhole) return splitSections(wrapper.code);\n const sections = splitSections(markdown);\n return sections.length === 0 && wrapper ? splitSections(wrapper.code) : sections;\n}\n\nfunction normalizeHeading(heading: string): string {\n return stripHeadingEdges(stripHeadingEdges(heading).replace(/^\\d+(?:\\.\\d+)*(?:\\.\\s+|\\)\\s*|\\s+)/u, ''))\n .replaceAll(/\\s+/gu, ' ')\n .toLowerCase();\n}\n\nfunction stripHeadingEdges(text: string): string {\n // Only the edges: `_` and `*` inside a heading belong to names such as `my_file.py`.\n return text.replaceAll(/^[\\s*_`~\"'「」]+|[\\s*_`~\"'「」::]+$/gu, '');\n}\n\nfunction splitSections(markdown: string): MarkdownSection[] {\n const lines = splitLines(markdown);\n const headings = findHeadings(lines);\n return headings.map((heading, index) => {\n let nextIndex = index + 1;\n while (nextIndex < headings.length && (headings[nextIndex]?.depth ?? 0) > heading.depth) nextIndex++;\n return {\n depth: heading.depth,\n heading: heading.text,\n content: lines\n .slice(heading.index + 1, headings[nextIndex]?.index)\n .join('\\n')\n .trim(),\n };\n });\n}\n\nfunction findOutermostCodeBlock(text: string): { language: string; code: string; isWhole: boolean } | undefined {\n // Keep the opening fence's indentation, which is stripped from the contents.\n const lines = splitLines(text.replace(/^\\s*\\n/u, '').trimEnd());\n const fence = parseOpeningFence(lines[0] ?? '');\n if (!fence) return;\n const lastIndex = lines.length - 1;\n const end =\n lastIndex > 0 && isClosingFence(lines[lastIndex] ?? '', fence) ? lastIndex : findClosingFence(lines, 1, fence);\n return {\n language: fence.language,\n code: lines\n .slice(1, end)\n .map((line) => stripIndent(line, fence.indent))\n .join('\\n'),\n isWhole: end >= lastIndex,\n };\n}\n\nfunction findHeadings(lines: readonly string[]): { index: number; depth: number; text: string }[] {\n const headings: { index: number; depth: number; text: string }[] = [];\n for (let index = 0; index < lines.length; index++) {\n const line = lines[index] ?? '';\n const fence = parseOpeningFence(line);\n if (fence) {\n index = findClosingFence(lines, index + 1, fence);\n continue;\n }\n const match = /^(#{1,6})(?:[ \\t]+(.*))?$/u.exec(line);\n if (!match) continue;\n const text = (match[2] ?? '')\n // The closing sequence of an ATX heading needs a space before it, so `# C#` keeps its `#`.\n .replace(/(?:^|[ \\t]+)#+[ \\t]*$/u, '')\n .trim()\n .replaceAll(/(`+)(.+?)\\1/gu, (_match, _delimiter: string, content: string) =>\n content.startsWith(' ') && content.endsWith(' ') ? content.slice(1, -1) : content\n );\n headings.push({ index, depth: match[1]?.length ?? 1, text });\n }\n return headings;\n}\n\nfunction parseOpeningFence(line: string): Fence | undefined {\n const match = /^( {0,3})(`{3,}|~{3,})(.*)$/u.exec(line);\n const fence = match?.[2];\n const info = match?.[3] ?? '';\n // A backtick in the info string makes the line inline code instead of a fence.\n if (!fence || (fence.startsWith('`') && info.includes('`'))) return;\n return {\n char: fence.charAt(0),\n length: fence.length,\n indent: match[1]?.length ?? 0,\n language: info.trim().split(/\\s/u)[0]?.toLowerCase() ?? '',\n };\n}\n\n/** Returns the index of the line closing `fence`, or the number of lines when it is never closed. */\nfunction findClosingFence(lines: readonly string[], start: number, fence: Fence): number {\n let index = start;\n while (index < lines.length && !isClosingFence(lines[index] ?? '', fence)) index++;\n return index;\n}\n\nfunction isClosingFence(line: string, fence: Fence): boolean {\n const closer = /^ {0,3}(`{3,}|~{3,})[ \\t]*$/u.exec(line)?.[1];\n return closer?.charAt(0) === fence.char && closer.length >= fence.length;\n}\n\nfunction stripIndent(line: string, indent: number): string {\n let index = 0;\n while (index < indent && line[index] === ' ') index++;\n return line.slice(index);\n}\n\nfunction splitLines(text: string): string[] {\n return text.split(/\\r?\\n/u);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"markdown.js","names":["extractCodeBlocks","lines","splitLines","markdown","blocks","index","fence","parseOpeningFence","end","findClosingFence","stripIndent","line","extractIfSingleOutermostCodeBlock","block","findOutermostCodeBlock","text","languages","language","WRAPPED_MARKDOWN_LANGUAGES","extractTaggedCodeBlock","tag","tagName","found","findTaggedCodeBlock","wrapper","enclosingFence","fenceIndex","contentLine","extractSections","candidates","parseMarkdownSections","section","normalizeHeading","requested","names","name","sections","best","candidate","key","other","splitSections","stripHeadingEdges","heading","headings","findHeadings","nextIndex","lastIndex","isClosingFence","match","content","info","start","closer","indent"],"sources":["../src/markdown.ts"],"sourcesContent":["export interface CodeBlock {\n /** The first word of the info string, lowercased; `undefined` when the fence has none. */\n language?: string;\n code: string;\n /** `false` when the text ends before the closing fence, e.g. because the LLM output was cut off. */\n isClosed: boolean;\n}\n\ninterface Fence {\n char: string;\n length: number;\n indent: number;\n language: string;\n}\n\n/**\n * Extracts the fenced code blocks (backticks or tildes, any fence length) of Markdown text such as an LLM response.\n * A block runs to the first closing fence of the same character that is at least as long as its opening fence,\n * so a longer fence can hold shorter fences. Only fences indented by at most three spaces are recognized; fences\n * inside block quotes, deeply nested list items, and indented code blocks are not.\n */\nexport function extractCodeBlocks(markdown: string): CodeBlock[] {\n const lines = splitLines(markdown);\n const blocks: CodeBlock[] = [];\n for (let index = 0; index < lines.length; index++) {\n const fence = parseOpeningFence(lines[index] ?? '');\n if (!fence) continue;\n const end = findClosingFence(lines, index + 1, fence);\n blocks.push({\n ...(fence.language && { language: fence.language }),\n code: lines\n .slice(index + 1, end)\n .map((line) => stripIndent(line, fence.indent))\n .join('\\n'),\n isClosed: end < lines.length,\n });\n index = end;\n }\n return blocks;\n}\n\n/**\n * Returns the contents of the code block that an LLM wrapped its whole response in, or `text` itself when the\n * response does not start with a fence or the fence's language is not one of a nonempty `languages` list\n * (compared case-insensitively). An omitted or empty list allows any language.\n * When the response also ends with a matching closing fence, everything between its first and last lines is returned,\n * so fences the LLM nested without lengthening the outer fence stay in the contents. Otherwise the first block is\n * returned and text after it is dropped; an unclosed block runs to the end of the text.\n */\nexport function extractIfSingleOutermostCodeBlock(text: string, languages?: readonly string[]): string {\n const block = findOutermostCodeBlock(text);\n if (!block) return text;\n if (languages?.length && !languages.some((language) => language.toLowerCase() === block.language)) return text;\n return block.code;\n}\n\nconst WRAPPED_MARKDOWN_LANGUAGES = new Set(['', 'markdown', 'md']);\n\n/**\n * Returns the trimmed contents of the first closed fenced code block (backticks or tildes) that follows a line holding\n * only `<tagName>` in text such as an LLM response, e.g. `<answer>\\n~~~\\n42\\n~~~`, or `undefined` when there is none.\n * Only blank lines may separate the tag line from the opening fence. Mentions of the tag within prose lines and tag\n * lines inside other fenced blocks (e.g. a format example) are skipped, but a whole-response `markdown`, `md`, or\n * unlabeled wrapper is read inside, as `parseMarkdownSections` does.\n */\nexport function extractTaggedCodeBlock(text: string, tagName: string): string | undefined {\n const tag = `<${tagName}>`;\n const found = findTaggedCodeBlock(splitLines(text), tag);\n if (found !== undefined) return found;\n // Only a real wrapper hides every tag line from the scan above; a leading example block paired with the tagged\n // block's closing fence merely looks like one, so its contents must not be read first.\n const wrapper = findOutermostCodeBlock(text);\n if (wrapper?.isWhole && WRAPPED_MARKDOWN_LANGUAGES.has(wrapper.language)) {\n return findTaggedCodeBlock(splitLines(wrapper.code), tag);\n }\n}\n\nfunction findTaggedCodeBlock(lines: readonly string[], tag: string): string | undefined {\n for (let index = 0; index < lines.length; index++) {\n const line = lines[index] ?? '';\n const enclosingFence = parseOpeningFence(line);\n if (enclosingFence) {\n index = findClosingFence(lines, index + 1, enclosingFence);\n continue;\n }\n if (line.trim() !== tag) continue;\n let fenceIndex = index + 1;\n while (fenceIndex < lines.length && !lines[fenceIndex]?.trim()) fenceIndex++;\n const fence = parseOpeningFence(lines[fenceIndex] ?? '');\n if (!fence) continue;\n const end = findClosingFence(lines, fenceIndex + 1, fence);\n if (end < lines.length) {\n return lines\n .slice(fenceIndex + 1, end)\n .map((contentLine) => stripIndent(contentLine, fence.indent))\n .join('\\n')\n .trim();\n }\n }\n}\n\nexport interface MarkdownSection {\n depth: number;\n /** The heading text with the closing `#` sequence and inline-code backticks removed. */\n heading: string;\n /** The source text up to the next heading at the same or a shallower depth, trimmed; subsections are included. */\n content: string;\n}\n\n/**\n * Extracts the content of the section headed by each of `names` from Markdown text such as an LLM response, keyed by\n * the given names. A heading matches a name when both are equal after removing decorations at their edges (such as\n * `**bold**`, backticks, and quotes), a leading number like `1.` or `2.1`, and a trailing colon, ignoring case and spacing;\n * headings at any depth are candidates.\n * Among matching headings, the shallowest wins, then one equal to the name as written, then the first; each heading\n * serves at most one name. When distinct requested names normalize alike, only exact matches at the shallowest\n * matching depth are returned. Missing, empty, or ambiguous sections are absent from the prototype-free result.\n */\nexport function extractSections<const Name extends string>(\n markdown: string,\n names: readonly Name[]\n): Partial<Record<Name, string>> {\n const candidates = parseMarkdownSections(markdown).map((section) => ({\n ...section,\n key: normalizeHeading(section.heading),\n }));\n const requested = [...new Set(names)].map((name) => ({ name, key: normalizeHeading(name) }));\n const sections: Partial<Record<Name, string>> = Object.create(null);\n for (const { name, key } of requested) {\n let best: (typeof candidates)[number] | undefined;\n for (const candidate of candidates) {\n if (candidate.key !== key) continue;\n if (\n !best ||\n candidate.depth < best.depth ||\n (candidate.depth === best.depth && candidate.heading === name && best.heading !== name)\n ) {\n best = candidate;\n }\n }\n if (!best) continue;\n if (best.heading !== name && requested.some((other) => other.name !== name && other.key === key)) continue;\n if (best.content) sections[name] = best.content;\n }\n return sections;\n}\n\n/**\n * Returns every ATX heading of Markdown text in order, with the source text under it.\n * Only headings starting at the beginning of a line outside fenced code blocks count; setext headings (underlined\n * with `=` or `-`) are ignored. A whole-response `markdown`, `md`, or unlabeled wrapper is read inside as\n * `extractIfSingleOutermostCodeBlock` finds it, preserving nested fences. A leading wrapper followed by prose is\n * also read inside, but only when there are no headings outside fences.\n */\nexport function parseMarkdownSections(markdown: string): MarkdownSection[] {\n const block = findOutermostCodeBlock(markdown);\n const wrapper = block && WRAPPED_MARKDOWN_LANGUAGES.has(block.language) ? block : undefined;\n if (wrapper?.isWhole) return splitSections(wrapper.code);\n const sections = splitSections(markdown);\n return sections.length === 0 && wrapper ? splitSections(wrapper.code) : sections;\n}\n\nfunction normalizeHeading(heading: string): string {\n return stripHeadingEdges(stripHeadingEdges(heading).replace(/^\\d+(?:\\.\\d+)*(?:\\.\\s+|\\)\\s*|\\s+)/u, ''))\n .replaceAll(/\\s+/gu, ' ')\n .toLowerCase();\n}\n\nfunction stripHeadingEdges(text: string): string {\n // Only the edges: `_` and `*` inside a heading belong to names such as `my_file.py`.\n return text.replaceAll(/^[\\s*_`~\"'「」]+|[\\s*_`~\"'「」::]+$/gu, '');\n}\n\nfunction splitSections(markdown: string): MarkdownSection[] {\n const lines = splitLines(markdown);\n const headings = findHeadings(lines);\n return headings.map((heading, index) => {\n let nextIndex = index + 1;\n while (nextIndex < headings.length && (headings[nextIndex]?.depth ?? 0) > heading.depth) nextIndex++;\n return {\n depth: heading.depth,\n heading: heading.text,\n content: lines\n .slice(heading.index + 1, headings[nextIndex]?.index)\n .join('\\n')\n .trim(),\n };\n });\n}\n\nfunction findOutermostCodeBlock(text: string): { language: string; code: string; isWhole: boolean } | undefined {\n // Keep the opening fence's indentation, which is stripped from the contents.\n const lines = splitLines(text.replace(/^\\s*\\n/u, '').trimEnd());\n const fence = parseOpeningFence(lines[0] ?? '');\n if (!fence) return;\n const lastIndex = lines.length - 1;\n const end =\n lastIndex > 0 && isClosingFence(lines[lastIndex] ?? '', fence) ? lastIndex : findClosingFence(lines, 1, fence);\n return {\n language: fence.language,\n code: lines\n .slice(1, end)\n .map((line) => stripIndent(line, fence.indent))\n .join('\\n'),\n isWhole: end >= lastIndex,\n };\n}\n\nfunction findHeadings(lines: readonly string[]): { index: number; depth: number; text: string }[] {\n const headings: { index: number; depth: number; text: string }[] = [];\n for (let index = 0; index < lines.length; index++) {\n const line = lines[index] ?? '';\n const fence = parseOpeningFence(line);\n if (fence) {\n index = findClosingFence(lines, index + 1, fence);\n continue;\n }\n const match = /^(#{1,6})(?:[ \\t]+(.*))?$/u.exec(line);\n if (!match) continue;\n const text = (match[2] ?? '')\n // The closing sequence of an ATX heading needs a space before it, so `# C#` keeps its `#`.\n .replace(/(?:^|[ \\t]+)#+[ \\t]*$/u, '')\n .trim()\n .replaceAll(/(`+)(.+?)\\1/gu, (_match, _delimiter: string, content: string) =>\n content.startsWith(' ') && content.endsWith(' ') ? content.slice(1, -1) : content\n );\n headings.push({ index, depth: match[1]?.length ?? 1, text });\n }\n return headings;\n}\n\nfunction parseOpeningFence(line: string): Fence | undefined {\n const match = /^( {0,3})(`{3,}|~{3,})(.*)$/u.exec(line);\n const fence = match?.[2];\n const info = match?.[3] ?? '';\n // A backtick in the info string makes the line inline code instead of a fence.\n if (!fence || (fence.startsWith('`') && info.includes('`'))) return;\n return {\n char: fence.charAt(0),\n length: fence.length,\n indent: match[1]?.length ?? 0,\n language: info.trim().split(/\\s/u)[0]?.toLowerCase() ?? '',\n };\n}\n\n/** Returns the index of the line closing `fence`, or the number of lines when it is never closed. */\nfunction findClosingFence(lines: readonly string[], start: number, fence: Fence): number {\n let index = start;\n while (index < lines.length && !isClosingFence(lines[index] ?? '', fence)) index++;\n return index;\n}\n\nfunction isClosingFence(line: string, fence: Fence): boolean {\n const closer = /^ {0,3}(`{3,}|~{3,})[ \\t]*$/u.exec(line)?.[1];\n return closer?.charAt(0) === fence.char && closer.length >= fence.length;\n}\n\nfunction stripIndent(line: string, indent: number): string {\n let index = 0;\n while (index < indent && line[index] === ' ') index++;\n return line.slice(index);\n}\n\nfunction splitLines(text: string): string[] {\n return text.split(/\\r?\\n/u);\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"number.cjs","names":[],"sources":["../src/number.ts"],"sourcesContent":["/**\n * Parses a decimal integer of at least 1 written without sign, whitespace, or leading zeros, e.g. a CLI option or an\n * environment variable. Returns undefined for any other input, including values beyond `Number.MAX_SAFE_INTEGER`.\n */\nexport function parsePositiveInteger(text: string): number | undefined {\n if (!/^[1-9]\\d*$/u.test(text)) return undefined;\n const value = Number(text);\n return Number.isSafeInteger(value) ? value : undefined;\n}\n\n/** Limits a number to the range from `min` to `max`, both inclusive. */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n"],"mappings":"aAIA,SAAgB,EAAqB,EAAkC,CACrE,GAAI,CAAC,cAAc,KAAK,CAAI,EAAG,OAC/B,IAAM,EAAQ,OAAO,CAAI,EACzB,OAAO,OAAO,cAAc,CAAK,EAAI,EAAQ,IAAA,EAC/C,CAGA,SAAgB,EAAM,EAAe,EAAa,EAAqB,CACrE,OAAO,KAAK,IAAI,KAAK,IAAI,EAAO,CAAG,EAAG,CAAG,CAC3C"}
1
+ {"version":3,"file":"number.cjs","names":["parsePositiveInteger","text","value","clamp","min","max"],"sources":["../src/number.ts"],"sourcesContent":["/**\n * Parses a decimal integer of at least 1 written without sign, whitespace, or leading zeros, e.g. a CLI option or an\n * environment variable. Returns undefined for any other input, including values beyond `Number.MAX_SAFE_INTEGER`.\n */\nexport function parsePositiveInteger(text: string): number | undefined {\n if (!/^[1-9]\\d*$/u.test(text)) return undefined;\n const value = Number(text);\n return Number.isSafeInteger(value) ? value : undefined;\n}\n\n/** Limits a number to the range from `min` to `max`, both inclusive. */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n"],"mappings":"aAIA,SAAgBA,EAAqB,EAAkC,CACrE,GAAI,CAAC,cAAc,KAAKC,CAAI,EAAG,OAC/B,IAAMC,EAAQ,OAAOD,CAAI,EACzB,OAAO,OAAO,cAAcC,CAAK,EAAIA,EAAQ,IAAA,EAC/C,CAGA,SAAgBC,EAAM,EAAe,EAAa,EAAqB,CACrE,OAAO,KAAK,IAAI,KAAK,IAAID,EAAOE,CAAG,EAAGC,CAAG,CAC3C"}
@@ -1 +1 @@
1
- {"version":3,"file":"number.js","names":[],"sources":["../src/number.ts"],"sourcesContent":["/**\n * Parses a decimal integer of at least 1 written without sign, whitespace, or leading zeros, e.g. a CLI option or an\n * environment variable. Returns undefined for any other input, including values beyond `Number.MAX_SAFE_INTEGER`.\n */\nexport function parsePositiveInteger(text: string): number | undefined {\n if (!/^[1-9]\\d*$/u.test(text)) return undefined;\n const value = Number(text);\n return Number.isSafeInteger(value) ? value : undefined;\n}\n\n/** Limits a number to the range from `min` to `max`, both inclusive. */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n"],"mappings":"AAIA,SAAgB,EAAqB,EAAkC,CACrE,GAAI,CAAC,cAAc,KAAK,CAAI,EAAG,OAC/B,IAAM,EAAQ,OAAO,CAAI,EACzB,OAAO,OAAO,cAAc,CAAK,EAAI,EAAQ,IAAA,EAC/C,CAGA,SAAgB,EAAM,EAAe,EAAa,EAAqB,CACrE,OAAO,KAAK,IAAI,KAAK,IAAI,EAAO,CAAG,EAAG,CAAG,CAC3C"}
1
+ {"version":3,"file":"number.js","names":["parsePositiveInteger","text","value","clamp","min","max"],"sources":["../src/number.ts"],"sourcesContent":["/**\n * Parses a decimal integer of at least 1 written without sign, whitespace, or leading zeros, e.g. a CLI option or an\n * environment variable. Returns undefined for any other input, including values beyond `Number.MAX_SAFE_INTEGER`.\n */\nexport function parsePositiveInteger(text: string): number | undefined {\n if (!/^[1-9]\\d*$/u.test(text)) return undefined;\n const value = Number(text);\n return Number.isSafeInteger(value) ? value : undefined;\n}\n\n/** Limits a number to the range from `min` to `max`, both inclusive. */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n"],"mappings":"AAIA,SAAgBA,EAAqB,EAAkC,CACrE,GAAI,CAAC,cAAc,KAAKC,CAAI,EAAG,OAC/B,IAAMC,EAAQ,OAAOD,CAAI,EACzB,OAAO,OAAO,cAAcC,CAAK,EAAIA,EAAQ,IAAA,EAC/C,CAGA,SAAgBC,EAAM,EAAe,EAAa,EAAqB,CACrE,OAAO,KAAK,IAAI,KAAK,IAAID,EAAOE,CAAG,EAAGC,CAAG,CAC3C"}
@@ -1 +1 @@
1
- {"version":3,"file":"object.cjs","names":[],"sources":["../src/object.ts"],"sourcesContent":["/** Whether a value is a non-null object other than an array, e.g. a parsed JSON object. */\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Returns a shallow copy of the own enumerable string-keyed properties whose values are not `undefined`,\n * e.g. to turn `process.env` into a `Record<string, string>`.\n * Expects a plain record: the copy is a plain object without the input's prototype, so the type rejects arrays and\n * class instances such as `Date`, though not a class that declares a string index signature.\n */\nexport function omitUndefined<T extends Readonly<Record<string, unknown>>>(value: T): WithoutUndefined<T> {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(value)) {\n const propertyValue = (value as Record<string, unknown>)[key];\n if (propertyValue === undefined) continue;\n if (key === '__proto__') {\n // Assignment would invoke the `__proto__` setter and replace the prototype instead of copying the key.\n Object.defineProperty(result, key, {\n configurable: true,\n enumerable: true,\n value: propertyValue,\n writable: true,\n });\n } else {\n result[key] = propertyValue;\n }\n }\n return result as WithoutUndefined<T>;\n}\n\n// A known key whose value may be `undefined` becomes optional because it may be omitted; an index signature, whose keys\n// are never guaranteed to exist, keeps its shape so that `process.env` yields `Record<string, string>`. Symbol keys are\n// not copied.\ntype WithoutUndefined<T> = {\n [\n K in keyof T as K extends symbol ? never : IsIndexKey<K> extends true ? K : undefined extends T[K] ? never : K\n ]: Exclude<T[K], undefined>;\n} & {\n [\n K in keyof T as K extends symbol ? never : IsIndexKey<K> extends true ? never : undefined extends T[K] ? K : never\n ]?: Exclude<T[K], undefined>;\n};\n\ntype IsIndexKey<K> = string extends K ? true : number extends K ? true : false;\n"],"mappings":"aACA,SAAgB,EAAS,EAAkD,CACzE,OAAO,OAAO,GAAU,YAAY,GAAkB,CAAC,MAAM,QAAQ,CAAK,CAC5E,CAQA,SAAgB,EAA2D,EAA+B,CACxG,IAAM,EAAkC,CAAC,EACzC,IAAK,IAAM,KAAO,OAAO,KAAK,CAAK,EAAG,CACpC,IAAM,EAAiB,EAAkC,GACrD,IAAkB,IAAA,KAClB,IAAQ,YAEV,OAAO,eAAe,EAAQ,EAAK,CACjC,aAAc,GACd,WAAY,GACZ,MAAO,EACP,SAAU,EACZ,CAAC,EAED,EAAO,GAAO,EAElB,CACA,OAAO,CACT"}
1
+ {"version":3,"file":"object.cjs","names":["isRecord","value","omitUndefined","result","key","propertyValue"],"sources":["../src/object.ts"],"sourcesContent":["/** Whether a value is a non-null object other than an array, e.g. a parsed JSON object. */\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Returns a shallow copy of the own enumerable string-keyed properties whose values are not `undefined`,\n * e.g. to turn `process.env` into a `Record<string, string>`.\n * Expects a plain record: the copy is a plain object without the input's prototype, so the type rejects arrays and\n * class instances such as `Date`, though not a class that declares a string index signature.\n */\nexport function omitUndefined<T extends Readonly<Record<string, unknown>>>(value: T): WithoutUndefined<T> {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(value)) {\n const propertyValue = (value as Record<string, unknown>)[key];\n if (propertyValue === undefined) continue;\n if (key === '__proto__') {\n // Assignment would invoke the `__proto__` setter and replace the prototype instead of copying the key.\n Object.defineProperty(result, key, {\n configurable: true,\n enumerable: true,\n value: propertyValue,\n writable: true,\n });\n } else {\n result[key] = propertyValue;\n }\n }\n return result as WithoutUndefined<T>;\n}\n\n// A known key whose value may be `undefined` becomes optional because it may be omitted; an index signature, whose keys\n// are never guaranteed to exist, keeps its shape so that `process.env` yields `Record<string, string>`. Symbol keys are\n// not copied.\ntype WithoutUndefined<T> = {\n [\n K in keyof T as K extends symbol ? never : IsIndexKey<K> extends true ? K : undefined extends T[K] ? never : K\n ]: Exclude<T[K], undefined>;\n} & {\n [\n K in keyof T as K extends symbol ? never : IsIndexKey<K> extends true ? never : undefined extends T[K] ? K : never\n ]?: Exclude<T[K], undefined>;\n};\n\ntype IsIndexKey<K> = string extends K ? true : number extends K ? true : false;\n"],"mappings":"aACA,SAAgBA,EAAS,EAAkD,CACzE,OAAO,OAAOC,GAAU,YAAYA,GAAkB,CAAC,MAAM,QAAQA,CAAK,CAC5E,CAQA,SAAgBC,EAA2D,EAA+B,CACxG,IAAMC,EAAkC,CAAC,EACzC,IAAK,IAAMC,KAAO,OAAO,KAAKH,CAAK,EAAG,CACpC,IAAMI,EAAiBJ,EAAkCG,GACrDC,IAAkB,IAAA,KAClBD,IAAQ,YAEV,OAAO,eAAeD,EAAQC,EAAK,CACjC,aAAc,GACd,WAAY,GACZ,MAAOC,EACP,SAAU,EACZ,CAAC,EAED,EAAOD,GAAOC,EAElB,CACA,OAAOF,CACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"object.js","names":[],"sources":["../src/object.ts"],"sourcesContent":["/** Whether a value is a non-null object other than an array, e.g. a parsed JSON object. */\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Returns a shallow copy of the own enumerable string-keyed properties whose values are not `undefined`,\n * e.g. to turn `process.env` into a `Record<string, string>`.\n * Expects a plain record: the copy is a plain object without the input's prototype, so the type rejects arrays and\n * class instances such as `Date`, though not a class that declares a string index signature.\n */\nexport function omitUndefined<T extends Readonly<Record<string, unknown>>>(value: T): WithoutUndefined<T> {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(value)) {\n const propertyValue = (value as Record<string, unknown>)[key];\n if (propertyValue === undefined) continue;\n if (key === '__proto__') {\n // Assignment would invoke the `__proto__` setter and replace the prototype instead of copying the key.\n Object.defineProperty(result, key, {\n configurable: true,\n enumerable: true,\n value: propertyValue,\n writable: true,\n });\n } else {\n result[key] = propertyValue;\n }\n }\n return result as WithoutUndefined<T>;\n}\n\n// A known key whose value may be `undefined` becomes optional because it may be omitted; an index signature, whose keys\n// are never guaranteed to exist, keeps its shape so that `process.env` yields `Record<string, string>`. Symbol keys are\n// not copied.\ntype WithoutUndefined<T> = {\n [\n K in keyof T as K extends symbol ? never : IsIndexKey<K> extends true ? K : undefined extends T[K] ? never : K\n ]: Exclude<T[K], undefined>;\n} & {\n [\n K in keyof T as K extends symbol ? never : IsIndexKey<K> extends true ? never : undefined extends T[K] ? K : never\n ]?: Exclude<T[K], undefined>;\n};\n\ntype IsIndexKey<K> = string extends K ? true : number extends K ? true : false;\n"],"mappings":"AACA,SAAgB,EAAS,EAAkD,CACzE,OAAO,OAAO,GAAU,YAAY,GAAkB,CAAC,MAAM,QAAQ,CAAK,CAC5E,CAQA,SAAgB,EAA2D,EAA+B,CACxG,IAAM,EAAkC,CAAC,EACzC,IAAK,IAAM,KAAO,OAAO,KAAK,CAAK,EAAG,CACpC,IAAM,EAAiB,EAAkC,GACrD,IAAkB,IAAA,KAClB,IAAQ,YAEV,OAAO,eAAe,EAAQ,EAAK,CACjC,aAAc,GACd,WAAY,GACZ,MAAO,EACP,SAAU,EACZ,CAAC,EAED,EAAO,GAAO,EAElB,CACA,OAAO,CACT"}
1
+ {"version":3,"file":"object.js","names":["isRecord","value","omitUndefined","result","key","propertyValue"],"sources":["../src/object.ts"],"sourcesContent":["/** Whether a value is a non-null object other than an array, e.g. a parsed JSON object. */\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Returns a shallow copy of the own enumerable string-keyed properties whose values are not `undefined`,\n * e.g. to turn `process.env` into a `Record<string, string>`.\n * Expects a plain record: the copy is a plain object without the input's prototype, so the type rejects arrays and\n * class instances such as `Date`, though not a class that declares a string index signature.\n */\nexport function omitUndefined<T extends Readonly<Record<string, unknown>>>(value: T): WithoutUndefined<T> {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(value)) {\n const propertyValue = (value as Record<string, unknown>)[key];\n if (propertyValue === undefined) continue;\n if (key === '__proto__') {\n // Assignment would invoke the `__proto__` setter and replace the prototype instead of copying the key.\n Object.defineProperty(result, key, {\n configurable: true,\n enumerable: true,\n value: propertyValue,\n writable: true,\n });\n } else {\n result[key] = propertyValue;\n }\n }\n return result as WithoutUndefined<T>;\n}\n\n// A known key whose value may be `undefined` becomes optional because it may be omitted; an index signature, whose keys\n// are never guaranteed to exist, keeps its shape so that `process.env` yields `Record<string, string>`. Symbol keys are\n// not copied.\ntype WithoutUndefined<T> = {\n [\n K in keyof T as K extends symbol ? never : IsIndexKey<K> extends true ? K : undefined extends T[K] ? never : K\n ]: Exclude<T[K], undefined>;\n} & {\n [\n K in keyof T as K extends symbol ? never : IsIndexKey<K> extends true ? never : undefined extends T[K] ? K : never\n ]?: Exclude<T[K], undefined>;\n};\n\ntype IsIndexKey<K> = string extends K ? true : number extends K ? true : false;\n"],"mappings":"AACA,SAAgBA,EAAS,EAAkD,CACzE,OAAO,OAAOC,GAAU,YAAYA,GAAkB,CAAC,MAAM,QAAQA,CAAK,CAC5E,CAQA,SAAgBC,EAA2D,EAA+B,CACxG,IAAMC,EAAkC,CAAC,EACzC,IAAK,IAAMC,KAAO,OAAO,KAAKH,CAAK,EAAG,CACpC,IAAMI,EAAiBJ,EAAkCG,GACrDC,IAAkB,IAAA,KAClBD,IAAQ,YAEV,OAAO,eAAeD,EAAQC,EAAK,CACjC,aAAc,GACd,WAAY,GACZ,MAAOC,EACP,SAAU,EACZ,CAAC,EAED,EAAOD,GAAOC,EAElB,CACA,OAAOF,CACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"parseCommandLineArgs.cjs","names":[],"sources":["../src/parseCommandLineArgs.ts"],"sourcesContent":["/**\n * Parses a command line string into an array of arguments, preserving quoted strings.\n *\n * This function handles:\n * - Space-separated arguments\n * - Double-quoted strings (preserves spaces within)\n * - Single-quoted strings (preserves spaces within)\n *\n * @param argsString The command line string to parse\n * @returns An array of parsed arguments\n */\nexport function parseCommandLineArgs(argsString: string): string[] {\n if (!argsString) return [];\n\n const result: string[] = [];\n let current = '';\n let inDoubleQuote = false;\n let inSingleQuote = false;\n\n for (const char of argsString) {\n if (char === '\"' && !inSingleQuote) {\n inDoubleQuote = !inDoubleQuote;\n continue;\n }\n\n if (char === \"'\" && !inDoubleQuote) {\n inSingleQuote = !inSingleQuote;\n continue;\n }\n\n if (char === ' ' && !inDoubleQuote && !inSingleQuote) {\n if (current) {\n result.push(current);\n current = '';\n }\n continue;\n }\n\n current += char;\n }\n\n if (current) {\n result.push(current);\n }\n\n return result;\n}\n"],"mappings":"aAWA,SAAgB,EAAqB,EAA8B,CACjE,GAAI,CAAC,EAAY,MAAO,CAAC,EAEzB,IAAM,EAAmB,CAAC,EACtB,EAAU,GACV,EAAgB,GAChB,EAAgB,GAEpB,IAAK,IAAM,KAAQ,EAAY,CAC7B,GAAI,IAAS,KAAO,CAAC,EAAe,CAClC,EAAgB,CAAC,EACjB,QACF,CAEA,GAAI,IAAS,KAAO,CAAC,EAAe,CAClC,EAAgB,CAAC,EACjB,QACF,CAEA,GAAI,IAAS,KAAO,CAAC,GAAiB,CAAC,EAAe,CACpD,AAEE,KADA,EAAO,KAAK,CAAO,EACT,IAEZ,QACF,CAEA,GAAW,CACb,CAMA,OAJI,GACF,EAAO,KAAK,CAAO,EAGd,CACT"}
1
+ {"version":3,"file":"parseCommandLineArgs.cjs","names":["parseCommandLineArgs","argsString","result","current","inDoubleQuote","inSingleQuote","char"],"sources":["../src/parseCommandLineArgs.ts"],"sourcesContent":["/**\n * Parses a command line string into an array of arguments, preserving quoted strings.\n *\n * This function handles:\n * - Space-separated arguments\n * - Double-quoted strings (preserves spaces within)\n * - Single-quoted strings (preserves spaces within)\n *\n * @param argsString The command line string to parse\n * @returns An array of parsed arguments\n */\nexport function parseCommandLineArgs(argsString: string): string[] {\n if (!argsString) return [];\n\n const result: string[] = [];\n let current = '';\n let inDoubleQuote = false;\n let inSingleQuote = false;\n\n for (const char of argsString) {\n if (char === '\"' && !inSingleQuote) {\n inDoubleQuote = !inDoubleQuote;\n continue;\n }\n\n if (char === \"'\" && !inDoubleQuote) {\n inSingleQuote = !inSingleQuote;\n continue;\n }\n\n if (char === ' ' && !inDoubleQuote && !inSingleQuote) {\n if (current) {\n result.push(current);\n current = '';\n }\n continue;\n }\n\n current += char;\n }\n\n if (current) {\n result.push(current);\n }\n\n return result;\n}\n"],"mappings":"aAWA,SAAgBA,EAAqB,EAA8B,CACjE,GAAI,CAACC,EAAY,MAAO,CAAC,EAEzB,IAAMC,EAAmB,CAAC,EACtBC,EAAU,GACVC,EAAgB,GAChBC,EAAgB,GAEpB,IAAK,IAAMC,KAAQL,EAAY,CAC7B,GAAIK,IAAS,KAAO,CAACD,EAAe,CAClC,EAAgB,CAACD,EACjB,QACF,CAEA,GAAIE,IAAS,KAAO,CAACF,EAAe,CAClC,EAAgB,CAACC,EACjB,QACF,CAEA,GAAIC,IAAS,KAAO,CAACF,GAAiB,CAACC,EAAe,CACpD,AAEEF,KADAD,EAAO,KAAKC,CAAO,EACT,IAEZ,QACF,CAEA,GAAWG,CACb,CAMA,OAJIH,GACFD,EAAO,KAAKC,CAAO,EAGdD,CACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"parseCommandLineArgs.js","names":[],"sources":["../src/parseCommandLineArgs.ts"],"sourcesContent":["/**\n * Parses a command line string into an array of arguments, preserving quoted strings.\n *\n * This function handles:\n * - Space-separated arguments\n * - Double-quoted strings (preserves spaces within)\n * - Single-quoted strings (preserves spaces within)\n *\n * @param argsString The command line string to parse\n * @returns An array of parsed arguments\n */\nexport function parseCommandLineArgs(argsString: string): string[] {\n if (!argsString) return [];\n\n const result: string[] = [];\n let current = '';\n let inDoubleQuote = false;\n let inSingleQuote = false;\n\n for (const char of argsString) {\n if (char === '\"' && !inSingleQuote) {\n inDoubleQuote = !inDoubleQuote;\n continue;\n }\n\n if (char === \"'\" && !inDoubleQuote) {\n inSingleQuote = !inSingleQuote;\n continue;\n }\n\n if (char === ' ' && !inDoubleQuote && !inSingleQuote) {\n if (current) {\n result.push(current);\n current = '';\n }\n continue;\n }\n\n current += char;\n }\n\n if (current) {\n result.push(current);\n }\n\n return result;\n}\n"],"mappings":"AAWA,SAAgB,EAAqB,EAA8B,CACjE,GAAI,CAAC,EAAY,MAAO,CAAC,EAEzB,IAAM,EAAmB,CAAC,EACtB,EAAU,GACV,EAAgB,GAChB,EAAgB,GAEpB,IAAK,IAAM,KAAQ,EAAY,CAC7B,GAAI,IAAS,KAAO,CAAC,EAAe,CAClC,EAAgB,CAAC,EACjB,QACF,CAEA,GAAI,IAAS,KAAO,CAAC,EAAe,CAClC,EAAgB,CAAC,EACjB,QACF,CAEA,GAAI,IAAS,KAAO,CAAC,GAAiB,CAAC,EAAe,CACpD,AAEE,KADA,EAAO,KAAK,CAAO,EACT,IAEZ,QACF,CAEA,GAAW,CACb,CAMA,OAJI,GACF,EAAO,KAAK,CAAO,EAGd,CACT"}
1
+ {"version":3,"file":"parseCommandLineArgs.js","names":["parseCommandLineArgs","argsString","result","current","inDoubleQuote","inSingleQuote","char"],"sources":["../src/parseCommandLineArgs.ts"],"sourcesContent":["/**\n * Parses a command line string into an array of arguments, preserving quoted strings.\n *\n * This function handles:\n * - Space-separated arguments\n * - Double-quoted strings (preserves spaces within)\n * - Single-quoted strings (preserves spaces within)\n *\n * @param argsString The command line string to parse\n * @returns An array of parsed arguments\n */\nexport function parseCommandLineArgs(argsString: string): string[] {\n if (!argsString) return [];\n\n const result: string[] = [];\n let current = '';\n let inDoubleQuote = false;\n let inSingleQuote = false;\n\n for (const char of argsString) {\n if (char === '\"' && !inSingleQuote) {\n inDoubleQuote = !inDoubleQuote;\n continue;\n }\n\n if (char === \"'\" && !inDoubleQuote) {\n inSingleQuote = !inSingleQuote;\n continue;\n }\n\n if (char === ' ' && !inDoubleQuote && !inSingleQuote) {\n if (current) {\n result.push(current);\n current = '';\n }\n continue;\n }\n\n current += char;\n }\n\n if (current) {\n result.push(current);\n }\n\n return result;\n}\n"],"mappings":"AAWA,SAAgBA,EAAqB,EAA8B,CACjE,GAAI,CAACC,EAAY,MAAO,CAAC,EAEzB,IAAMC,EAAmB,CAAC,EACtBC,EAAU,GACVC,EAAgB,GAChBC,EAAgB,GAEpB,IAAK,IAAMC,KAAQL,EAAY,CAC7B,GAAIK,IAAS,KAAO,CAACD,EAAe,CAClC,EAAgB,CAACD,EACjB,QACF,CAEA,GAAIE,IAAS,KAAO,CAACF,EAAe,CAClC,EAAgB,CAACC,EACjB,QACF,CAEA,GAAIC,IAAS,KAAO,CAACF,GAAiB,CAACC,EAAe,CACpD,AAEEF,KADAD,EAAO,KAAKC,CAAO,EACT,IAEZ,QACF,CAEA,GAAWG,CACb,CAMA,OAJIH,GACFD,EAAO,KAAKC,CAAO,EAGdD,CACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"parseIsoDate.cjs","names":[],"sources":["../src/parseIsoDate.ts"],"sourcesContent":["export type ParsedIsoDate = { kind: 'date'; value: string } | { kind: 'datetime'; value: string };\n\n/**\n * Parses an ISO calendar date or a timestamp with an explicit UTC offset, without guessing\n * a timezone or rolling invalid calendar dates forward. Returns undefined for unsupported input.\n *\n * Accepts YYYY-MM-DD and YYYY-MM-DDTHH:mm[:ss[.fraction]] followed by Z or ±HH:mm\n * (±HHmm also works). Surrounding whitespace is ignored. Date-only values stay date-only;\n * timestamps become UTC strings, retaining all fractional digits. Local timestamps, unknown\n * offsets (-00:00/-0000), leap seconds, and input or normalized UTC years outside 0000–9999\n * are unsupported.\n */\nexport function parseIsoDate(input: unknown): ParsedIsoDate | undefined {\n if (typeof input !== 'string') return undefined;\n const value = input.trim();\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})(?:T(\\d{2}):(\\d{2})(?::(\\d{2})(\\.\\d+)?)?(Z|[+-]\\d{2}:?\\d{2}))?$/u.exec(value);\n if (!match) return undefined;\n const [, yearText, monthText, dayText, hourText, minuteText, secondText, fraction, zone] = match;\n const year = Number(yearText);\n const month = Number(monthText);\n const day = Number(dayText);\n const local = new Date(0);\n local.setUTCFullYear(year, month - 1, day);\n if (local.getUTCFullYear() !== year || local.getUTCMonth() !== month - 1 || local.getUTCDate() !== day) {\n return undefined;\n }\n if (hourText === undefined) return { kind: 'date', value };\n const hour = Number(hourText);\n const minute = Number(minuteText);\n const second = Number(secondText ?? 0);\n if (hour > 23 || minute > 59 || second > 59) return undefined;\n const offset = parseOffset(zone!);\n if (offset === undefined) return undefined;\n local.setUTCHours(hour, minute - offset, second);\n if (local.getUTCFullYear() < 0 || local.getUTCFullYear() > 9999) return undefined;\n return { kind: 'datetime', value: `${local.toISOString().slice(0, 19)}${fraction ?? ''}Z` };\n}\n\nfunction parseOffset(zone: string): number | undefined {\n if (zone === 'Z') return 0;\n const digits = zone.slice(1).replace(':', '');\n const hours = Number(digits.slice(0, 2));\n const minutes = Number(digits.slice(2));\n if (hours > 23 || minutes > 59 || (zone.startsWith('-') && hours === 0 && minutes === 0)) return undefined;\n return (zone.startsWith('-') ? -1 : 1) * (hours * 60 + minutes);\n}\n"],"mappings":"aAYA,SAAgB,EAAa,EAA2C,CACtE,GAAI,OAAO,GAAU,SAAU,OAC/B,IAAM,EAAQ,EAAM,KAAK,EACnB,EAAQ,2FAA2F,KAAK,CAAK,EACnH,GAAI,CAAC,EAAO,OACZ,GAAM,EAAG,EAAU,EAAW,EAAS,EAAU,EAAY,EAAY,EAAU,GAAQ,EACrF,EAAO,OAAO,CAAQ,EACtB,EAAQ,OAAO,CAAS,EACxB,EAAM,OAAO,CAAO,EACpB,kBAAQ,IAAI,KAAK,CAAC,EAExB,GADA,EAAM,eAAe,EAAM,EAAQ,EAAG,CAAG,EACrC,EAAM,eAAe,IAAM,GAAQ,EAAM,YAAY,IAAM,EAAQ,GAAK,EAAM,WAAW,IAAM,EACjG,OAEF,GAAI,IAAa,IAAA,GAAW,MAAO,CAAE,KAAM,OAAQ,OAAM,EACzD,IAAM,EAAO,OAAO,CAAQ,EACtB,EAAS,OAAO,CAAU,EAC1B,EAAS,OAAO,GAAc,CAAC,EACrC,GAAI,EAAO,IAAM,EAAS,IAAM,EAAS,GAAI,OAC7C,IAAM,EAAS,EAAY,CAAK,EAC5B,OAAW,IAAA,KACf,EAAM,YAAY,EAAM,EAAS,EAAQ,CAAM,EAC3C,IAAM,eAAe,EAAI,GAAK,EAAM,eAAe,EAAI,OAC3D,MAAO,CAAE,KAAM,WAAY,MAAO,GAAG,EAAM,YAAY,CAAC,CAAC,MAAM,EAAG,EAAE,IAAI,GAAY,GAAG,EAAG,CAC5F,CAEA,SAAS,EAAY,EAAkC,CACrD,GAAI,IAAS,IAAK,MAAO,GACzB,IAAM,EAAS,EAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,IAAK,EAAE,EACtC,EAAQ,OAAO,EAAO,MAAM,EAAG,CAAC,CAAC,EACjC,EAAU,OAAO,EAAO,MAAM,CAAC,CAAC,EAClC,OAAQ,IAAM,EAAU,IAAO,EAAK,WAAW,GAAG,GAAK,IAAU,GAAK,IAAY,GACtF,OAAQ,EAAK,WAAW,GAAG,EAAI,GAAK,IAAM,EAAQ,GAAK,EACzD"}
1
+ {"version":3,"file":"parseIsoDate.cjs","names":["parseIsoDate","input","value","match","yearText","monthText","dayText","hourText","minuteText","secondText","fraction","zone","year","month","day","local","hour","minute","second","offset","parseOffset","digits","hours","minutes"],"sources":["../src/parseIsoDate.ts"],"sourcesContent":["export type ParsedIsoDate = { kind: 'date'; value: string } | { kind: 'datetime'; value: string };\n\n/**\n * Parses an ISO calendar date or a timestamp with an explicit UTC offset, without guessing\n * a timezone or rolling invalid calendar dates forward. Returns undefined for unsupported input.\n *\n * Accepts YYYY-MM-DD and YYYY-MM-DDTHH:mm[:ss[.fraction]] followed by Z or ±HH:mm\n * (±HHmm also works). Surrounding whitespace is ignored. Date-only values stay date-only;\n * timestamps become UTC strings, retaining all fractional digits. Local timestamps, unknown\n * offsets (-00:00/-0000), leap seconds, and input or normalized UTC years outside 0000–9999\n * are unsupported.\n */\nexport function parseIsoDate(input: unknown): ParsedIsoDate | undefined {\n if (typeof input !== 'string') return undefined;\n const value = input.trim();\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})(?:T(\\d{2}):(\\d{2})(?::(\\d{2})(\\.\\d+)?)?(Z|[+-]\\d{2}:?\\d{2}))?$/u.exec(value);\n if (!match) return undefined;\n const [, yearText, monthText, dayText, hourText, minuteText, secondText, fraction, zone] = match;\n const year = Number(yearText);\n const month = Number(monthText);\n const day = Number(dayText);\n const local = new Date(0);\n local.setUTCFullYear(year, month - 1, day);\n if (local.getUTCFullYear() !== year || local.getUTCMonth() !== month - 1 || local.getUTCDate() !== day) {\n return undefined;\n }\n if (hourText === undefined) return { kind: 'date', value };\n const hour = Number(hourText);\n const minute = Number(minuteText);\n const second = Number(secondText ?? 0);\n if (hour > 23 || minute > 59 || second > 59) return undefined;\n const offset = parseOffset(zone!);\n if (offset === undefined) return undefined;\n local.setUTCHours(hour, minute - offset, second);\n if (local.getUTCFullYear() < 0 || local.getUTCFullYear() > 9999) return undefined;\n return { kind: 'datetime', value: `${local.toISOString().slice(0, 19)}${fraction ?? ''}Z` };\n}\n\nfunction parseOffset(zone: string): number | undefined {\n if (zone === 'Z') return 0;\n const digits = zone.slice(1).replace(':', '');\n const hours = Number(digits.slice(0, 2));\n const minutes = Number(digits.slice(2));\n if (hours > 23 || minutes > 59 || (zone.startsWith('-') && hours === 0 && minutes === 0)) return undefined;\n return (zone.startsWith('-') ? -1 : 1) * (hours * 60 + minutes);\n}\n"],"mappings":"aAYA,SAAgBA,EAAa,EAA2C,CACtE,GAAI,OAAOC,GAAU,SAAU,OAC/B,IAAMC,EAAQD,EAAM,KAAK,EACnBE,EAAQ,2FAA2F,KAAKD,CAAK,EACnH,GAAI,CAACC,EAAO,OACZ,GAAM,EAAGC,EAAUC,EAAWC,EAASC,EAAUC,EAAYC,EAAYC,EAAUC,GAAQR,EACrFS,EAAO,OAAOR,CAAQ,EACtBS,EAAQ,OAAOR,CAAS,EACxBS,EAAM,OAAOR,CAAO,EACpBS,kBAAQ,IAAI,KAAK,CAAC,EAExB,GADAA,EAAM,eAAeH,EAAMC,EAAQ,EAAGC,CAAG,EACrCC,EAAM,eAAe,IAAMH,GAAQG,EAAM,YAAY,IAAMF,EAAQ,GAAKE,EAAM,WAAW,IAAMD,EACjG,OAEF,GAAIP,IAAa,IAAA,GAAW,MAAO,CAAE,KAAM,OAAQ,OAAM,EACzD,IAAMS,EAAO,OAAOT,CAAQ,EACtBU,EAAS,OAAOT,CAAU,EAC1BU,EAAS,OAAOT,GAAc,CAAC,EACrC,GAAIO,EAAO,IAAMC,EAAS,IAAMC,EAAS,GAAI,OAC7C,IAAMC,EAASC,EAAYT,CAAK,EAChC,GAAIQ,IAAW,IAAA,KACfJ,EAAM,YAAYC,EAAMC,EAASE,EAAQD,CAAM,EAC3C,IAAM,eAAe,EAAI,GAAKH,EAAM,eAAe,EAAI,OAC3D,MAAO,CAAE,KAAM,WAAY,MAAO,GAAGA,EAAM,YAAY,CAAC,CAAC,MAAM,EAAG,EAAE,IAAIL,GAAY,GAAG,EAAG,CAC5F,CAEA,SAASU,EAAY,EAAkC,CACrD,GAAIT,IAAS,IAAK,MAAO,GACzB,IAAMU,EAASV,EAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,IAAK,EAAE,EACtCW,EAAQ,OAAOD,EAAO,MAAM,EAAG,CAAC,CAAC,EACjCE,EAAU,OAAOF,EAAO,MAAM,CAAC,CAAC,EACtC,GAAI,IAAQ,IAAME,EAAU,IAAOZ,EAAK,WAAW,GAAG,GAAKW,IAAU,GAAKC,IAAY,GACtF,OAAQZ,EAAK,WAAW,GAAG,EAAI,GAAK,IAAMW,EAAQ,GAAKC,EACzD"}
@@ -1 +1 @@
1
- {"version":3,"file":"parseIsoDate.js","names":[],"sources":["../src/parseIsoDate.ts"],"sourcesContent":["export type ParsedIsoDate = { kind: 'date'; value: string } | { kind: 'datetime'; value: string };\n\n/**\n * Parses an ISO calendar date or a timestamp with an explicit UTC offset, without guessing\n * a timezone or rolling invalid calendar dates forward. Returns undefined for unsupported input.\n *\n * Accepts YYYY-MM-DD and YYYY-MM-DDTHH:mm[:ss[.fraction]] followed by Z or ±HH:mm\n * (±HHmm also works). Surrounding whitespace is ignored. Date-only values stay date-only;\n * timestamps become UTC strings, retaining all fractional digits. Local timestamps, unknown\n * offsets (-00:00/-0000), leap seconds, and input or normalized UTC years outside 0000–9999\n * are unsupported.\n */\nexport function parseIsoDate(input: unknown): ParsedIsoDate | undefined {\n if (typeof input !== 'string') return undefined;\n const value = input.trim();\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})(?:T(\\d{2}):(\\d{2})(?::(\\d{2})(\\.\\d+)?)?(Z|[+-]\\d{2}:?\\d{2}))?$/u.exec(value);\n if (!match) return undefined;\n const [, yearText, monthText, dayText, hourText, minuteText, secondText, fraction, zone] = match;\n const year = Number(yearText);\n const month = Number(monthText);\n const day = Number(dayText);\n const local = new Date(0);\n local.setUTCFullYear(year, month - 1, day);\n if (local.getUTCFullYear() !== year || local.getUTCMonth() !== month - 1 || local.getUTCDate() !== day) {\n return undefined;\n }\n if (hourText === undefined) return { kind: 'date', value };\n const hour = Number(hourText);\n const minute = Number(minuteText);\n const second = Number(secondText ?? 0);\n if (hour > 23 || minute > 59 || second > 59) return undefined;\n const offset = parseOffset(zone!);\n if (offset === undefined) return undefined;\n local.setUTCHours(hour, minute - offset, second);\n if (local.getUTCFullYear() < 0 || local.getUTCFullYear() > 9999) return undefined;\n return { kind: 'datetime', value: `${local.toISOString().slice(0, 19)}${fraction ?? ''}Z` };\n}\n\nfunction parseOffset(zone: string): number | undefined {\n if (zone === 'Z') return 0;\n const digits = zone.slice(1).replace(':', '');\n const hours = Number(digits.slice(0, 2));\n const minutes = Number(digits.slice(2));\n if (hours > 23 || minutes > 59 || (zone.startsWith('-') && hours === 0 && minutes === 0)) return undefined;\n return (zone.startsWith('-') ? -1 : 1) * (hours * 60 + minutes);\n}\n"],"mappings":"AAYA,SAAgB,EAAa,EAA2C,CACtE,GAAI,OAAO,GAAU,SAAU,OAC/B,IAAM,EAAQ,EAAM,KAAK,EACnB,EAAQ,2FAA2F,KAAK,CAAK,EACnH,GAAI,CAAC,EAAO,OACZ,GAAM,EAAG,EAAU,EAAW,EAAS,EAAU,EAAY,EAAY,EAAU,GAAQ,EACrF,EAAO,OAAO,CAAQ,EACtB,EAAQ,OAAO,CAAS,EACxB,EAAM,OAAO,CAAO,EACpB,kBAAQ,IAAI,KAAK,CAAC,EAExB,GADA,EAAM,eAAe,EAAM,EAAQ,EAAG,CAAG,EACrC,EAAM,eAAe,IAAM,GAAQ,EAAM,YAAY,IAAM,EAAQ,GAAK,EAAM,WAAW,IAAM,EACjG,OAEF,GAAI,IAAa,IAAA,GAAW,MAAO,CAAE,KAAM,OAAQ,OAAM,EACzD,IAAM,EAAO,OAAO,CAAQ,EACtB,EAAS,OAAO,CAAU,EAC1B,EAAS,OAAO,GAAc,CAAC,EACrC,GAAI,EAAO,IAAM,EAAS,IAAM,EAAS,GAAI,OAC7C,IAAM,EAAS,EAAY,CAAK,EAC5B,OAAW,IAAA,KACf,EAAM,YAAY,EAAM,EAAS,EAAQ,CAAM,EAC3C,IAAM,eAAe,EAAI,GAAK,EAAM,eAAe,EAAI,OAC3D,MAAO,CAAE,KAAM,WAAY,MAAO,GAAG,EAAM,YAAY,CAAC,CAAC,MAAM,EAAG,EAAE,IAAI,GAAY,GAAG,EAAG,CAC5F,CAEA,SAAS,EAAY,EAAkC,CACrD,GAAI,IAAS,IAAK,MAAO,GACzB,IAAM,EAAS,EAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,IAAK,EAAE,EACtC,EAAQ,OAAO,EAAO,MAAM,EAAG,CAAC,CAAC,EACjC,EAAU,OAAO,EAAO,MAAM,CAAC,CAAC,EAClC,OAAQ,IAAM,EAAU,IAAO,EAAK,WAAW,GAAG,GAAK,IAAU,GAAK,IAAY,GACtF,OAAQ,EAAK,WAAW,GAAG,EAAI,GAAK,IAAM,EAAQ,GAAK,EACzD"}
1
+ {"version":3,"file":"parseIsoDate.js","names":["parseIsoDate","input","value","match","yearText","monthText","dayText","hourText","minuteText","secondText","fraction","zone","year","month","day","local","hour","minute","second","offset","parseOffset","digits","hours","minutes"],"sources":["../src/parseIsoDate.ts"],"sourcesContent":["export type ParsedIsoDate = { kind: 'date'; value: string } | { kind: 'datetime'; value: string };\n\n/**\n * Parses an ISO calendar date or a timestamp with an explicit UTC offset, without guessing\n * a timezone or rolling invalid calendar dates forward. Returns undefined for unsupported input.\n *\n * Accepts YYYY-MM-DD and YYYY-MM-DDTHH:mm[:ss[.fraction]] followed by Z or ±HH:mm\n * (±HHmm also works). Surrounding whitespace is ignored. Date-only values stay date-only;\n * timestamps become UTC strings, retaining all fractional digits. Local timestamps, unknown\n * offsets (-00:00/-0000), leap seconds, and input or normalized UTC years outside 0000–9999\n * are unsupported.\n */\nexport function parseIsoDate(input: unknown): ParsedIsoDate | undefined {\n if (typeof input !== 'string') return undefined;\n const value = input.trim();\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})(?:T(\\d{2}):(\\d{2})(?::(\\d{2})(\\.\\d+)?)?(Z|[+-]\\d{2}:?\\d{2}))?$/u.exec(value);\n if (!match) return undefined;\n const [, yearText, monthText, dayText, hourText, minuteText, secondText, fraction, zone] = match;\n const year = Number(yearText);\n const month = Number(monthText);\n const day = Number(dayText);\n const local = new Date(0);\n local.setUTCFullYear(year, month - 1, day);\n if (local.getUTCFullYear() !== year || local.getUTCMonth() !== month - 1 || local.getUTCDate() !== day) {\n return undefined;\n }\n if (hourText === undefined) return { kind: 'date', value };\n const hour = Number(hourText);\n const minute = Number(minuteText);\n const second = Number(secondText ?? 0);\n if (hour > 23 || minute > 59 || second > 59) return undefined;\n const offset = parseOffset(zone!);\n if (offset === undefined) return undefined;\n local.setUTCHours(hour, minute - offset, second);\n if (local.getUTCFullYear() < 0 || local.getUTCFullYear() > 9999) return undefined;\n return { kind: 'datetime', value: `${local.toISOString().slice(0, 19)}${fraction ?? ''}Z` };\n}\n\nfunction parseOffset(zone: string): number | undefined {\n if (zone === 'Z') return 0;\n const digits = zone.slice(1).replace(':', '');\n const hours = Number(digits.slice(0, 2));\n const minutes = Number(digits.slice(2));\n if (hours > 23 || minutes > 59 || (zone.startsWith('-') && hours === 0 && minutes === 0)) return undefined;\n return (zone.startsWith('-') ? -1 : 1) * (hours * 60 + minutes);\n}\n"],"mappings":"AAYA,SAAgBA,EAAa,EAA2C,CACtE,GAAI,OAAOC,GAAU,SAAU,OAC/B,IAAMC,EAAQD,EAAM,KAAK,EACnBE,EAAQ,2FAA2F,KAAKD,CAAK,EACnH,GAAI,CAACC,EAAO,OACZ,GAAM,EAAGC,EAAUC,EAAWC,EAASC,EAAUC,EAAYC,EAAYC,EAAUC,GAAQR,EACrFS,EAAO,OAAOR,CAAQ,EACtBS,EAAQ,OAAOR,CAAS,EACxBS,EAAM,OAAOR,CAAO,EACpBS,kBAAQ,IAAI,KAAK,CAAC,EAExB,GADAA,EAAM,eAAeH,EAAMC,EAAQ,EAAGC,CAAG,EACrCC,EAAM,eAAe,IAAMH,GAAQG,EAAM,YAAY,IAAMF,EAAQ,GAAKE,EAAM,WAAW,IAAMD,EACjG,OAEF,GAAIP,IAAa,IAAA,GAAW,MAAO,CAAE,KAAM,OAAQ,OAAM,EACzD,IAAMS,EAAO,OAAOT,CAAQ,EACtBU,EAAS,OAAOT,CAAU,EAC1BU,EAAS,OAAOT,GAAc,CAAC,EACrC,GAAIO,EAAO,IAAMC,EAAS,IAAMC,EAAS,GAAI,OAC7C,IAAMC,EAASC,EAAYT,CAAK,EAChC,GAAIQ,IAAW,IAAA,KACfJ,EAAM,YAAYC,EAAMC,EAASE,EAAQD,CAAM,EAC3C,IAAM,eAAe,EAAI,GAAKH,EAAM,eAAe,EAAI,OAC3D,MAAO,CAAE,KAAM,WAAY,MAAO,GAAGA,EAAM,YAAY,CAAC,CAAC,MAAM,EAAG,EAAE,IAAIL,GAAY,GAAG,EAAG,CAC5F,CAEA,SAASU,EAAY,EAAkC,CACrD,GAAIT,IAAS,IAAK,MAAO,GACzB,IAAMU,EAASV,EAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,IAAK,EAAE,EACtCW,EAAQ,OAAOD,EAAO,MAAM,EAAG,CAAC,CAAC,EACjCE,EAAU,OAAOF,EAAO,MAAM,CAAC,CAAC,EACtC,GAAI,IAAQ,IAAME,EAAU,IAAOZ,EAAK,WAAW,GAAG,GAAKW,IAAU,GAAKC,IAAY,GACtF,OAAQZ,EAAK,WAAW,GAAG,EAAI,GAAK,IAAMW,EAAQ,GAAKC,EACzD"}
package/dist/prompt.cjs CHANGED
@@ -1,17 +1,17 @@
1
- "use strict";const e=require("./text.cjs"),t=/^(?:~|[Nn]ull|NULL|[Tt]rue|TRUE|[Ff]alse|FALSE|0o[0-7]+|[-+]?[0-9]+|0x[0-9a-fA-F]+|[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN|[-+]?(?:\.[0-9]+|[0-9]+(?:\.[0-9]*)?)[eE][-+]?[0-9]+|[-+]?(?:\.[0-9]+|[0-9]+\.[0-9]*))?$/u,n=/^(?:[\t ,[\]{}#&*!|>'"%@`]|[?-](?:[ \t]|$))/u,r=/:[ \t]|[ \t]#/u,i=/[\t :]$/u,a={"0000":String.raw`\0`,"0007":String.raw`\a`,"000b":String.raw`\v`,"001b":String.raw`\e`};function o(t){return e.toTildeCodeBlock(`${b(S(t),{indent:``})}\n`,`yaml`)}function s(t,n){let r=(typeof n==`string`?[n]:n).flatMap(l);return e.toTildeCodeBlock(`${b(S(t),{indent:``,tagPatterns:r})}\n`,`yaml`)}function c(e,t){return e.includes(`<`)?u(e,l(t)):e}function l(t){let n=e.escapeRegExp(t);return[RegExp(`<\\s*(?:(/)\\s*)?(${n})\\s*>`,`giu`),RegExp(`<\\s*(?:(/)\\s*)?(${n})(?![\\w-])`,`giu`)]}function u(e,t){if(!e.includes(`<`))return e;for(let n of t)e=e.replaceAll(n,`[$1$2]`);return e}const d=/^[ \t]*((`{3,}|~{3,})[^\n]*)$/u,f=/[^\s~][ \t]*~{3,}yaml[ \t]*$/u;function p(e){let t=e.split(`
1
+ "use strict";const e=require("./text.cjs"),t=/^(?:~|[Nn]ull|NULL|[Tt]rue|TRUE|[Ff]alse|FALSE|0o[0-7]+|[-+]?[0-9]+|0x[0-9a-fA-F]+|[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN|[-+]?(?:\.[0-9]+|[0-9]+(?:\.[0-9]*)?)[eE][-+]?[0-9]+|[-+]?(?:\.[0-9]+|[0-9]+\.[0-9]*))?$/u,n=/^(?:[\t ,[\]{}#&*!|>'"%@`]|[?-](?:[ \t]|$))/u,r=/:[ \t]|[ \t]#/u,i=/[\t :]$/u,a={"0000":String.raw`\0`,"0007":String.raw`\a`,"000b":String.raw`\v`,"001b":String.raw`\e`};function o(t){return e.toTildeCodeBlock(`${b(E(t),{indent:``})}\n`,`yaml`)}function s(t,n){let r=(typeof n==`string`?[n]:n).flatMap(l);return e.toTildeCodeBlock(`${b(E(t),{indent:``,tagPatterns:r})}\n`,`yaml`)}function c(e,t){return e.includes(`<`)?u(e,l(t)):e}function l(t){let n=e.escapeRegExp(t);return[RegExp(`<\\s*(?:(/)\\s*)?(${n})\\s*>`,`giu`),RegExp(`<\\s*(?:(/)\\s*)?(${n})(?![\\w-])`,`giu`)]}function u(e,t){if(!e.includes(`<`))return e;for(let n of t)e=e.replaceAll(n,`[$1$2]`);return e}const d=/^[ \t]*((`{3,}|~{3,})[^\n]*)$/u,f=/[^\s~][ \t]*~{3,}yaml[ \t]*$/u;function p(e){let t=e.split(`
2
2
  `),n=m(t),r=``,i=``;for(let e=0;e<t.length;e++){let a=t[e]??``,o=n[e];if(o===void 0){if(f.test(a))throw TypeError(`Interpolate a serializeForPrompt block at the start of a line`);i+=`${a}\n`;continue}let s=t.slice(e+1,o.end+1);s[s.length-1]=s.at(-1)?.trimStart()??``,r+=`${_(i)}${o.opener}\n${s.join(`
3
3
  `)}`,i=`
4
4
  `,e=o.end}return(r+_(i)).trim()}function m(e){let t=[],n=/* @__PURE__ */ new Map,r=[],i=[];for(let a=e.length-1;a>=0;a--){let o=d.exec(e[a]??``),s=o?.[1]?.trimEnd(),c=o?.[2];if(s===void 0||c===void 0)continue;let l=c[0]==="`"?r:i,u=0,f=l.length;for(;u<f;){let e=u+f>>>1;(l[e]?.length??0)>=c.length?u=e+1:f=e}let p=l[u-1]?.index??-1;if(/^(?:[ \t].*)?$/u.test((o?.[1]??``).slice(c.length))){for(;l.length>0&&(l.at(-1)?.length??0)<=c.length;)l.pop();l.push({length:c.length,index:a})}let m=n.get(c[0]??``);p!==-1&&m!==void 0&&h(m,p)>c.length&&(p=-1),p!==-1&&(t[a]={opener:s,end:p},m===void 0&&(m=new Uint32Array(e.length*2),n.set(c[0]??``,m)),g(m,a+1,p,c.length))}return t}function h(e,t){let n=0;for(let r=t+e.length/2;r>0;r>>>=1)n=Math.max(n,e[r]??0);return n}function g(e,t,n,r){let i=t+e.length/2,a=n+e.length/2;for(;i<=a;)i%2==1&&(e[i]=Math.max(e[i]??0,r),i++),a%2==0&&(e[a]=Math.max(e[a]??0,r),a--),i>>>=1,a>>>=1}function _(e){return e.replaceAll(/\n\s+("""|'''|```|~{3,})|\n\s*/gu,v).replaceAll(/\n\s+(#+\s)|\n\s*/gu,v).replaceAll(/(?<!\s)\s*\n\s*\n/gu,`
5
5
 
6
- `)}function v(e,t){return t===void 0?e:`\n${t}`}function y(t,n){return t.length<=n?t:`${e.sliceWithoutSplittingSurrogates(t,n)}\n...<truncated>`}function b(e,t){switch(typeof e){case`undefined`:return`null`;case`boolean`:return String(e);case`number`:return w(e);case`bigint`:return String(e);case`string`:return T(e,t);case`object`:{if(e===null)return`null`;let n=`\n${t.indent}`,r=``;if(Array.isArray(e)){if(e.length===0)return`[]`;let i={indent:t.indent+` `,tagPatterns:t.tagPatterns};for(let t of e)r+=`${r?n:``}- ${b(S(t),i)}`;return r}if(e instanceof Map){for(let[i,a]of e)a!==void 0&&(r+=`${r?n:``}${x(i,a,t)}`);return r||`{}`}let i=e;for(let e of Object.keys(i)){let a=i[e];a!==void 0&&(r+=`${r?n:``}${x(e,a,t)}`)}return r||`{}`}default:throw TypeError(`Cannot serialize a ${typeof e} value for a prompt`)}}function x(e,t,n){let r=n.indent+` `,i=S(e),a=S(t),o=b(i,{indent:r,implicitKey:!0,tagPatterns:n.tagPatterns}),s=b(a,{indent:r,tagPatterns:n.tagPatterns});return C(i)||o.length>1024?`? ${o}\n${n.indent}: ${s}`:`${o}:${C(a)&&s!==`[]`&&s!==`{}`?`\n${r}`:` `}${s}`}function S(e){let t=typeof e?.toJSON==`function`?e.toJSON():e;return typeof t!=`object`||!t||Array.isArray(t)||t instanceof Map?t:t instanceof String||t instanceof Number||t instanceof Boolean||t instanceof BigInt?t.valueOf():t instanceof Error?{name:t.name,message:t.message,...Object.fromEntries(Object.entries(t)),...`cause`in t&&{cause:t.cause},...t instanceof AggregateError&&{errors:t.errors}}:t instanceof RegExp?String(t):Symbol.iterator in t?[...t]:t}function C(e){return typeof e==`object`&&!!e}function w(e){return Number.isNaN(e)?`.nan`:Number.isFinite(e)?Object.is(e,-0)?`-0`:JSON.stringify(e):e<0?`-.inf`:`.inf`}function T(e,t){let n=t.tagPatterns===void 0?e:u(e,t.tagPatterns);return t.tagPatterns?.length&&/<\s*(?:\/\s*)?$/u.test(n)?A(n,t,!1):/[\u0000-\u0008\u000B-\u001F\u007F-\u009F\u{D800}-\u{DFFF}]/u.test(n)?A(n,t):E(n,t)}function E(e,a){let{implicitKey:o,indent:s}=a;if(e.includes(`
7
- `))return o?O(e,a):D(e,a);if(n.test(e)||i.test(e.slice(-1))||r.test(e))return O(e,a);if(j(e)){if(s===``)return D(e,a);if(o&&s===` `)return O(e,a)}return t.test(e)?O(e,a):e}function D(e,t){let n=e.length;for(;n>0&&N(e.codePointAt(n-1));)n--;let r=e.slice(n);if(r.includes(`
6
+ `)}function v(e,t){return t===void 0?e:`\n${t}`}function y(t,n){return t.length<=n?t:`${e.sliceWithoutSplittingSurrogates(t,n)}\n...<truncated>`}function b(e,t){switch(typeof e){case`undefined`:return`null`;case`boolean`:return String(e);case`number`:return O(e);case`bigint`:return String(e);case`string`:return k(e,t);case`object`:return x(e,t);default:throw TypeError(`Cannot serialize a ${typeof e} value for a prompt`)}}function x(e,t){return e===null?`null`:Array.isArray(e)?S(e,t):C(e instanceof Map?e:w(e),t)}function S(e,t){if(e.length===0)return`[]`;let n=`\n${t.indent}`,r={indent:t.indent+` `,tagPatterns:t.tagPatterns},i=``;for(let t of e)i+=`${i?n:``}- ${b(E(t),r)}`;return i}function C(e,t){let n=`\n${t.indent}`,r=``;for(let[i,a]of e)a!==void 0&&(r+=`${r?n:``}${T(i,a,t)}`);return r||`{}`}function*w(e){for(let t of Object.keys(e))yield[t,e[t]]}function T(e,t,n){let r=n.indent+` `,i=E(e),a=E(t),o=b(i,{indent:r,implicitKey:!0,tagPatterns:n.tagPatterns}),s=b(a,{indent:r,tagPatterns:n.tagPatterns});return D(i)||o.length>1024?`? ${o}\n${n.indent}: ${s}`:`${o}:${D(a)&&s!==`[]`&&s!==`{}`?`\n${r}`:` `}${s}`}function E(e){let t=typeof e?.toJSON==`function`?e.toJSON():e;return typeof t!=`object`||!t||Array.isArray(t)||t instanceof Map?t:t instanceof String||t instanceof Number||t instanceof Boolean||t instanceof BigInt?t.valueOf():t instanceof Error?{name:t.name,message:t.message,...Object.fromEntries(Object.entries(t)),...`cause`in t&&{cause:t.cause},...t instanceof AggregateError&&{errors:t.errors}}:t instanceof RegExp?String(t):Symbol.iterator in t?[...t]:t}function D(e){return typeof e==`object`&&!!e}function O(e){return Number.isNaN(e)?`.nan`:Number.isFinite(e)?Object.is(e,-0)?`-0`:JSON.stringify(e):e<0?`-.inf`:`.inf`}function k(e,t){let n=t.tagPatterns===void 0?e:u(e,t.tagPatterns);return t.tagPatterns?.length&&/<\s*(?:\/\s*)?$/u.test(n)?P(n,t,!1):/[\u0000-\u0008\u000B-\u001F\u007F-\u009F\u{D800}-\u{DFFF}]/u.test(n)?P(n,t):A(n,t)}function A(e,a){let{implicitKey:o,indent:s}=a;if(e.includes(`
7
+ `))return o?M(e,a):j(e,a);if(n.test(e)||i.test(e.slice(-1))||r.test(e))return M(e,a);if(F(e)){if(s===``)return j(e,a);if(o&&s===` `)return M(e,a)}return t.test(e)?M(e,a):e}function j(e,t){let n=e.length;for(;n>0&&L(e.codePointAt(n-1));)n--;let r=e.slice(n);if(r.includes(`
8
8
  `)&&!r.endsWith(`
9
- `))return O(e,t);let i=t.indent||(j(e)?` `:``),a=r.indexOf(`
9
+ `))return M(e,t);let i=t.indent||(F(e)?` `:``),a=r.indexOf(`
10
10
  `),o=a===-1?`-`:e===r||a!==r.length-1?`+`:``;r&&=(e=e.slice(0,-r.length),r.endsWith(`
11
11
  `)&&(r=r.slice(0,-1)),r.replaceAll(/(?:^|(?<!\n))\n+(?!\n|$)/gu,`$&${i}`));let s=/^[\n ]*/u.exec(e)?.[0]??``,c=s.includes(` `),l=e.slice(0,s.lastIndexOf(`
12
- `)+1);return l&&=(e=e.slice(l.length),l.replaceAll(/\n+/gu,`$&${i}`)),`|${(c?i?`2`:`1`:``)+o}\n${i}${l}${M(e,i)}${r}`}function O(e,t){return e.includes(`"`)&&!e.includes(`'`)?k(e,t):A(e,t)}function k(e,t){return e.includes(`
13
- `)?A(e,t):`'${e.replaceAll(`'`,`''`)}'`}function A(e,t,n=!t.implicitKey){let r=JSON.stringify(e),i=t.indent||(j(e)?` `:``),o=``,s=0;for(let e=0;e<r.length;e++){let t=r[e];if(t===` `&&r[e+1]===`\\`&&r[e+2]===`n`&&(o+=`${r.slice(s,e)}\\ `,e++,s=e,t=`\\`),t===`\\`){if(r[e+1]===`u`){let t=r.slice(e+2,e+6);o+=r.slice(s,e)+(a[t]??(t.startsWith(`00`)?`\\x${t.slice(2)}`:r.slice(e,e+6))),e+=5,s=e+1}else if(r[e+1]===`n`&&n&&r[e+2]!==`"`&&r.length>=40){for(o+=`${r.slice(s,e)}\n\n`;r[e+2]===`\\`&&r[e+3]===`n`&&r[e+4]!==`"`;)o+=`
14
- `,e+=2;o+=i,r[e+2]===` `&&(o+=`\\`),e++,s=e+1}else e++}}return s?o+r.slice(s):r}function j(e){return/^(?:%|---|\.\.\.)/mu.test(e)}function M(e,t){let n=e.split(`
12
+ `)+1);return l&&=(e=e.slice(l.length),l.replaceAll(/\n+/gu,`$&${i}`)),`|${(c?i?`2`:`1`:``)+o}\n${i}${l}${I(e,i)}${r}`}function M(e,t){return e.includes(`"`)&&!e.includes(`'`)?N(e,t):P(e,t)}function N(e,t){return e.includes(`
13
+ `)?P(e,t):`'${e.replaceAll(`'`,`''`)}'`}function P(e,t,n=!t.implicitKey){let r=JSON.stringify(e),i=t.indent||(F(e)?` `:``),o=``,s=0;for(let e=0;e<r.length;e++){let t=r[e];if(t===` `&&r[e+1]===`\\`&&r[e+2]===`n`&&(o+=`${r.slice(s,e)}\\ `,e++,s=e,t=`\\`),t===`\\`){if(r[e+1]===`u`){let t=r.slice(e+2,e+6);o+=r.slice(s,e)+(a[t]??(t.startsWith(`00`)?`\\x${t.slice(2)}`:r.slice(e,e+6))),e+=5,s=e+1}else if(r[e+1]===`n`&&n&&r[e+2]!==`"`&&r.length>=40){for(o+=`${r.slice(s,e)}\n\n`;r[e+2]===`\\`&&r[e+3]===`n`&&r[e+4]!==`"`;)o+=`
14
+ `,e+=2;o+=i,r[e+2]===` `&&(o+=`\\`),e++,s=e+1}else e++}}return s?o+r.slice(s):r}function F(e){return/^(?:%|---|\.\.\.)/mu.test(e)}function I(e,t){let n=e.split(`
15
15
  `),r=n[0]??``;for(let e=1;e<n.length;e++){let i=n[e];r+=i?`\n${t}${i}`:`
16
- `}return r}function N(e){return e===10||e===9||e===32}exports.escapePromptTag=c,exports.formatPrompt=p,exports.serializeForPrompt=o,exports.serializeForPromptInTag=s,exports.truncateForPrompt=y;
16
+ `}return r}function L(e){return e===10||e===9||e===32}exports.escapePromptTag=c,exports.formatPrompt=p,exports.serializeForPrompt=o,exports.serializeForPromptInTag=s,exports.truncateForPrompt=y;
17
17
  //# sourceMappingURL=prompt.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompt.cjs","names":["toTildeCodeBlock","escapeRegExp","sliceWithoutSplittingSurrogates"],"sources":["../src/prompt.ts"],"sourcesContent":["import { escapeRegExp, sliceWithoutSplittingSurrogates, toTildeCodeBlock } from './text.js';\n\nconst INDENT_STEP = ' ';\nconst MAX_IMPLICIT_KEY_LENGTH = 1024;\nconst MIN_MULTI_LINE_DOUBLE_QUOTED_LENGTH = 40;\n\n/** Strings matching this would be read back as a non-string scalar (null, bool, int, or float), so they must be quoted. */\nconst NON_STRING_SCALAR =\n /^(?:~|[Nn]ull|NULL|[Tt]rue|TRUE|[Ff]alse|FALSE|0o[0-7]+|[-+]?[0-9]+|0x[0-9a-fA-F]+|[-+]?\\.(?:inf|Inf|INF)|\\.nan|\\.NaN|\\.NAN|[-+]?(?:\\.[0-9]+|[0-9]+(?:\\.[0-9]*)?)[eE][-+]?[0-9]+|[-+]?(?:\\.[0-9]+|[0-9]+\\.[0-9]*))?$/u;\n\n// A single-line string must be quoted if it matches any of these. Checking the start, the middle, and the end separately\n// is much faster on long strings than one regex whose anchored alternatives are retried at every position.\nconst UNSAFE_PLAIN_START = /^(?:[\\t ,[\\]{}#&*!|>'\"%@`]|[?-](?:[ \\t]|$))/u;\nconst UNSAFE_PLAIN_MIDDLE = /:[ \\t]|[ \\t]#/u;\nconst UNSAFE_PLAIN_END = /[\\t :]$/u;\n\nconst SHORT_UNICODE_ESCAPES: Record<string, string> = {\n '0000': String.raw`\\0`,\n '0007': String.raw`\\a`,\n '000b': String.raw`\\v`,\n '001b': String.raw`\\e`,\n};\n\ninterface Context {\n indent: string;\n implicitKey?: boolean;\n tagPatterns?: readonly RegExp[];\n}\n\n/**\n * Serializes data into a code block to embed in an LLM prompt, so that the LLM can read its contents.\n * Accepts JSON data (honoring `toJSON` such as that of `Date`) as well as `undefined`, `NaN`, `Infinity`, bigints,\n * `Map`s (including non-string keys), `Set`s and other iterables, `Error`s (with their name, message, cause, and own properties),\n * and `RegExp`s. Symbols and functions without `toJSON` throw. The output is not meant to be deserialized back into the original value.\n * The format inside the code block is an implementation detail and may change.\n */\nexport function serializeForPrompt(value: unknown): string {\n return toTildeCodeBlock(`${stringifyValue(toSerializable(value), { indent: '' })}\\n`, 'yaml');\n}\n\n/**\n * Serializes data with `serializeForPrompt` for embedding inside a `<tagName>` element of a prompt, escaping that tag\n * in every string so that untrusted data cannot close the element and have the rest read as instructions.\n * The caller must wrap the result in the same tag.\n *\n * Only the named elements are protected, so a block nested inside other tagged elements takes every enclosing name.\n * Escaping the finished block instead is not an option: it would turn a plain scalar holding the escaped notation\n * into a YAML flow sequence, since the quoting of each scalar is decided as it is written.\n *\n * The escaped notation is the one `escapePromptTag` writes, and text that already holds it is left as it is, so two\n * strings differing only in that notation are written alike. Keys taken from untrusted data can therefore collide\n * into one duplicate key of the emitted mapping.\n */\nexport function serializeForPromptInTag(value: unknown, tagName: string | readonly string[]): string {\n const escapedTags = typeof tagName === 'string' ? [tagName] : tagName;\n const tagPatterns = escapedTags.flatMap(createTagPatterns);\n return toTildeCodeBlock(`${stringifyValue(toSerializable(value), { indent: '', tagPatterns })}\\n`, 'yaml');\n}\n\n/**\n * Replaces `<tagName` and `</tagName` not followed by `[\\w-]` with a harmless notation such as `[/tagName]`, so that\n * data embedded in a `<tagName>` element of a prompt cannot close the element and have the rest read as instructions.\n * A closing `>` is not required, since an HTML reader also closes an element on a tag carrying attribute-like junk,\n * on a trailing solidus, or on the next `>` anywhere in the prompt; the whitespace between `<` and the name is\n * dropped along with the brackets. Case is ignored deliberately: `tagName` is expected to be a literal written by\n * the caller, while the data is not.\n */\nexport function escapePromptTag(text: string, tagName: string): string {\n return text.includes('<') ? escapeTags(text, createTagPatterns(tagName)) : text;\n}\n\nfunction createTagPatterns(tagName: string): RegExp[] {\n const name = escapeRegExp(tagName);\n // Keep well-formed tags readable while also catching incomplete and malformed tags.\n return [\n new RegExp(`<\\\\s*(?:(/)\\\\s*)?(${name})\\\\s*>`, 'giu'),\n new RegExp(`<\\\\s*(?:(/)\\\\s*)?(${name})(?![\\\\w-])`, 'giu'),\n ];\n}\n\nfunction escapeTags(text: string, patterns: readonly RegExp[]): string {\n if (!text.includes('<')) return text;\n for (const pattern of patterns) text = text.replaceAll(pattern, '[$1$2]');\n return text;\n}\n\n/** The line opening a fenced block, with the indentation an interpolation may put before it. */\nconst BLOCK_OPENER = /^[ \\t]*((`{3,}|~{3,})[^\\n]*)$/u;\n\n/** A block interpolated after other text on its line, which no rule can tell from prose that ends in `~~~yaml`. */\nconst MISPLACED_BLOCK_OPENER = /[^\\s~][ \\t]*~{3,}yaml[ \\t]*$/u;\n\ninterface PromptBlock {\n opener: string;\n end: number;\n}\n\n/**\n * Strips template-literal indentation from Markdown headings, code fences, and triple-quote delimiters (`\"\"\"` and\n * `'''`), and collapses blank lines.\n * The contents of a fenced block are left untouched, since reindenting them would rewrite the data they carry, such\n * as the YAML of `serializeForPrompt` or the source of `toCodeBlock`. Every fenced block must be interpolated at\n * the start of a line. Only recognizable mid-line `~~~yaml` markers throw, including prose mentions;\n * this is not a complete placement validator, since preceding tildes can merge into an indistinguishable fence.\n * Blocks end at the first compatible same-character fence, which may carry trailing prose, unless a longer fence\n * of the same character opens and contains that candidate closing line. Other fence characters have no nesting\n * significance. Balance authored fences before interpolating blocks: an unmatched sample can consume part of a\n * later block and leave its tail subject to prose formatting.\n */\nexport function formatPrompt(prompt: string): string {\n const lines = prompt.split('\\n');\n const blocks = findBlocks(lines);\n let formatted = '';\n let prose = '';\n for (let index = 0; index < lines.length; index++) {\n const line = lines[index] ?? '';\n const block = blocks[index];\n if (block === undefined) {\n // An opening fence the prompt itself writes and never closes is prose, and so is every line inside a block.\n if (MISPLACED_BLOCK_OPENER.test(line)) {\n throw new TypeError('Interpolate a serializeForPrompt block at the start of a line');\n }\n prose += `${line}\\n`;\n continue;\n }\n // Dropping the opener's indentation keeps four spaces of it from turning the fence into an indented code block.\n const blockLines = lines.slice(index + 1, block.end + 1);\n blockLines[blockLines.length - 1] = blockLines.at(-1)?.trimStart() ?? '';\n formatted += `${dedentPromptMarkers(prose)}${block.opener}\\n${blockLines.join('\\n')}`;\n prose = '\\n';\n index = block.end;\n }\n return (formatted + dedentPromptMarkers(prose)).trim();\n}\n\nfunction findBlocks(lines: string[]): (PromptBlock | undefined)[] {\n const blocks: (PromptBlock | undefined)[] = [];\n const nestedFenceLengths = new Map<string, Uint32Array>();\n const backtickClosers: { length: number; index: number }[] = [];\n const tildeClosers: { length: number; index: number }[] = [];\n for (let index = lines.length - 1; index >= 0; index--) {\n const match = BLOCK_OPENER.exec(lines[index] ?? '');\n const opener = match?.[1]?.trimEnd();\n const fence = match?.[2];\n if (opener === undefined || fence === undefined) continue;\n const closers = fence[0] === '`' ? backtickClosers : tildeClosers;\n let low = 0;\n let high = closers.length;\n while (low < high) {\n const middle = (low + high) >>> 1;\n if ((closers[middle]?.length ?? 0) >= fence.length) low = middle + 1;\n else high = middle;\n }\n let end = closers[low - 1]?.index ?? -1;\n if (/^(?:[ \\t].*)?$/u.test((match?.[1] ?? '').slice(fence.length))) {\n // A nearer, longer closer also closes every fence that a shorter one could close.\n while (closers.length > 0 && (closers.at(-1)?.length ?? 0) <= fence.length) closers.pop();\n closers.push({ length: fence.length, index });\n }\n let lengths = nestedFenceLengths.get(fence[0] ?? '');\n if (end !== -1 && lengths !== undefined && maximumFenceLengthAt(lengths, end) > fence.length) end = -1;\n if (end !== -1) {\n blocks[index] = { opener, end };\n if (lengths === undefined) {\n lengths = new Uint32Array(lines.length * 2);\n nestedFenceLengths.set(fence[0] ?? '', lengths);\n }\n recordFenceLength(lengths, index + 1, end, fence.length);\n }\n }\n return blocks;\n}\n\nfunction maximumFenceLengthAt(lengths: Uint32Array, index: number): number {\n let maximum = 0;\n for (let node = index + lengths.length / 2; node > 0; node >>>= 1) {\n maximum = Math.max(maximum, lengths[node] ?? 0);\n }\n return maximum;\n}\n\nfunction recordFenceLength(lengths: Uint32Array, start: number, end: number, length: number): void {\n let left = start + lengths.length / 2;\n let right = end + lengths.length / 2;\n while (left <= right) {\n if (left % 2 === 1) {\n lengths[left] = Math.max(lengths[left] ?? 0, length);\n left++;\n }\n if (right % 2 === 0) {\n lengths[right] = Math.max(lengths[right] ?? 0, length);\n right--;\n }\n left >>>= 1;\n right >>>= 1;\n }\n}\n\nfunction dedentPromptMarkers(text: string): string {\n // Consume failed marker searches, and start blank-line searches only at whitespace-run boundaries.\n return text\n .replaceAll(/\\n\\s+(\"\"\"|'''|```|~{3,})|\\n\\s*/gu, replaceIndentedMarker)\n .replaceAll(/\\n\\s+(#+\\s)|\\n\\s*/gu, replaceIndentedMarker)\n .replaceAll(/(?<!\\s)\\s*\\n\\s*\\n/gu, '\\n\\n');\n}\n\nfunction replaceIndentedMarker(match: string, marker: string | undefined): string {\n return marker === undefined ? match : `\\n${marker}`;\n}\n\n/** Cuts text down to `maxLength` characters, marking it so that an LLM reads the rest as missing rather than absent. */\nexport function truncateForPrompt(text: string, maxLength: number): string {\n if (text.length <= maxLength) return text;\n return `${sliceWithoutSplittingSurrogates(text, maxLength)}\\n...<truncated>`;\n}\n\n// The functions below reproduce `stringify(value, { lineWidth: 0, aliasDuplicateObjects: false, blockQuote: 'literal' })`\n// of the `yaml` package, except that `toSerializable` makes `Error`s and `RegExp`s readable instead of `{}`.\n\nfunction stringifyValue(value: unknown, ctx: Context): string {\n switch (typeof value) {\n case 'undefined': {\n return 'null';\n }\n case 'boolean': {\n return String(value);\n }\n case 'number': {\n return stringifyNumber(value);\n }\n case 'bigint': {\n return String(value);\n }\n case 'string': {\n return stringifyString(value, ctx);\n }\n case 'object': {\n if (value === null) return 'null';\n const separator = `\\n${ctx.indent}`;\n let str = '';\n if (Array.isArray(value)) {\n if (value.length === 0) return '[]';\n const itemCtx = { indent: ctx.indent + INDENT_STEP, tagPatterns: ctx.tagPatterns };\n for (const item of value as unknown[]) {\n str += `${str ? separator : ''}- ${stringifyValue(toSerializable(item), itemCtx)}`;\n }\n return str;\n }\n if (value instanceof Map) {\n for (const [key, item] of value) {\n if (item !== undefined) str += `${str ? separator : ''}${stringifyPair(key, item, ctx)}`;\n }\n return str || '{}';\n }\n const record = value as Record<string, unknown>;\n for (const key of Object.keys(record)) {\n const item = record[key];\n if (item !== undefined) str += `${str ? separator : ''}${stringifyPair(key, item, ctx)}`;\n }\n return str || '{}';\n }\n default: {\n throw new TypeError(`Cannot serialize a ${typeof value} value for a prompt`);\n }\n }\n}\n\nfunction stringifyPair(rawKey: unknown, rawValue: unknown, ctx: Context): string {\n const indent = ctx.indent + INDENT_STEP;\n const key = toSerializable(rawKey);\n const value = toSerializable(rawValue);\n const keyStr = stringifyValue(key, { indent, implicitKey: true, tagPatterns: ctx.tagPatterns });\n const valueStr = stringifyValue(value, { indent, tagPatterns: ctx.tagPatterns });\n if (isCollection(key) || keyStr.length > MAX_IMPLICIT_KEY_LENGTH) return `? ${keyStr}\\n${ctx.indent}: ${valueStr}`;\n const isBlockCollection = isCollection(value) && valueStr !== '[]' && valueStr !== '{}';\n return `${keyStr}:${isBlockCollection ? `\\n${indent}` : ' '}${valueStr}`;\n}\n\nfunction toSerializable(rawValue: unknown): unknown {\n // Like `yaml`, call `toJSON` only once, but classify its result.\n const value =\n typeof (rawValue as { toJSON?: unknown } | null | undefined)?.toJSON === 'function'\n ? (rawValue as { toJSON: () => unknown }).toJSON()\n : rawValue;\n if (typeof value !== 'object' || value === null || Array.isArray(value) || value instanceof Map) return value;\n // oxlint-disable-next-line unicorn/no-instanceof-builtins -- boxed primitives have no typeof check; `yaml` unwraps them the same way.\n if (value instanceof String || value instanceof Number || value instanceof Boolean || value instanceof BigInt) {\n return value.valueOf();\n }\n if (value instanceof Error) {\n // `name` and `message` usually live on the prototype, and `cause` and `errors` are not enumerable.\n return {\n name: value.name,\n message: value.message,\n ...Object.fromEntries(Object.entries(value)),\n ...('cause' in value && { cause: value.cause }),\n ...(value instanceof AggregateError && { errors: value.errors }),\n };\n }\n if (value instanceof RegExp) return String(value);\n return Symbol.iterator in value ? [...(value as Iterable<unknown>)] : value;\n}\n\nfunction isCollection(value: unknown): value is object {\n return typeof value === 'object' && value !== null;\n}\n\nfunction stringifyNumber(value: number): string {\n if (Number.isNaN(value)) return '.nan';\n if (!Number.isFinite(value)) return value < 0 ? '-.inf' : '.inf';\n return Object.is(value, -0) ? '-0' : JSON.stringify(value);\n}\n\nfunction stringifyString(rawValue: string, ctx: Context): string {\n const value = ctx.tagPatterns === undefined ? rawValue : escapeTags(rawValue, ctx.tagPatterns);\n // A closing quote separates an unfinished tag prefix from the next mapping key.\n if (ctx.tagPatterns?.length && /<\\s*(?:\\/\\s*)?$/u.test(value)) return doubleQuotedString(value, ctx, false);\n // oxlint-disable-next-line no-control-regex -- control characters and lone surrogates can only be written escaped.\n return /[\\u0000-\\u0008\\u000B-\\u001F\\u007F-\\u009F\\u{D800}-\\u{DFFF}]/u.test(value)\n ? doubleQuotedString(value, ctx)\n : plainString(value, ctx);\n}\n\nfunction plainString(value: string, ctx: Context): string {\n const { implicitKey, indent } = ctx;\n if (value.includes('\\n')) return implicitKey ? quotedString(value, ctx) : blockString(value, ctx);\n if (UNSAFE_PLAIN_START.test(value) || UNSAFE_PLAIN_END.test(value.slice(-1)) || UNSAFE_PLAIN_MIDDLE.test(value)) {\n return quotedString(value, ctx);\n }\n if (containsDocumentMarker(value)) {\n if (indent === '') return blockString(value, ctx);\n if (implicitKey && indent === INDENT_STEP) return quotedString(value, ctx);\n }\n return NON_STRING_SCALAR.test(value) ? quotedString(value, ctx) : value;\n}\n\nfunction blockString(value: string, ctx: Context): string {\n let endStart = value.length;\n while (endStart > 0 && isBlockEndWhitespace(value.codePointAt(endStart - 1))) endStart--;\n let end = value.slice(endStart);\n // A block scalar cannot end with a whitespace-only line.\n if (end.includes('\\n') && !end.endsWith('\\n')) return quotedString(value, ctx);\n const indent = ctx.indent || (containsDocumentMarker(value) ? INDENT_STEP : '');\n\n const endNewlinePos = end.indexOf('\\n');\n const chomp = endNewlinePos === -1 ? '-' : value === end || endNewlinePos !== end.length - 1 ? '+' : '';\n if (end) {\n value = value.slice(0, -end.length);\n if (end.endsWith('\\n')) end = end.slice(0, -1);\n end = end.replaceAll(/(?:^|(?<!\\n))\\n+(?!\\n|$)/gu, `$&${indent}`);\n }\n\n const leadingWhitespace = /^[\\n ]*/u.exec(value)?.[0] ?? '';\n const startsWithSpace = leadingWhitespace.includes(' ');\n let start = value.slice(0, leadingWhitespace.lastIndexOf('\\n') + 1);\n if (start) {\n value = value.slice(start.length);\n start = start.replaceAll(/\\n+/gu, `$&${indent}`);\n }\n\n const header = (startsWithSpace ? (indent ? '2' : '1') : '') + chomp;\n return `|${header}\\n${indent}${start}${indentLines(value, indent)}${end}`;\n}\n\nfunction quotedString(value: string, ctx: Context): string {\n return value.includes('\"') && !value.includes(\"'\") ? singleQuotedString(value, ctx) : doubleQuotedString(value, ctx);\n}\n\nfunction singleQuotedString(value: string, ctx: Context): string {\n // Every multi-line value reaching here would contain a space or tab next to a newline or be an implicit key,\n // both of which need double quotes.\n if (value.includes('\\n')) return doubleQuotedString(value, ctx);\n return `'${value.replaceAll(\"'\", \"''\")}'`;\n}\n\nfunction doubleQuotedString(value: string, ctx: Context, foldMultiline = !ctx.implicitKey): string {\n const json = JSON.stringify(value);\n const indent = ctx.indent || (containsDocumentMarker(value) ? INDENT_STEP : '');\n let str = '';\n let start = 0;\n for (let i = 0; i < json.length; i++) {\n let ch = json[i];\n if (ch === ' ' && json[i + 1] === '\\\\' && json[i + 2] === 'n') {\n // A space before a line break would be folded away unless escaped.\n str += `${json.slice(start, i)}\\\\ `;\n i++;\n start = i;\n ch = '\\\\';\n }\n if (ch !== '\\\\') continue;\n if (json[i + 1] === 'u') {\n const code = json.slice(i + 2, i + 6);\n str +=\n json.slice(start, i) +\n (SHORT_UNICODE_ESCAPES[code] ?? (code.startsWith('00') ? `\\\\x${code.slice(2)}` : json.slice(i, i + 6)));\n i += 5;\n start = i + 1;\n } else if (\n json[i + 1] === 'n' &&\n foldMultiline &&\n json[i + 2] !== '\"' &&\n json.length >= MIN_MULTI_LINE_DOUBLE_QUOTED_LENGTH\n ) {\n // Folding turns the first of the written line breaks back into a space, hence the extra one.\n str += `${json.slice(start, i)}\\n\\n`;\n while (json[i + 2] === '\\\\' && json[i + 3] === 'n' && json[i + 4] !== '\"') {\n str += '\\n';\n i += 2;\n }\n str += indent;\n // A space after a line break would be folded away unless escaped.\n if (json[i + 2] === ' ') str += '\\\\';\n i++;\n start = i + 1;\n } else {\n i++;\n }\n }\n return start ? str + json.slice(start) : json;\n}\n\nfunction containsDocumentMarker(value: string): boolean {\n return /^(?:%|---|\\.\\.\\.)/mu.test(value);\n}\n\n/** Equivalent to `text.replaceAll(/\\n+/g, `$&${indent}`)` for text without leading or trailing newlines, but faster. */\nfunction indentLines(text: string, indent: string): string {\n const lines = text.split('\\n');\n let str = lines[0] ?? '';\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i];\n str += line ? `\\n${indent}${line}` : '\\n';\n }\n return str;\n}\n\nfunction isBlockEndWhitespace(codePoint: number | undefined): boolean {\n return codePoint === 0x0A || codePoint === 0x09 || codePoint === 0x20;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"prompt.cjs","names":["toTildeCodeBlock","escapeRegExp","sliceWithoutSplittingSurrogates","require_text","NON_STRING_SCALAR","UNSAFE_PLAIN_START","UNSAFE_PLAIN_MIDDLE","UNSAFE_PLAIN_END","SHORT_UNICODE_ESCAPES","serializeForPrompt","stringifyValue","toSerializable","value","serializeForPromptInTag","tagPatterns","tagName","createTagPatterns","escapePromptTag","text","escapeTags","name","pattern","patterns","BLOCK_OPENER","MISPLACED_BLOCK_OPENER","formatPrompt","lines","prompt","blocks","findBlocks","formatted","prose","index","line","block","blockLines","dedentPromptMarkers","nestedFenceLengths","backtickClosers","tildeClosers","match","opener","fence","closers","low","high","middle","end","lengths","maximumFenceLengthAt","recordFenceLength","maximum","node","left","start","right","length","replaceIndentedMarker","marker","truncateForPrompt","maxLength","stringifyNumber","stringifyString","ctx","stringifyObject","stringifyArray","stringifyEntries","lazyEntries","separator","itemCtx","str","item","key","entries","stringifyPair","record","indent","rawKey","rawValue","keyStr","valueStr","isCollection","doubleQuotedString","plainString","implicitKey","quotedString","blockString","containsDocumentMarker","endStart","isBlockEndWhitespace","endNewlinePos","chomp","leadingWhitespace","startsWithSpace","indentLines","singleQuotedString","json","i","ch","code","foldMultiline","codePoint"],"sources":["../src/prompt.ts"],"sourcesContent":["import { escapeRegExp, sliceWithoutSplittingSurrogates, toTildeCodeBlock } from './text.js';\n\nconst INDENT_STEP = ' ';\nconst MAX_IMPLICIT_KEY_LENGTH = 1024;\nconst MIN_MULTI_LINE_DOUBLE_QUOTED_LENGTH = 40;\n\n/** Strings matching this would be read back as a non-string scalar (null, bool, int, or float), so they must be quoted. */\nconst NON_STRING_SCALAR =\n /^(?:~|[Nn]ull|NULL|[Tt]rue|TRUE|[Ff]alse|FALSE|0o[0-7]+|[-+]?[0-9]+|0x[0-9a-fA-F]+|[-+]?\\.(?:inf|Inf|INF)|\\.nan|\\.NaN|\\.NAN|[-+]?(?:\\.[0-9]+|[0-9]+(?:\\.[0-9]*)?)[eE][-+]?[0-9]+|[-+]?(?:\\.[0-9]+|[0-9]+\\.[0-9]*))?$/u;\n\n// A single-line string must be quoted if it matches any of these. Checking the start, the middle, and the end separately\n// is much faster on long strings than one regex whose anchored alternatives are retried at every position.\nconst UNSAFE_PLAIN_START = /^(?:[\\t ,[\\]{}#&*!|>'\"%@`]|[?-](?:[ \\t]|$))/u;\nconst UNSAFE_PLAIN_MIDDLE = /:[ \\t]|[ \\t]#/u;\nconst UNSAFE_PLAIN_END = /[\\t :]$/u;\n\nconst SHORT_UNICODE_ESCAPES: Record<string, string> = {\n '0000': String.raw`\\0`,\n '0007': String.raw`\\a`,\n '000b': String.raw`\\v`,\n '001b': String.raw`\\e`,\n};\n\ninterface Context {\n indent: string;\n implicitKey?: boolean;\n tagPatterns?: readonly RegExp[];\n}\n\n/**\n * Serializes data into a code block to embed in an LLM prompt, so that the LLM can read its contents.\n * Accepts JSON data (honoring `toJSON` such as that of `Date`) as well as `undefined`, `NaN`, `Infinity`, bigints,\n * `Map`s (including non-string keys), `Set`s and other iterables, `Error`s (with their name, message, cause, and own properties),\n * and `RegExp`s. Symbols and functions without `toJSON` throw. The output is not meant to be deserialized back into the original value.\n * The format inside the code block is an implementation detail and may change.\n */\nexport function serializeForPrompt(value: unknown): string {\n return toTildeCodeBlock(`${stringifyValue(toSerializable(value), { indent: '' })}\\n`, 'yaml');\n}\n\n/**\n * Serializes data with `serializeForPrompt` for embedding inside a `<tagName>` element of a prompt, escaping that tag\n * in every string so that untrusted data cannot close the element and have the rest read as instructions.\n * The caller must wrap the result in the same tag.\n *\n * Only the named elements are protected, so a block nested inside other tagged elements takes every enclosing name.\n * Escaping the finished block instead is not an option: it would turn a plain scalar holding the escaped notation\n * into a YAML flow sequence, since the quoting of each scalar is decided as it is written.\n *\n * The escaped notation is the one `escapePromptTag` writes, and text that already holds it is left as it is, so two\n * strings differing only in that notation are written alike. Keys taken from untrusted data can therefore collide\n * into one duplicate key of the emitted mapping.\n */\nexport function serializeForPromptInTag(value: unknown, tagName: string | readonly string[]): string {\n const escapedTags = typeof tagName === 'string' ? [tagName] : tagName;\n const tagPatterns = escapedTags.flatMap(createTagPatterns);\n return toTildeCodeBlock(`${stringifyValue(toSerializable(value), { indent: '', tagPatterns })}\\n`, 'yaml');\n}\n\n/**\n * Replaces `<tagName` and `</tagName` not followed by `[\\w-]` with a harmless notation such as `[/tagName]`, so that\n * data embedded in a `<tagName>` element of a prompt cannot close the element and have the rest read as instructions.\n * A closing `>` is not required, since an HTML reader also closes an element on a tag carrying attribute-like junk,\n * on a trailing solidus, or on the next `>` anywhere in the prompt; the whitespace between `<` and the name is\n * dropped along with the brackets. Case is ignored deliberately: `tagName` is expected to be a literal written by\n * the caller, while the data is not.\n */\nexport function escapePromptTag(text: string, tagName: string): string {\n return text.includes('<') ? escapeTags(text, createTagPatterns(tagName)) : text;\n}\n\nfunction createTagPatterns(tagName: string): RegExp[] {\n const name = escapeRegExp(tagName);\n // Keep well-formed tags readable while also catching incomplete and malformed tags.\n return [\n new RegExp(`<\\\\s*(?:(/)\\\\s*)?(${name})\\\\s*>`, 'giu'),\n new RegExp(`<\\\\s*(?:(/)\\\\s*)?(${name})(?![\\\\w-])`, 'giu'),\n ];\n}\n\nfunction escapeTags(text: string, patterns: readonly RegExp[]): string {\n if (!text.includes('<')) return text;\n for (const pattern of patterns) text = text.replaceAll(pattern, '[$1$2]');\n return text;\n}\n\n/** The line opening a fenced block, with the indentation an interpolation may put before it. */\nconst BLOCK_OPENER = /^[ \\t]*((`{3,}|~{3,})[^\\n]*)$/u;\n\n/** A block interpolated after other text on its line, which no rule can tell from prose that ends in `~~~yaml`. */\nconst MISPLACED_BLOCK_OPENER = /[^\\s~][ \\t]*~{3,}yaml[ \\t]*$/u;\n\ninterface PromptBlock {\n opener: string;\n end: number;\n}\n\n/**\n * Strips template-literal indentation from Markdown headings, code fences, and triple-quote delimiters (`\"\"\"` and\n * `'''`), and collapses blank lines.\n * The contents of a fenced block are left untouched, since reindenting them would rewrite the data they carry, such\n * as the YAML of `serializeForPrompt` or the source of `toCodeBlock`. Every fenced block must be interpolated at\n * the start of a line. Only recognizable mid-line `~~~yaml` markers throw, including prose mentions;\n * this is not a complete placement validator, since preceding tildes can merge into an indistinguishable fence.\n * Blocks end at the first compatible same-character fence, which may carry trailing prose, unless a longer fence\n * of the same character opens and contains that candidate closing line. Other fence characters have no nesting\n * significance. Balance authored fences before interpolating blocks: an unmatched sample can consume part of a\n * later block and leave its tail subject to prose formatting.\n */\nexport function formatPrompt(prompt: string): string {\n const lines = prompt.split('\\n');\n const blocks = findBlocks(lines);\n let formatted = '';\n let prose = '';\n for (let index = 0; index < lines.length; index++) {\n const line = lines[index] ?? '';\n const block = blocks[index];\n if (block === undefined) {\n // An opening fence the prompt itself writes and never closes is prose, and so is every line inside a block.\n if (MISPLACED_BLOCK_OPENER.test(line)) {\n throw new TypeError('Interpolate a serializeForPrompt block at the start of a line');\n }\n prose += `${line}\\n`;\n continue;\n }\n // Dropping the opener's indentation keeps four spaces of it from turning the fence into an indented code block.\n const blockLines = lines.slice(index + 1, block.end + 1);\n blockLines[blockLines.length - 1] = blockLines.at(-1)?.trimStart() ?? '';\n formatted += `${dedentPromptMarkers(prose)}${block.opener}\\n${blockLines.join('\\n')}`;\n prose = '\\n';\n index = block.end;\n }\n return (formatted + dedentPromptMarkers(prose)).trim();\n}\n\nfunction findBlocks(lines: string[]): (PromptBlock | undefined)[] {\n const blocks: (PromptBlock | undefined)[] = [];\n const nestedFenceLengths = new Map<string, Uint32Array>();\n const backtickClosers: { length: number; index: number }[] = [];\n const tildeClosers: { length: number; index: number }[] = [];\n for (let index = lines.length - 1; index >= 0; index--) {\n const match = BLOCK_OPENER.exec(lines[index] ?? '');\n const opener = match?.[1]?.trimEnd();\n const fence = match?.[2];\n if (opener === undefined || fence === undefined) continue;\n const closers = fence[0] === '`' ? backtickClosers : tildeClosers;\n let low = 0;\n let high = closers.length;\n while (low < high) {\n const middle = (low + high) >>> 1;\n if ((closers[middle]?.length ?? 0) >= fence.length) low = middle + 1;\n else high = middle;\n }\n let end = closers[low - 1]?.index ?? -1;\n if (/^(?:[ \\t].*)?$/u.test((match?.[1] ?? '').slice(fence.length))) {\n // A nearer, longer closer also closes every fence that a shorter one could close.\n while (closers.length > 0 && (closers.at(-1)?.length ?? 0) <= fence.length) closers.pop();\n closers.push({ length: fence.length, index });\n }\n let lengths = nestedFenceLengths.get(fence[0] ?? '');\n if (end !== -1 && lengths !== undefined && maximumFenceLengthAt(lengths, end) > fence.length) end = -1;\n if (end !== -1) {\n blocks[index] = { opener, end };\n if (lengths === undefined) {\n lengths = new Uint32Array(lines.length * 2);\n nestedFenceLengths.set(fence[0] ?? '', lengths);\n }\n recordFenceLength(lengths, index + 1, end, fence.length);\n }\n }\n return blocks;\n}\n\nfunction maximumFenceLengthAt(lengths: Uint32Array, index: number): number {\n let maximum = 0;\n for (let node = index + lengths.length / 2; node > 0; node >>>= 1) {\n maximum = Math.max(maximum, lengths[node] ?? 0);\n }\n return maximum;\n}\n\nfunction recordFenceLength(lengths: Uint32Array, start: number, end: number, length: number): void {\n let left = start + lengths.length / 2;\n let right = end + lengths.length / 2;\n while (left <= right) {\n if (left % 2 === 1) {\n lengths[left] = Math.max(lengths[left] ?? 0, length);\n left++;\n }\n if (right % 2 === 0) {\n lengths[right] = Math.max(lengths[right] ?? 0, length);\n right--;\n }\n left >>>= 1;\n right >>>= 1;\n }\n}\n\nfunction dedentPromptMarkers(text: string): string {\n // Consume failed marker searches, and start blank-line searches only at whitespace-run boundaries.\n return text\n .replaceAll(/\\n\\s+(\"\"\"|'''|```|~{3,})|\\n\\s*/gu, replaceIndentedMarker)\n .replaceAll(/\\n\\s+(#+\\s)|\\n\\s*/gu, replaceIndentedMarker)\n .replaceAll(/(?<!\\s)\\s*\\n\\s*\\n/gu, '\\n\\n');\n}\n\nfunction replaceIndentedMarker(match: string, marker: string | undefined): string {\n return marker === undefined ? match : `\\n${marker}`;\n}\n\n/** Cuts text down to `maxLength` characters, marking it so that an LLM reads the rest as missing rather than absent. */\nexport function truncateForPrompt(text: string, maxLength: number): string {\n if (text.length <= maxLength) return text;\n return `${sliceWithoutSplittingSurrogates(text, maxLength)}\\n...<truncated>`;\n}\n\n// The functions below reproduce `stringify(value, { lineWidth: 0, aliasDuplicateObjects: false, blockQuote: 'literal' })`\n// of the `yaml` package, except that `toSerializable` makes `Error`s and `RegExp`s readable instead of `{}`.\n\nfunction stringifyValue(value: unknown, ctx: Context): string {\n switch (typeof value) {\n case 'undefined': {\n return 'null';\n }\n case 'boolean': {\n return String(value);\n }\n case 'number': {\n return stringifyNumber(value);\n }\n case 'bigint': {\n return String(value);\n }\n case 'string': {\n return stringifyString(value, ctx);\n }\n case 'object': {\n return stringifyObject(value, ctx);\n }\n default: {\n throw new TypeError(`Cannot serialize a ${typeof value} value for a prompt`);\n }\n }\n}\n\nfunction stringifyObject(value: object | null, ctx: Context): string {\n if (value === null) return 'null';\n if (Array.isArray(value)) return stringifyArray(value, ctx);\n return stringifyEntries(value instanceof Map ? value : lazyEntries(value as Record<string, unknown>), ctx);\n}\n\nfunction stringifyArray(value: unknown[], ctx: Context): string {\n if (value.length === 0) return '[]';\n const separator = `\\n${ctx.indent}`;\n const itemCtx = { indent: ctx.indent + INDENT_STEP, tagPatterns: ctx.tagPatterns };\n let str = '';\n for (const item of value) {\n str += `${str ? separator : ''}- ${stringifyValue(toSerializable(item), itemCtx)}`;\n }\n return str;\n}\n\nfunction stringifyEntries(entries: Iterable<[unknown, unknown]>, ctx: Context): string {\n const separator = `\\n${ctx.indent}`;\n let str = '';\n for (const [key, item] of entries) {\n if (item !== undefined) str += `${str ? separator : ''}${stringifyPair(key, item, ctx)}`;\n }\n return str || '{}';\n}\n\n// Reads each property only when its turn comes, as serializing an earlier one may run a `toJSON` that mutates the record.\nfunction* lazyEntries(record: Record<string, unknown>): Generator<[unknown, unknown]> {\n for (const key of Object.keys(record)) yield [key, record[key]];\n}\n\nfunction stringifyPair(rawKey: unknown, rawValue: unknown, ctx: Context): string {\n const indent = ctx.indent + INDENT_STEP;\n const key = toSerializable(rawKey);\n const value = toSerializable(rawValue);\n const keyStr = stringifyValue(key, { indent, implicitKey: true, tagPatterns: ctx.tagPatterns });\n const valueStr = stringifyValue(value, { indent, tagPatterns: ctx.tagPatterns });\n if (isCollection(key) || keyStr.length > MAX_IMPLICIT_KEY_LENGTH) return `? ${keyStr}\\n${ctx.indent}: ${valueStr}`;\n const isBlockCollection = isCollection(value) && valueStr !== '[]' && valueStr !== '{}';\n return `${keyStr}:${isBlockCollection ? `\\n${indent}` : ' '}${valueStr}`;\n}\n\nfunction toSerializable(rawValue: unknown): unknown {\n // Like `yaml`, call `toJSON` only once, but classify its result.\n const value =\n typeof (rawValue as { toJSON?: unknown } | null | undefined)?.toJSON === 'function'\n ? (rawValue as { toJSON: () => unknown }).toJSON()\n : rawValue;\n if (typeof value !== 'object' || value === null || Array.isArray(value) || value instanceof Map) return value;\n // oxlint-disable-next-line unicorn/no-instanceof-builtins -- boxed primitives have no typeof check; `yaml` unwraps them the same way.\n if (value instanceof String || value instanceof Number || value instanceof Boolean || value instanceof BigInt) {\n return value.valueOf();\n }\n if (value instanceof Error) {\n // `name` and `message` usually live on the prototype, and `cause` and `errors` are not enumerable.\n return {\n name: value.name,\n message: value.message,\n ...Object.fromEntries(Object.entries(value)),\n ...('cause' in value && { cause: value.cause }),\n ...(value instanceof AggregateError && { errors: value.errors }),\n };\n }\n if (value instanceof RegExp) return String(value);\n return Symbol.iterator in value ? [...(value as Iterable<unknown>)] : value;\n}\n\nfunction isCollection(value: unknown): value is object {\n return typeof value === 'object' && value !== null;\n}\n\nfunction stringifyNumber(value: number): string {\n if (Number.isNaN(value)) return '.nan';\n if (!Number.isFinite(value)) return value < 0 ? '-.inf' : '.inf';\n return Object.is(value, -0) ? '-0' : JSON.stringify(value);\n}\n\nfunction stringifyString(rawValue: string, ctx: Context): string {\n const value = ctx.tagPatterns === undefined ? rawValue : escapeTags(rawValue, ctx.tagPatterns);\n // A closing quote separates an unfinished tag prefix from the next mapping key.\n if (ctx.tagPatterns?.length && /<\\s*(?:\\/\\s*)?$/u.test(value)) return doubleQuotedString(value, ctx, false);\n // oxlint-disable-next-line no-control-regex -- control characters and lone surrogates can only be written escaped.\n return /[\\u0000-\\u0008\\u000B-\\u001F\\u007F-\\u009F\\u{D800}-\\u{DFFF}]/u.test(value)\n ? doubleQuotedString(value, ctx)\n : plainString(value, ctx);\n}\n\nfunction plainString(value: string, ctx: Context): string {\n const { implicitKey, indent } = ctx;\n if (value.includes('\\n')) return implicitKey ? quotedString(value, ctx) : blockString(value, ctx);\n if (UNSAFE_PLAIN_START.test(value) || UNSAFE_PLAIN_END.test(value.slice(-1)) || UNSAFE_PLAIN_MIDDLE.test(value)) {\n return quotedString(value, ctx);\n }\n if (containsDocumentMarker(value)) {\n if (indent === '') return blockString(value, ctx);\n if (implicitKey && indent === INDENT_STEP) return quotedString(value, ctx);\n }\n return NON_STRING_SCALAR.test(value) ? quotedString(value, ctx) : value;\n}\n\nfunction blockString(value: string, ctx: Context): string {\n let endStart = value.length;\n while (endStart > 0 && isBlockEndWhitespace(value.codePointAt(endStart - 1))) endStart--;\n let end = value.slice(endStart);\n // A block scalar cannot end with a whitespace-only line.\n if (end.includes('\\n') && !end.endsWith('\\n')) return quotedString(value, ctx);\n const indent = ctx.indent || (containsDocumentMarker(value) ? INDENT_STEP : '');\n\n const endNewlinePos = end.indexOf('\\n');\n const chomp = endNewlinePos === -1 ? '-' : value === end || endNewlinePos !== end.length - 1 ? '+' : '';\n if (end) {\n value = value.slice(0, -end.length);\n if (end.endsWith('\\n')) end = end.slice(0, -1);\n end = end.replaceAll(/(?:^|(?<!\\n))\\n+(?!\\n|$)/gu, `$&${indent}`);\n }\n\n const leadingWhitespace = /^[\\n ]*/u.exec(value)?.[0] ?? '';\n const startsWithSpace = leadingWhitespace.includes(' ');\n let start = value.slice(0, leadingWhitespace.lastIndexOf('\\n') + 1);\n if (start) {\n value = value.slice(start.length);\n start = start.replaceAll(/\\n+/gu, `$&${indent}`);\n }\n\n const header = (startsWithSpace ? (indent ? '2' : '1') : '') + chomp;\n return `|${header}\\n${indent}${start}${indentLines(value, indent)}${end}`;\n}\n\nfunction quotedString(value: string, ctx: Context): string {\n return value.includes('\"') && !value.includes(\"'\") ? singleQuotedString(value, ctx) : doubleQuotedString(value, ctx);\n}\n\nfunction singleQuotedString(value: string, ctx: Context): string {\n // Every multi-line value reaching here would contain a space or tab next to a newline or be an implicit key,\n // both of which need double quotes.\n if (value.includes('\\n')) return doubleQuotedString(value, ctx);\n return `'${value.replaceAll(\"'\", \"''\")}'`;\n}\n\nfunction doubleQuotedString(value: string, ctx: Context, foldMultiline = !ctx.implicitKey): string {\n const json = JSON.stringify(value);\n const indent = ctx.indent || (containsDocumentMarker(value) ? INDENT_STEP : '');\n let str = '';\n let start = 0;\n for (let i = 0; i < json.length; i++) {\n let ch = json[i];\n if (ch === ' ' && json[i + 1] === '\\\\' && json[i + 2] === 'n') {\n // A space before a line break would be folded away unless escaped.\n str += `${json.slice(start, i)}\\\\ `;\n i++;\n start = i;\n ch = '\\\\';\n }\n if (ch !== '\\\\') continue;\n if (json[i + 1] === 'u') {\n const code = json.slice(i + 2, i + 6);\n str +=\n json.slice(start, i) +\n (SHORT_UNICODE_ESCAPES[code] ?? (code.startsWith('00') ? `\\\\x${code.slice(2)}` : json.slice(i, i + 6)));\n i += 5;\n start = i + 1;\n } else if (\n json[i + 1] === 'n' &&\n foldMultiline &&\n json[i + 2] !== '\"' &&\n json.length >= MIN_MULTI_LINE_DOUBLE_QUOTED_LENGTH\n ) {\n // Folding turns the first of the written line breaks back into a space, hence the extra one.\n str += `${json.slice(start, i)}\\n\\n`;\n while (json[i + 2] === '\\\\' && json[i + 3] === 'n' && json[i + 4] !== '\"') {\n str += '\\n';\n i += 2;\n }\n str += indent;\n // A space after a line break would be folded away unless escaped.\n if (json[i + 2] === ' ') str += '\\\\';\n i++;\n start = i + 1;\n } else {\n i++;\n }\n }\n return start ? str + json.slice(start) : json;\n}\n\nfunction containsDocumentMarker(value: string): boolean {\n return /^(?:%|---|\\.\\.\\.)/mu.test(value);\n}\n\n/** Equivalent to `text.replaceAll(/\\n+/g, `$&${indent}`)` for text without leading or trailing newlines, but faster. */\nfunction indentLines(text: string, indent: string): string {\n const lines = text.split('\\n');\n let str = lines[0] ?? '';\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i];\n str += line ? `\\n${indent}${line}` : '\\n';\n }\n return str;\n}\n\nfunction isBlockEndWhitespace(codePoint: number | undefined): boolean {\n return codePoint === 0x0A || codePoint === 0x09 || codePoint === 0x20;\n}\n"],"mappings":"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"}
package/dist/prompt.js CHANGED
@@ -1,17 +1,17 @@
1
- import{escapeRegExp as e,sliceWithoutSplittingSurrogates as t,toTildeCodeBlock as n}from"./text.js";const r=/^(?:~|[Nn]ull|NULL|[Tt]rue|TRUE|[Ff]alse|FALSE|0o[0-7]+|[-+]?[0-9]+|0x[0-9a-fA-F]+|[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN|[-+]?(?:\.[0-9]+|[0-9]+(?:\.[0-9]*)?)[eE][-+]?[0-9]+|[-+]?(?:\.[0-9]+|[0-9]+\.[0-9]*))?$/u,i=/^(?:[\t ,[\]{}#&*!|>'"%@`]|[?-](?:[ \t]|$))/u,a=/:[ \t]|[ \t]#/u,o=/[\t :]$/u,s={"0000":String.raw`\0`,"0007":String.raw`\a`,"000b":String.raw`\v`,"001b":String.raw`\e`};function c(e){return n(`${S(w(e),{indent:``})}\n`,`yaml`)}function l(e,t){let r=(typeof t==`string`?[t]:t).flatMap(d);return n(`${S(w(e),{indent:``,tagPatterns:r})}\n`,`yaml`)}function u(e,t){return e.includes(`<`)?f(e,d(t)):e}function d(t){let n=e(t);return[RegExp(`<\\s*(?:(/)\\s*)?(${n})\\s*>`,`giu`),RegExp(`<\\s*(?:(/)\\s*)?(${n})(?![\\w-])`,`giu`)]}function f(e,t){if(!e.includes(`<`))return e;for(let n of t)e=e.replaceAll(n,`[$1$2]`);return e}const p=/^[ \t]*((`{3,}|~{3,})[^\n]*)$/u,m=/[^\s~][ \t]*~{3,}yaml[ \t]*$/u;function h(e){let t=e.split(`
1
+ import{escapeRegExp as e,sliceWithoutSplittingSurrogates as t,toTildeCodeBlock as n}from"./text.js";const r=/^(?:~|[Nn]ull|NULL|[Tt]rue|TRUE|[Ff]alse|FALSE|0o[0-7]+|[-+]?[0-9]+|0x[0-9a-fA-F]+|[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN|[-+]?(?:\.[0-9]+|[0-9]+(?:\.[0-9]*)?)[eE][-+]?[0-9]+|[-+]?(?:\.[0-9]+|[0-9]+\.[0-9]*))?$/u,i=/^(?:[\t ,[\]{}#&*!|>'"%@`]|[?-](?:[ \t]|$))/u,a=/:[ \t]|[ \t]#/u,o=/[\t :]$/u,s={"0000":String.raw`\0`,"0007":String.raw`\a`,"000b":String.raw`\v`,"001b":String.raw`\e`};function c(e){return n(`${S(O(e),{indent:``})}\n`,`yaml`)}function l(e,t){let r=(typeof t==`string`?[t]:t).flatMap(d);return n(`${S(O(e),{indent:``,tagPatterns:r})}\n`,`yaml`)}function u(e,t){return e.includes(`<`)?f(e,d(t)):e}function d(t){let n=e(t);return[RegExp(`<\\s*(?:(/)\\s*)?(${n})\\s*>`,`giu`),RegExp(`<\\s*(?:(/)\\s*)?(${n})(?![\\w-])`,`giu`)]}function f(e,t){if(!e.includes(`<`))return e;for(let n of t)e=e.replaceAll(n,`[$1$2]`);return e}const p=/^[ \t]*((`{3,}|~{3,})[^\n]*)$/u,m=/[^\s~][ \t]*~{3,}yaml[ \t]*$/u;function h(e){let t=e.split(`
2
2
  `),n=g(t),r=``,i=``;for(let e=0;e<t.length;e++){let a=t[e]??``,o=n[e];if(o===void 0){if(m.test(a))throw TypeError(`Interpolate a serializeForPrompt block at the start of a line`);i+=`${a}\n`;continue}let s=t.slice(e+1,o.end+1);s[s.length-1]=s.at(-1)?.trimStart()??``,r+=`${y(i)}${o.opener}\n${s.join(`
3
3
  `)}`,i=`
4
4
  `,e=o.end}return(r+y(i)).trim()}function g(e){let t=[],n=/* @__PURE__ */ new Map,r=[],i=[];for(let a=e.length-1;a>=0;a--){let o=p.exec(e[a]??``),s=o?.[1]?.trimEnd(),c=o?.[2];if(s===void 0||c===void 0)continue;let l=c[0]==="`"?r:i,u=0,d=l.length;for(;u<d;){let e=u+d>>>1;(l[e]?.length??0)>=c.length?u=e+1:d=e}let f=l[u-1]?.index??-1;if(/^(?:[ \t].*)?$/u.test((o?.[1]??``).slice(c.length))){for(;l.length>0&&(l.at(-1)?.length??0)<=c.length;)l.pop();l.push({length:c.length,index:a})}let m=n.get(c[0]??``);f!==-1&&m!==void 0&&_(m,f)>c.length&&(f=-1),f!==-1&&(t[a]={opener:s,end:f},m===void 0&&(m=new Uint32Array(e.length*2),n.set(c[0]??``,m)),v(m,a+1,f,c.length))}return t}function _(e,t){let n=0;for(let r=t+e.length/2;r>0;r>>>=1)n=Math.max(n,e[r]??0);return n}function v(e,t,n,r){let i=t+e.length/2,a=n+e.length/2;for(;i<=a;)i%2==1&&(e[i]=Math.max(e[i]??0,r),i++),a%2==0&&(e[a]=Math.max(e[a]??0,r),a--),i>>>=1,a>>>=1}function y(e){return e.replaceAll(/\n\s+("""|'''|```|~{3,})|\n\s*/gu,b).replaceAll(/\n\s+(#+\s)|\n\s*/gu,b).replaceAll(/(?<!\s)\s*\n\s*\n/gu,`
5
5
 
6
- `)}function b(e,t){return t===void 0?e:`\n${t}`}function x(e,n){return e.length<=n?e:`${t(e,n)}\n...<truncated>`}function S(e,t){switch(typeof e){case`undefined`:return`null`;case`boolean`:return String(e);case`number`:return E(e);case`bigint`:return String(e);case`string`:return D(e,t);case`object`:{if(e===null)return`null`;let n=`\n${t.indent}`,r=``;if(Array.isArray(e)){if(e.length===0)return`[]`;let i={indent:t.indent+` `,tagPatterns:t.tagPatterns};for(let t of e)r+=`${r?n:``}- ${S(w(t),i)}`;return r}if(e instanceof Map){for(let[i,a]of e)a!==void 0&&(r+=`${r?n:``}${C(i,a,t)}`);return r||`{}`}let i=e;for(let e of Object.keys(i)){let a=i[e];a!==void 0&&(r+=`${r?n:``}${C(e,a,t)}`)}return r||`{}`}default:throw TypeError(`Cannot serialize a ${typeof e} value for a prompt`)}}function C(e,t,n){let r=n.indent+` `,i=w(e),a=w(t),o=S(i,{indent:r,implicitKey:!0,tagPatterns:n.tagPatterns}),s=S(a,{indent:r,tagPatterns:n.tagPatterns});return T(i)||o.length>1024?`? ${o}\n${n.indent}: ${s}`:`${o}:${T(a)&&s!==`[]`&&s!==`{}`?`\n${r}`:` `}${s}`}function w(e){let t=typeof e?.toJSON==`function`?e.toJSON():e;return typeof t!=`object`||!t||Array.isArray(t)||t instanceof Map?t:t instanceof String||t instanceof Number||t instanceof Boolean||t instanceof BigInt?t.valueOf():t instanceof Error?{name:t.name,message:t.message,...Object.fromEntries(Object.entries(t)),...`cause`in t&&{cause:t.cause},...t instanceof AggregateError&&{errors:t.errors}}:t instanceof RegExp?String(t):Symbol.iterator in t?[...t]:t}function T(e){return typeof e==`object`&&!!e}function E(e){return Number.isNaN(e)?`.nan`:Number.isFinite(e)?Object.is(e,-0)?`-0`:JSON.stringify(e):e<0?`-.inf`:`.inf`}function D(e,t){let n=t.tagPatterns===void 0?e:f(e,t.tagPatterns);return t.tagPatterns?.length&&/<\s*(?:\/\s*)?$/u.test(n)?M(n,t,!1):/[\u0000-\u0008\u000B-\u001F\u007F-\u009F\u{D800}-\u{DFFF}]/u.test(n)?M(n,t):O(n,t)}function O(e,t){let{implicitKey:n,indent:s}=t;if(e.includes(`
7
- `))return n?A(e,t):k(e,t);if(i.test(e)||o.test(e.slice(-1))||a.test(e))return A(e,t);if(N(e)){if(s===``)return k(e,t);if(n&&s===` `)return A(e,t)}return r.test(e)?A(e,t):e}function k(e,t){let n=e.length;for(;n>0&&F(e.codePointAt(n-1));)n--;let r=e.slice(n);if(r.includes(`
6
+ `)}function b(e,t){return t===void 0?e:`\n${t}`}function x(e,n){return e.length<=n?e:`${t(e,n)}\n...<truncated>`}function S(e,t){switch(typeof e){case`undefined`:return`null`;case`boolean`:return String(e);case`number`:return A(e);case`bigint`:return String(e);case`string`:return j(e,t);case`object`:return C(e,t);default:throw TypeError(`Cannot serialize a ${typeof e} value for a prompt`)}}function C(e,t){return e===null?`null`:Array.isArray(e)?w(e,t):T(e instanceof Map?e:E(e),t)}function w(e,t){if(e.length===0)return`[]`;let n=`\n${t.indent}`,r={indent:t.indent+` `,tagPatterns:t.tagPatterns},i=``;for(let t of e)i+=`${i?n:``}- ${S(O(t),r)}`;return i}function T(e,t){let n=`\n${t.indent}`,r=``;for(let[i,a]of e)a!==void 0&&(r+=`${r?n:``}${D(i,a,t)}`);return r||`{}`}function*E(e){for(let t of Object.keys(e))yield[t,e[t]]}function D(e,t,n){let r=n.indent+` `,i=O(e),a=O(t),o=S(i,{indent:r,implicitKey:!0,tagPatterns:n.tagPatterns}),s=S(a,{indent:r,tagPatterns:n.tagPatterns});return k(i)||o.length>1024?`? ${o}\n${n.indent}: ${s}`:`${o}:${k(a)&&s!==`[]`&&s!==`{}`?`\n${r}`:` `}${s}`}function O(e){let t=typeof e?.toJSON==`function`?e.toJSON():e;return typeof t!=`object`||!t||Array.isArray(t)||t instanceof Map?t:t instanceof String||t instanceof Number||t instanceof Boolean||t instanceof BigInt?t.valueOf():t instanceof Error?{name:t.name,message:t.message,...Object.fromEntries(Object.entries(t)),...`cause`in t&&{cause:t.cause},...t instanceof AggregateError&&{errors:t.errors}}:t instanceof RegExp?String(t):Symbol.iterator in t?[...t]:t}function k(e){return typeof e==`object`&&!!e}function A(e){return Number.isNaN(e)?`.nan`:Number.isFinite(e)?Object.is(e,-0)?`-0`:JSON.stringify(e):e<0?`-.inf`:`.inf`}function j(e,t){let n=t.tagPatterns===void 0?e:f(e,t.tagPatterns);return t.tagPatterns?.length&&/<\s*(?:\/\s*)?$/u.test(n)?I(n,t,!1):/[\u0000-\u0008\u000B-\u001F\u007F-\u009F\u{D800}-\u{DFFF}]/u.test(n)?I(n,t):M(n,t)}function M(e,t){let{implicitKey:n,indent:s}=t;if(e.includes(`
7
+ `))return n?P(e,t):N(e,t);if(i.test(e)||o.test(e.slice(-1))||a.test(e))return P(e,t);if(L(e)){if(s===``)return N(e,t);if(n&&s===` `)return P(e,t)}return r.test(e)?P(e,t):e}function N(e,t){let n=e.length;for(;n>0&&z(e.codePointAt(n-1));)n--;let r=e.slice(n);if(r.includes(`
8
8
  `)&&!r.endsWith(`
9
- `))return A(e,t);let i=t.indent||(N(e)?` `:``),a=r.indexOf(`
9
+ `))return P(e,t);let i=t.indent||(L(e)?` `:``),a=r.indexOf(`
10
10
  `),o=a===-1?`-`:e===r||a!==r.length-1?`+`:``;r&&=(e=e.slice(0,-r.length),r.endsWith(`
11
11
  `)&&(r=r.slice(0,-1)),r.replaceAll(/(?:^|(?<!\n))\n+(?!\n|$)/gu,`$&${i}`));let s=/^[\n ]*/u.exec(e)?.[0]??``,c=s.includes(` `),l=e.slice(0,s.lastIndexOf(`
12
- `)+1);return l&&=(e=e.slice(l.length),l.replaceAll(/\n+/gu,`$&${i}`)),`|${(c?i?`2`:`1`:``)+o}\n${i}${l}${P(e,i)}${r}`}function A(e,t){return e.includes(`"`)&&!e.includes(`'`)?j(e,t):M(e,t)}function j(e,t){return e.includes(`
13
- `)?M(e,t):`'${e.replaceAll(`'`,`''`)}'`}function M(e,t,n=!t.implicitKey){let r=JSON.stringify(e),i=t.indent||(N(e)?` `:``),a=``,o=0;for(let e=0;e<r.length;e++){let t=r[e];if(t===` `&&r[e+1]===`\\`&&r[e+2]===`n`&&(a+=`${r.slice(o,e)}\\ `,e++,o=e,t=`\\`),t===`\\`){if(r[e+1]===`u`){let t=r.slice(e+2,e+6);a+=r.slice(o,e)+(s[t]??(t.startsWith(`00`)?`\\x${t.slice(2)}`:r.slice(e,e+6))),e+=5,o=e+1}else if(r[e+1]===`n`&&n&&r[e+2]!==`"`&&r.length>=40){for(a+=`${r.slice(o,e)}\n\n`;r[e+2]===`\\`&&r[e+3]===`n`&&r[e+4]!==`"`;)a+=`
14
- `,e+=2;a+=i,r[e+2]===` `&&(a+=`\\`),e++,o=e+1}else e++}}return o?a+r.slice(o):r}function N(e){return/^(?:%|---|\.\.\.)/mu.test(e)}function P(e,t){let n=e.split(`
12
+ `)+1);return l&&=(e=e.slice(l.length),l.replaceAll(/\n+/gu,`$&${i}`)),`|${(c?i?`2`:`1`:``)+o}\n${i}${l}${R(e,i)}${r}`}function P(e,t){return e.includes(`"`)&&!e.includes(`'`)?F(e,t):I(e,t)}function F(e,t){return e.includes(`
13
+ `)?I(e,t):`'${e.replaceAll(`'`,`''`)}'`}function I(e,t,n=!t.implicitKey){let r=JSON.stringify(e),i=t.indent||(L(e)?` `:``),a=``,o=0;for(let e=0;e<r.length;e++){let t=r[e];if(t===` `&&r[e+1]===`\\`&&r[e+2]===`n`&&(a+=`${r.slice(o,e)}\\ `,e++,o=e,t=`\\`),t===`\\`){if(r[e+1]===`u`){let t=r.slice(e+2,e+6);a+=r.slice(o,e)+(s[t]??(t.startsWith(`00`)?`\\x${t.slice(2)}`:r.slice(e,e+6))),e+=5,o=e+1}else if(r[e+1]===`n`&&n&&r[e+2]!==`"`&&r.length>=40){for(a+=`${r.slice(o,e)}\n\n`;r[e+2]===`\\`&&r[e+3]===`n`&&r[e+4]!==`"`;)a+=`
14
+ `,e+=2;a+=i,r[e+2]===` `&&(a+=`\\`),e++,o=e+1}else e++}}return o?a+r.slice(o):r}function L(e){return/^(?:%|---|\.\.\.)/mu.test(e)}function R(e,t){let n=e.split(`
15
15
  `),r=n[0]??``;for(let e=1;e<n.length;e++){let i=n[e];r+=i?`\n${t}${i}`:`
16
- `}return r}function F(e){return e===10||e===9||e===32}export{u as escapePromptTag,h as formatPrompt,c as serializeForPrompt,l as serializeForPromptInTag,x as truncateForPrompt};
16
+ `}return r}function z(e){return e===10||e===9||e===32}export{u as escapePromptTag,h as formatPrompt,c as serializeForPrompt,l as serializeForPromptInTag,x as truncateForPrompt};
17
17
  //# sourceMappingURL=prompt.js.map