markdown-to-jsx 9.5.1 → 9.5.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.
- package/dist/html.cjs +95 -96
- package/dist/html.js +95 -96
- package/dist/html.js.map +5 -5
- package/dist/index.cjs +100 -101
- package/dist/index.js +100 -101
- package/dist/index.js.map +5 -5
- package/dist/markdown.cjs +113 -114
- package/dist/markdown.js +113 -114
- package/dist/markdown.js.map +5 -5
- package/dist/native.cjs +99 -100
- package/dist/native.js +99 -100
- package/dist/native.js.map +5 -5
- package/dist/react.cjs +100 -101
- package/dist/react.js +100 -101
- package/dist/react.js.map +5 -5
- package/dist/solid.cjs +99 -100
- package/dist/solid.js +99 -100
- package/dist/solid.js.map +5 -5
- package/dist/vue.cjs +98 -99
- package/dist/vue.js +98 -99
- package/dist/vue.js.map +5 -5
- package/package.json +1 -1
package/dist/html.js.map
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["src/constants.ts", "src/types.ts", "src/utils.ts", "src/parse.ts", "src/html.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"// Character codes\nexport const CHAR_SPACE = 32\nexport const CHAR_TAB = 9\nexport const CHAR_CR = 13\nexport const CHAR_NEWLINE = 10\nexport const CHAR_BACKTICK = 96\nexport const CHAR_TILDE = 126\nexport const CHAR_BRACKET_OPEN = 91\nexport const CHAR_CARET = 94\nexport const CHAR_GT = 62\nexport const CHAR_HASH = 35\nexport const CHAR_PERCENT = 37\nexport const CHAR_DASH = 45\nexport const CHAR_EQ = 61\nexport const CHAR_BACKSLASH = 92\nexport const CHAR_ASTERISK = 42\nexport const CHAR_UNDERSCORE = 95\nexport const CHAR_LT = 60\nexport const CHAR_AT = 64\nexport const CHAR_BRACKET_CLOSE = 93\nexport const CHAR_EXCLAMATION = 33\nexport const CHAR_AMPERSAND = 38\nexport const CHAR_COLON = 58\nexport const CHAR_F = 70\nexport const CHAR_f = 102\nexport const CHAR_H = 104\nexport const CHAR_W = 119\nexport const CHAR_t = 116\nexport const CHAR_p = 112\nexport const CHAR_s = 115\nexport const CHAR_NBSP = 160\nexport const CHAR_FF = 12\nexport const CHAR_COMMA = 44\nexport const CHAR_SEMICOLON = 59\nexport const CHAR_QUESTION = 63\nexport const CHAR_PERIOD = 46\nexport const CHAR_SLASH = 47\nexport const CHAR_SINGLE_QUOTE = 39\nexport const CHAR_DOUBLE_QUOTE = 34\nexport const CHAR_PLUS = 43\nexport const CHAR_PIPE = 124\nexport const CHAR_BRACE_OPEN = 123 // {\nexport const CHAR_BRACE_CLOSE = 125 // }\nexport const CHAR_x = 120\nexport const CHAR_X = 88\n// Character code ranges for common character classes\nexport const CHAR_DIGIT_0 = 48\nexport const CHAR_DIGIT_9 = 57\nexport const CHAR_A = 65\nexport const CHAR_Z = 90\nexport const CHAR_a = 97\nexport const CHAR_z = 122\nexport const CHAR_ASCII_BOUNDARY = 128\n// Case conversion offset: difference between uppercase and lowercase ASCII letters\nexport const CHAR_CASE_OFFSET = 32 // 'A' (65) to 'a' (97) = 32\n",
|
|
5
|
+
"// Character codes\nexport const CHAR_SPACE = 32\nexport const CHAR_TAB = 9\nexport const CHAR_CR = 13\nexport const CHAR_NEWLINE = 10\nexport const CHAR_BACKTICK = 96\nexport const CHAR_TILDE = 126\nexport const CHAR_BRACKET_OPEN = 91\nexport const CHAR_CARET = 94\nexport const CHAR_GT = 62\nexport const CHAR_HASH = 35\nexport const CHAR_PERCENT = 37\nexport const CHAR_DASH = 45\nexport const CHAR_EQ = 61\nexport const CHAR_BACKSLASH = 92\nexport const CHAR_ASTERISK = 42\nexport const CHAR_UNDERSCORE = 95\nexport const CHAR_LT = 60\nexport const CHAR_AT = 64\nexport const CHAR_BRACKET_CLOSE = 93\nexport const CHAR_EXCLAMATION = 33\nexport const CHAR_AMPERSAND = 38\nexport const CHAR_COLON = 58\nexport const CHAR_F = 70\nexport const CHAR_f = 102\nexport const CHAR_H = 104\nexport const CHAR_W = 119\nexport const CHAR_t = 116\nexport const CHAR_p = 112\nexport const CHAR_s = 115\nexport const CHAR_NBSP = 160\nexport const CHAR_FF = 12\nexport const CHAR_COMMA = 44\nexport const CHAR_SEMICOLON = 59\nexport const CHAR_QUESTION = 63\nexport const CHAR_PERIOD = 46\nexport const CHAR_SLASH = 47\nexport const CHAR_SINGLE_QUOTE = 39\nexport const CHAR_DOUBLE_QUOTE = 34\nexport const CHAR_PLUS = 43\nexport const CHAR_PIPE = 124\nexport const CHAR_BRACE_OPEN = 123 // {\nexport const CHAR_BRACE_CLOSE = 125 // }\nexport const CHAR_PAREN_OPEN = 40 // (\nexport const CHAR_PAREN_CLOSE = 41 // )\nexport const CHAR_x = 120\nexport const CHAR_X = 88\n// Character code ranges for common character classes\nexport const CHAR_DIGIT_0 = 48\nexport const CHAR_DIGIT_9 = 57\nexport const CHAR_A = 65\nexport const CHAR_Z = 90\nexport const CHAR_a = 97\nexport const CHAR_z = 122\nexport const CHAR_ASCII_BOUNDARY = 128\n// Case conversion offset: difference between uppercase and lowercase ASCII letters\nexport const CHAR_CASE_OFFSET = 32 // 'A' (65) to 'a' (97) = 32\n",
|
|
6
6
|
"// Re-export React for convenience since types reference it\nimport * as React from 'react'\n\n/**\n * Analogous to `node.type`. Please note that the values here may change at any time,\n * so do not hard code against the value directly.\n */\nconst RuleTypeConst = {\n blockQuote: 0,\n breakLine: 1,\n breakThematic: 2,\n codeBlock: 3,\n codeInline: 4,\n footnote: 5,\n footnoteReference: 6,\n frontmatter: 7,\n gfmTask: 8,\n heading: 9,\n htmlBlock: 10,\n htmlComment: 11,\n htmlSelfClosing: 12,\n image: 13,\n link: 14,\n orderedList: 15,\n paragraph: 16,\n ref: 17,\n refCollection: 18,\n table: 19,\n text: 20,\n textFormatted: 21,\n unorderedList: 22,\n} as const\n\nif (process.env.NODE_ENV === 'test') {\n // In test mode, use strings for better debugging\n Object.keys(RuleTypeConst).forEach(key => (RuleTypeConst[key] = key))\n}\n\ntype RuleTypeValue = (typeof RuleTypeConst)[keyof typeof RuleTypeConst]\n\n/**\n * markdown-to-jsx types and interfaces\n * @lang zh markdown-to-jsx 类型和接口\n * @lang hi markdown-to-jsx प्रकार और इंटरफ़ेस\n */\ndeclare namespace MarkdownToJSX {\n /**\n * RequireAtLeastOne<{ ... }> <- only requires at least one key\n * @lang zh RequireAtLeastOne<{ ... }> <- 只需要至少一个键\n * @lang hi RequireAtLeastOne<{ ... }> <- केवल कम से कम एक कुंजी की आवश्यकता है\n */\n type RequireAtLeastOne<T, Keys extends keyof T = keyof T> = Pick<\n T,\n Exclude<keyof T, Keys>\n > &\n {\n [K in Keys]-?: Required<Pick<T, K>> & Partial<Pick<T, Exclude<Keys, K>>>\n }[Keys]\n\n /**\n * React.createElement function type\n * @lang zh React.createElement 函数类型\n * @lang hi React.createElement फ़ंक्शन प्रकार\n */\n export type CreateElement = typeof React.createElement\n\n /**\n * HTML tag names that can be used in JSX\n * @lang zh 可在 JSX 中使用的 HTML 标签名称\n * @lang hi HTML टैग नाम जो JSX में उपयोग किए जा सकते हैं\n */\n export type HTMLTags = keyof React.JSX.IntrinsicElements & (string & {})\n\n /**\n * Parser and renderer state\n * @lang zh 解析器和渲染器状态\n * @lang hi पार्सर और रेंडरर स्थिति\n */\n export type State = {\n /** true if the current content is inside anchor link grammar */\n /** @lang zh 如果当前内容在锚点链接语法内,则为 true */\n /** @lang hi true यदि वर्तमान सामग्री एंकर लिंक व्याकरण के अंदर है */\n inAnchor?: boolean\n /** true if inside a blockquote */\n /** @lang zh 如果在引用块内,则为 true */\n /** @lang hi true यदि ब्लॉककोट के अंदर है */\n inBlockQuote?: boolean\n /** true if parsing in an HTML context */\n /** @lang zh 如果在 HTML 上下文中解析,则为 true */\n /** @lang hi true यदि HTML संदर्भ में पार्स कर रहे हैं */\n inHTML?: boolean\n /** true if in a list */\n /** @lang zh 如果在列表中,则为 true */\n /** @lang hi true यदि सूची में है */\n inList?: boolean\n /** true if parsing in an inline context (subset of rules around formatting and links) */\n /** @lang zh 如果在内联上下文中解析(围绕格式和链接的规则子集),则为 true */\n /** @lang hi true यदि इनलाइन संदर्भ में पार्स कर रहे हैं (फ़ॉर्मेटिंग और लिंक के आसपास के नियमों का उपसमुच्चय) */\n inline?: boolean\n\n /** use this for the `key` prop */\n /** @lang zh 用于 `key` 属性 */\n /** @lang hi `key` prop के लिए इसका उपयोग करें */\n key?: string | number\n /** reference definitions (footnotes are stored with '^' prefix) */\n /** @lang zh 引用定义(脚注以 '^' 前缀存储) */\n /** @lang hi संदर्भ परिभाषाएं (फ़ुटनोट्स '^' उपसर्ग के साथ संग्रहीत हैं) */\n refs?: { [key: string]: { target: string; title: string | undefined } }\n /** current recursion depth during rendering */\n /** @lang zh 渲染期间的当前递归深度 */\n /** @lang hi रेंडरिंग के दौरान वर्तमान पुनरावृत्ति गहराई */\n renderDepth?: number\n }\n\n /**\n * Blockquote node in the AST\n * @lang zh AST 中的引用块节点\n * @lang hi AST में ब्लॉककोट नोड\n */\n export interface BlockQuoteNode {\n /** Optional alert type (Note, Tip, Warning, etc.) */\n /** @lang zh 可选的警告类型 (Note, Tip, Warning 等) */\n /** @lang hi वैकल्पिक अलर्ट प्रकार (Note, Tip, Warning, आदि) */\n alert?: string\n /** Child nodes within the blockquote */\n /** @lang zh 引用块中的子节点 */\n /** @lang hi ब्लॉककोट के भीतर चाइल्ड नोड्स */\n children: MarkdownToJSX.ASTNode[]\n type: typeof RuleType.blockQuote\n }\n\n /**\n * Hard line break node\n * @lang zh 硬换行节点\n * @lang hi हार्ड लाइन ब्रेक नोड\n */\n export interface BreakLineNode {\n type: typeof RuleType.breakLine\n }\n\n /**\n * Thematic break (horizontal rule) node\n * @lang zh 分隔线(水平线)节点\n * @lang hi थीमैटिक ब्रेक (क्षैतिज नियम) नोड\n */\n export interface BreakThematicNode {\n type: typeof RuleType.breakThematic\n }\n\n /**\n * Code block node (fenced code blocks)\n * @lang zh 代码块节点(围栏代码块)\n * @lang hi कोड ब्लॉक नोड (फ़ेंस्ड कोड ब्लॉक्स)\n */\n export interface CodeBlockNode {\n type: typeof RuleType.codeBlock\n /** HTML attributes for the code block */\n /** @lang zh 代码块的 HTML 属性 */\n /** @lang hi कोड ब्लॉक के लिए HTML एट्रिब्यूट्स */\n attrs?: React.JSX.IntrinsicAttributes\n /** Programming language identifier */\n /** @lang zh 编程语言标识符 */\n /** @lang hi प्रोग्रामिंग भाषा पहचानकर्ता */\n lang?: string\n /** Code content */\n /** @lang zh 代码内容 */\n /** @lang hi कोड सामग्री */\n text: string\n }\n\n /**\n * Inline code node\n * @lang zh 内联代码节点\n * @lang hi इनलाइन कोड नोड\n */\n export interface CodeInlineNode {\n type: typeof RuleType.codeInline\n /** Code text */\n /** @lang zh 代码文本 */\n /** @lang hi कोड टेक्स्ट */\n text: string\n }\n\n /**\n * Footnote definition node (not rendered, stored in refCollection)\n * @lang zh 脚注定义节点(不渲染,存储在 refCollection 中)\n * @lang hi फ़ुटनोट परिभाषा नोड (रेंडर नहीं किया गया, refCollection में संग्रहीत)\n */\n export interface FootnoteNode {\n type: typeof RuleType.footnote\n }\n\n /**\n * Footnote reference node\n * @lang zh 脚注引用节点\n * @lang hi फ़ुटनोट संदर्भ नोड\n */\n export interface FootnoteReferenceNode {\n type: typeof RuleType.footnoteReference\n /** Link target (anchor) */\n /** @lang zh 链接目标(锚点) */\n /** @lang hi लिंक लक्ष्य (एंकर) */\n target: string\n /** Display text */\n /** @lang zh 显示文本 */\n /** @lang hi प्रदर्शन टेक्स्ट */\n text: string\n }\n\n /**\n * YAML frontmatter node\n * @lang zh YAML 前置元数据节点\n * @lang hi YAML फ्रंटमैटर नोड\n */\n export interface FrontmatterNode {\n type: typeof RuleType.frontmatter\n /** Frontmatter content */\n /** @lang zh 前置元数据内容 */\n /** @lang hi फ्रंटमैटर सामग्री */\n text: string\n }\n\n /**\n * GFM task list item node\n * @lang zh GFM 任务列表项节点\n * @lang hi GFM टास्क लिस्ट आइटम नोड\n */\n export interface GFMTaskNode {\n type: typeof RuleType.gfmTask\n /** Whether the task is completed */\n /** @lang zh 任务是否已完成 */\n /** @lang hi क्या टास्क पूर्ण है */\n completed: boolean\n }\n\n /**\n * Heading node\n * @lang zh 标题节点\n * @lang hi हेडिंग नोड\n */\n export interface HeadingNode {\n type: typeof RuleType.heading\n /** Child nodes (text content) */\n /** @lang zh 子节点(文本内容) */\n /** @lang hi चाइल्ड नोड्स (टेक्स्ट सामग्री) */\n children: MarkdownToJSX.ASTNode[]\n /** Generated HTML ID for anchor linking */\n /** @lang zh 用于锚点链接的生成的 HTML ID */\n /** @lang hi एंकर लिंकिंग के लिए जेनरेट किया गया HTML ID */\n id: string\n /** Heading level (1-6) */\n /** @lang zh 标题级别 (1-6) */\n /** @lang hi हेडिंग स्तर (1-6) */\n level: 1 | 2 | 3 | 4 | 5 | 6\n }\n\n /**\n * HTML comment node\n * @lang zh HTML 注释节点\n * @lang hi HTML कमेंट नोड\n */\n export interface HTMLCommentNode {\n type: typeof RuleType.htmlComment\n /** Comment text */\n /** @lang zh 注释文本 */\n /** @lang hi कमेंट टेक्स्ट */\n text: string\n }\n\n /**\n * Image node\n * @lang zh 图像节点\n * @lang hi छवि नोड\n */\n export interface ImageNode {\n type: typeof RuleType.image\n /** Alt text */\n /** @lang zh 替代文本 */\n /** @lang hi Alt टेक्स्ट */\n alt?: string\n /** Image URL */\n /** @lang zh 图像 URL */\n /** @lang hi छवि URL */\n target: string\n /** Title attribute */\n /** @lang zh 标题属性 */\n /** @lang hi शीर्षक एट्रिब्यूट */\n title?: string\n }\n\n /**\n * Link node\n * @lang zh 链接节点\n * @lang hi लिंक नोड\n */\n export interface LinkNode {\n type: typeof RuleType.link\n /** Child nodes (link text) */\n /** @lang zh 子节点(链接文本) */\n /** @lang hi चाइल्ड नोड्स (लिंक टेक्स्ट) */\n children: MarkdownToJSX.ASTNode[]\n /** Link URL (null for reference links without definition) */\n /** @lang zh 链接 URL(对于没有定义的引用链接为 null) */\n /** @lang hi लिंक URL (परिभाषा के बिना संदर्भ लिंक के लिए null) */\n target: string | null\n /** Title attribute */\n /** @lang zh 标题属性 */\n /** @lang hi शीर्षक एट्रिब्यूट */\n title?: string\n }\n\n /**\n * Ordered list node\n * @lang zh 有序列表节点\n * @lang hi क्रमबद्ध सूची नोड\n */\n export interface OrderedListNode {\n type: typeof RuleType.orderedList\n /** Array of list items, each item is an array of nodes */\n /** @lang zh 列表项数组,每个项是节点数组 */\n /** @lang hi सूची आइटम्स की सरणी, प्रत्येक आइटम नोड्स की एक सरणी है */\n items: MarkdownToJSX.ASTNode[][]\n /** Starting number for the list */\n /** @lang zh 列表的起始编号 */\n /** @lang hi सूची के लिए प्रारंभिक संख्या */\n start?: number\n }\n\n /**\n * Unordered list node\n * @lang zh 无序列表节点\n * @lang hi अक्रमबद्ध सूची नोड\n */\n export interface UnorderedListNode {\n type: typeof RuleType.unorderedList\n /** Array of list items, each item is an array of nodes */\n /** @lang zh 列表项数组,每个项是节点数组 */\n /** @lang hi सूची आइटम्स की सरणी, प्रत्येक आइटम नोड्स की एक सरणी है */\n items: MarkdownToJSX.ASTNode[][]\n }\n\n /**\n * Paragraph node\n * @lang zh 段落节点\n * @lang hi पैराग्राफ नोड\n */\n export interface ParagraphNode {\n type: typeof RuleType.paragraph\n /** Child nodes */\n /** @lang zh 子节点 */\n /** @lang hi चाइल्ड नोड्स */\n children: MarkdownToJSX.ASTNode[]\n }\n\n /**\n * Reference definition node (not rendered, stored in refCollection)\n * @lang zh 引用定义节点(不渲染,存储在 refCollection 中)\n * @lang hi संदर्भ परिभाषा नोड (रेंडर नहीं किया गया, refCollection में संग्रहीत)\n */\n export interface ReferenceNode {\n type: typeof RuleType.ref\n }\n\n /**\n * Reference collection node (appears at AST root, includes footnotes with '^' prefix)\n * @lang zh 引用集合节点(出现在 AST 根部,包括以 '^' 前缀的脚注)\n * @lang hi संदर्भ संग्रह नोड (AST रूट पर दिखाई देता है, '^' उपसर्ग के साथ फ़ुटनोट्स शामिल हैं)\n */\n export interface ReferenceCollectionNode {\n type: typeof RuleType.refCollection\n /** Map of reference labels to their definitions */\n /** @lang zh 引用标签到其定义的映射 */\n /** @lang hi संदर्भ लेबल्स से उनकी परिभाषाओं का मैप */\n refs: { [key: string]: { target: string; title: string | undefined } }\n }\n\n /**\n * Table node\n * @lang zh 表格节点\n * @lang hi टेबल नोड\n */\n export interface TableNode {\n type: typeof RuleType.table\n /**\n * alignment for each table column\n * @lang zh 每个表格列的对齐方式\n * @lang hi प्रत्येक टेबल कॉलम के लिए संरेखण\n */\n align: ('left' | 'right' | 'center')[]\n /** Table cells (3D array: rows -> cells -> nodes) */\n /** @lang zh 表格单元格(三维数组:行 -> 单元格 -> 节点) */\n /** @lang hi टेबल सेल्स (3D सरणी: पंक्तियाँ -> सेल्स -> नोड्स) */\n cells: MarkdownToJSX.ASTNode[][][]\n /** Table header row */\n /** @lang zh 表格标题行 */\n /** @lang hi टेबल हेडर पंक्ति */\n header: MarkdownToJSX.ASTNode[][]\n }\n\n /**\n * Plain text node\n * @lang zh 纯文本节点\n * @lang hi सादा टेक्स्ट नोड\n */\n export interface TextNode {\n type: typeof RuleType.text\n /** Text content */\n /** @lang zh 文本内容 */\n /** @lang hi टेक्स्ट सामग्री */\n text: string\n }\n\n /**\n * Formatted text node (bold, italic, etc.)\n * @lang zh 格式化文本节点(加粗、斜体等)\n * @lang hi फ़ॉर्मेट किया गया टेक्स्ट नोड (बोल्ड, इटैलिक, आदि)\n */\n export interface FormattedTextNode {\n type: typeof RuleType.textFormatted\n /**\n * the corresponding html tag\n * @lang zh 对应的 HTML 标签\n * @lang hi संबंधित HTML टैग\n */\n tag: string\n /** Child nodes */\n /** @lang zh 子节点 */\n /** @lang hi चाइल्ड नोड्स */\n children: MarkdownToJSX.ASTNode[]\n }\n\n /**\n * HTML block node (includes JSX components)\n * @lang zh HTML 块节点(包括 JSX 组件)\n * @lang hi HTML ब्लॉक नोड (JSX कंपोनेंट्स शामिल हैं)\n */\n export interface HTMLNode {\n type: typeof RuleType.htmlBlock\n /** Parsed HTML attributes */\n /** @lang zh 解析后的 HTML 属性 */\n /** @lang hi पार्स किए गए HTML एट्रिब्यूट्स */\n attrs?: Record<string, any>\n /** Parsed child nodes (always parsed, even for verbatim blocks) */\n /** @lang zh 解析后的子节点(始终解析,即使是逐字块) */\n /** @lang hi पार्स किए गए चाइल्ड नोड्स (हमेशा पार्स किए जाते हैं, यहां तक कि verbatim ब्लॉक्स के लिए भी) */\n children?: ASTNode[] | undefined\n /** Whether this is a verbatim block (script, style, pre, etc.) */\n /** @lang zh 这是否是逐字块(script、style、pre 等) */\n /** @lang hi क्या यह एक verbatim ब्लॉक है (script, style, pre, आदि) */\n verbatim?: boolean\n /** Original raw attribute string */\n /** @lang zh 原始属性字符串 */\n /** @lang hi मूल raw एट्रिब्यूट स्ट्रिंग */\n rawAttrs?: string\n /** Original raw HTML content (for verbatim blocks) */\n /** @lang zh 原始 HTML 内容(用于逐字块) */\n /** @lang hi मूल raw HTML सामग्री (verbatim ब्लॉक्स के लिए) */\n rawText?: string | undefined\n /** @deprecated Use `rawText` instead. This property will be removed in a future major version. */\n /** @lang zh @deprecated 请使用 `rawText` 代替。此属性将在未来的主要版本中移除。 */\n /** @lang hi @deprecated कृपया इसके बजाय `rawText` का उपयोग करें। यह प्रॉपर्टी भविष्य के प्रमुख संस्करण में हटा दी जाएगी। */\n text?: string | undefined\n /** HTML tag name */\n /** @lang zh HTML 标签名称 */\n /** @lang hi HTML टैग नाम */\n tag: string\n }\n\n /**\n * Self-closing HTML tag node\n * @lang zh 自闭合 HTML 标签节点\n * @lang hi स्व-बंद होने वाला HTML टैग नोड\n */\n export interface HTMLSelfClosingNode {\n type: typeof RuleType.htmlSelfClosing\n /** Parsed HTML attributes */\n /** @lang zh 解析后的 HTML 属性 */\n /** @lang hi पार्स किए गए HTML एट्रिब्यूट्स */\n attrs?: Record<string, any>\n /** Whether this is a closing tag */\n /** @lang zh 这是否是闭合标签 */\n /** @lang hi क्या यह एक बंद करने वाला टैग है */\n isClosingTag?: boolean\n /** HTML tag name */\n /** @lang zh HTML 标签名称 */\n /** @lang hi HTML टैग नाम */\n tag: string\n /** Original raw HTML content */\n /** @lang zh 原始 HTML 内容 */\n /** @lang hi मूल raw HTML सामग्री */\n rawText?: string\n }\n\n /**\n * Union type of all possible AST node types\n * @lang zh 所有可能的 AST 节点类型的联合类型\n * @lang hi सभी संभावित AST नोड प्रकारों का संघ प्रकार\n */\n export type ASTNode =\n | BlockQuoteNode\n | BreakLineNode\n | BreakThematicNode\n | CodeBlockNode\n | CodeInlineNode\n | FootnoteNode\n | FootnoteReferenceNode\n | FrontmatterNode\n | GFMTaskNode\n | HeadingNode\n | HTMLCommentNode\n | ImageNode\n | LinkNode\n | OrderedListNode\n | UnorderedListNode\n | ParagraphNode\n | ReferenceNode\n | ReferenceCollectionNode\n | TableNode\n | TextNode\n | FormattedTextNode\n | HTMLNode\n | HTMLSelfClosingNode\n\n /**\n * Function type for rendering AST nodes\n * @lang zh 用于渲染 AST 节点的函数类型\n * @lang hi AST नोड्स को रेंडर करने के लिए फ़ंक्शन प्रकार\n */\n export type ASTRender = (\n ast: MarkdownToJSX.ASTNode | MarkdownToJSX.ASTNode[],\n state: MarkdownToJSX.State\n ) => React.ReactNode\n\n /**\n * Override configuration for HTML tags or custom components\n * @lang zh HTML 标签或自定义组件的覆盖配置\n * @lang hi HTML टैग्स या कस्टम कंपोनेंट्स के लिए ओवरराइड कॉन्फ़िगरेशन\n */\n export type Override =\n | RequireAtLeastOne<{\n component: React.ElementType\n props: Object\n }>\n | React.ElementType\n\n /**\n * Map of HTML tags and custom components to their override configurations\n * @lang zh HTML 标签和自定义组件到其覆盖配置的映射\n * @lang hi HTML टैग्स और कस्टम कंपोनेंट्स से उनकी ओवरराइड कॉन्फ़िगरेशन का मैप\n */\n export type Overrides = {\n [tag in HTMLTags]?: Override\n } & {\n [customComponent: string]: Override\n }\n\n /**\n * Compiler options\n * @lang zh 编译器选项\n * @lang hi कंपाइलर विकल्प\n */\n export type Options = Partial<{\n /**\n * Ultimate control over the output of all rendered JSX.\n * @lang zh 对所有渲染的 JSX 输出的最终控制。\n * @lang hi सभी रेंडर किए गए JSX आउटपुट पर अंतिम नियंत्रण।\n */\n createElement: (\n tag: Parameters<CreateElement>[0],\n props: React.JSX.IntrinsicAttributes,\n ...children: React.ReactNode[]\n ) => React.ReactNode\n\n /**\n * The library automatically generates an anchor tag for bare URLs included in the markdown\n * document, but this behavior can be disabled if desired.\n * @lang zh 库会自动为 Markdown 文档中包含的裸 URL 生成锚点标签,但可以根据需要禁用此行为。\n * @lang hi लाइब्रेरी markdown दस्तावेज़ में शामिल नंगे URLs के लिए स्वचालित रूप से एक एंकर टैग जेनरेट करती है, लेकिन यदि वांछित हो तो इस व्यवहार को अक्षम किया जा सकता है।\n */\n disableAutoLink: boolean\n\n /**\n * Disable the compiler's best-effort transcription of provided raw HTML\n * into JSX-equivalent. This is the functionality that prevents the need to\n * use `dangerouslySetInnerHTML` in React.\n * @lang zh 禁用编译器将提供的原始 HTML 转换为 JSX 等效项的最佳努力。此功能可避免在 React 中使用 `dangerouslySetInnerHTML`。\n * @lang hi कंपाइलर के प्रदान किए गए raw HTML को JSX-समतुल्य में ट्रांसक्राइब करने के सर्वोत्तम प्रयास को अक्षम करें। यह वह कार्यक्षमता है जो React में `dangerouslySetInnerHTML` का उपयोग करने की आवश्यकता को रोकती है।\n */\n disableParsingRawHTML: boolean\n\n /**\n * Enable GFM tagfilter extension to filter potentially dangerous HTML tags.\n * When enabled, the following tags are escaped: title, textarea, style, xmp,\n * iframe, noembed, noframes, script, plaintext.\n * https://github.github.com/gfm/#disallowed-raw-html-extension-\n * @lang zh 启用 GFM tagfilter 扩展以过滤潜在危险的 HTML 标签。启用后,以下标签将被转义:title、textarea、style、xmp、iframe、noembed、noframes、script、plaintext。\n * @lang hi संभावित खतरनाक HTML टैग्स को फ़िल्टर करने के लिए GFM tagfilter एक्सटेंशन सक्षम करें। सक्षम होने पर, निम्नलिखित टैग्स एस्केप किए जाते हैं: title, textarea, style, xmp, iframe, noembed, noframes, script, plaintext।\n * @default true\n */\n tagfilter?: boolean\n\n /**\n * Forces the compiler to have space between hash sign and the header text which\n * is explicitly stated in the most of the markdown specs.\n * https://github.github.com/gfm/#atx-heading\n * `The opening sequence of # characters must be followed by a space or by the end of line.`\n * @lang zh 强制编译器在井号和标题文本之间有空格,这在大多数 Markdown 规范中都有明确规定。\n * @lang hi कंपाइलर को हैश चिह्न और हेडर टेक्स्ट के बीच स्थान रखने के लिए बाध्य करता है, जो अधिकांश markdown विनिर्देशों में स्पष्ट रूप से कहा गया है。\n */\n enforceAtxHeadings: boolean\n\n /**\n * **⚠️ SECURITY WARNING: STRONGLY DISCOURAGED FOR USER INPUTS**\n *\n * When enabled, attempts to eval expressions in JSX props that cannot be serialized\n * as JSON (functions, variables, complex expressions). This uses `eval()` which can\n * execute arbitrary code.\n *\n * **ONLY use this option when:**\n * - The markdown source is completely trusted (e.g., your own documentation)\n * - You control all JSX components and their props\n * - The content is NOT user-generated or user-editable\n *\n * **DO NOT use this option when:**\n * - Processing user-submitted markdown\n * - Rendering untrusted content\n * - Building public-facing applications with user content\n *\n * Example unsafe input: `<Component onClick={() => fetch('/admin/delete-all')} />`\n *\n * When disabled (default), unserializable expressions remain as strings that can be\n * safely inspected or handled on a case-by-case basis via custom renderRule logic.\n *\n * @lang zh **⚠️ 安全警告:强烈建议不要用于用户输入**\n *\n * 启用后,尝试计算 JSX 属性中无法序列化为 JSON 的表达式(函数、变量、复杂表达式)。这使用 `eval()`,可能会执行任意代码。\n *\n * **仅在以下情况下使用此选项:**\n * - Markdown 源完全可信(例如,您自己的文档)\n * - 您控制所有 JSX 组件及其属性\n * - 内容不是用户生成或用户可编辑的\n *\n * **在以下情况下不要使用此选项:**\n * - 处理用户提交的 Markdown\n * - 渲染不可信内容\n * - 构建面向公众的用户内容应用程序\n *\n * 不安全的输入示例:`<Component onClick={() => fetch('/admin/delete-all')} />`\n *\n * 禁用时(默认),不可序列化的表达式保持为字符串,可以通过自定义 renderRule 逻辑安全地检查或逐例处理。\n *\n * @lang hi **⚠️ सुरक्षा चेतावनी: उपयोगकर्ता इनपुट के लिए अत्यधिक हतोत्साहित**\n *\n * सक्षम होने पर, JSX props में expressions को eval करने का प्रयास करता है जिन्हें JSON के रूप में सीरियलाइज़ नहीं किया जा सकता है (फ़ंक्शन, वेरिएबल, जटिल expressions)। यह `eval()` का उपयोग करता है जो मनमाने कोड को निष्पादित कर सकता है।\n *\n * **केवल निम्नलिखित स्थितियों में इस विकल्प का उपयोग करें:**\n * - Markdown स्रोत पूरी तरह से विश्वसनीय है (उदाहरण के लिए, आपका अपना दस्तावेज़ीकरण)\n * - आप सभी JSX कंपोनेंट्स और उनके props को नियंत्रित करते हैं\n * - सामग्री उपयोगकर्ता-जनित या उपयोगकर्ता-संपादन योग्य नहीं है\n *\n * **निम्नलिखित स्थितियों में इस विकल्प का उपयोग न करें:**\n * - उपयोगकर्ता-सबमिट किए गए markdown को प्रोसेस कर रहे हों\n * - अविश्वसनीय सामग्री रेंडर कर रहे हों\n * - उपयोगकर्ता सामग्री वाले सार्वजनिक-सामना करने वाले एप्लिकेशन बना रहे हों\n *\n * असुरक्षित इनपुट उदाहरण: `<Component onClick={() => fetch('/admin/delete-all')} />`\n *\n * अक्षम होने पर (डिफ़ॉल्ट), अनसीरियलाइज़ेबल expressions स्ट्रिंग्स के रूप में रहते हैं जिन्हें कस्टम renderRule लॉजिक के माध्यम से सुरक्षित रूप से जांचा जा सकता है या केस-बाई-केस हैंडल किया जा सकता है।\n *\n * @default false\n */\n evalUnserializableExpressions?: boolean\n\n /**\n * Forces the compiler to always output content with a block-level wrapper\n * (`<p>` or any block-level syntax your markdown already contains.)\n * @lang zh 强制编译器始终使用块级包装器输出内容(`<p>` 或您的 Markdown 已包含的任何块级语法)。\n * @lang hi कंपाइलर को हमेशा ब्लॉक-स्तरीय रैपर के साथ सामग्री आउटपुट करने के लिए बाध्य करता है (`<p>` या आपके markdown में पहले से मौजूद कोई भी ब्लॉक-स्तरीय सिंटैक्स)।\n */\n forceBlock: boolean\n\n /**\n * Forces the compiler to always output content with an inline wrapper (`<span>`)\n * @lang zh 强制编译器始终使用内联包装器(`<span>`)输出内容\n * @lang hi कंपाइलर को हमेशा इनलाइन रैपर (`<span>`) के साथ सामग्री आउटपुट करने के लिए बाध्य करता है\n */\n forceInline: boolean\n\n /**\n * Forces the compiler to wrap results, even if there is only a single\n * child or no children.\n * @lang zh 强制编译器包装结果,即使只有一个子元素或没有子元素。\n * @lang hi कंपाइलर को परिणामों को रैप करने के लिए बाध्य करता है, भले ही केवल एक चाइल्ड हो या कोई चाइल्ड न हो।\n */\n forceWrapper: boolean\n\n /**\n * Selectively control the output of particular HTML tags as they would be\n * emitted by the compiler.\n * @lang zh 选择性地控制特定 HTML 标签的输出,就像编译器会发出的一样。\n * @lang hi चुनिंदा रूप से विशिष्ट HTML टैग्स के आउटपुट को नियंत्रित करें जैसा कि कंपाइलर द्वारा उत्सर्जित किया जाएगा।\n */\n overrides: Overrides\n\n /**\n * Allows for full control over rendering of particular rules.\n * For example, to implement a LaTeX renderer such as `react-katex`:\n *\n * ```\n * renderRule(next, node, renderChildren, state) {\n * if (node.type === RuleType.codeBlock && node.lang === 'latex') {\n * return (\n * <TeX as=\"div\" key={state.key}>\n * {String.raw`${node.text}`}\n * </TeX>\n * )\n * }\n *\n * return next();\n * }\n * ```\n *\n * Thar be dragons obviously, but you can do a lot with this\n * (have fun!) To see how things work internally, check the `render`\n * method in source for a particular rule.\n * @lang zh 允许完全控制特定规则的渲染。例如,要实现像 `react-katex` 这样的 LaTeX 渲染器:\n *\n * 显然有风险,但您可以用它做很多事情(玩得开心!)要了解内部工作原理,请查看源代码中特定规则的 `render` 方法。\n * @lang hi विशिष्ट नियमों के रेंडरिंग पर पूर्ण नियंत्रण की अनुमति देता है। उदाहरण के लिए, `react-katex` जैसे LaTeX रेंडरर को लागू करने के लिए:\n *\n * स्पष्ट रूप से जोखिम हैं, लेकिन आप इसके साथ बहुत कुछ कर सकते हैं (मज़े करें!) आंतरिक रूप से चीजें कैसे काम करती हैं यह देखने के लिए, किसी विशिष्ट नियम के लिए स्रोत में `render` विधि देखें।\n */\n renderRule: (\n /** Resume normal processing, call this function as a fallback if you are not returning custom JSX. */\n /** @lang zh 恢复正常处理,如果您不返回自定义 JSX,请调用此函数作为后备。 */\n /** @lang hi सामान्य प्रोसेसिंग फिर से शुरू करें, यदि आप कस्टम JSX वापस नहीं कर रहे हैं तो इस फ़ंक्शन को फ़ॉलबैक के रूप में कॉल करें। */\n next: () => React.ReactNode,\n /** the current AST node, use `RuleType` against `node.type` for identification */\n /** @lang zh 当前的 AST 节点,使用 `RuleType` 与 `node.type` 进行比较以进行识别 */\n /** @lang hi वर्तमान AST नोड, पहचान के लिए `node.type` के खिलाफ `RuleType` का उपयोग करें */\n node: ASTNode,\n /** use as `renderChildren(node.children)` for block nodes */\n /** @lang zh 对于块节点,使用 `renderChildren(node.children)` */\n /** @lang hi ब्लॉक नोड्स के लिए `renderChildren(node.children)` के रूप में उपयोग करें */\n renderChildren: ASTRender,\n /** contains `key` which should be supplied to the topmost JSX element */\n /** @lang zh 包含应提供给最顶层 JSX 元素的 `key` */\n /** @lang hi `key` शामिल है जो सबसे ऊपरी JSX एलिमेंट को प्रदान किया जाना चाहिए */\n state: State\n ) => React.ReactNode\n\n /**\n * Override the built-in sanitizer function for URLs, etc if desired. The built-in version is available as a library\n export called `sanitizer`.\n * @lang zh 如果需要,覆盖内置的 URL 清理函数等。内置版本可作为名为 `sanitizer` 的库导出使用。\n * @lang hi यदि वांछित हो तो URLs आदि के लिए बिल्ट-इन सैनिटाइज़र फ़ंक्शन को ओवरराइड करें। बिल्ट-इन संस्करण `sanitizer` नामक लाइब्रेरी export के रूप में उपलब्ध है।\n */\n sanitizer: (value: string, tag: string, attribute: string) => string | null\n\n /**\n * Override normalization of non-URI-safe characters for use in generating\n * HTML IDs for anchor linking purposes.\n * @lang zh 覆盖非 URI 安全字符的规范化,用于生成用于锚点链接的 HTML ID。\n * @lang hi एंकर लिंकिंग उद्देश्यों के लिए HTML IDs जेनरेट करने में उपयोग के लिए गैर-URI-सुरक्षित वर्णों के सामान्यीकरण को ओवरराइड करें।\n */\n slugify: (input: string, defaultFn: (input: string) => string) => string\n\n /**\n * Declare the type of the wrapper to be used when there are multiple\n * children to render. Set to `null` to get an array of children back\n * without any wrapper, or use `React.Fragment` to get a React element\n * that won't show up in the DOM.\n * @lang zh 声明在有多个子元素要渲染时使用的包装器类型。设置为 `null` 以在没有包装器的情况下返回子元素数组,或使用 `React.Fragment` 获取不会出现在 DOM 中的 React 元素。\n * @lang hi रैपर के प्रकार को घोषित करें जब कई children को रेंडर करना हो। बिना किसी रैपर के children की एक सरणी वापस पाने के लिए `null` पर सेट करें, या DOM में दिखाई न देने वाला React एलिमेंट प्राप्त करने के लिए `React.Fragment` का उपयोग करें।\n */\n wrapper: React.ElementType | null\n\n /**\n * Props to apply to the wrapper element.\n * @lang zh 应用于包装元素的属性。\n * @lang hi रैपर एलिमेंट पर लागू करने के लिए props।\n */\n wrapperProps?: React.JSX.IntrinsicAttributes\n\n /**\n * Preserve frontmatter in the output by rendering it as a <pre> element.\n * By default, frontmatter is parsed but not rendered.\n * @lang zh 通过将其渲染为 <pre> 元素来保留输出中的前置元数据。默认情况下,前置元数据会被解析但不会渲染。\n * @lang hi इसे <pre> एलिमेंट के रूप में रेंडर करके आउटपुट में फ्रंटमैटर को संरक्षित करें। डिफ़ॉल्ट रूप से, फ्रंटमैटर को पार्स किया जाता है लेकिन रेंडर नहीं किया जाता है।\n * @default false\n */\n preserveFrontmatter?: boolean\n }>\n}\n\nexport const RuleType: typeof RuleTypeConst = RuleTypeConst\nexport type RuleType = RuleTypeValue\n\nexport type RequireAtLeastOne<\n T,\n Keys extends keyof T = keyof T,\n> = MarkdownToJSX.RequireAtLeastOne<T, Keys>\n\nexport { MarkdownToJSX }\n",
|
|
7
|
-
"import {\n NAMED_CODES_TO_UNICODE as util,\n decodeEntity,\n} from '#entities'\nimport * as $ from './constants'\n\n/**\n * Parse frontmatter bounds and validate YAML\n *\n * @param input - Input string to parse\n * @returns Object with end position and YAML validity, or null if no frontmatter\n */\nexport function parseFrontmatterBounds(\n input: string\n): { endPos: number; hasValidYaml: boolean } | null {\n if (!startsWith(input, '---')) return null\n let pos = 3\n while (pos < input.length && (input[pos] === ' ' || input[pos] === '\\t'))\n pos++\n if (pos >= input.length || input[pos] !== '\\n') return null\n pos++\n\n let hasValidYaml = false\n while (pos < input.length) {\n const lineStart = pos\n while (pos < input.length && input[pos] !== '\\n') pos++\n if (pos >= input.length) break\n const lineEnd = pos++\n if (startsWith(input, '---', lineStart))\n return { endPos: pos, hasValidYaml }\n // Check if line contains ':' anywhere\n // OPTIMIZATION: Use indexOf directly to avoid slice allocation\n const colonIndex = input.indexOf(':', lineStart)\n if (colonIndex !== -1 && colonIndex < lineEnd) hasValidYaml = true\n }\n return null\n}\n\n/**\n * Named HTML entity codes to unicode character mapping\n * Pre-computed from generated entity set\n * Numeric references ({ and «) are fully supported without any mapping.\n * Unknown named entities pass through as literal text (CommonMark-compliant).\n * @lang zh 命名的 HTML 实体代码到 Unicode 字符的映射\n * 从生成的实体集预计算\n * 数字引用({ 和 «)完全支持,无需映射。\n * 未知的命名实体作为字面文本传递(符合 CommonMark)。\n * @lang hi नामित HTML एंटिटी कोड से Unicode वर्णों का मैपिंग\n * जेनरेट किए गए एंटिटी सेट से पूर्व-गणना की गई\n * संख्यात्मक संदर्भ ({ और «) बिना किसी मैपिंग के पूरी तरह से समर्थित हैं।\n * अज्ञात नामित एंटिटीज़ शाब्दिक टेक्स्ट के रूप में पास होती हैं (CommonMark-अनुरूप)।\n */\nexport const NAMED_CODES_TO_UNICODE: Record<string, string> = util\n\n/**\n * Regex for matching HTML character references (&entity; or { or «)\n * Matches: & followed by entity name or # followed by decimal or hex digits, ending with ;\n * @lang zh 用于匹配 HTML 字符引用的正则表达式(&entity; 或 { 或 «)\n * 匹配:& 后跟实体名称或 # 后跟十进制或十六进制数字,以 ; 结尾\n * @lang hi HTML वर्ण संदर्भों से मिलान करने के लिए रेगेक्स (&entity; या { या «)\n * मैच: & के बाद एंटिटी नाम या # के बाद दशमलव या हेक्स अंक, ; के साथ समाप्त होता है\n */\nexport const HTML_CHAR_CODE_R: RegExp =\n /&([a-zA-Z0-9]+|#[0-9]{1,7}|#x[0-9a-fA-F]{1,6});/gi\n\n/**\n * Regex for determining if markdown content should be rendered as block-level\n * Matches: newlines, list items, headings, indented content, thematic breaks, blockquotes\n * @lang zh 用于确定 Markdown 内容是否应渲染为块级的正则表达式\n * 匹配:换行符、列表项、标题、缩进内容、分隔线、引用块\n * @lang hi यह निर्धारित करने के लिए रेगेक्स कि markdown सामग्री को ब्लॉक-स्तरीय के रूप में रेंडर किया जाना चाहिए\n * मैच: नई लाइनें, सूची आइटम्स, हेडिंग्स, इंडेंटेड सामग्री, थीमैटिक ब्रेक्स, ब्लॉककोट्स\n */\n// Mapping of lowercase HTML attributes to JSX prop names\n// Shared between React and Solid renderers (Vue uses HTML attributes directly)\nexport const HTML_TO_JSX_MAP: Record<string, string> = {\n class: 'className',\n for: 'htmlFor',\n allowfullscreen: 'allowFullScreen',\n allowtransparency: 'allowTransparency',\n autocomplete: 'autoComplete',\n autofocus: 'autoFocus',\n autoplay: 'autoPlay',\n cellpadding: 'cellPadding',\n cellspacing: 'cellSpacing',\n charset: 'charSet',\n classid: 'classId',\n colspan: 'colSpan',\n contenteditable: 'contentEditable',\n contextmenu: 'contextMenu',\n crossorigin: 'crossOrigin',\n enctype: 'encType',\n formaction: 'formAction',\n formenctype: 'formEncType',\n formmethod: 'formMethod',\n formnovalidate: 'formNoValidate',\n formtarget: 'formTarget',\n frameborder: 'frameBorder',\n hreflang: 'hrefLang',\n inputmode: 'inputMode',\n keyparams: 'keyParams',\n keytype: 'keyType',\n marginheight: 'marginHeight',\n marginwidth: 'marginWidth',\n maxlength: 'maxLength',\n mediagroup: 'mediaGroup',\n minlength: 'minLength',\n novalidate: 'noValidate',\n radiogroup: 'radioGroup',\n readonly: 'readOnly',\n rowspan: 'rowSpan',\n spellcheck: 'spellCheck',\n srcdoc: 'srcDoc',\n srclang: 'srcLang',\n srcset: 'srcSet',\n tabindex: 'tabIndex',\n usemap: 'useMap',\n}\n\n/**\n * Convert HTML attributes to JSX props\n * Maps HTML attribute names (e.g., \"class\", \"for\") to JSX prop names (e.g., \"className\", \"htmlFor\")\n *\n * @param attrs - HTML attributes object\n * @returns JSX props object\n */\nexport function htmlAttrsToJSXProps(\n attrs: Record<string, any>\n): Record<string, any> {\n var jsxProps: Record<string, any> = {}\n\n for (var key in attrs) {\n var keyLower = key.toLowerCase()\n var mappedKey = HTML_TO_JSX_MAP[keyLower]\n jsxProps[mappedKey || key] = attrs[key]\n }\n\n return jsxProps\n}\n\nexport const SHOULD_RENDER_AS_BLOCK_R: RegExp =\n /(\\n|^[-*]\\s|^#|^ {2,}|^-{2,}|^>\\s)/\n\n/**\n * Decode HTML entity references to Unicode characters\n *\n * @param text - The text containing HTML entities\n * @returns The decoded text\n */\nexport function decodeEntityReferences(text: string): string {\n if (text.indexOf('&') === -1) return text\n\n return text.replace(HTML_CHAR_CODE_R, (full, inner) => {\n // Named entity lookup via swappable decoder\n // In browser builds, this uses DOM; in Node, uses lookup table\n var entity = decodeEntity(inner)\n if (entity) return entity\n\n // Numeric entities (always computed, no lookup needed)\n if (inner[0] === '#') {\n var code =\n inner[1] === 'x' || inner[1] === 'X'\n ? parseInt(inner.slice(2), 16)\n : parseInt(inner.slice(1), 10)\n\n if (code === 0 || (code >= 0xd800 && code <= 0xdfff) || code > 0x10ffff) {\n return '\\uFFFD'\n }\n return code <= 0xffff\n ? String.fromCharCode(code)\n : String.fromCharCode(\n 0xd800 + ((code - 0x10000) >> 10),\n 0xdc00 + ((code - 0x10000) & 0x3ff)\n )\n }\n\n return full\n })\n}\n\nexport const SANITIZE_R: RegExp = /(javascript|vbscript|data(?!:image)):/i\n\n/**\n * Sanitize URLs and other input values to prevent XSS attacks.\n * Filters out javascript:, vbscript:, and data: URLs (except data:image).\n *\n * @lang zh 清理 URL 和其他输入值以防止 XSS 攻击。过滤掉 javascript:、vbscript: 和 data: URL(data:image 除外)。\n * @lang hi XSS हमलों को रोकने के लिए URLs और अन्य इनपुट मानों को सैनिटाइज़ करता है। javascript:, vbscript:, और data: URLs को फ़िल्टर करता है (data:image को छोड़कर)।\n *\n * @param input - The URL or value to sanitize\n * @lang zh @param input - 要清理的 URL 或值\n * @lang hi @param input - सैनिटाइज़ करने के लिए URL या मान\n * @returns Sanitized value, or null if unsafe\n * @lang zh @returns 清理后的值,如果不安全则返回 null\n * @lang hi @returns सैनिटाइज़ किया गया मान, या असुरक्षित होने पर null\n */\nexport function sanitizer(input: string): string | null {\n if (SANITIZE_R.test(input)) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n 'Input contains an unsafe JavaScript/VBScript/data expression, it will not be rendered.',\n input\n )\n }\n return null\n }\n\n if (input.indexOf('%') === -1) return input\n\n try {\n const decoded = decodeURIComponent(input).replace(/[^A-Za-z0-9/:]/g, '')\n if (SANITIZE_R.test(decoded)) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n 'Input contains an unsafe JavaScript/VBScript/data expression, it will not be rendered.',\n decoded\n )\n }\n return null\n }\n } catch (e) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n 'Input could not be decoded due to malformed syntax or characters, it will not be rendered.',\n input\n )\n }\n return null\n }\n\n return input\n}\n\n// Character replacement lookup table for slugify (Unicode to ASCII)\nvar slugifyReplaceTable: Record<number, string> = {}\nvar codes: number[], i: number\ncodes = [192, 193, 194, 195, 196, 197, 224, 225, 226, 227, 228, 229, 230, 198]\nfor (i = 0; i < codes.length; i++) slugifyReplaceTable[codes[i]] = 'a'\nslugifyReplaceTable[231] = slugifyReplaceTable[199] = 'c'\nslugifyReplaceTable[240] = slugifyReplaceTable[208] = 'd'\ncodes = [200, 201, 202, 203, 233, 232, 234, 235]\nfor (i = 0; i < codes.length; i++) slugifyReplaceTable[codes[i]] = 'e'\ncodes = [207, 239, 206, 238, 205, 237, 204, 236]\nfor (i = 0; i < codes.length; i++) slugifyReplaceTable[codes[i]] = 'i'\nslugifyReplaceTable[209] = slugifyReplaceTable[241] = 'n'\ncodes = [248, 216, 339, 338, 213, 245, 212, 244, 211, 243, 210, 242]\nfor (i = 0; i < codes.length; i++) slugifyReplaceTable[codes[i]] = 'o'\ncodes = [220, 252, 219, 251, 218, 250, 217, 249]\nfor (i = 0; i < codes.length; i++) slugifyReplaceTable[codes[i]] = 'u'\nslugifyReplaceTable[376] =\n slugifyReplaceTable[255] =\n slugifyReplaceTable[221] =\n slugifyReplaceTable[253] =\n 'y'\n\n/**\n * Check if a character code is alphanumeric (0-9, A-Z, a-z)\n *\n * @param code - Character code to check\n * @returns True if alphanumeric\n */\nexport function isAlnumCode(code: number): boolean {\n return (\n (code >= $.CHAR_DIGIT_0 && code <= $.CHAR_DIGIT_9) ||\n (code >= $.CHAR_A && code <= $.CHAR_Z) ||\n (code >= $.CHAR_a && code <= $.CHAR_z)\n )\n}\n\n/**\n * Convert a string to a URL-safe slug by normalizing characters and replacing spaces with hyphens.\n * Based on https://stackoverflow.com/a/18123682/1141611\n * Not complete, but probably good enough.\n *\n * @lang zh 通过规范化字符并用连字符替换空格,将字符串转换为 URL 安全的别名。不完整,但可能足够好。\n * @lang hi वर्णों को सामान्यीकृत करके और रिक्त स्थान को हाइफ़न से बदलकर स्ट्रिंग को URL-सुरक्षित slug में बदलता है। पूर्ण नहीं है, लेकिन शायद पर्याप्त है।\n *\n * @param str - String to slugify\n * @lang zh @param str - 要转换为别名的字符串\n * @lang hi @param str - slugify करने के लिए स्ट्रिंग\n * @returns URL-safe slug\n * @lang zh @returns URL 安全的别名\n * @lang hi @returns URL-सुरक्षित slug\n */\nexport function slugify(str: string): string {\n var parts: string[] = []\n for (var i = 0; i < str.length; i++) {\n var code = str.charCodeAt(i)\n if (isAlnumCode(code)) {\n if (code >= $.CHAR_A && code <= $.CHAR_Z) {\n parts.push(String.fromCharCode(code + $.CHAR_CASE_OFFSET))\n } else {\n parts.push(str[i])\n }\n } else if (code === $.CHAR_SPACE || code === $.CHAR_DASH) {\n parts.push('-')\n } else {\n var replacement = slugifyReplaceTable[code]\n if (replacement) parts.push(replacement)\n }\n }\n return parts.join('')\n}\n\n/**\n * Check if a string includes a substring\n *\n * @param str - String to search in\n * @param search - Substring to search for\n * @returns True if substring is found\n */\nexport function includes(str: string, search: string): boolean {\n return str.indexOf(search) !== -1\n}\n\n/**\n * Check if a string starts with a prefix\n *\n * @param str - String to check\n * @param prefix - Prefix to check for\n * @param pos - Optional starting position\n * @returns True if string starts with prefix\n */\nexport function startsWith(str: string, prefix: string, pos?: number): boolean {\n return str.startsWith(prefix, pos)\n}\n\n/**\n * Check if a string ends with a suffix\n *\n * @param str - String to check\n * @param suffix - Suffix to check for\n * @param pos - Optional ending position\n * @returns True if string ends with suffix\n */\nexport function endsWith(str: string, suffix: string, pos?: number): boolean {\n return str.startsWith(\n suffix,\n (pos === undefined ? str.length : pos) - suffix.length\n )\n}\n\n// Known void elements (HTML5 and SVG) that don't require closing tag or />\n// Use Set for O(1) lookups instead of O(n) array.includes()\nexport const VOID_ELEMENTS: Set<string> = new Set([\n // HTML5 void elements\n 'area',\n 'base',\n 'br',\n 'col',\n 'embed',\n 'hr',\n 'img',\n 'input',\n 'link',\n 'meta',\n 'param',\n 'source',\n 'track',\n 'wbr',\n // SVG void elements\n 'circle',\n 'ellipse',\n 'line',\n 'path',\n 'polygon',\n 'polyline',\n 'rect',\n 'use',\n 'stop',\n 'animate',\n 'animateTransform',\n 'set',\n])\n\n/**\n * Check if an element is a void element (doesn't require closing tag)\n *\n * @param tagName - HTML tag name\n * @returns True if void element\n */\nexport function isVoidElement(tagName: string): boolean {\n let lowerTag = tagName.toLowerCase()\n if (VOID_ELEMENTS.has(lowerTag)) return true\n // Handle SVG namespace prefixes like svg:circle\n const colonIndex = lowerTag.indexOf(':')\n if (colonIndex !== -1) {\n lowerTag = lowerTag.slice(colonIndex + 1)\n return VOID_ELEMENTS.has(lowerTag)\n }\n return false\n}\n\n/** Attributes that should be sanitized for security */\nexport const ATTRIBUTES_TO_SANITIZE: readonly string[] = [\n 'src',\n 'href',\n 'data',\n 'formAction',\n 'srcDoc',\n 'action',\n]\n\n// Character classification flags (bitfield)\nconst CHAR_WHITESPACE = 1\nconst CHAR_PUNCTUATION = 2\n\n// Inline character type constants\n// const INLINE_CHAR_TYPE_NORMAL = 0\nconst INLINE_CHAR_TYPE_SPECIAL = 1\nconst INLINE_CHAR_TYPE_ESCAPE = 2\nconst INLINE_CHAR_TYPE_DELIMITER = 3\nconst INLINE_CHAR_TYPE_LINK = 4\n\n// Lookup table for ASCII characters (0-127)\nexport const charClassTable: Uint8Array = (function () {\n const t = new Uint8Array(128)\n let i\n t[$.CHAR_TAB] =\n t[$.CHAR_NEWLINE] =\n t[$.CHAR_FF] =\n t[$.CHAR_CR] =\n t[$.CHAR_SPACE] =\n CHAR_WHITESPACE\n for (i = $.CHAR_EXCLAMATION; i <= $.CHAR_SLASH; i++) t[i] = CHAR_PUNCTUATION\n for (i = $.CHAR_COLON; i <= $.CHAR_AT; i++) t[i] = CHAR_PUNCTUATION\n for (i = $.CHAR_BRACKET_OPEN; i <= $.CHAR_BACKTICK; i++)\n t[i] = CHAR_PUNCTUATION\n for (i = $.CHAR_BRACE_OPEN; i <= $.CHAR_TILDE; i++) t[i] = CHAR_PUNCTUATION\n return t\n})()\n\n// Lookup table for inline character types (0-127): 0=normal, 1=special, 2=escape, 3=delimiter, 4=link\nexport const inlineCharTypeTable: Uint8Array = (function () {\n const t = new Uint8Array(128)\n t[$.CHAR_BACKSLASH] = INLINE_CHAR_TYPE_ESCAPE\n t[$.CHAR_BRACKET_OPEN] = INLINE_CHAR_TYPE_LINK\n t[$.CHAR_ASTERISK] =\n t[$.CHAR_UNDERSCORE] =\n t[$.CHAR_TILDE] =\n t[$.CHAR_EQ] =\n INLINE_CHAR_TYPE_DELIMITER\n t[$.CHAR_BACKTICK] =\n t[$.CHAR_LT] =\n t[$.CHAR_AT] =\n t[$.CHAR_BRACKET_CLOSE] =\n t[$.CHAR_NEWLINE] =\n t[$.CHAR_SPACE] =\n t[$.CHAR_EXCLAMATION] =\n INLINE_CHAR_TYPE_SPECIAL\n t[$.CHAR_f] = t[$.CHAR_H] = t[$.CHAR_W] = INLINE_CHAR_TYPE_SPECIAL\n return t\n})()\n\nexport function isASCIIPunctuation(code: number): boolean {\n return (\n code < $.CHAR_ASCII_BOUNDARY &&\n (charClassTable[code] & CHAR_PUNCTUATION) !== 0\n )\n}\n\nexport function isASCIIWhitespace(code: number): boolean {\n return (\n code < $.CHAR_ASCII_BOUNDARY &&\n (charClassTable[code] & CHAR_WHITESPACE) !== 0\n )\n}\n\n// Unicode property escapes for spec-compliant character classification\n// Per GFM spec Section 2.1: \"A punctuation character is a character in the general Unicode categories\n// Pc, Pd, Pe, Pf, Pi, Po, or Ps\" - this is \\p{P}\n// BUT also includes some currency symbols and other symbols per the spec's explicit list\nconst UNICODE_PUNCT_R = /[\\p{P}\\p{S}]/u\nconst UNICODE_WHITESPACE_R = /\\p{Zs}/u\n\nexport function isUnicodeWhitespace(c: string): boolean {\n if (!c) return true\n const code = c.charCodeAt(0)\n return code < $.CHAR_ASCII_BOUNDARY\n ? (charClassTable[code] & CHAR_WHITESPACE) !== 0\n : UNICODE_WHITESPACE_R.test(c)\n}\n\nexport function isUnicodePunctuation(c: string | number): boolean {\n if (typeof c === 'number')\n return (\n c < $.CHAR_ASCII_BOUNDARY && (charClassTable[c] & CHAR_PUNCTUATION) !== 0\n )\n if (!c) return false\n const code = c.charCodeAt(0)\n return code < $.CHAR_ASCII_BOUNDARY\n ? (charClassTable[code] & CHAR_PUNCTUATION) !== 0\n : UNICODE_PUNCT_R.test(c)\n}\n\n/**\n * Find the end of the current line\n * Optimized: Pure indexOf is faster than hybrid approach - JS engine optimizes it better\n */\nexport function findLineEnd(source: string, startPos: number): number {\n const newlinePos = source.indexOf('\\n', startPos)\n return newlinePos !== -1 ? newlinePos : source.length\n}\n\n/**\n * Skip whitespace characters\n */\nexport function skipWhitespace(\n source: string,\n pos: number,\n maxPos?: number\n): number {\n const end = maxPos ?? source.length\n while (pos < end && (source[pos] === ' ' || source[pos] === '\\t')) pos++\n return pos\n}\n\n/**\n * Fast check if object has any enumerable properties\n * Optimized alternative to Object.keys(obj).length > 0\n */\nexport function hasKeys(obj: Record<string, any> | null | undefined): boolean {\n if (!obj) return false\n for (var key in obj) {\n return true\n }\n return false\n}\n\n/**\n * Extract plain text from AST nodes (for image alt text, heading slugs, etc.)\n * Shared between JSX and HTML renderers\n */\n/**\n * Get nested property from object using dot notation path\n */\nexport function get(source: any, path: string, fallback: any): any {\n var result = source\n var segments = path.split('.')\n var i = 0\n while (i < segments.length) {\n result = result?.[segments[i]]\n if (result === undefined) break\n i++\n }\n return result || fallback\n}\n\n/**\n * Get tag name from override object, supporting both string and component object overrides\n */\nexport function getTag<\n T extends string | { component?: string; props?: Record<string, any> },\n>(tag: string, overrides?: Record<string, T>): string {\n if (!overrides) return tag\n const override = get(overrides, tag, undefined)\n if (typeof override === 'string') return override\n if (typeof override === 'object' && override.component)\n return override.component\n return tag\n}\n\n/**\n * Get override props from override object\n */\nexport function getOverrideProps<\n T extends string | { component?: string; props?: Record<string, any> },\n>(\n tag: string,\n overrides?: Record<string, T>\n): Record<string, string | number | boolean> {\n if (!overrides) return {}\n const override = get(overrides, tag, undefined)\n return typeof override === 'object' && override.props ? override.props : {}\n}\n\nexport function extractPlainText(nodes: Array<any>, RuleType: any): string {\n var result = ''\n for (var i = 0, len = nodes.length; i < len; i++) {\n var node = nodes[i],\n type = node.type\n if (type === RuleType.text || type === RuleType.codeInline) {\n var text = node.text\n if (text) result += text\n } else if (type === RuleType.textFormatted || type === RuleType.link) {\n if (node.children) result += extractPlainText(node.children, RuleType)\n } else if (type === RuleType.image) {\n if (node.alt) {\n result += node.alt\n }\n }\n }\n return result\n}\n\n/**\n * Check if tag should be filtered per GFM tagfilter extension\n */\nexport function shouldFilterTag(tagName: string): boolean {\n var lowerTag = tagName.toLowerCase()\n return (\n lowerTag === 'title' ||\n lowerTag === 'textarea' ||\n lowerTag === 'style' ||\n lowerTag === 'xmp' ||\n lowerTag === 'iframe' ||\n lowerTag === 'noembed' ||\n lowerTag === 'noframes' ||\n lowerTag === 'script' ||\n lowerTag === 'plaintext'\n )\n}\n\n/**\n * Apply tagfilter to text content - escape dangerous tags\n */\nexport function applyTagFilterToText(text: string): string {\n // Escape dangerous tags in raw HTML text\n // Matches opening tags like <tag> or <tag attr=\"val\">\n return text.replace(\n /<(\\/?)(title|textarea|style|xmp|iframe|noembed|noframes|script|plaintext)(\\s|>|\\/)/gi,\n function (match, slash, tagName, after) {\n // Only escape the opening <\n return '<' + slash + tagName + after\n }\n )\n}\n",
|
|
8
|
-
"import { RuleType, type MarkdownToJSX } from './types'\nimport * as $ from './constants'\nimport * as util from './utils'\n\n// NOTE: All debug and tracking functions are automatically removed by build-plugins.ts\n\n// Global parseMetrics - accessible via global.parseMetrics from all files\ndeclare global {\n var parseMetrics: {\n blockParsers: {\n [key: string]: {\n attempts: number\n hits: number\n hitTimings: number[]\n }\n }\n inlineParsers: {\n [key: string]: {\n attempts: number\n hits: number\n hitTimings: number[]\n }\n }\n totalOperations: number\n blockParseIterations: number\n inlineParseIterations: number\n } | null\n var parseMetricsStartTimes: Map<string, number> | null\n}\n\nexport {};\n\nfunction warn(message: string): void {\n console.warn(message)\n}\n\nfunction countConsecutiveChars(\n source: string,\n pos: number,\n targetChar: string,\n maxCount?: number\n): number {\n var targetCode = charCode(targetChar)\n var len = source.length\n var max = maxCount ?? len - pos\n var count = 0\n while (\n count < max &&\n pos + count < len &&\n charCode(source, pos + count) === targetCode\n )\n count++\n return count\n}\n\n// Unified flanking check: dir=0 for left, dir=1 for right\nfunction checkFlanking(\n source: string,\n delimiterStart: number,\n delimiterEnd: number,\n bound: number,\n dir: number\n): boolean {\n if (dir === 0 ? delimiterEnd >= bound : delimiterStart <= bound) return false\n\n const adjacentChar =\n dir === 0 ? source[delimiterEnd] : source[delimiterStart - 1]\n const oppositeChar =\n dir === 0\n ? delimiterStart > 0\n ? source[delimiterStart - 1]\n : null\n : delimiterEnd < source.length\n ? source[delimiterEnd]\n : null\n\n var adjacentCode = charCode(adjacentChar)\n\n if (\n adjacentCode < $.CHAR_ASCII_BOUNDARY\n ? util.isASCIIWhitespace(adjacentCode)\n : util.isUnicodeWhitespace(adjacentChar)\n ) {\n return false\n }\n\n var oppositeCode = oppositeChar ? charCode(oppositeChar) : null\n var isOppositeWS =\n oppositeChar === null ||\n oppositeChar === '\\n' ||\n oppositeChar === '\\r' ||\n (oppositeCode !== null\n ? oppositeCode < $.CHAR_ASCII_BOUNDARY\n ? util.isASCIIWhitespace(oppositeCode)\n : util.isUnicodeWhitespace(oppositeChar)\n : true)\n\n var isAdjacentPunct = isPunctuation(adjacentCode, adjacentChar)\n\n if (!isAdjacentPunct) return true\n if (isOppositeWS) return true\n\n return oppositeChar\n ? isPunctuation(charCode(oppositeChar), oppositeChar)\n : false\n}\n\n// Per CommonMark spec: backslashes escape ASCII punctuation characters in link destinations\n// For non-punctuation characters, the backslash is preserved as a literal backslash\n// Per CommonMark spec: backslash unescaping and entity reference decoding for URLs and titles\n// Any ASCII punctuation character may be backslash-escaped\n// Entity references are recognized and decoded to Unicode\nfunction unescapeUrlOrTitle(str: string): string {\n var result = '',\n i = 0\n while (i < str.length) {\n if (str[i] === '\\\\' && i + 1 < str.length) {\n var next = str[i + 1]\n result += util.isUnicodePunctuation(charCode(next)) ? next : '\\\\' + next\n i += 2\n } else {\n result += str[i++]\n }\n }\n return util.decodeEntityReferences(result)\n}\n\nfunction skipToNextLine(source: string, lineEnd: number): number {\n return lineEnd + (lineEnd < source.length ? 1 : 0)\n}\n\nfunction getCharType(code: number, skipAutoLink: boolean): number {\n if (code >= $.CHAR_ASCII_BOUNDARY) return 0\n var type = util.inlineCharTypeTable[code]\n if (\n skipAutoLink &&\n type === 1 &&\n (code === $.CHAR_f || code === $.CHAR_H || code === $.CHAR_W)\n ) {\n return 0\n }\n return type\n}\n\nfunction tryMergeBlockquoteContinuation(\n source: string,\n currentPos: number,\n lastItem: MarkdownToJSX.ASTNode[],\n continuationContent: string,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): number | null {\n if (\n !lastItem.length ||\n lastItem[lastItem.length - 1].type !== RuleType.blockQuote\n )\n return null\n const checkPos = util.skipWhitespace(\n continuationContent,\n 0,\n continuationContent.length\n )\n if (\n checkPos >= continuationContent.length ||\n continuationContent[checkPos] !== '>'\n )\n return null\n // We've already verified it starts with '>', so try blockquote directly\n // (parseBlock might match fenced code blocks first due to indentation)\n const cont = parseBlockQuote(source, currentPos, state, options)\n if (!cont) return null\n const lastBlockQuote = lastItem[\n lastItem.length - 1\n ] as MarkdownToJSX.BlockQuoteNode\n const contBlockQuote = cont as MarkdownToJSX.BlockQuoteNode & {\n endPos: number\n }\n if (contBlockQuote.children)\n lastBlockQuote.children.push(...contBlockQuote.children)\n return contBlockQuote.endPos\n}\n\nfunction createHeading(\n level: number,\n children: MarkdownToJSX.ASTNode[],\n content: string,\n slugify: (str: string) => string\n): MarkdownToJSX.HeadingNode {\n return {\n type: RuleType.heading,\n level,\n children,\n id: slugify(content),\n } as MarkdownToJSX.HeadingNode\n}\n\n// Static regex patterns for performance\nexport const UNESCAPE_R: RegExp = /\\\\(.)/g\nconst HEADING_TRAILING_HASHES_R = /\\s+#+\\s*$/\n// Unified regex for all list item patterns: ordered (digit + delimiter + content) or unordered (marker + content)\n// Groups: 1=ordered_num, 2=ordered_delim, 3=ordered_content, 4=ordered_empty_num, 5=ordered_empty_delim, 6=unordered_marker, 7=unordered_content, 8=unordered_empty_marker\nconst LIST_ITEM_R =\n /^(?:(\\d{1,9})([.)])\\s+(.*)$|(\\d{1,9})([.)])\\s*$|([-*+])\\s+(.*)$|([-*+])\\s*$)/\n// List items with content (marker + whitespace + content or end of line) - for continuation matching\nconst ORDERED_LIST_ITEM_WITH_CONTENT_R = /^(\\d{1,9})([.)])(\\s+|$)/\nconst UNORDERED_LIST_ITEM_WITH_CONTENT_R = /^([*+\\-])(\\s+|$)/\nexport const HTML_BLOCK_ELEMENT_START_R: RegExp =\n /^<([a-z][^ >/\\n\\r]*) ?([^>]*?)>/i\nexport const HTML_BLOCK_ELEMENT_START_R_ATTR: RegExp =\n /^<([a-z][^ >/]*) ?(?:[^>/]+[^/]|)>/i\n\nvar charCode = function (c: string, pos: number = 0) {\n return c.charCodeAt(pos)\n}\nvar isAlnum = function (c: string): boolean {\n return util.isAlnumCode(charCode(c))\n}\nvar isWS = function (c: string) {\n return util.isASCIIWhitespace(charCode(c))\n}\nvar isSpaceOrTab = function (c: string): boolean {\n return c === ' ' || c === '\\t'\n}\nvar isPunctuation = function (code: number, char: string): boolean {\n return util.isUnicodePunctuation(code < $.CHAR_ASCII_BOUNDARY ? code : char)\n}\nvar isNameChar = function (c: string) {\n var n = charCode(c)\n return (\n isAlnum(c) ||\n n === $.CHAR_DASH ||\n n === $.CHAR_UNDERSCORE ||\n n === $.CHAR_COLON ||\n n === $.CHAR_PERIOD\n )\n}\n\n// HTML validation functions removed - parser only recognizes boundaries, not validates syntax\n// Per GFM spec: parser's job is to identify HTML boundaries and pass content opaquely\n\nfunction parseHTMLTagName(\n source: string,\n pos: number\n): { tagName: string; tagLower: string; nextPos: number } | null {\n var sourceLen = source.length\n if (pos >= sourceLen) return null\n var firstCharCode = charCode(source[pos])\n if (!isAlphaCode(firstCharCode)) return null\n var tagNameStart = pos\n var tagNameEnd = pos\n while (tagNameEnd < sourceLen) {\n var code = charCode(source[tagNameEnd])\n if (\n (code >= $.CHAR_a && code <= $.CHAR_z) ||\n (code >= $.CHAR_A && code <= $.CHAR_Z) ||\n (code >= $.CHAR_DIGIT_0 && code <= $.CHAR_DIGIT_9) ||\n code === $.CHAR_DASH\n ) {\n tagNameEnd++\n } else {\n var tagEndCode = charCode(source[tagNameEnd])\n if (\n tagEndCode === $.CHAR_SPACE ||\n tagEndCode === $.CHAR_TAB ||\n tagEndCode === $.CHAR_NEWLINE ||\n tagEndCode === $.CHAR_CR ||\n tagEndCode === $.CHAR_GT ||\n tagEndCode === $.CHAR_SLASH\n ) {\n break\n } else {\n return null\n }\n }\n }\n if (tagNameEnd === tagNameStart) return null\n var tagName = source.slice(tagNameStart, tagNameEnd)\n\n // Validate tag name according to spec: only ASCII letters, digits, hyphens\n for (var i = 0; i < tagName.length; i++) {\n var code = charCode(tagName[i])\n if (\n !(\n (code >= $.CHAR_a && code <= $.CHAR_z) ||\n (code >= $.CHAR_A && code <= $.CHAR_Z) ||\n (code >= $.CHAR_DIGIT_0 && code <= $.CHAR_DIGIT_9) ||\n code === $.CHAR_DASH\n )\n ) {\n return null\n }\n }\n\n return { tagName, tagLower: tagName.toLowerCase(), nextPos: tagNameEnd }\n}\n\n/** Unified HTML tag parser that handles opening, closing, and self-closing tags */\nexport function parseHTMLTag(\n source: string,\n pos: number\n): {\n tagName: string\n tagLower: string\n attrs: string\n endPos: number\n isClosing: boolean\n isSelfClosing: boolean\n hasNewline: boolean\n hasSpaceBeforeSlash: boolean\n whitespaceBeforeAttrs: string\n} | null {\n var token = scanRawHTML(source, pos)\n if (!token || token.kind !== 'tag') return null\n\n // Note: hasSpaceBeforeSlash is already validated in scanner (returns null if invalid)\n return {\n tagName: token.tagName || '',\n tagLower: token.tagNameLower || '',\n attrs: token.attrs || '',\n endPos: token.endPos,\n isClosing: token.isClosing || false,\n isSelfClosing: token.isSelfClosing || false,\n hasNewline: token.hasNewline,\n hasSpaceBeforeSlash: false,\n whitespaceBeforeAttrs: token.whitespaceBeforeAttrs || '',\n }\n}\n\n/** Find matching closing tag position for inline HTML tags. Returns [contentEnd, closingTagEnd] or null */\nfunction findInlineClosingTag(\n source: string,\n startPos: number,\n tagNameLower: string\n): [number, number] | null {\n var depth = 1\n var searchPos = startPos\n while (depth > 0 && searchPos < source.length) {\n var tagIdx = source.indexOf('<', searchPos)\n if (tagIdx === -1) return null\n var tagParseResult = parseHTMLTag(source, tagIdx)\n if (!tagParseResult) {\n searchPos = tagIdx + 1\n continue\n }\n if (\n tagParseResult.isClosing &&\n tagParseResult.tagLower === tagNameLower &&\n --depth === 0\n )\n return [tagIdx, tagParseResult.endPos]\n if (\n !tagParseResult.isClosing &&\n !tagParseResult.isSelfClosing &&\n tagParseResult.tagLower === tagNameLower\n )\n depth++\n searchPos = tagParseResult.endPos\n }\n return null\n}\n\nexport const INTERPOLATION_R: RegExp = /^\\{.*\\}$/\nconst DOUBLE_NEWLINE_R = /\\n\\n/\nconst BLOCK_SYNTAX_R =\n /^(\\s{0,3}#[#\\s]|\\s{0,3}[-*+]\\s|\\s{0,3}\\d+\\.\\s|\\s{0,3}>\\s|\\s{0,3}```)/m\nconst TYPE1_TAG_R = /<\\/?(?:pre|script|style|textarea)\\b/i\nexport const UPPERCASE_TAG_R: RegExp = /^<[A-Z]/\nconst TRAILING_NEWLINE_R = /\\n$/\nconst BLOCK_START_CHARS_SET = new Set([\n '#',\n '>',\n '-',\n '*',\n '+',\n '`',\n '|',\n '0',\n '1',\n '2',\n '3',\n '4',\n '5',\n '6',\n '7',\n '8',\n '9',\n])\n\n/** Find the next occurrence of a character, ignoring escaped versions */\nfunction findUnescapedChar(\n source: string,\n startPos: number,\n endPos: number,\n targetChar: string\n): number {\n let i = startPos\n while (i < endPos) {\n if (source[i] === '\\\\' && i + 1 < endPos) {\n i += 2\n continue\n }\n if (source[i] === targetChar) return i\n i++\n }\n return -1\n}\n\ntype StyleTuple = [key: string, value: string]\n\nfunction addStyleToCollection(styles: StyleTuple[], buffer: string): void {\n var colonIndex = buffer.indexOf(':')\n if (colonIndex > 0) {\n var value = buffer.slice(colonIndex + 1).trim()\n var len = value.length\n if (len >= 2) {\n var first = value[0]\n if ((first === '\"' || first === \"'\") && value[len - 1] === first) {\n value = value.slice(1, -1)\n }\n }\n styles.push([buffer.slice(0, colonIndex).trim(), value])\n }\n}\n\nexport function parseStyleAttribute(styleString: string): StyleTuple[] {\n var styles: StyleTuple[] = []\n if (!styleString) return styles\n\n var buffer = ''\n var depth = 0\n var quoteChar = ''\n\n for (var i = 0; i < styleString.length; i++) {\n var char = styleString[i]\n\n if (char === '\"' || char === \"'\") {\n if (!quoteChar) {\n quoteChar = char\n depth++\n } else if (char === quoteChar) {\n quoteChar = ''\n depth--\n }\n } else if (char === '(' && util.endsWith(buffer, 'url')) {\n depth++\n } else if (char === ')' && depth > 0) {\n depth--\n } else if (char === ';' && depth === 0) {\n addStyleToCollection(styles, buffer)\n buffer = ''\n continue\n }\n\n buffer += char\n }\n\n addStyleToCollection(styles, buffer)\n\n return styles\n}\n\nfunction attributeValueToJSXPropValue(\n tag: MarkdownToJSX.HTMLTags,\n key: string,\n value: string,\n sanitizeUrlFn: (\n value: string,\n tag: string,\n attribute: string\n ) => string | null,\n options: ParseOptions\n): any {\n if (key === 'style') {\n return parseStyleAttribute(value).reduce(\n function (styles, [k, v]) {\n const sanitized = sanitizeUrlFn(v, tag, k)\n if (sanitized != null) {\n styles[k.replace(/(-[a-z])/g, substr => substr[1].toUpperCase())] =\n sanitized\n }\n return styles\n },\n {} as { [key: string]: any }\n );\n }\n\n // Handle JSX expressions (braces) before sanitization\n // This allows parsing of arrays/objects in JSX props\n if (value.match(INTERPOLATION_R)) {\n value = value.slice(1, value.length - 1)\n value = value ? value.replace(UNESCAPE_R, '$1') : value\n\n // Try to parse as JSON for arrays/objects (best effort)\n // Keep as raw string for functions and complex expressions\n if (value.length > 0) {\n const firstChar = value[0]\n // Check if it looks like an array or object literal\n if (firstChar === '[' || firstChar === '{') {\n try {\n return JSON.parse(value)\n } catch (e) {\n // Not valid JSON, keep as string (e.g., functions, JSX expressions)\n return value\n }\n }\n }\n // For other expressions (functions, variables, etc.), keep as string by default\n // Only eval if explicitly opted-in (NOT recommended for user inputs)\n if (value === 'true') return true\n if (value === 'false') return false\n\n // Attempt to eval unserializable expressions only if explicitly enabled\n // ⚠️ WARNING: This uses eval() and should only be used with trusted content\n if (options.evalUnserializableExpressions) {\n try {\n // Try to evaluate as an expression (function, variable, etc.)\n // eslint-disable-next-line no-eval\n return eval(`(${value})`)\n } catch (e) {\n // If eval fails, return as string\n return value\n }\n }\n\n // Don't apply sanitization to JSX expressions\n // Keep as string - can be handled via renderRule on a case-by-case basis\n return value\n }\n\n if (util.ATTRIBUTES_TO_SANITIZE.indexOf(key) !== -1) {\n return sanitizeUrlFn(\n value ? value.replace(UNESCAPE_R, '$1') : value,\n tag,\n key\n )\n }\n\n return value === 'true' ? true : value === 'false' ? false : value\n}\n\nfunction parseHTMLAttributes(\n attrs: string,\n tagName: string,\n tagNameOriginal: string,\n options: ParseOptions\n): { [key: string]: any } {\n const result: { [key: string]: any } = {}\n if (!attrs || !attrs.trim()) return result\n\n const attrMatches: string[] = []\n let i = 0\n const len = attrs.length\n while (i < len) {\n while (i < len && isSpaceOrTab(attrs[i])) i++\n if (i >= len) break\n const nameStart = i\n while (i < len && isNameChar(attrs[i])) i++\n if (i === nameStart) {\n i++\n continue\n }\n const name = attrs.slice(nameStart, i)\n while (i < len && isSpaceOrTab(attrs[i])) i++\n if (i >= len || attrs[i] !== '=') {\n attrMatches.push(name)\n continue\n }\n i++\n while (i < len && isSpaceOrTab(attrs[i])) i++\n if (i >= len) {\n attrMatches.push(name + '=')\n break\n }\n const valueStart = i\n const q = attrs[i]\n if (q === '\"' || q === \"'\") {\n i++\n while (i < len) {\n if (attrs[i] === q) {\n if (i + 1 >= len) {\n i++\n break\n }\n const nextChar = attrs[i + 1]\n if (isSpaceOrTab(nextChar) || nextChar === '/') {\n i++\n break\n }\n }\n i++\n }\n } else if (q === '{') {\n let depth = 1\n i++\n while (i < len && depth > 0) {\n if (attrs[i] === '{') depth++\n else if (attrs[i] === '}') {\n depth--\n if (depth === 0) {\n i++\n break\n }\n }\n i++\n }\n } else {\n while (i < len && !isSpaceOrTab(attrs[i])) i++\n }\n attrMatches.push(name + '=' + attrs.slice(valueStart, i))\n }\n\n if (!attrMatches?.length) return result\n const tagNameLower = tagName.toLowerCase(),\n isJSXComponent =\n tagNameOriginal.length > 0 &&\n tagNameOriginal[0] >= 'A' &&\n tagNameOriginal[0] <= 'Z'\n for (let i = 0; i < attrMatches.length; i++) {\n const rawAttr = attrMatches[i],\n delimiterIdx = rawAttr.indexOf('=')\n if (delimiterIdx !== -1) {\n const key = rawAttr.slice(0, delimiterIdx).trim(),\n keyLower = key.toLowerCase()\n if (keyLower === 'ref') continue\n const attrKey = isJSXComponent ? key : keyLower,\n rawValue = rawAttr.slice(delimiterIdx + 1).trim(),\n value = ((str: string) => {\n const first = str[0]\n if (\n (first === '\"' || first === \"'\") &&\n str.length >= 2 &&\n str[str.length - 1] === first\n )\n return str.slice(1, -1)\n return str\n })(rawValue)\n\n if (\n (keyLower === 'href' && tagNameLower === 'a') ||\n (keyLower === 'src' && tagNameLower === 'img')\n ) {\n const safe = options.sanitizer(\n value,\n tagNameLower as MarkdownToJSX.HTMLTags,\n keyLower\n )\n if (safe == null) {\n warn(`Stripped unsafe ${keyLower} on <${tagNameOriginal}>`)\n continue\n }\n result[attrKey] = safe\n } else {\n const normalizedValue = attributeValueToJSXPropValue(\n tagNameLower as MarkdownToJSX.HTMLTags,\n keyLower,\n value,\n options.sanitizer,\n options\n )\n result[attrKey] = normalizedValue\n }\n } else if (rawAttr !== 'style')\n result[isJSXComponent ? rawAttr : rawAttr.toLowerCase()] = true\n }\n // Check for URI-encoded malicious content in the raw attributes string\n // Only decode if % is present (performance optimization)\n if (attrs.indexOf('%') !== -1) {\n try {\n if (util.SANITIZE_R.test(decodeURIComponent(attrs)))\n for (var key in result) delete result[key]\n } catch (e) {\n // Invalid URI encoding (e.g., \"100%\") - skip the check\n // Individual attributes were already sanitized above\n }\n } else if (util.SANITIZE_R.test(attrs)) {\n for (var key in result) delete result[key]\n }\n return result\n}\n\nexport type ParseResult = (MarkdownToJSX.ASTNode & { endPos: number }) | null\n\n/** Options passed to parsers */\nexport type ParseOptions = Omit<MarkdownToJSX.Options, 'slugify'> & {\n slugify: (input: string) => string\n}\n\nvar isBlockStartChar = function (c: string): boolean {\n return BLOCK_START_CHARS_SET.has(c)\n}\n\ninterface BracketEntry {\n type: 'link' | 'image'\n pos: number\n resultIdx: number\n inAnchor: boolean\n}\n\n// Check if an invalid reference definition should be skipped per CommonMark Examples 208 and 210\nfunction shouldSkipInvalidReferenceDefinition(\n input: string,\n refCheckPos: number,\n isAtDocumentStart: boolean\n): { shouldSkip: boolean; newPos: number } {\n // Find closing ']' handling escapes\n let bracketEnd = refCheckPos + 1\n while (bracketEnd < input.length && input[bracketEnd] !== ']') {\n if (input[bracketEnd] === '\\\\' && bracketEnd + 1 < input.length) {\n bracketEnd += 2\n continue\n }\n bracketEnd++\n }\n if (bracketEnd >= input.length) return { shouldSkip: false, newPos: 0 }\n\n // Check if label starts/ends with newline (Example 208 pattern)\n const labelStart = refCheckPos + 1\n const labelEnd = bracketEnd\n const labelStartsWithNewline =\n labelStart < labelEnd &&\n (input[labelStart] === '\\n' || input[labelStart] === '\\r')\n const labelEndsWithNewline =\n labelEnd > labelStart &&\n (input[labelEnd - 1] === '\\n' || input[labelEnd - 1] === '\\r')\n\n let afterBracket = bracketEnd + 1\n // Skip whitespace after ']'\n afterBracket = util.skipWhitespace(input, afterBracket)\n\n // Check for colon\n if (afterBracket >= input.length || input[afterBracket] !== ':') {\n return { shouldSkip: false, newPos: 0 }\n }\n\n // Found colon - check for Example 208 pattern (label starts/ends with newline at document start)\n if ((labelStartsWithNewline || labelEndsWithNewline) && isAtDocumentStart) {\n // Invalid ref definition per Example 208 - skip to next line after URL\n let skipPos = afterBracket + 1\n skipPos = util.skipWhitespace(input, skipPos)\n // Skip optional newline\n if (skipPos < input.length && input[skipPos] === '\\n') {\n skipPos = util.skipWhitespace(input, skipPos + 1)\n }\n // Find end of URL line (next newline)\n while (skipPos < input.length && input[skipPos] !== '\\n') {\n skipPos++\n }\n if (skipPos < input.length) {\n skipPos++\n }\n return { shouldSkip: true, newPos: skipPos }\n }\n\n // Check for Example 210 pattern (trailing text after title)\n return checkExample210Pattern(input, afterBracket)\n}\n\n// Helper for Example 210: trailing text after title\nfunction checkExample210Pattern(\n input: string,\n colonPos: number\n): { shouldSkip: boolean; newPos: number } {\n let urlEnd = colonPos + 1\n urlEnd = util.skipWhitespace(input, urlEnd)\n // Skip optional newline\n if (urlEnd < input.length && input[urlEnd] === '\\n') {\n urlEnd = util.skipWhitespace(input, urlEnd + 1)\n }\n // Find end of URL (next newline)\n while (urlEnd < input.length && input[urlEnd] !== '\\n') {\n urlEnd++\n }\n if (urlEnd >= input.length) return { shouldSkip: false, newPos: 0 }\n\n urlEnd++\n // Check for title delimiter on next line\n let titleLineStart = util.skipWhitespace(input, urlEnd)\n if (\n titleLineStart >= input.length ||\n (input[titleLineStart] !== '\"' && input[titleLineStart] !== \"'\")\n ) {\n return { shouldSkip: false, newPos: 0 }\n }\n\n // Has title delimiter - check for trailing text (Example 210)\n const titleChar = input[titleLineStart]\n let titleEnd = titleLineStart + 1\n while (\n titleEnd < input.length &&\n input[titleEnd] !== titleChar &&\n input[titleEnd] !== '\\n'\n ) {\n if (input[titleEnd] === '\\\\' && titleEnd + 1 < input.length) {\n titleEnd += 2\n continue\n }\n titleEnd++\n }\n if (titleEnd >= input.length || input[titleEnd] !== titleChar) {\n return { shouldSkip: false, newPos: 0 }\n }\n\n // Found closing quote - check for trailing text\n let afterTitle = util.skipWhitespace(input, titleEnd + 1)\n if (\n afterTitle < input.length &&\n input[afterTitle] !== '\\n' &&\n input[afterTitle] !== '\\r'\n ) {\n // Trailing text found - invalid ref definition per Example 210\n return { shouldSkip: true, newPos: urlEnd }\n }\n\n return { shouldSkip: false, newPos: 0 }\n}\n\n// Check if nodes contain a link (prevents nested links per CommonMark)\nfunction containsLink(nodes: MarkdownToJSX.ASTNode[]): boolean {\n for (var i = 0; i < nodes.length; i++) {\n var node = nodes[i]\n if (node.type === RuleType.link) return true\n if (node.type === RuleType.textFormatted) {\n var formattedNode = node as MarkdownToJSX.FormattedTextNode\n if (formattedNode.children && containsLink(formattedNode.children))\n return true\n }\n }\n return false\n}\n\nfunction extractAllTextFromNodes(nodes: MarkdownToJSX.ASTNode[]): string {\n var text = ''\n for (var i = 0, len = nodes.length; i < len; i++) {\n var node = nodes[i]\n var type = node.type\n if (type === RuleType.text) {\n text += (node as MarkdownToJSX.TextNode).text\n } else if (type === RuleType.image) {\n var imgNode = node as MarkdownToJSX.ImageNode\n if (imgNode.alt) text += imgNode.alt\n } else if (type === RuleType.textFormatted) {\n var formattedNode = node as MarkdownToJSX.FormattedTextNode\n if (formattedNode.children) {\n text += extractAllTextFromNodes(formattedNode.children)\n }\n } else if (type === RuleType.link) {\n var linkNode = node as MarkdownToJSX.LinkNode\n if (linkNode.children) {\n text += extractAllTextFromNodes(linkNode.children)\n }\n }\n }\n return text\n}\n\nconst WHITESPACE_CHARS = new Set([' ', '\\t', '\\r', '\\n', '\\f', '\\v'])\n\n/**\n * Single pass, no recursion, eliminates parseLink/parseImage/parseRefLink/parseRefImage functions\n */\nfunction parseInlineSpan(\n source: string,\n start: number,\n end: number,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): MarkdownToJSX.ASTNode[] {\n var result: MarkdownToJSX.ASTNode[] = []\n var delimiterStack: DelimiterEntry[] = []\n var bracketStack: BracketEntry[] = []\n\n var pos = start\n var textStart = start\n var skipAutoLink = options.disableAutoLink || state.inAnchor\n var hasAmpersand = false\n var inAnchor = !!state.inAnchor\n var disableParsingRawHTML = !!options.disableParsingRawHTML\n\n // Helper: handle HTML tag parsing (angle brace autolinks, comments, tags, type 7 blocks)\n var handleHTMLTag = function (\n checkType7Block: boolean,\n respectDisableAutoLink: boolean\n ): boolean {\n if (!inAnchor && (!respectDisableAutoLink || !options.disableAutoLink)) {\n var angleBraceResult = parseLinkOrImage(source, pos, state, options, '<')\n if (angleBraceResult) {\n flushText(pos)\n result.push(angleBraceResult)\n pos = angleBraceResult.endPos\n textStart = pos\n return true\n }\n }\n\n // Skip HTML parsing if disableParsingRawHTML is enabled\n if (disableParsingRawHTML) {\n return false\n }\n\n var htmlResult = parseHTML(source, pos, state, options)\n if (htmlResult) {\n flushText(pos)\n result.push(htmlResult)\n pos = htmlResult.endPos\n textStart = pos\n return true\n }\n\n if (!checkType7Block) return false\n var tagCheckResult = parseHTMLTag(source, pos)\n if (!tagCheckResult) return false\n var tagNameStart = pos + (tagCheckResult.isClosing ? 2 : 1)\n if (tagNameStart >= source.length || isSpaceOrTab(source[tagNameStart]))\n return false\n var closeIdx = source.indexOf('>', pos + 1)\n if (closeIdx !== -1) {\n var contentStart = pos + 1\n var contentLen = closeIdx - contentStart\n if (contentLen >= 7) {\n var isHttp = util.startsWith(source, 'http://', contentStart)\n if (isHttp || util.startsWith(source, 'https://', contentStart)) {\n for (var j = contentStart; j < closeIdx; j++) {\n if (isSpaceOrTab(source[j])) return false\n }\n }\n }\n }\n var tagFirstCharCode = charCode(source, tagNameStart)\n if (\n isAlphaCode(tagFirstCharCode) &&\n tagNameStart + 1 < source.length &&\n source[tagNameStart + 1] === ':'\n )\n return false\n if (tagCheckResult.isClosing && tagCheckResult.attrs.trim().length)\n return false\n\n if (tagCheckResult.attrs.length) {\n var inQuotes = false\n var quoteChar = ''\n for (var i = 0; i < tagCheckResult.attrs.length; i++) {\n var ch = tagCheckResult.attrs[i]\n if (inQuotes && ch === quoteChar) {\n inQuotes = false\n } else if (!inQuotes && (ch === '\"' || ch === \"'\")) {\n inQuotes = true\n quoteChar = ch\n } else if (ch === '*' || ch === '#' || ch === '!') {\n var checkAhead = i + 1\n while (\n checkAhead < tagCheckResult.attrs.length &&\n tagCheckResult.attrs[checkAhead] !== '=' &&\n tagCheckResult.attrs[checkAhead] !== ' ' &&\n tagCheckResult.attrs[checkAhead] !== '\\t'\n )\n checkAhead++\n if (\n checkAhead < tagCheckResult.attrs.length &&\n tagCheckResult.attrs[checkAhead] === '='\n )\n return false\n }\n }\n }\n\n // Valid tag with newline - type 7 block, preserve as raw HTML\n // But still parse content into children\n var rawText = source.slice(pos, tagCheckResult.endPos)\n var tagName = tagCheckResult.tagName.toLowerCase()\n var contentToParse = rawText\n // Extract content if rawText includes opening tag\n var tagEnd = contentToParse.indexOf('>')\n if (tagEnd !== -1) {\n contentToParse = contentToParse.slice(tagEnd + 1)\n var closingTag = '</' + tagName + '>'\n var closingIdx = contentToParse.indexOf(closingTag)\n if (closingIdx !== -1) {\n contentToParse = contentToParse.slice(0, closingIdx)\n }\n }\n var children: MarkdownToJSX.ASTNode[] = []\n if (contentToParse.trim() && options) {\n var parseState: MarkdownToJSX.State = {\n ...state,\n inline: false,\n inHTML: true,\n }\n var trimmed = contentToParse.trim()\n if (\n DOUBLE_NEWLINE_R.test(trimmed) ||\n BLOCK_SYNTAX_R.test(trimmed) ||\n HTML_BLOCK_ELEMENT_START_R.test(trimmed)\n ) {\n children = parseBlocksInHTML(trimmed, parseState, options)\n } else if (trimmed) {\n parseState.inline = true\n children = parseInlineSpan(\n trimmed,\n 0,\n trimmed.length,\n parseState,\n options\n )\n }\n }\n var htmlBlockResult = {\n type: RuleType.htmlBlock,\n tag: tagCheckResult.tagName as MarkdownToJSX.HTMLTags,\n attrs: {},\n children: children,\n rawText: rawText,\n text: rawText, // @deprecated - use rawText instead\n verbatim: true,\n endPos: tagCheckResult.endPos,\n } as MarkdownToJSX.HTMLNode & { endPos: number }\n flushText(pos)\n result.push(htmlBlockResult)\n pos = htmlBlockResult.endPos\n textStart = pos\n return true\n }\n\n var flushText = function (endPos: number) {\n if (endPos > textStart) {\n var text = source.slice(textStart, endPos)\n result.push({\n type: RuleType.text,\n text: hasAmpersand ? util.decodeEntityReferences(text) : text,\n } as MarkdownToJSX.TextNode)\n textStart = endPos\n hasAmpersand = false\n }\n }\n\n while (pos < end) {\n var code = charCode(source, pos)\n var charType = getCharType(code, skipAutoLink)\n\n if (charType === 0) {\n if (code === $.CHAR_AMPERSAND) hasAmpersand = true\n pos++\n // Fast path for ASCII text - avoid repeated charCode calls and lookups\n while (pos < end) {\n code = charCode(source, pos)\n if (code >= $.CHAR_ASCII_BOUNDARY) break\n if (code === $.CHAR_AMPERSAND) hasAmpersand = true\n var lookupCharType = util.inlineCharTypeTable[code]\n if (lookupCharType !== 0) {\n // Check for autolink exception\n if (\n skipAutoLink &&\n lookupCharType === 1 &&\n (code === $.CHAR_f || code === $.CHAR_H || code === $.CHAR_W)\n ) {\n pos++\n continue\n }\n break\n }\n pos++\n }\n continue\n }\n\n // CODE SPANS (highest priority, no nesting)\n if (code === $.CHAR_BACKTICK) {\n var backtickStart = pos\n var backtickCount = 0\n while (pos + backtickCount < end) {\n if (charCode(source, pos + backtickCount) !== $.CHAR_BACKTICK) break\n backtickCount++\n }\n\n if (backtickCount > 0) {\n var contentStart = pos + backtickCount\n var contentEnd = -1\n var i = contentStart\n // Scan character by character for closing backticks - faster than indexOf\n while (i < end) {\n // Find next backtick\n while (i < end && charCode(source, i) !== $.CHAR_BACKTICK) i++\n if (i >= end) break\n\n // Count consecutive backticks\n var closingCount = 0\n while (\n i + closingCount < end &&\n charCode(source, i + closingCount) === $.CHAR_BACKTICK\n ) {\n closingCount++\n }\n if (closingCount > backtickCount) closingCount = backtickCount\n var j = i + closingCount\n\n // Check if this is a valid closing sequence\n if (\n closingCount === backtickCount &&\n (i <= contentStart ||\n charCode(source, i - 1) !== $.CHAR_BACKTICK) &&\n (j >= end || charCode(source, j) !== $.CHAR_BACKTICK)\n ) {\n contentEnd = i\n i = j\n break\n }\n i++\n }\n\n if (contentEnd !== -1) {\n var rawContent = source.slice(contentStart, contentEnd)\n var hasNewline = false\n for (var k = 0; k < rawContent.length; k++) {\n var nlCode = charCode(rawContent, k)\n if (nlCode === $.CHAR_NEWLINE || nlCode === $.CHAR_CR) {\n hasNewline = true\n break\n }\n }\n var content = rawContent\n if (hasNewline) {\n // Optimize newline replacement by avoiding regex\n content = rawContent\n .replace(/\\r\\n/g, ' ')\n .replace(/\\r/g, ' ')\n .replace(/\\n/g, ' ')\n }\n if (content.length > 0) {\n var firstChar = charCode(content, 0)\n var lastChar = charCode(content, content.length - 1)\n if (firstChar === $.CHAR_SPACE && lastChar === $.CHAR_SPACE) {\n for (var idx = 1; idx < content.length - 1; idx++) {\n if (charCode(content, idx) !== $.CHAR_SPACE) {\n content = content.slice(1, content.length - 1)\n break\n }\n }\n }\n }\n\n flushText(backtickStart)\n result.push({\n type: RuleType.codeInline,\n text: content,\n } as MarkdownToJSX.CodeInlineNode)\n pos = i\n textStart = pos\n continue\n }\n pos = contentStart\n continue\n }\n }\n\n // AUTOLINKS: BARE URLS AND EMAIL (check BEFORE escapes to preserve backslashes in URLs)\n if (\n !inAnchor &&\n !skipAutoLink &&\n (code === $.CHAR_f || code === $.CHAR_H || code === $.CHAR_W)\n ) {\n var autolinkType: 'h' | 'w' | 'f' | null = null\n // Cache character codes to avoid repeated function calls\n var c1 = pos + 1 < end ? charCode(source, pos + 1) : 0\n var c2 = pos + 2 < end ? charCode(source, pos + 2) : 0\n var c3 = pos + 3 < end ? charCode(source, pos + 3) : 0\n var c4 = pos + 4 < end ? charCode(source, pos + 4) : 0\n var c5 = pos + 5 < end ? charCode(source, pos + 5) : 0\n\n if (\n code === $.CHAR_H &&\n c1 === $.CHAR_t &&\n c2 === $.CHAR_t &&\n c3 === $.CHAR_p\n ) {\n autolinkType = 'h'\n } else if (\n code === $.CHAR_W &&\n c1 === $.CHAR_W &&\n c2 === $.CHAR_W &&\n c3 === $.CHAR_PERIOD\n ) {\n autolinkType = 'w'\n } else if (\n code === $.CHAR_f &&\n c1 === $.CHAR_t &&\n c2 === $.CHAR_p &&\n c3 === $.CHAR_COLON &&\n c4 === $.CHAR_SLASH &&\n c5 === $.CHAR_SLASH\n ) {\n autolinkType = 'f'\n }\n if (autolinkType) {\n var bareUrlResult = parseLinkOrImage(\n source,\n pos,\n state,\n options,\n autolinkType\n )\n if (bareUrlResult) {\n flushText(pos)\n result.push(bareUrlResult)\n pos = bareUrlResult.endPos\n textStart = pos\n continue\n }\n }\n }\n\n if (!inAnchor && !skipAutoLink && code === $.CHAR_AT) {\n var emailResult = parseLinkOrImage(source, pos, state, options, '@')\n if (emailResult && 'emailStart' in emailResult) {\n var emailStart = (\n emailResult as MarkdownToJSX.LinkNode & {\n endPos: number\n emailStart: number\n }\n ).emailStart\n var emailEnd = emailResult.endPos\n var removedIndices: number[] = []\n for (var j = delimiterStack.length - 1; j >= 0; j--) {\n var delim = delimiterStack[j]\n if (delim.sourcePos >= emailStart && delim.sourcePos < emailEnd) {\n if (delim.nodeIndex >= 0 && delim.nodeIndex < result.length) {\n result.splice(delim.nodeIndex, 1)\n removedIndices.push(delim.nodeIndex)\n }\n delimiterStack.splice(j, 1)\n }\n }\n if (emailStart < textStart) {\n for (var i = result.length - 1; i >= 0; i--) {\n if (result[i].type === RuleType.text) {\n result.splice(i, 1)\n removedIndices.push(i)\n break\n }\n }\n textStart = emailStart\n }\n // Batch update delimiter indices after all removals (O(n+m) instead of O(n*m))\n if (removedIndices.length) {\n removedIndices.sort(function (a, b) {\n return a - b\n })\n var removedIdx = 0\n for (var m = 0; m < delimiterStack.length; m++) {\n var delim = delimiterStack[m]\n while (\n removedIdx < removedIndices.length &&\n removedIndices[removedIdx] < delim.nodeIndex\n )\n removedIdx++\n delim.nodeIndex -= removedIdx\n }\n }\n flushText(emailStart)\n result.push(emailResult)\n pos = emailEnd\n textStart = pos\n continue\n }\n }\n\n // HTML TAGS AND AUTOLINKS (check BEFORE escapes to preserve backslashes in autolinks)\n if (code === $.CHAR_LT) {\n if (handleHTMLTag(true, false)) continue\n }\n\n // BACKSLASH ESCAPES\n if (code === $.CHAR_BACKSLASH) {\n if (pos + 1 < end && charCode(source, pos + 1) === $.CHAR_NEWLINE) {\n var afterNewline = pos + 2\n while (\n afterNewline < end &&\n charCode(source, afterNewline) === $.CHAR_SPACE\n )\n afterNewline++\n if (afterNewline >= end) {\n pos++\n continue\n }\n flushText(pos)\n result.push({ type: RuleType.breakLine } as MarkdownToJSX.BreakLineNode)\n pos += 2\n while (pos < end && charCode(source, pos) === $.CHAR_SPACE) pos++\n textStart = pos\n continue\n }\n\n var nextChar = pos + 1 < end ? source[pos + 1] : ''\n if (\n nextChar &&\n '!\"#$%&\\'()*+,-./:;<=>?@[\\\\]^_`{|}~'.indexOf(nextChar) !== -1\n ) {\n flushText(pos)\n result.push({\n type: RuleType.text,\n text: nextChar === '&' ? '&\\u200B' : nextChar,\n } as MarkdownToJSX.TextNode)\n pos += 2\n textStart = pos\n continue\n }\n }\n\n // LINKS AND IMAGES - OPENING BRACKET\n if (code === $.CHAR_BRACKET_OPEN) {\n if (!inAnchor) {\n if (pos + 1 < end && source[pos + 1] === '^') {\n var footnoteEndPos = pos + 2\n while (footnoteEndPos < end && source[footnoteEndPos] !== ']')\n footnoteEndPos++\n if (footnoteEndPos < end) {\n var identifier = source.slice(pos + 2, footnoteEndPos)\n flushText(pos)\n result.push({\n type: RuleType.footnoteReference,\n target: `#${options.slugify(identifier)}`,\n text: identifier,\n } as MarkdownToJSX.FootnoteReferenceNode)\n pos = footnoteEndPos + 1\n textStart = pos\n continue\n }\n }\n\n if (\n state.inList &&\n pos + 2 < end &&\n charCode(source, pos + 2) === $.CHAR_BRACKET_CLOSE\n ) {\n var nextCode = charCode(source, pos + 1)\n if (\n nextCode === $.CHAR_SPACE ||\n nextCode === $.CHAR_x ||\n nextCode === $.CHAR_X\n ) {\n flushText(pos)\n result.push({\n type: RuleType.gfmTask,\n completed: nextCode === $.CHAR_x || nextCode === $.CHAR_X,\n } as MarkdownToJSX.GFMTaskNode)\n pos += 3\n textStart = pos\n continue\n }\n }\n }\n\n var isImage = false\n if (pos > start && source[pos - 1] === '!') {\n var backslashCount = 0\n for (\n var checkPos = pos - 2;\n checkPos >= start && source[checkPos] === '\\\\';\n checkPos--\n )\n backslashCount++\n if ((backslashCount & 1) === 0) {\n isImage = true\n if (textStart < pos - 1) flushText(pos - 1)\n if (\n result.length > 0 &&\n result[result.length - 1].type === RuleType.text\n ) {\n var lastText = result[result.length - 1] as MarkdownToJSX.TextNode\n if (lastText.text.endsWith('!')) {\n lastText.text = lastText.text.slice(0, -1)\n if (!lastText.text) result.pop()\n }\n }\n }\n }\n if (!isImage) flushText(pos)\n textStart = pos + 1\n if (!inAnchor || isImage) {\n bracketStack.push({\n type: isImage ? 'image' : 'link',\n pos: isImage ? pos - 1 : pos,\n resultIdx: result.length,\n inAnchor: inAnchor,\n })\n }\n\n pos++\n continue\n }\n\n // LINKS AND IMAGES - CLOSING BRACKET\n if (code === $.CHAR_BRACKET_CLOSE && bracketStack.length > 0) {\n var bracket = bracketStack[bracketStack.length - 1]\n var linkTextStart = bracket.pos + (bracket.type === 'image' ? 2 : 1)\n var linkTextEnd = pos\n flushText(pos)\n var afterBracket = pos + 1\n var linkChildren = buildLinkChildren(result, bracket)\n var hasNestedLink = bracket.type === 'link' && containsLink(linkChildren)\n var foundRefBrackets = false\n\n if (\n !hasNestedLink &&\n afterBracket < end &&\n source[afterBracket] === '('\n ) {\n var urlResult = parseUrlAndTitle(source, afterBracket + 1, true)\n if (urlResult) {\n finalizeLinkOrImageNode(\n result,\n delimiterStack,\n bracketStack,\n bracket,\n linkTextStart,\n linkTextEnd,\n options.sanitizer(\n unescapeUrlOrTitle(urlResult.target),\n 'a',\n 'href'\n ),\n urlResult.title ? unescapeUrlOrTitle(urlResult.title) : undefined\n )\n pos = urlResult.endPos\n textStart = pos\n continue\n }\n }\n\n var refs = state.refs || {}\n util.hasKeys(refs);\n var refLabel: string | null = null\n var refEnd = pos\n if (afterBracket < end && source[afterBracket] === '[') {\n var refStart = afterBracket + 1\n var i = refStart\n while (i < end && source[i] !== ']') i++\n if (i < end) {\n refLabel = source.slice(refStart, i)\n refEnd = i\n foundRefBrackets = true\n }\n }\n if (!foundRefBrackets || refLabel === '')\n refLabel = source.slice(linkTextStart, linkTextEnd)\n var normalizedRef = normalizeReferenceLabel(refLabel)\n if (!hasNestedLink && refs && refs[normalizedRef]) {\n var ref = refs[normalizedRef]\n finalizeLinkOrImageNode(\n result,\n delimiterStack,\n bracketStack,\n bracket,\n linkTextStart,\n linkTextEnd,\n ref.target,\n ref.title\n )\n pos = refEnd + 1\n textStart = pos\n continue\n }\n\n var bracketResultIdx = bracket.resultIdx\n bracketStack.pop()\n result.length = bracketResultIdx\n if (bracket.type === 'image')\n result.push({\n type: RuleType.text,\n text: '!',\n } as MarkdownToJSX.TextNode)\n result.push(\n { type: RuleType.text, text: '[' } as MarkdownToJSX.TextNode,\n ...linkChildren,\n { type: RuleType.text, text: ']' } as MarkdownToJSX.TextNode\n )\n for (var k = 0; k < delimiterStack.length; k++) {\n if (delimiterStack[k].nodeIndex >= bracketResultIdx)\n delimiterStack[k].nodeIndex++\n }\n pos++\n textStart = pos\n continue\n }\n\n // ========================================\n // EMPHASIS AND STRIKETHROUGH DELIMITERS (*, _, ~~, ==)\n // ========================================\n if (\n code === $.CHAR_ASTERISK ||\n code === $.CHAR_UNDERSCORE ||\n code === $.CHAR_TILDE ||\n code === $.CHAR_EQ\n ) {\n var delimChar = source[pos]\n var delimStart = pos\n var delimCount = countConsecutiveChars(source, pos, delimChar)\n\n // GFM strikethrough (~~) and marked text (==) require exactly 2 delimiters\n if ((delimChar === '~' || delimChar === '=') && delimCount !== 2) {\n pos++\n continue\n }\n\n var delimiterEnd = delimStart + delimCount\n var leftFlanking = checkFlanking(source, delimStart, delimiterEnd, end, 0)\n var rightFlanking = checkFlanking(\n source,\n delimStart,\n delimiterEnd,\n start,\n 1\n )\n var canOpen = leftFlanking\n var canClose = rightFlanking\n if (delimChar === '_' && leftFlanking && rightFlanking) {\n if (delimStart > 0) {\n var precedingChar = source[delimStart - 1]\n var precedingCode = charCode(precedingChar)\n canOpen = isPunctuation(precedingCode, precedingChar)\n }\n if (delimiterEnd < end) {\n var followingChar = source[delimiterEnd]\n var followingCode = charCode(followingChar)\n canClose = isPunctuation(followingCode, followingChar)\n }\n }\n flushText(delimStart)\n delimiterStack.push({\n nodeIndex: result.length,\n type: delimChar as '*' | '_' | '~' | '=',\n length: delimCount,\n canOpen: canOpen,\n canClose: canClose,\n active: true,\n sourcePos: delimStart,\n inAnchor: inAnchor,\n })\n result.push({\n type: RuleType.text,\n text: source.slice(delimStart, delimStart + delimCount),\n } as MarkdownToJSX.TextNode)\n\n pos = delimStart + delimCount\n textStart = pos\n continue\n }\n\n // ========================================\n // LINE BREAKS\n // ========================================\n if (code === $.CHAR_NEWLINE) {\n var checkPos = pos - 1\n var spaceCount = 0\n while (\n checkPos >= textStart &&\n charCode(source, checkPos) === $.CHAR_SPACE\n ) {\n spaceCount++\n checkPos--\n }\n if (spaceCount >= 2) {\n var afterNewline = pos + 1\n while (\n afterNewline < end &&\n charCode(source, afterNewline) === $.CHAR_SPACE\n )\n afterNewline++\n if (afterNewline >= end) {\n flushText(checkPos + 1)\n pos = end\n textStart = end\n continue\n }\n flushText(checkPos + 1)\n result.push({ type: RuleType.breakLine } as MarkdownToJSX.BreakLineNode)\n pos++\n while (pos < end && charCode(source, pos) === $.CHAR_SPACE) pos++\n textStart = pos\n continue\n }\n\n var prevCode = pos > textStart ? charCode(source, pos - 1) : 0\n var nextCode = pos + 1 < end ? charCode(source, pos + 1) : 0\n var flushPos =\n pos > textStart &&\n prevCode === $.CHAR_SPACE &&\n nextCode === $.CHAR_SPACE\n ? pos - 1\n : pos\n flushText(flushPos)\n result.push({ type: RuleType.text, text: '\\n' } as MarkdownToJSX.TextNode)\n textStart = pos + 1\n if (\n pos > start &&\n prevCode === $.CHAR_SPACE &&\n textStart < end &&\n charCode(source, textStart) === $.CHAR_SPACE\n )\n textStart++\n pos = textStart\n continue\n }\n\n if (code === $.CHAR_AMPERSAND) hasAmpersand = true\n pos++\n while (pos < end) {\n var code = charCode(source, pos)\n if (code >= $.CHAR_ASCII_BOUNDARY) break\n if (code === $.CHAR_AMPERSAND) hasAmpersand = true\n var lookupCharType = util.inlineCharTypeTable[code]\n if (lookupCharType === 0) {\n pos++\n continue\n }\n if (\n lookupCharType === 1 &&\n (code === $.CHAR_f || code === $.CHAR_H || code === $.CHAR_W) &&\n skipAutoLink\n ) {\n pos++\n continue\n }\n break\n }\n }\n\n flushText(pos)\n\n // Process emphasis using delimiter stack algorithm\n if (delimiterStack.length) {\n processEmphasis(result, delimiterStack, null)\n }\n\n // Insert bracket text nodes in forward order (more efficient than reverse splices)\n if (bracketStack.length) {\n bracketStack.sort(function (a, b) {\n return a.resultIdx - b.resultIdx\n })\n for (var i = 0; i < bracketStack.length; i++) {\n result.splice(bracketStack[i].resultIdx + i, 0, {\n type: RuleType.text,\n text: bracketStack[i].type === 'image' ? '![' : '[',\n } as MarkdownToJSX.TextNode)\n }\n }\n\n return result\n}\n\n// Helper: Process emphasis within link/image text and update delimiter stack\nfunction processEmphasisInLinkText(\n result: MarkdownToJSX.ASTNode[],\n delimiterStack: DelimiterEntry[],\n bracket: BracketEntry,\n linkTextStart: number,\n linkTextEnd: number\n): void {\n var hasDelims = false\n for (var di = 0; di < delimiterStack.length; di++) {\n if (\n delimiterStack[di].sourcePos >= linkTextStart &&\n delimiterStack[di].sourcePos < linkTextEnd\n ) {\n hasDelims = true\n break\n }\n }\n if (!hasDelims) return\n\n var tempNodes = buildLinkChildren(result, bracket)\n var tempDelims: DelimiterEntry[] = []\n for (var di = 0; di < delimiterStack.length; di++) {\n var delim = delimiterStack[di]\n if (delim.sourcePos >= linkTextStart && delim.sourcePos < linkTextEnd) {\n tempDelims.push({\n nodeIndex: delim.nodeIndex - bracket.resultIdx,\n type: delim.type,\n length: delim.length,\n canOpen: delim.canOpen,\n canClose: delim.canClose,\n active: delim.active,\n sourcePos: delim.sourcePos,\n inAnchor: delim.inAnchor,\n })\n }\n }\n processEmphasis(tempNodes, tempDelims, null)\n result.length = bracket.resultIdx\n for (var i = 0; i < tempNodes.length; i++) result.push(tempNodes[i])\n var newDelimStack: DelimiterEntry[] = []\n for (var di = 0; di < delimiterStack.length; di++) {\n if (\n delimiterStack[di].sourcePos < linkTextStart ||\n delimiterStack[di].sourcePos >= linkTextEnd\n ) {\n newDelimStack.push(delimiterStack[di])\n }\n }\n delimiterStack.length = 0\n for (var i = 0; i < newDelimStack.length; i++)\n delimiterStack.push(newDelimStack[i])\n}\n\n// Helper: Create link or image node from children and target/title\nfunction createLinkOrImageNode(\n bracket: BracketEntry,\n linkChildren: MarkdownToJSX.ASTNode[],\n target: string | null,\n title: string | undefined\n): MarkdownToJSX.ASTNode {\n if (bracket.type === 'link') {\n return {\n type: RuleType.link,\n target: target,\n title: title,\n children: linkChildren,\n } as MarkdownToJSX.LinkNode\n }\n return {\n type: RuleType.image,\n target: target || '',\n alt: extractAllTextFromNodes(linkChildren),\n title: title,\n } as MarkdownToJSX.ImageNode\n}\n\nfunction buildLinkChildren(\n result: MarkdownToJSX.ASTNode[],\n bracket: BracketEntry\n): MarkdownToJSX.ASTNode[] {\n return result.slice(bracket.resultIdx)\n}\n\nfunction finalizeLinkOrImageNode(\n result: MarkdownToJSX.ASTNode[],\n delimiterStack: DelimiterEntry[],\n bracketStack: BracketEntry[],\n bracket: BracketEntry,\n linkTextStart: number,\n linkTextEnd: number,\n target: string | null,\n title: string | undefined\n): void {\n processEmphasisInLinkText(\n result,\n delimiterStack,\n bracket,\n linkTextStart,\n linkTextEnd\n )\n var linkChildren = buildLinkChildren(result, bracket)\n bracketStack.pop()\n result.length = bracket.resultIdx\n result.push(createLinkOrImageNode(bracket, linkChildren, target, title))\n}\n\n/** Parse URL and optional title from parentheses: (url \"title\") */\n// Parse link destination (URL) - handles angle brackets and regular URLs\nfunction parseLinkDestination(\n source: string,\n start: number,\n allowNestedParens: boolean\n): { target: string; endPos: number; hadSpace: boolean } | null {\n let i = util.skipWhitespace(source, start)\n const hasAngleBrackets = i < source.length && source[i] === '<'\n if (hasAngleBrackets) i++\n const actualUrlStart = i\n\n // Handle empty angle brackets <>\n if (hasAngleBrackets && i < source.length && source[i] === '>') {\n return { target: '', endPos: i + 1, hadSpace: false }\n }\n\n let target: string\n let urlEnd: number\n var foundSpace = false\n\n if (hasAngleBrackets) {\n // For angle bracket URLs, parse until '>', allowing spaces and handling escapes\n urlEnd = i\n while (urlEnd < source.length && source[urlEnd] !== '>') {\n const c = source[urlEnd]\n if (c === '\\n' || c === '\\r' || c === '<') return null\n if (c === '\\\\') {\n urlEnd += 2\n continue\n }\n urlEnd++\n }\n if (urlEnd >= source.length || source[urlEnd] !== '>') return null\n urlEnd++\n // Trim leading and trailing whitespace inside < >\n let actualStart = actualUrlStart\n while (actualStart < urlEnd - 1 && isSpaceOrTab(source[actualStart]))\n actualStart++\n let actualEnd = urlEnd - 1\n while (actualEnd > actualStart && isSpaceOrTab(source[actualEnd - 1]))\n actualEnd--\n target = source.slice(actualStart, actualEnd)\n i = urlEnd\n } else {\n // Non-angle bracket URL: break on whitespace, newline\n let parenDepth = 0\n urlEnd = i\n while (urlEnd < source.length) {\n const c = source[urlEnd]\n if (c === ' ' || c === '\\t' || c === '\\n') {\n foundSpace = true\n break\n }\n if (!allowNestedParens && c === ')') break\n if (allowNestedParens && c === '(') {\n if (urlEnd > 0 && source[urlEnd - 1] === '\\\\') {\n urlEnd++\n continue\n }\n parenDepth++\n urlEnd++\n continue\n }\n if (allowNestedParens && c === ')') {\n if (urlEnd > 0 && source[urlEnd - 1] === '\\\\') {\n urlEnd++\n continue\n }\n if (parenDepth === 0) break\n parenDepth--\n urlEnd++\n continue\n }\n urlEnd++\n }\n target = source.slice(actualUrlStart, urlEnd)\n i = urlEnd\n }\n\n return { target, endPos: i, hadSpace: foundSpace }\n}\n\n// Parse link title - handles quoted and parenthesized titles\nfunction parseLinkTitle(\n source: string,\n start: number,\n hadSpaceInUrl: boolean,\n hasAngleBrackets: boolean\n): { title: string | undefined; endPos: number } {\n let i = start\n // Skip whitespace after URL\n let newlineCount = 0\n while (i < source.length) {\n const c = source[i]\n if (isSpaceOrTab(c)) {\n i++\n } else if (c === '\\n') {\n if (newlineCount >= 1) break\n newlineCount++\n i++\n } else if (util.isUnicodeWhitespace(c)) {\n break\n } else {\n break\n }\n }\n\n // If URL contained spaces and there's no title delimiter, the link is invalid\n if (hadSpaceInUrl && !hasAngleBrackets) {\n if (\n i >= source.length ||\n (source[i] !== '\"' && source[i] !== \"'\" && source[i] !== '(')\n ) {\n return { title: undefined, endPos: i }\n }\n }\n let title: string | undefined = undefined\n if (i < source.length) {\n const titleChar = source[i]\n if (titleChar === '\"' || titleChar === \"'\") {\n i++\n const titleStart = i\n while (i < source.length && source[i] !== titleChar) {\n if (source[i] === '\\\\') i++\n i++\n }\n if (i < source.length) {\n title = source.slice(titleStart, i)\n i++\n }\n } else if (titleChar === '(') {\n i++\n const titleStart = i\n let parenDepth = 1\n while (i < source.length && parenDepth > 0) {\n if (source[i] === '\\\\' && i + 1 < source.length) i++\n else if (source[i] === '(') parenDepth++\n else if (source[i] === ')') parenDepth--\n i++\n }\n if (parenDepth === 0) {\n title = source.slice(titleStart, i - 1)\n }\n }\n }\n\n i = util.skipWhitespace(source, i)\n return { title, endPos: i }\n}\n\nfunction parseUrlAndTitle(\n source: string,\n urlStart: number,\n allowNestedParens: boolean\n): { target: string; title: string | undefined; endPos: number } | null {\n const destResult = parseLinkDestination(source, urlStart, allowNestedParens)\n if (!destResult) return null\n\n let i = urlStart\n i = util.skipWhitespace(source, i)\n const hasAngleBrackets = i < source.length && source[i] === '<'\n\n // Handle empty angle brackets <>\n if (\n hasAngleBrackets &&\n destResult.target === '' &&\n destResult.endPos === i + 2\n ) {\n const titleResult = parseLinkTitle(\n source,\n destResult.endPos,\n false,\n hasAngleBrackets\n )\n if (\n titleResult.endPos >= source.length ||\n source[titleResult.endPos] !== ')'\n )\n return null\n return {\n target: '',\n title: titleResult.title,\n endPos: titleResult.endPos + 1,\n }\n }\n\n const titleResult = parseLinkTitle(\n source,\n destResult.endPos,\n destResult.hadSpace,\n hasAngleBrackets\n )\n if (titleResult.endPos >= source.length || source[titleResult.endPos] !== ')')\n return null\n\n return {\n target: destResult.target,\n title: titleResult.title,\n endPos: titleResult.endPos + 1,\n }\n}\n\nenum AutolinkMode {\n URI,\n EMAIL,\n ANGLE,\n}\n\nfunction isAlphaCode(code: number): boolean {\n return (\n (code >= $.CHAR_A && code <= $.CHAR_Z) ||\n (code >= $.CHAR_a && code <= $.CHAR_z)\n )\n}\n\nfunction isValidUriScheme(content: string): boolean {\n const colonPos = content.indexOf(':')\n if (colonPos < 2 || colonPos > 32) return false\n\n const firstCharCode = charCode(content)\n if (!isAlphaCode(firstCharCode)) {\n return false\n }\n\n // Check if all chars before colon are valid scheme chars\n for (let j = 1; j < colonPos; j++) {\n const c = content[j]\n const cCode = charCode(c)\n if (!isAlnum(c) && c !== '+' && c !== '.' && c !== '-') {\n return false\n }\n }\n return true\n}\n\nfunction isValidAutolinkContext(\n source: string,\n start: number,\n includeCR: boolean\n): boolean {\n if (start === 0) return true\n let validChars = includeCR ? ' \\t\\n\\r*_~(' : ' \\t\\n*_~('\n return validChars.indexOf(source[start - 1]) !== -1\n}\n\nfunction sanitizeAndCreate(\n target: string,\n linkText: string,\n endPos: number,\n sanitizer: (url: string, tag: string, attr: string) => string | null,\n emailStart?: number\n): ParseResult | null {\n let safe = sanitizer(target, 'a', 'href')\n if (!safe) return null\n return {\n type: RuleType.link,\n target: safe,\n children: [{ type: RuleType.text, text: linkText }],\n endPos: endPos,\n ...(emailStart !== undefined ? { emailStart } : {}),\n } as MarkdownToJSX.LinkNode & { endPos: number; emailStart?: number }\n}\n\nfunction parseAutolink(\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions,\n mode: AutolinkMode\n): ParseResult | null {\n if (\n state.inAnchor ||\n (mode !== AutolinkMode.ANGLE && options.disableAutoLink)\n )\n return null\n\n if (mode === AutolinkMode.ANGLE) {\n if (source[pos] !== '<') return null\n let end = pos + 1\n while (end < source.length && source[end] !== '>') {\n const endCode = charCode(source, end)\n if (\n endCode === $.CHAR_SPACE ||\n endCode === $.CHAR_TAB ||\n endCode === $.CHAR_NEWLINE ||\n endCode === $.CHAR_CR ||\n endCode < $.CHAR_SPACE\n )\n return null\n end++\n }\n if (end >= source.length || source[end] !== '>') return null\n let content = source.slice(pos + 1, end)\n if (!content.length) return null\n\n let hasBackslash = content.indexOf('\\\\') !== -1\n let hasValidUriScheme = isValidUriScheme(content)\n let isHttp =\n util.startsWith(content, 'http://') ||\n util.startsWith(content, 'https://')\n let isMailto = false\n if (!hasValidUriScheme && !isHttp && content.length >= 7) {\n const firstChar = content[0]\n if (firstChar === 'm' || firstChar === 'M') {\n const contentLower = content.toLowerCase()\n if (util.startsWith(contentLower, 'mailto:')) {\n isMailto = true\n let colonPos = contentLower.indexOf(':')\n let mailtoText = content.slice(colonPos + 1)\n return sanitizeAndCreate(\n 'mailto:' + mailtoText,\n content,\n end + 1,\n options.sanitizer\n )\n }\n }\n }\n let isEmailLike =\n !hasBackslash &&\n content.indexOf('@') !== -1 &&\n content.indexOf('//') === -1 &&\n !hasValidUriScheme\n\n if (!isHttp && !isMailto && !isEmailLike && !hasValidUriScheme) return null\n\n let target = content,\n linkText = content\n if (!isMailto && !hasValidUriScheme && !isHttp && isEmailLike) {\n target = 'mailto:' + content\n }\n\n return sanitizeAndCreate(target, linkText, end + 1, options.sanitizer)\n }\n\n if (mode === AutolinkMode.EMAIL) {\n let emailStart = pos\n while (\n emailStart > 0 &&\n (isAlnum(source[emailStart - 1]) ||\n '.+-_'.indexOf(source[emailStart - 1]) !== -1)\n )\n emailStart--\n if (emailStart >= pos || !isValidAutolinkContext(source, emailStart, true))\n return null\n\n let emailEnd = pos + 1\n let hasDot = false\n while (emailEnd < source.length) {\n let c = source[emailEnd]\n if (c === '.') {\n hasDot = true\n emailEnd++\n } else if (isAlnum(c) || c === '-' || c === '_') emailEnd++\n else break\n }\n\n if (!hasDot || emailEnd <= pos + 1) return null\n while (emailEnd > pos + 1 && source[emailEnd - 1] === '.') emailEnd--\n if (\n emailEnd > pos + 1 &&\n (source[emailEnd - 1] === '-' || source[emailEnd - 1] === '_')\n )\n return null\n // Check if email contains at least one dot\n // For large documents, prefer slice+includes to avoid scanning entire document\n const emailLength = emailEnd - (pos + 1)\n if (emailLength < 10000) {\n if (\n source.indexOf('.', pos + 1) >= emailEnd ||\n source.indexOf('.', pos + 1) === -1\n )\n return null\n } else {\n if (source.slice(pos + 1, emailEnd).indexOf('.') === -1) return null\n }\n\n let email = source.slice(emailStart, emailEnd)\n return sanitizeAndCreate(\n 'mailto:' + email,\n email,\n emailEnd,\n options.sanitizer,\n emailStart\n )\n }\n\n let isHttp =\n util.startsWith(source, 'http://', pos) ||\n util.startsWith(source, 'https://', pos)\n let isFtp = !isHttp && util.startsWith(source, 'ftp://', pos)\n let isWww = !isHttp && !isFtp && util.startsWith(source, 'www.', pos)\n if (\n !(isHttp || isFtp || isWww) ||\n !isValidAutolinkContext(source, pos, false)\n )\n return null\n\n var urlEnd =\n pos +\n (isHttp ? (charCode(source, pos + 4) === $.CHAR_s ? 8 : 7) : isFtp ? 6 : 4)\n var domainStart = urlEnd\n // Inline scanDomain\n while (urlEnd < source.length) {\n const code = charCode(source, urlEnd)\n if (\n code === $.CHAR_SPACE ||\n code === $.CHAR_TAB ||\n code === $.CHAR_NEWLINE ||\n code === $.CHAR_LT ||\n code === $.CHAR_GT\n )\n break\n urlEnd++\n }\n if (urlEnd <= domainStart) return null\n // Inline trimTrailingPunct\n let trimmed = urlEnd\n while (trimmed > domainStart) {\n let lastChar = source[trimmed - 1]\n if (trimmed > domainStart + 1 && source[trimmed - 2] === '\\\\') break\n if (\n lastChar === '?' ||\n lastChar === '!' ||\n lastChar === '.' ||\n lastChar === ',' ||\n lastChar === ':' ||\n lastChar === '*' ||\n lastChar === '_' ||\n lastChar === '~'\n ) {\n trimmed--\n } else if (lastChar === ';') {\n let ampPos = trimmed - 2\n while (\n ampPos >= domainStart &&\n source[ampPos] !== '&' &&\n source[ampPos] !== ' '\n )\n ampPos--\n if (ampPos >= domainStart && source[ampPos] === '&') {\n let entityName = source.slice(ampPos + 1, trimmed - 1)\n if (\n entityName.length >= 2 &&\n entityName.length <= 10 &&\n /^[a-zA-Z0-9]+$/.test(entityName) &&\n (entityName === 'lt' ||\n entityName === 'gt' ||\n (entityName.length >= 3 &&\n (util.startsWith(entityName, 'amp') ||\n util.startsWith(entityName, 'apos') ||\n util.startsWith(entityName, 'quot') ||\n util.startsWith(entityName, 'nbsp') ||\n /^[a-z]{3,10}$/.test(entityName))))\n )\n break\n trimmed = ampPos\n break\n }\n trimmed--\n } else if (lastChar === ')') {\n let openCount = 0,\n closeCount = 0\n for (let i = domainStart; i < trimmed; i++) {\n if (source[i] === '(') openCount++\n if (source[i] === ')') closeCount++\n }\n if (closeCount > openCount) trimmed--\n else break\n } else break\n }\n urlEnd = trimmed\n if (urlEnd <= domainStart) return null\n\n var domainEnd = domainStart\n var lastDot = -1\n var secondLastDot = -1\n while (domainEnd < urlEnd) {\n const domainCode = charCode(source, domainEnd)\n if (\n (domainCode >= $.CHAR_A && domainCode <= $.CHAR_Z) ||\n (domainCode >= $.CHAR_a && domainCode <= $.CHAR_z) ||\n (domainCode >= $.CHAR_DIGIT_0 && domainCode <= $.CHAR_DIGIT_9) ||\n domainCode === $.CHAR_DASH ||\n domainCode === $.CHAR_UNDERSCORE ||\n domainCode === $.CHAR_PERIOD\n ) {\n if (domainCode === $.CHAR_PERIOD) {\n secondLastDot = lastDot\n lastDot = domainEnd\n }\n domainEnd++\n continue\n }\n break\n }\n if (domainEnd === domainStart || lastDot === -1) return null\n if (secondLastDot === -1) secondLastDot = domainStart - 1\n for (let i = secondLastDot + 1; i < lastDot; i++) {\n if (source[i] === '_') return null\n }\n for (let i = lastDot + 1; i < domainEnd; i++) {\n if (source[i] === '_') return null\n }\n\n let linkText = source.slice(pos, urlEnd)\n return sanitizeAndCreate(\n isWww ? 'http://' + linkText : linkText,\n linkText,\n urlEnd,\n options.sanitizer\n )\n}\n\n// Unified link/image parser - handles all link/image types based on starting character\nfunction parseLinkOrImage(\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions,\n startChar: '[' | '!' | '<' | 'h' | 'f' | 'w' | '@'\n): ParseResult | null {\n // Angle brace autolink: <url>\n if (startChar === '<') {\n return parseAutolink(\n source,\n pos,\n state,\n options,\n AutolinkMode.ANGLE\n ) as ParseResult\n }\n\n // Bare URL autolink: http://, https://, ftp://, www.\n if (startChar === 'h' || startChar === 'f' || startChar === 'w') {\n return parseAutolink(\n source,\n pos,\n state,\n options,\n AutolinkMode.URI\n ) as ParseResult\n }\n\n // Email autolink: @example.com\n if (startChar === '@') {\n return parseAutolink(\n source,\n pos,\n state,\n options,\n AutolinkMode.EMAIL\n ) as ParseResult | null\n }\n\n // Bracket-based links/images are handled inline in parseInlineSpan\n // This function only handles autolinks\n return null\n}\n\nfunction normalizeReferenceLabel(label: string): string {\n var trimmed = label.trim()\n var normalized = trimmed.replace(/[\\s\\t\\n\\r]+/g, ' ')\n if (normalized.indexOf('\\u1E9E') !== -1) {\n return normalized.replace(/\\u1E9E/g, 'ss').toLowerCase();\n }\n return normalized.toLowerCase()\n}\n\nfunction parseGFMTask(\n source: string,\n pos: number,\n state: MarkdownToJSX.State\n): ParseResult {\n if (pos + 3 >= source.length || source[pos] !== '[') return null\n const marker = source[pos + 1]\n if (marker !== ' ' && marker !== 'x' && marker !== 'X') return null\n if (source[pos + 2] !== ']') return null\n return {\n type: RuleType.gfmTask,\n completed: marker.toLowerCase() === 'x',\n endPos: pos + 3,\n } as MarkdownToJSX.GFMTaskNode & { endPos: number }\n}\n\nfunction parseBlocksWithState(\n content: string,\n state: MarkdownToJSX.State,\n options: ParseOptions,\n config: { inline?: boolean; list?: boolean; inBlockQuote?: boolean }\n): MarkdownToJSX.ASTNode[] {\n const originalInline = state.inline\n const originalList = state.inList\n const originalInBlockQuote = state.inBlockQuote\n if (config.inline !== undefined) state.inline = config.inline\n if (config.list !== undefined) state.inList = config.list\n if (config.inBlockQuote !== undefined)\n state.inBlockQuote = config.inBlockQuote\n const blocks = parseBlocksInHTML(content, state, options)\n state.inline = originalInline\n state.inList = originalList\n state.inBlockQuote = originalInBlockQuote\n return blocks\n}\n\nfunction parseInlineWithState(\n content: string,\n start: number,\n end: number,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): MarkdownToJSX.ASTNode[] {\n return parseWithInlineMode(state, true, () =>\n parseInlineSpan(content, start, end, state, options)\n )\n}\n\ntype BlockParserFn = (\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions\n) => ParseResult | null\n\nfunction parseBlock(\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): ParseResult | null {\n var char = source[pos]\n if (char === undefined) return null\n var effectivePos = pos\n var indentInfo: ReturnType<typeof calculateIndent> | null = null\n var firstChar = char\n var lineEnd: number | null = null\n\n var charCodeVal = charCode(char)\n var isIndentChar = charCodeVal === $.CHAR_SPACE || charCodeVal === $.CHAR_TAB\n if (isIndentChar) {\n lineEnd = util.findLineEnd(source, pos)\n indentInfo = calculateIndent(source, pos, lineEnd)\n effectivePos = pos + indentInfo.charCount\n if (effectivePos >= source.length) return parseCodeBlock(source, pos, state)\n firstChar = source[effectivePos]\n }\n var spaceEquivalent = indentInfo ? indentInfo.spaceEquivalent : 0\n if (spaceEquivalent >= 4) {\n if (isIndentChar) return parseCodeBlock(source, pos, state)\n return null\n }\n var firstCharCode = charCode(firstChar)\n if (firstCharCode === $.CHAR_GT) {\n var blockQuoteResult = parseBlockQuote(source, pos, state, options)\n if (blockQuoteResult) return blockQuoteResult\n } else if (firstCharCode === $.CHAR_UNDERSCORE) {\n return parseBreakThematic(source, pos, state, options)\n } else if (\n firstCharCode === $.CHAR_DASH ||\n firstCharCode === $.CHAR_ASTERISK ||\n firstCharCode === $.CHAR_PLUS\n ) {\n var thematicBreakResult = parseBreakThematic(source, pos, state, options)\n if (thematicBreakResult) return thematicBreakResult\n var listResult = parseList(source, pos, state, options)\n if (listResult) return listResult\n } else if (\n firstCharCode >= $.CHAR_DIGIT_0 &&\n firstCharCode <= $.CHAR_DIGIT_9\n ) {\n var listResult = parseList(source, pos, state, options)\n if (listResult) return listResult\n } else if (firstCharCode === $.CHAR_HASH) {\n return parseHeading(source, effectivePos, state, options)\n } else if (firstCharCode === $.CHAR_BRACKET_OPEN) {\n return parseDefinition(\n source,\n effectivePos,\n state,\n options,\n effectivePos + 1 < source.length &&\n charCode(source, effectivePos + 1) === $.CHAR_CARET\n )\n } else if (firstCharCode === $.CHAR_LT && !options.disableParsingRawHTML) {\n return parseHTML(source, effectivePos, state, options)\n } else if (\n firstCharCode === $.CHAR_BACKTICK ||\n firstCharCode === $.CHAR_TILDE\n ) {\n if (!lineEnd) lineEnd = util.findLineEnd(source, pos)\n if (!indentInfo) indentInfo = calculateIndent(source, pos, lineEnd)\n if (indentInfo.spaceEquivalent <= 3)\n return parseCodeFenced(source, effectivePos, state, options)\n } else if (firstCharCode === $.CHAR_PIPE) {\n return parseTable(source, pos, state, options)\n }\n if (isIndentChar) return parseCodeBlock(source, pos, state)\n return null\n}\n\n/** Parse blocks inside HTML content */\nfunction parseBlocksInHTML(\n input: string,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): MarkdownToJSX.ASTNode[] {\n const result: MarkdownToJSX.ASTNode[] = []\n let pos = 0\n\n while (pos < input.length) {\n while (pos < input.length && input[pos] === '\\n') {\n pos++\n }\n\n if (pos >= input.length) break\n\n var char = input[pos]\n\n // Fast path: check for setext heading in list context\n // Per CommonMark: setext headings take precedence over thematic breaks\n if (state.inList && result.length > 0) {\n var lastBlock = result[result.length - 1]\n if (lastBlock?.type === RuleType.paragraph) {\n var paragraph = lastBlock as MarkdownToJSX.ParagraphNode\n // Quick check for potential setext underline characters\n var code = charCode(char)\n if (\n code === $.CHAR_DASH ||\n code === $.CHAR_EQ ||\n code === $.CHAR_SPACE ||\n code === $.CHAR_TAB\n ) {\n var lineEnd = util.findLineEnd(input, pos)\n var lineContent = input.slice(pos, lineEnd)\n\n // Check indentation (up to 3 spaces allowed for setext headings)\n var indentInfo = calculateIndent(input, pos, lineEnd)\n if (indentInfo.spaceEquivalent < 4) {\n var trimmed = lineContent.slice(indentInfo.charCount).trim()\n // Use convertSetextHeadingInListItem helper to check and convert\n if (convertSetextHeadingInListItem(result, trimmed, options)) {\n pos =\n lineEnd +\n (lineEnd < input.length && input[lineEnd] === '\\n' ? 1 : 0)\n continue\n }\n }\n }\n }\n }\n\n // Try parseBlock first (handles most block types)\n var blockResult = parseBlock(input, pos, state, options)\n if (blockResult) {\n result.push(blockResult)\n pos = blockResult.endPos\n continue\n }\n\n // Try setext heading (not handled by parseBlock)\n var setextResult = parseHeadingSetext(input, pos, state, options)\n if (setextResult) {\n result.push(setextResult)\n pos = setextResult.endPos\n continue\n }\n\n var remaining = input.slice(pos).trim()\n if (remaining) {\n // Per CommonMark spec example 293: Before parsing a paragraph, check if there's\n // a blockquote ending with a paragraph in recent blocks that this should merge into\n if (state.inBlockQuote && result.length > 0) {\n // Find the deepest blockquote ending with a paragraph in recent blocks\n // (may be nested inside list items)\n function findBlockquoteWithParagraphEnd(\n node: MarkdownToJSX.ASTNode\n ): MarkdownToJSX.ParagraphNode | null {\n if (node.type === RuleType.blockQuote) {\n var blockQuote = node as MarkdownToJSX.BlockQuoteNode\n if (blockQuote.children && blockQuote.children.length > 0) {\n var lastChild =\n blockQuote.children[blockQuote.children.length - 1]\n if (lastChild.type === RuleType.paragraph) {\n return lastChild as MarkdownToJSX.ParagraphNode\n }\n }\n } else if (\n node.type === RuleType.orderedList ||\n node.type === RuleType.unorderedList\n ) {\n var list = node as\n | MarkdownToJSX.OrderedListNode\n | MarkdownToJSX.UnorderedListNode\n if (list.items && list.items.length > 0) {\n var lastItem = list.items[list.items.length - 1]\n if (lastItem && lastItem.length > 0) {\n var lastItemChild = lastItem[lastItem.length - 1]\n var found = findBlockquoteWithParagraphEnd(lastItemChild)\n if (found) return found\n }\n }\n }\n return null\n }\n\n // Check recent blocks (from end) for blockquote ending with paragraph\n for (var i = result.length - 1; i >= 0; i--) {\n var paragraph = findBlockquoteWithParagraphEnd(result[i])\n if (paragraph) {\n var parseResult = parseParagraph(input, pos, state, options)\n if (parseResult) {\n var newParagraph = parseResult as MarkdownToJSX.ParagraphNode\n // Merge the new paragraph's children into the blockquote's paragraph\n if (paragraph.children && newParagraph.children) {\n paragraph.children.push(\n { type: RuleType.text, text: '\\n' } as MarkdownToJSX.TextNode,\n ...newParagraph.children\n )\n }\n pos = parseResult.endPos\n continue\n }\n }\n }\n }\n\n var parseResult = parseParagraph(input, pos, state, options)\n if (parseResult) {\n result.push(parseResult)\n pos = parseResult.endPos\n continue\n }\n }\n\n pos++\n }\n\n return result\n}\n\nfunction parseHeading(\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): ParseResult {\n if (state.inline) return null\n\n // Find line end to limit expensive indentation scan\n const lineEnd = util.findLineEnd(source, pos)\n const indentResult = calculateIndent(source, pos, lineEnd, 3)\n if (indentResult.spaceEquivalent > 3 && !state.inList) return null\n var i = pos + indentResult.charCount\n\n if (i >= source.length || source[i] !== '#') return null\n\n const level = countConsecutiveChars(source, i, '#', 6)\n i += level\n\n if (i >= source.length) return null\n const afterHash = source[i]\n if (afterHash === '\\n' || afterHash === '\\r') {\n const lineEnd = util.findLineEnd(source, i)\n return {\n ...createHeading(level, [], '', options.slugify),\n endPos: lineEnd + (lineEnd < source.length ? 1 : 0),\n } as MarkdownToJSX.HeadingNode & { endPos: number }\n }\n if (afterHash !== ' ' && afterHash !== '\\t') return null\n\n const contentStart = i\n const contentEnd = util.findLineEnd(source, contentStart)\n var content = source\n .slice(contentStart, contentEnd)\n .replace(HEADING_TRAILING_HASHES_R, '')\n .trim()\n\n const children = parseInlineWithState(\n content,\n 0,\n content.length,\n state,\n options\n )\n\n return {\n ...createHeading(level, children, content, options.slugify),\n endPos: contentEnd + (contentEnd < source.length ? 1 : 0),\n } as MarkdownToJSX.HeadingNode & { endPos: number }\n}\n\nfunction parseHeadingSetext(\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): ParseResult {\n if (state.inline || state.inBlockQuote || state.inList) return null\n\n const firstLineEnd = util.findLineEnd(source, pos)\n if (firstLineEnd >= source.length) return null\n\n // Find underline pattern first, then validate backwards\n let underlineLineStart = firstLineEnd + 1,\n underlineLineEnd = -1,\n underlineChar: string | null = null\n\n // Scan forward for underline (= or - with up to 3 spaces indentation)\n for (\n var linesScanned = 0;\n underlineLineStart < source.length && linesScanned < 10;\n linesScanned++\n ) {\n const lineEnd = util.findLineEnd(source, underlineLineStart)\n if (lineEnd >= source.length) break\n\n // Check if blank line (stops setext headings)\n var i = underlineLineStart\n while (\n i < lineEnd &&\n (charCode(source, i) === $.CHAR_SPACE ||\n charCode(source, i) === $.CHAR_TAB ||\n charCode(source, i) === $.CHAR_CR)\n )\n i++\n if (i >= lineEnd) break\n\n // Check indentation (up to 3 spaces) and first char\n var indentCount = 0,\n checkPos = underlineLineStart\n while (\n checkPos < lineEnd &&\n indentCount < 3 &&\n charCode(source, checkPos) === $.CHAR_SPACE\n ) {\n indentCount++\n checkPos++\n }\n\n if (checkPos < lineEnd) {\n const code = charCode(source, checkPos)\n if (code === $.CHAR_EQ || code === $.CHAR_DASH) {\n // Validate underline: only = or - with optional trailing spaces, no internal spaces\n const char = source[checkPos]\n var underlineCount = 0,\n hasSeenWS = false,\n p = checkPos\n while (p < lineEnd) {\n const c = charCode(source, p)\n if (c === code) {\n if (hasSeenWS) {\n underlineCount = 0\n break\n }\n underlineCount++\n } else if (c === $.CHAR_SPACE || c === $.CHAR_TAB) {\n hasSeenWS = true\n } else {\n underlineCount = 0\n break\n }\n p++\n }\n\n if (underlineCount >= 1) {\n underlineLineEnd = lineEnd\n underlineChar = char\n break\n }\n }\n }\n\n underlineLineStart = lineEnd + 1\n }\n\n if (!underlineChar) return null\n\n // Quick validation: content cannot start with certain block characters\n const firstCharCode = charCode(source, pos)\n if (\n firstCharCode === $.CHAR_HASH ||\n firstCharCode === $.CHAR_GT ||\n source[pos] === '|'\n )\n return null\n\n // Collect content lines forward to underline\n let contentEnd = pos\n var currentPos = pos,\n hasContent = false\n\n while (currentPos < underlineLineStart) {\n const lineEnd = util.findLineEnd(source, currentPos)\n if (lineEnd >= underlineLineStart) break\n\n // Check if line has non-whitespace content\n var j = currentPos\n while (\n j < lineEnd &&\n (charCode(source, j) === $.CHAR_SPACE ||\n charCode(source, j) === $.CHAR_TAB ||\n charCode(source, j) === $.CHAR_CR)\n )\n j++\n if (j < lineEnd) {\n // Line has content\n hasContent = true\n contentEnd = lineEnd\n }\n\n currentPos = lineEnd + 1\n }\n\n if (!hasContent) return null\n\n // Extract and trim content\n const rawContent = source.slice(pos, contentEnd)\n var startTrim = 0,\n endTrim = rawContent.length\n while (\n startTrim < endTrim &&\n (rawContent.charCodeAt(startTrim) === $.CHAR_SPACE ||\n rawContent.charCodeAt(startTrim) === $.CHAR_TAB ||\n rawContent.charCodeAt(startTrim) === $.CHAR_CR ||\n rawContent.charCodeAt(startTrim) === $.CHAR_NEWLINE)\n )\n startTrim++\n while (\n endTrim > startTrim &&\n (rawContent.charCodeAt(endTrim - 1) === $.CHAR_SPACE ||\n rawContent.charCodeAt(endTrim - 1) === $.CHAR_TAB ||\n rawContent.charCodeAt(endTrim - 1) === $.CHAR_CR ||\n rawContent.charCodeAt(endTrim - 1) === $.CHAR_NEWLINE)\n )\n endTrim--\n const content = rawContent.slice(startTrim, endTrim)\n\n if (!content) return null\n\n const level = underlineChar === '=' ? 1 : 2\n const children = parseInlineWithState(\n content,\n 0,\n content.length,\n state,\n options\n )\n\n return {\n ...createHeading(level, children, content, options.slugify),\n endPos: underlineLineEnd + (underlineLineEnd < source.length ? 1 : 0),\n } as MarkdownToJSX.HeadingNode & { endPos: number }\n}\n\nfunction parseParagraph(\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): ParseResult {\n // Note: We don't check isBlockStartChar here because this is called as a fallback\n // after other block parsers have already tried and failed\n if (state.inline) return null\n let endPos = pos\n const sourceLen = source.length\n\n while (endPos < sourceLen) {\n let lineEnd = util.findLineEnd(source, endPos)\n let isEmptyLine = true\n\n for (let i = endPos; i < lineEnd; i++) {\n const code = charCode(source, i)\n if (code !== $.CHAR_SPACE && code !== $.CHAR_TAB && code !== $.CHAR_CR) {\n isEmptyLine = false\n break\n }\n }\n\n if (isEmptyLine) {\n endPos = lineEnd\n break\n }\n\n if (lineEnd >= sourceLen) {\n endPos = sourceLen\n break\n }\n\n const nextLineStart = lineEnd + 1\n if (nextLineStart >= sourceLen) {\n endPos = sourceLen\n break\n }\n\n let nextLineEnd = util.findLineEnd(source, nextLineStart)\n let nextLineIsEmpty = true\n let nextLineFirstChar = ''\n\n for (let i = nextLineStart; i < nextLineEnd; i++) {\n const code = charCode(source, i)\n if (code !== $.CHAR_SPACE && code !== $.CHAR_TAB && code !== $.CHAR_CR) {\n nextLineIsEmpty = false\n if (nextLineFirstChar === '') nextLineFirstChar = source[i]\n break\n }\n }\n\n if (nextLineIsEmpty) {\n endPos = lineEnd\n break\n }\n\n // Check if next line starts with a block element\n // BUT: per CommonMark, lines indented by exactly 4 spaces are paragraph continuation,\n // not code blocks or other blocks, even if they start with block-starting characters.\n let shouldBreak = false\n const nextIndentInfo = calculateIndent(source, nextLineStart, nextLineEnd)\n const isExact4SpaceIndent =\n nextIndentInfo.spaceEquivalent === 4 && nextIndentInfo.charCount === 4\n\n // Check for HTML blocks first (types 1-6 can interrupt paragraphs)\n // Per CommonMark spec: HTML blocks of types 1-6 can interrupt paragraphs\n if (\n nextLineFirstChar === '<' &&\n !isExact4SpaceIndent &&\n !options.disableParsingRawHTML\n ) {\n const htmlCheckPos = nextLineStart\n let htmlLineStart = htmlCheckPos\n let htmlIndent = 0\n while (htmlLineStart < nextLineEnd && htmlIndent < 3) {\n const code = charCode(source, htmlLineStart)\n if (code === $.CHAR_SPACE || code === $.CHAR_TAB) {\n htmlIndent++\n htmlLineStart++\n } else {\n break\n }\n }\n if (htmlLineStart < nextLineEnd && source[htmlLineStart] === '<') {\n var htmlResult = parseHTML(\n source,\n htmlLineStart,\n { ...state, inline: false },\n options\n )\n if (htmlResult) {\n shouldBreak =\n !('canInterruptParagraph' in htmlResult) ||\n (htmlResult.canInterruptParagraph as boolean)\n }\n }\n }\n\n // In list context, lines indented to the content start column are also continuation\n // For now, treat 4-space indented lines as continuation regardless of context\n if (isExact4SpaceIndent) {\n // Line is indented exactly 4 spaces - this is paragraph continuation\n // Per CommonMark spec: lines indented by exactly 4 spaces are paragraph continuation,\n // not code blocks or other blocks, even if they start with block-starting characters.\n // Don't break, continue paragraph across this line\n shouldBreak = false\n } else if (\n !shouldBreak &&\n nextLineFirstChar &&\n isBlockStartChar(nextLineFirstChar)\n ) {\n // Reference definitions don't break paragraphs - skip them\n if (nextLineFirstChar === '[') {\n // Check if it's a reference definition (not a footnote)\n const checkPos = nextLineStart\n if (checkPos + 1 >= sourceLen || source[checkPos + 1] !== '^') {\n // Could be a reference definition - don't break paragraph\n shouldBreak = false\n } else {\n // Footnote definition - break paragraph\n shouldBreak = true\n }\n } else if (nextLineFirstChar === '*' || nextLineFirstChar === '+') {\n // Asterisk/plus is only a block start for lists (*/+ followed by space/tab) or thematic breaks (3+ alone)\n // But thematic breaks can have up to 3 spaces indentation, so check for thematic break first\n const thematicBreakResult = parseBreakThematic(\n source,\n nextLineStart,\n state,\n options\n )\n if (thematicBreakResult) {\n shouldBreak = true\n } else {\n // Check if it's a list (followed by space/tab)\n const secondChar =\n nextLineStart + 1 < sourceLen ? source[nextLineStart + 1] : ''\n if (secondChar && isSpaceOrTab(secondChar)) {\n shouldBreak = true\n } else {\n // Not a list or thematic break - don't break paragraph\n shouldBreak = false\n }\n }\n } else {\n // Use parseBlock to check if next line starts a block\n // Special handling needed for setext headings and ordered lists\n const blockResult = parseBlock(source, nextLineStart, state, options)\n\n if (blockResult) {\n // Check if it's a code block from 4+ space indentation (paragraph continuation)\n if (blockResult.type === RuleType.codeBlock) {\n const blockIndentInfo = calculateIndent(\n source,\n nextLineStart,\n nextLineEnd\n )\n if (blockIndentInfo.spaceEquivalent >= 4) {\n // 4+ space indentation is paragraph continuation, not a block start\n shouldBreak = false\n } else {\n // Fenced code block - break paragraph\n shouldBreak = true\n }\n } else if (\n blockResult.type === RuleType.unorderedList ||\n blockResult.type === RuleType.orderedList\n ) {\n // Lists can interrupt paragraphs, but ordered lists starting with numbers other than 1 cannot\n if (blockResult.type === RuleType.orderedList) {\n const orderedList = blockResult as MarkdownToJSX.OrderedListNode\n // Only ordered lists starting with 1 can interrupt paragraphs\n shouldBreak = orderedList.start === 1\n } else {\n shouldBreak = true\n }\n } else if (nextLineFirstChar === '-') {\n // Dash could be setext heading underline if preceded by content\n // Per CommonMark: setext headings take precedence over thematic breaks\n if (endPos > pos) {\n // We have content - break paragraph to let setext heading parser check\n shouldBreak = true\n } else {\n // No content - use the block result (thematic break or list)\n shouldBreak = true\n }\n } else if (blockResult.type === RuleType.ref) {\n // Reference definitions don't break paragraphs\n shouldBreak = false\n } else {\n // Other block types break paragraphs\n shouldBreak = true\n }\n }\n }\n } else {\n // Next line doesn't start with a block-starting character\n // Per CommonMark: in paragraph context, lines indented by exactly 4 spaces\n // are paragraph continuation, not code blocks. Only 4+ spaces at document\n // start (not in paragraph) are code blocks.\n // So we don't break on 4-space indentation in paragraph continuation.\n }\n\n if (shouldBreak) {\n endPos = lineEnd\n break\n }\n\n // Continue paragraph across single newline\n endPos = lineEnd + 1\n }\n\n if (endPos <= pos) return null\n\n // Per CommonMark: lines indented by exactly 4 spaces in paragraph context\n // are continuation, not code blocks. We need to remove the 4-space indentation\n // from continuation lines but preserve them as part of the paragraph.\n var contentStart = pos\n var contentEnd = endPos\n\n while (contentStart < contentEnd) {\n const code = charCode(source, contentStart)\n if (code === $.CHAR_SPACE || code === $.CHAR_TAB) {\n contentStart++\n } else {\n break\n }\n }\n\n // Fast path: if no newlines, use content directly (common case)\n // Check if there's a newline between contentStart and contentEnd\n // We can optimize by checking if contentEnd is beyond the first line\n const firstLineEnd = util.findLineEnd(source, contentStart)\n var hasNewline = contentEnd > firstLineEnd\n\n var processedContent\n if (!hasNewline) {\n // Single line - no processing needed\n processedContent = source.slice(contentStart, contentEnd)\n } else {\n // Multi-line: process 4-space indentation\n var processedParts: string[] = []\n var lineStart = contentStart\n var lineIndex = 0\n\n while (lineStart < contentEnd) {\n var lineEnd = util.findLineEnd(source, lineStart)\n if (lineEnd > contentEnd) lineEnd = contentEnd\n\n if (lineIndex === 0) {\n processedParts.push(source.slice(lineStart, lineEnd))\n } else {\n // Check for exactly 4 leading spaces\n var spaceCount = 0\n while (spaceCount < 4 && lineStart + spaceCount < lineEnd) {\n if (charCode(source, lineStart + spaceCount) === $.CHAR_SPACE) {\n spaceCount++\n } else {\n break\n }\n }\n var start = spaceCount === 4 ? lineStart + 4 : lineStart\n processedParts.push(source.slice(start, lineEnd))\n }\n\n if (\n lineEnd < contentEnd &&\n charCode(source, lineEnd) === $.CHAR_NEWLINE\n ) {\n processedParts.push('\\n')\n lineStart = lineEnd + 1\n } else {\n lineStart = contentEnd\n }\n lineIndex++\n }\n processedContent = processedParts.join('')\n }\n\n var processedContentEnd = processedContent.length\n while (processedContentEnd > 0) {\n var c = processedContent.charCodeAt(processedContentEnd - 1)\n if (c === $.CHAR_SPACE || c === $.CHAR_TAB) {\n processedContentEnd--\n } else {\n break\n }\n }\n if (processedContentEnd < processedContent.length) {\n processedContent = processedContent.slice(0, processedContentEnd)\n }\n\n // Check if processed content has actual content\n let hasProcessedContent = false\n for (let i = 0; i < processedContent.length; i++) {\n const code = processedContent.charCodeAt(i)\n if (\n code !== $.CHAR_SPACE &&\n code !== $.CHAR_TAB &&\n code !== $.CHAR_NEWLINE &&\n code !== $.CHAR_CR\n ) {\n hasProcessedContent = true\n break\n }\n }\n if (!hasProcessedContent) return null\n\n // Per CommonMark spec: Extract link reference definitions from paragraph content\n // Reference definitions can appear at the end of paragraph content\n // They should be extracted and stored, not parsed as inline content\n // Scan backwards from endPos in source to find reference definitions\n var extractedContent = processedContent\n var extractedEndPos = endPos\n // Find the last newline in the source before endPos (optimized: manual scan instead of lastIndexOf)\n var lastNewlinePos = -1\n var searchPos = endPos - 1\n while (searchPos >= contentStart) {\n if (charCode(source, searchPos) === $.CHAR_NEWLINE) {\n lastNewlinePos = searchPos\n break\n }\n searchPos--\n }\n if (lastNewlinePos >= 0) {\n // Per CommonMark spec: \"A link reference definition cannot interrupt a paragraph.\"\n // Only extract reference definitions if they're at the START of the paragraph (no content before them)\n // Check if there's any non-whitespace content before the last newline\n var hasContentBeforeNewline = false\n for (var checkPos = contentStart; checkPos < lastNewlinePos; checkPos++) {\n const code = charCode(source, checkPos)\n if (\n code !== $.CHAR_SPACE &&\n code !== $.CHAR_TAB &&\n code !== $.CHAR_NEWLINE &&\n code !== $.CHAR_CR\n ) {\n hasContentBeforeNewline = true\n break\n }\n }\n\n // Only extract reference definition if there's no content before the newline\n // (i.e., it's at the start of the paragraph)\n if (!hasContentBeforeNewline) {\n // Check if the content after the last newline is a reference definition\n var refDefStartPos = lastNewlinePos + 1\n // Skip any leading whitespace\n while (refDefStartPos < source.length) {\n const code = charCode(source, refDefStartPos)\n if (code === $.CHAR_SPACE || code === $.CHAR_TAB) {\n refDefStartPos++\n } else {\n break\n }\n }\n // Check indentation - reference definitions can't be indented 4+ spaces\n var refDefIndent = refDefStartPos - (lastNewlinePos + 1)\n if (\n refDefIndent < 4 &&\n refDefStartPos < source.length &&\n source[refDefStartPos] === '['\n ) {\n var refDefState = { ...state, inline: false }\n var refDefResult = parseDefinition(\n source,\n refDefStartPos,\n refDefState,\n options,\n false\n )\n if (refDefResult) {\n // Reference definition was successfully parsed - exclude it from paragraph content\n // Find the corresponding position in processedContent\n // Count newlines from contentStart to lastNewlinePos\n var newlineCount = 0\n var searchPos = contentStart\n while (searchPos <= lastNewlinePos) {\n const nlPos = source.indexOf('\\n', searchPos)\n if (nlPos === -1 || nlPos > lastNewlinePos) break\n newlineCount++\n searchPos = nlPos + 1\n }\n // Find the corresponding position in processedContent\n var newlinePosInProcessed = 0\n var newlinesFound = 0\n searchPos = 0\n while (searchPos < processedContent.length) {\n const nlPos = processedContent.indexOf('\\n', searchPos)\n if (nlPos === -1) break\n newlinesFound++\n if (newlinesFound === newlineCount) {\n newlinePosInProcessed = nlPos + 1\n break\n }\n searchPos = nlPos + 1\n }\n if (newlinePosInProcessed > 0) {\n extractedContent = processedContent.slice(\n 0,\n newlinePosInProcessed - 1\n )\n }\n extractedEndPos = refDefResult.endPos\n // Update state.refs from the parsed reference\n state.refs = refDefState.refs\n }\n }\n }\n }\n\n // Parse as inline (newlines are preserved by default)\n const children = parseInlineWithState(\n extractedContent,\n 0,\n extractedContent.length,\n state,\n options\n )\n\n var result: MarkdownToJSX.ParagraphNode & {\n endPos: number\n removedClosingTags?: MarkdownToJSX.ASTNode[]\n } = {\n type: RuleType.paragraph,\n children,\n endPos: extractedEndPos,\n }\n\n // Per CommonMark spec Example 148: when paragraphs contain multiple closing tags at the end,\n // only the first closing tag should be kept in the paragraph, the rest should be removed\n // This handles cases where closing tags are part of HTML block structures\n // Heuristic: if there are 3+ consecutive closing tags, remove all but the first one\n // Example 148: <p><em>world</em>.</pre></p> should keep </pre> but remove </td>, </tr>, </table> (4 tags)\n // Example 623: <p></a></foo ></p> should keep both </a> and </foo > (2 tags, not removed)\n if (children.length > 0) {\n // Find closing tags at the end of paragraph children (ignoring whitespace-only text nodes)\n // Keep the first closing tag but remove the rest\n var closingTagIndices: number[] = []\n for (var i = children.length - 1; i >= 0; i--) {\n var child = children[i]\n if (\n child.type === RuleType.htmlSelfClosing &&\n child.isClosingTag === true\n ) {\n closingTagIndices.push(i)\n } else if (child.type === RuleType.text) {\n var textNode = child as MarkdownToJSX.TextNode\n // Skip whitespace-only text nodes when looking for consecutive closing tags\n if (textNode.text && textNode.text.trim().length > 0) {\n break\n }\n } else {\n // Stop at first non-closing-tag, non-whitespace node\n break\n }\n }\n // If we found 3+ consecutive closing tags at the end, remove all but the first one\n // Store the removed closing tags on the paragraph node so html() can render them separately\n // Heuristic: 3+ tags indicates HTML block structure (like </pre></td></tr></table>)\n // 2 tags might be standalone (like </a></foo >) - keep both\n if (closingTagIndices.length >= 3) {\n // Keep only the first closing tag (earliest in array), remove the rest\n var firstClosingTagIdx = closingTagIndices[closingTagIndices.length - 1]\n var removedClosingTags = children.slice(firstClosingTagIdx + 1)\n children.splice(firstClosingTagIdx + 1)\n result.removedClosingTags = removedClosingTags\n }\n }\n\n return result\n}\n\nfunction parseFrontmatter(source: string, pos: number): ParseResult {\n if (pos !== 0) return null\n const bounds = util.parseFrontmatterBounds(source)\n if (!bounds?.hasValidYaml) return null\n return {\n type: RuleType.frontmatter,\n text: source.slice(0, bounds.endPos - 1),\n endPos: bounds.endPos,\n } as MarkdownToJSX.FrontmatterNode & { endPos: number }\n}\n\nfunction parseBreakThematic(\n source: string,\n pos: number,\n state?: MarkdownToJSX.State,\n options?: ParseOptions\n): ParseResult {\n // Find the end of the line\n const lineEnd = util.findLineEnd(source, pos)\n\n // Per CommonMark: up to 3 spaces of indentation allowed\n // Count indentation, checking if it exceeds 3 spaces\n // OPTIMIZATION: Work directly on source string to avoid slice allocation\n const indentResult = calculateIndent(source, pos, lineEnd, 3)\n if (indentResult.spaceEquivalent > 3) return null\n var checkPos = pos + indentResult.charCount\n\n // Now check for thematic break character (-, *, or _)\n if (checkPos >= lineEnd) return null\n const startChar = source[checkPos]\n if (startChar !== '-' && startChar !== '*' && startChar !== '_') return null\n\n // OPTIMIZATION: Fast path - count matching characters before full validation\n // This eliminates 96% of failed attempts (102 attempts -> ~4 attempts)\n // Thematic break requires 3+ matching chars per CommonMark spec\n var charCount = 0\n var scanPos = checkPos\n while (scanPos < lineEnd) {\n var char = source[scanPos]\n if (char === startChar) {\n charCount++\n } else if (char !== ' ' && char !== '\\t') {\n // Non-matching non-whitespace character - not a thematic break\n return null\n }\n scanPos++\n }\n\n if (charCount < 3) {\n return null // Need at least 3 matching characters per CommonMark spec\n }\n\n return {\n type: RuleType.breakThematic,\n endPos: skipToNextLine(source, lineEnd),\n } as MarkdownToJSX.BreakThematicNode & { endPos: number }\n}\n\n/** Calculate the space-equivalent indentation at a position (tabs = 4 spaces) */\nexport function calculateIndent(\n source: string,\n pos: number,\n maxPos: number,\n maxSpaces?: number\n): { spaceEquivalent: number; charCount: number } {\n let spaceEquivalent = 0\n let charCount = 0\n let i = pos\n while (i < maxPos) {\n var iCode = charCode(source, i)\n if (iCode !== $.CHAR_SPACE && iCode !== $.CHAR_TAB) break\n if (maxSpaces !== undefined && spaceEquivalent >= maxSpaces) break\n if (iCode === $.CHAR_TAB) {\n spaceEquivalent += 4 - (spaceEquivalent % 4)\n } else {\n spaceEquivalent += 1\n }\n charCount++\n i++\n }\n return { spaceEquivalent, charCount }\n}\n\nfunction extractCodeBlockLineContent(\n source: string,\n lineStart: number,\n lineEnd: number,\n startColumn: number\n): string {\n let indentChars = 0\n let indentSpaceEquivalent = 0\n let currentColumn = startColumn\n for (let i = lineStart; i < lineEnd && indentSpaceEquivalent < 4; i++) {\n var iCode = charCode(source, i)\n if (iCode === $.CHAR_TAB) {\n const spaces = 4 - (currentColumn % 4)\n indentSpaceEquivalent += spaces\n indentChars++\n currentColumn += spaces\n if (indentSpaceEquivalent >= 4) break\n } else if (iCode === $.CHAR_SPACE) {\n indentSpaceEquivalent++\n indentChars++\n currentColumn++\n if (indentSpaceEquivalent >= 4) break\n } else {\n break\n }\n }\n\n let content = source.slice(lineStart + indentChars, lineEnd)\n var tabCount = 0\n for (var tc = lineStart; tc < lineEnd; tc++) {\n if (source[tc] === '\\t') tabCount++\n if (tabCount >= 2) break\n }\n if (tabCount >= 2 && util.startsWith(content, '\\t') && startColumn > 0) {\n content = ' ' + content.slice(1)\n }\n return content\n}\n\nfunction parseCodeBlock(\n source: string,\n pos: number,\n state: MarkdownToJSX.State\n): ParseResult {\n // Limit indentation scan to current line\n const lineEndForIndent = util.findLineEnd(source, pos)\n const indentInfo = calculateIndent(source, pos, lineEndForIndent)\n if (indentInfo.spaceEquivalent < 4) return null\n\n const initialIndent = indentInfo.spaceEquivalent\n const lineEnd = util.findLineEnd(source, pos + indentInfo.charCount)\n const lineStart = pos\n\n let column = 0\n var i = lineStart - 1\n while (i >= 0 && source[i] !== '\\n' && source[i] !== '\\r') {\n i--\n }\n i++\n while (i < lineStart) {\n if (source[i] === '\\t') {\n column = column + 4 - (column % 4)\n } else {\n column++\n }\n i++\n }\n\n let firstLineContent = extractCodeBlockLineContent(\n source,\n lineStart,\n lineEnd,\n column\n )\n const contentStart = skipToNextLine(source, lineEnd)\n if (contentStart >= source.length) {\n if (!firstLineContent.trim()) return null\n return {\n type: RuleType.codeBlock,\n text: firstLineContent,\n endPos: contentStart,\n } as MarkdownToJSX.CodeBlockNode & { endPos: number }\n }\n\n var parts: string[] = []\n parts.push(firstLineContent)\n let endPos = contentStart\n\n while (endPos < source.length) {\n const nextLineEnd = util.findLineEnd(source, endPos)\n if (isBlankLineCheck(source, endPos, nextLineEnd)) {\n const nextLinePos = nextLineEnd + 1\n if (nextLinePos < source.length) {\n const nextLineEnd = util.findLineEnd(source, nextLinePos)\n const nextIndentInfo = calculateIndent(source, nextLinePos, nextLineEnd)\n const nextChar = source[nextLinePos + nextIndentInfo.charCount]\n if (\n nextChar &&\n nextChar !== '\\n' &&\n (nextIndentInfo.spaceEquivalent < 4 ||\n (nextChar === '>' &&\n nextIndentInfo.spaceEquivalent < initialIndent))\n ) {\n break\n }\n }\n parts.push('\\n')\n } else {\n const currentIndentInfo = calculateIndent(source, endPos, nextLineEnd)\n if (currentIndentInfo.spaceEquivalent < 4) {\n break\n }\n\n let lineContent = extractCodeBlockLineContent(\n source,\n endPos,\n nextLineEnd,\n 0\n )\n parts.push('\\n')\n parts.push(lineContent)\n }\n\n endPos = skipToNextLine(source, nextLineEnd)\n }\n\n let content = parts.join('')\n content = content.replace(TRAILING_NEWLINE_R, '')\n if (!content.trim()) return null\n\n return {\n type: RuleType.codeBlock,\n text: content,\n endPos,\n } as MarkdownToJSX.CodeBlockNode & { endPos: number }\n}\n\nexport function parseCodeFenced(\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): ParseResult {\n const fenceChar = source[pos]\n if (fenceChar !== '`' && fenceChar !== '~') return null\n\n // Fast check: must have at least 3 consecutive fence chars\n const fenceLength = countConsecutiveChars(source, pos, fenceChar)\n if (fenceLength < 3) return null\n\n // Find line start for indentation calculation\n let lineStart = pos\n while (lineStart > 0 && charCode(source, lineStart - 1) !== $.CHAR_NEWLINE)\n lineStart--\n\n // Calculate indentation (caller already verified <= 3, but we need exact value)\n const indentInfo = calculateIndent(source, lineStart, pos)\n let openingIndent = indentInfo.spaceEquivalent\n let contentIndentToRemove = openingIndent\n\n // Handle 4-space indentation special case (simplified)\n if (openingIndent === 4 && indentInfo.charCount === 4) {\n // All 4 chars before pos are spaces/tabs, so this is indented code block\n openingIndent = 0\n contentIndentToRemove = 4\n }\n\n // Should not happen since caller checks indent <= 3, but keep for safety\n if (openingIndent >= 4) return null\n\n let i = util.skipWhitespace(source, pos + fenceLength)\n const lineEnd = util.findLineEnd(source, i)\n let langAndAttrs = source.slice(i, lineEnd).trim()\n\n if (fenceChar === '`' && langAndAttrs.indexOf('`') !== -1) return null\n\n langAndAttrs = langAndAttrs.replace(UNESCAPE_R, '$1')\n const langSpaceIdx = langAndAttrs.indexOf(' ')\n const lang =\n langSpaceIdx > 0 ? langAndAttrs.slice(0, langSpaceIdx) : langAndAttrs\n const attrsString =\n langSpaceIdx > 0 ? langAndAttrs.slice(langSpaceIdx + 1).trim() : ''\n const attrs =\n attrsString && /=\\s*[\"']/.test(attrsString)\n ? parseHTMLAttributes(attrsString, 'code', 'code', options)\n : undefined\n\n let contentStart = skipToNextLine(source, lineEnd)\n let endPos = contentStart\n\n while (endPos < source.length) {\n let lineEndPos = util.findLineEnd(source, endPos)\n\n let fenceStart = endPos\n let indentCount = 0\n while (fenceStart < lineEndPos) {\n const code = charCode(source, fenceStart)\n if (code === $.CHAR_SPACE) {\n indentCount++\n fenceStart++\n if (indentCount >= 4) break\n } else if (code === $.CHAR_TAB) {\n indentCount += 4 - (indentCount % 4)\n fenceStart++\n if (indentCount >= 4) break\n } else {\n break\n }\n }\n\n if (indentCount < 4) {\n let closeLen = countConsecutiveChars(\n source,\n fenceStart,\n fenceChar,\n lineEndPos - fenceStart\n )\n if (closeLen >= fenceLength) {\n let afterFence = fenceStart + closeLen\n while (afterFence < lineEndPos) {\n const code = charCode(source, afterFence)\n if (code === $.CHAR_SPACE || code === $.CHAR_TAB) {\n afterFence++\n } else {\n break\n }\n }\n if (afterFence === lineEndPos) {\n break\n }\n }\n } else if (\n contentIndentToRemove === 4 &&\n openingIndent === 0 &&\n indentCount === 4\n ) {\n let closeLen = countConsecutiveChars(\n source,\n fenceStart,\n fenceChar,\n lineEndPos - fenceStart\n )\n if (\n closeLen >= fenceLength &&\n isBlankLineCheck(source, fenceStart + closeLen, lineEndPos)\n ) {\n break\n }\n }\n\n endPos = skipToNextLine(source, lineEndPos)\n }\n\n let contentEnd =\n endPos > contentStart && source[endPos - 1] === '\\n' ? endPos - 1 : endPos\n let rawContent = source.slice(contentStart, contentEnd)\n if (contentIndentToRemove) {\n rawContent = removeExtraIndentFromCodeBlock(\n rawContent,\n contentIndentToRemove\n )\n }\n\n let finalEndPos =\n endPos < source.length\n ? skipToNextLine(source, util.findLineEnd(source, endPos))\n : endPos\n\n return {\n type: RuleType.codeBlock,\n text: rawContent,\n lang: lang,\n attrs: attrs,\n endPos: finalEndPos,\n } as MarkdownToJSX.CodeBlockNode & { endPos: number }\n}\n\nfunction parseBlockQuoteChildren(\n content: string,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): MarkdownToJSX.ASTNode[] {\n // Fast check: if content is empty or only whitespace, return early\n for (var i = 0; i < content.length; i++) {\n if (!isWS(content[i])) {\n // Parse all blocks using parseBlocksWithState (which uses parseBlock via parseBlocksInHTML)\n const blockChildren = parseBlocksWithState(content, state, options, {\n inline: false,\n inBlockQuote: true,\n })\n // Remove endPos property efficiently without creating intermediate objects\n for (var j = 0; j < blockChildren.length; j++) {\n const node = blockChildren[j] as MarkdownToJSX.ASTNode & {\n endPos?: number\n }\n if ('endPos' in node) {\n delete node.endPos\n }\n }\n return blockChildren\n }\n }\n return []\n}\n\nfunction parseBlockQuote(\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): ParseResult {\n if (state.inline) return null\n\n let checkPos = pos\n while (\n checkPos < source.length &&\n (source[checkPos] === ' ' || source[checkPos] === '\\t')\n ) {\n checkPos++\n }\n if (checkPos >= source.length || source[checkPos] !== '>') return null\n\n // Find the end of the blockquote and process content in single pass\n let endPos = pos\n var processedParts: string[] = []\n var alertType: string | undefined = undefined\n var hasContent = false\n var firstLineStart = -1\n\n // Track if we're currently in a code block (indented or fenced) that requires > prefix\n var inCodeBlock = false\n var codeBlockType: 'indented' | 'fenced' | null = null\n var fencedFenceChar: string | null = null\n var fencedFenceLength = 0\n var previousLineWasEmpty = false\n\n while (endPos < source.length) {\n const lineEnd = util.findLineEnd(source, endPos)\n\n // Check if this line starts a blockquote\n let lineStart = endPos\n // Skip leading whitespace\n while (\n lineStart < lineEnd &&\n (source[lineStart] === ' ' || source[lineStart] === '\\t')\n ) {\n lineStart++\n }\n\n // If line starts with '>', it's part of the blockquote\n if (lineStart < lineEnd && source[lineStart] === '>') {\n let contentStart = lineStart + 1\n if (contentStart < lineEnd && source[contentStart] === ' ') contentStart++\n\n // Inline code block detection (was detectCodeBlockInBlockQuote)\n const indentInfo = calculateIndent(source, contentStart, lineEnd)\n const isIndented = indentInfo.spaceEquivalent >= 4\n let isFenced = false\n let fenceChar: string | null = null\n let fenceLen = 0\n if (contentStart < lineEnd) {\n const firstChar = source[contentStart]\n if (firstChar === '`' || firstChar === '~') {\n let len = 0\n let i = contentStart\n while (i < lineEnd && source[i] === firstChar && len < 20) {\n len++\n i++\n }\n if (len >= 3) {\n isFenced = true\n fenceChar = firstChar\n fenceLen = len\n }\n }\n }\n\n // Update code block state\n if (\n inCodeBlock &&\n codeBlockType === 'fenced' &&\n fenceChar === fencedFenceChar &&\n fenceLen >= fencedFenceLength\n ) {\n inCodeBlock = false\n codeBlockType = null\n fencedFenceChar = null\n fencedFenceLength = 0\n } else if (isIndented || isFenced) {\n inCodeBlock = true\n codeBlockType = isIndented ? 'indented' : 'fenced'\n fencedFenceChar = fenceChar\n fencedFenceLength = fenceLen\n }\n\n // Inline blank line check (was isBlankLineCheck)\n var isBlankLine = !isIndented && !isFenced\n if (isBlankLine) {\n for (var i = contentStart; i < lineEnd; i++) {\n if (!isWS(source[i])) {\n isBlankLine = false\n break\n }\n }\n }\n previousLineWasEmpty = isBlankLine\n\n // Track first line for alert extraction\n if (firstLineStart === -1 && !isBlankLine) {\n firstLineStart = processedParts.length\n }\n if (!isBlankLine) hasContent = true\n\n // Process line content: remove > marker and optional space, handle tabs\n const afterMarkerStart = lineStart + 1\n\n // Check if first char after > is a tab (needs special handling)\n if (afterMarkerStart < lineEnd && source[afterMarkerStart] === '\\t') {\n // Expand tabs to spaces\n processedParts.push(' ') // First tab after > becomes 2 spaces\n let col = 4\n for (let k = afterMarkerStart + 1; k < lineEnd; k++) {\n const char = source[k]\n var code = charCode(char)\n if (code === $.CHAR_TAB) {\n const spaces = 4 - (col % 4)\n // Use fixed strings for common cases\n if (spaces === 1) processedParts.push(' ')\n else if (spaces === 2) processedParts.push(' ')\n else if (spaces === 3) processedParts.push(' ')\n else processedParts.push(' '.repeat(spaces))\n col += spaces\n } else {\n processedParts.push(char)\n col++\n }\n }\n if (lineEnd < source.length) processedParts.push('\\n')\n } else {\n // Fast path: no tab immediately after > (common case)\n let processedContentStart = afterMarkerStart\n if (\n processedContentStart < lineEnd &&\n source[processedContentStart] === ' '\n ) {\n processedContentStart++\n }\n processedParts.push(source.slice(processedContentStart, lineEnd))\n if (lineEnd < source.length) processedParts.push('\\n')\n }\n } else {\n // Check for lazy continuation line (line without > that continues blockquote)\n // Inline blank line check\n var isEmptyLine = true\n for (var i = endPos; i < lineEnd; i++) {\n if (!isWS(source[i])) {\n isEmptyLine = false\n break\n }\n }\n\n // Stop blockquote if: empty line, or in code block (code blocks require > prefix)\n if (isEmptyLine || inCodeBlock) {\n break\n }\n\n const lazyIndentInfo = calculateIndent(source, endPos, lineEnd)\n if (lazyIndentInfo.spaceEquivalent === 0) {\n // Check if this line starts a block (excluding reference definitions which don't break blockquotes)\n const blockResult = parseBlock(source, endPos, state, options)\n if (\n blockResult &&\n blockResult.type !== RuleType.ref &&\n blockResult.type !== RuleType.codeBlock\n ) {\n break\n }\n if (previousLineWasEmpty) {\n break\n }\n }\n processedParts.push(source.slice(endPos, lineEnd))\n if (lineEnd < source.length) processedParts.push('\\n')\n }\n\n endPos = skipToNextLine(source, lineEnd)\n }\n\n // Empty blockquotes are valid (e.g., \">\\n\" or \">\\n> \\n> \\n\")\n // Only reject if we didn't process any lines at all\n if (endPos === pos) return null\n\n // Remove trailing newline if present (avoid endsWith check by tracking)\n if (\n processedParts.length > 0 &&\n processedParts[processedParts.length - 1] === '\\n'\n ) {\n processedParts.pop()\n }\n\n let processedContent = processedParts.join('')\n\n // Extract alert type (check start of content for [!...]\\n pattern)\n if (\n processedContent.length >= 4 &&\n processedContent.charCodeAt(0) === $.CHAR_BRACKET_OPEN &&\n processedContent.charCodeAt(1) === $.CHAR_EXCLAMATION\n ) {\n const alertEnd = processedContent.indexOf(']\\n', 2)\n if (alertEnd > 2) {\n alertType = processedContent.slice(2, alertEnd)\n processedContent = processedContent.slice(alertEnd + 2)\n }\n }\n\n const children = parseBlockQuoteChildren(processedContent, state, options)\n\n const result: MarkdownToJSX.BlockQuoteNode & { endPos: number } = {\n type: RuleType.blockQuote,\n children,\n endPos,\n }\n if (alertType) {\n result.alert = alertType\n }\n return result\n}\n\n/** Remove extra indentation from code block text when used in list items */\nfunction removeExtraIndentFromCodeBlock(\n codeBlockText: string,\n extraIndent: number\n): string {\n return codeBlockText\n .split('\\n')\n .map(function (line) {\n if (line.length === 0) return line\n let toRemove = extraIndent\n let removed = 0\n let i = 0\n let currentColumn = 0\n while (i < line.length && removed < toRemove) {\n if (line[i] === ' ') {\n removed++\n currentColumn++\n i++\n } else if (line[i] === '\\t') {\n const spacesFromTab = 4 - (currentColumn % 4)\n if (removed + spacesFromTab <= toRemove) {\n removed += spacesFromTab\n currentColumn += spacesFromTab\n i++\n } else {\n const remainingToRemove = toRemove - removed\n const spacesToKeep = Math.max(0, spacesFromTab - remainingToRemove)\n return ' '.repeat(spacesToKeep) + line.slice(i + 1)\n }\n } else {\n break\n }\n }\n return line.slice(i)\n })\n .join('\\n')\n}\n\nfunction appendListContinuation(\n continuationContent: string,\n lastItem: MarkdownToJSX.ASTNode[],\n state: MarkdownToJSX.State,\n options: ParseOptions,\n addNewline: boolean = true\n): void {\n const sourceToParse = (addNewline ? '\\n' : '') + continuationContent\n const continuationInline = parseInlineWithState(\n sourceToParse,\n 0,\n sourceToParse.length,\n state,\n options\n )\n if (\n lastItem.length > 0 &&\n lastItem[lastItem.length - 1].type === RuleType.paragraph\n ) {\n ;(\n lastItem[lastItem.length - 1] as MarkdownToJSX.ParagraphNode\n ).children.push(...continuationInline)\n } else {\n lastItem.push(...continuationInline)\n }\n}\n\n// Helper: Check if list item contains block-level content\nfunction listItemHasBlockContent(item: MarkdownToJSX.ASTNode[]): boolean {\n return item.some(function (node) {\n return (\n node.type === RuleType.codeBlock ||\n node.type === RuleType.paragraph ||\n node.type === RuleType.blockQuote ||\n node.type === RuleType.orderedList ||\n node.type === RuleType.unorderedList ||\n node.type === RuleType.heading\n )\n })\n}\n\n// Helper: Check if line matches any list item pattern\nfunction isLineListItem(line: string): boolean {\n return !!line.match(LIST_ITEM_R)\n}\n\n// Helper: Find deepest nested list parent in item hierarchy\nfunction findNestedListParent(\n item: MarkdownToJSX.ASTNode[]\n): MarkdownToJSX.ASTNode[] {\n if (item.length === 0) return item\n var lastBlock = item[item.length - 1]\n if (\n (lastBlock.type === RuleType.orderedList ||\n lastBlock.type === RuleType.unorderedList) &&\n (\n lastBlock as\n | MarkdownToJSX.OrderedListNode\n | MarkdownToJSX.UnorderedListNode\n ).items?.length > 0\n ) {\n return findNestedListParent(\n (\n lastBlock as\n | MarkdownToJSX.OrderedListNode\n | MarkdownToJSX.UnorderedListNode\n ).items.slice(-1)[0]\n )\n }\n return item\n}\n\n// Helper: Skip link reference definition if present\nfunction skipLinkReferenceDefinition(\n source: string,\n linePos: number,\n lineEnd: number,\n indentInfo: ReturnType<typeof calculateIndent>,\n lineWithoutIndent: string,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): number | null {\n if (!util.startsWith(lineWithoutIndent, '[')) return null\n var refCheckState = { inline: false, list: false, refs: state.refs || {} }\n var refResult = parseDefinition(\n source,\n linePos + indentInfo.charCount,\n refCheckState,\n options,\n false\n )\n return refResult ? refResult.endPos : null\n}\n\n// Helper: Check if we should break list due to empty item after blank line\nfunction shouldBreakForEmptyItem(\n items: MarkdownToJSX.ASTNode[][],\n isEmptyItem: boolean,\n prevLineWasBlank: boolean,\n firstItemContent: string\n): boolean {\n if (items.length !== 1 || !prevLineWasBlank) return false\n const lastItem = items[0] // Since items.length === 1, this is the only item\n if (lastItem.length !== 0) return false\n if (isEmptyItem) return true\n if (!isEmptyItem && firstItemContent.trim() === '') return true\n return false\n}\n\n// Helper: Calculate content start column for a list item\n// Helper: Calculate marker end position from match\nfunction calculateMarkerEnd(match: RegExpMatchArray, ordered: boolean): number {\n var markerStart = match.index || 0\n return ordered\n ? markerStart + match[1].length + match[2].length + 1\n : markerStart + match[1].length + 1\n}\n\nfunction calculateListItemContentColumn(\n source: string,\n contentStartInSource: number,\n lineEnd: number,\n baseIndent: number,\n markerEndInLine: number\n): { contentStartColumn: number; contentStartPos: number } {\n var spacesAfterMarker = 0\n var col = baseIndent + markerEndInLine\n var contentCheckPos = contentStartInSource\n while (contentCheckPos < lineEnd && spacesAfterMarker < 4) {\n var code = charCode(source, contentCheckPos)\n if (code === $.CHAR_SPACE) {\n spacesAfterMarker++\n col++\n } else if (code === $.CHAR_TAB) {\n var spaces = 4 - (col % 4)\n if (spacesAfterMarker + spaces > 4) break\n spacesAfterMarker += spaces\n col += spaces\n } else {\n break\n }\n contentCheckPos++\n }\n return { contentStartColumn: col, contentStartPos: contentCheckPos }\n}\n\nfunction matchListItem(\n lineWithoutIndent: string\n): { match: RegExpMatchArray; ordered: boolean; listItemRegex: RegExp } | null {\n var match = lineWithoutIndent.match(LIST_ITEM_R)\n if (!match) return null\n\n // Groups: 1=ordered_num, 2=ordered_delim, 3=ordered_content, 4=ordered_empty_num, 5=ordered_empty_delim, 6=unordered_marker, 7=unordered_content, 8=unordered_empty_marker\n if (match[1]) {\n // Ordered with content: (\\d{1,9})([.)])\\s+(.*)\n return {\n match: [lineWithoutIndent, match[1], match[2], match[3]],\n ordered: true,\n listItemRegex: ORDERED_LIST_ITEM_WITH_CONTENT_R,\n }\n }\n if (match[4]) {\n // Ordered empty: (\\d{1,9})([.)])\\s*\n return {\n match: [lineWithoutIndent, match[4], match[5], ''],\n ordered: true,\n listItemRegex: ORDERED_LIST_ITEM_WITH_CONTENT_R,\n }\n }\n if (match[6]) {\n // Unordered with content: ([-*+])\\s+(.*)\n return {\n match: [lineWithoutIndent, match[6], match[7]],\n ordered: false,\n listItemRegex: UNORDERED_LIST_ITEM_WITH_CONTENT_R,\n }\n }\n if (match[8]) {\n // Unordered empty: ([-*+])\\s*\n return {\n match: [lineWithoutIndent, match[8], ''],\n ordered: false,\n listItemRegex: UNORDERED_LIST_ITEM_WITH_CONTENT_R,\n }\n }\n return null\n}\n\n// Helper: Check if a line is a matching list item for the current list\nfunction isMatchingListItem(\n lineWithoutIndent: string,\n indentInfo: ReturnType<typeof calculateIndent>,\n ordered: boolean,\n marker: string | undefined,\n delimiter: string | undefined,\n baseIndent: number,\n listItemRegex: RegExp\n): boolean {\n if (indentInfo.spaceEquivalent !== baseIndent) return false\n var match = lineWithoutIndent.match(listItemRegex)\n if (match) {\n return ordered ? match[2] === delimiter : match[1] === marker\n }\n var emptyMatch = lineWithoutIndent.match(LIST_ITEM_R)\n if (!emptyMatch) return false\n if (ordered) {\n return emptyMatch[4] && emptyMatch[5] === delimiter\n } else {\n return emptyMatch[8] === marker\n }\n}\n\n// Helper: Handle fenced code blocks that span multiple lines in list items\nfunction expandMultilineFencedCodeBlock(\n source: string,\n itemContent: string,\n startPos: number,\n markerWidth: number\n): { content: string; endPos: number } {\n var content = itemContent\n var pos = startPos\n var fenceChar = itemContent[0]\n while (pos < source.length) {\n var lineEnd = util.findLineEnd(source, pos)\n var line = source.slice(pos, lineEnd)\n var processedLine = util.startsWith(line, ' '.repeat(markerWidth))\n ? line.slice(markerWidth)\n : line\n if (\n util.startsWith(processedLine.trim(), fenceChar) &&\n countConsecutiveChars(processedLine.trim(), 0, fenceChar) >= 3\n ) {\n return { content: content, endPos: skipToNextLine(source, lineEnd) }\n }\n content += '\\n' + processedLine\n pos = skipToNextLine(source, lineEnd)\n }\n return { content: content, endPos: pos }\n}\n\n// Helper function to add a new list item with all standard processing\nfunction addListItem(\n source: string,\n items: MarkdownToJSX.ASTNode[][],\n itemContentStartColumns: number[],\n itemContent: string,\n startPos: number,\n nextLineEnd: number,\n nextIndent: number,\n nextIndentChars: number,\n nextMatch: RegExpMatchArray,\n ordered: boolean,\n hasBlankLines: boolean,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): { newCurrentPos: number; itemHasBlankLine: boolean } {\n // Derive marker/delimiter/regex (cheap to recompute vs passing 3 extra params)\n var marker = ordered ? undefined : nextMatch[1]\n var delimiter = ordered ? nextMatch[2] : undefined\n var listItemRegex = ordered\n ? ORDERED_LIST_ITEM_WITH_CONTENT_R\n : UNORDERED_LIST_ITEM_WITH_CONTENT_R\n\n // Check if item has blank lines\n var itemHasBlankLine = hasBlankLines\n if (!hasBlankLines) {\n var startCheckPos = skipToNextLine(source, nextLineEnd)\n var checkItemPos = startCheckPos\n while (checkItemPos < source.length) {\n var checkLineEnd = util.findLineEnd(source, checkItemPos)\n var checkLine = source.slice(checkItemPos, checkLineEnd)\n var checkIndentInfo = calculateIndent(source, checkItemPos, checkLineEnd)\n var checkIndent = checkIndentInfo.spaceEquivalent\n if (isBlankLineCheck(source, checkItemPos, checkLineEnd)) {\n var afterBlank = skipToNextLine(source, checkLineEnd)\n if (afterBlank < source.length) {\n var afterBlankLineEnd = util.findLineEnd(source, afterBlank)\n var afterBlankIndentInfo = calculateIndent(\n source,\n afterBlank,\n afterBlankLineEnd\n )\n var afterBlankIndent = afterBlankIndentInfo.spaceEquivalent\n var thisItemMarkerEnd = calculateMarkerEnd(nextMatch, ordered)\n var thisItemContentStartInSource =\n startPos + nextIndentChars + thisItemMarkerEnd\n var thisItemResult = calculateListItemContentColumn(\n source,\n thisItemContentStartInSource,\n nextLineEnd,\n nextIndent,\n thisItemMarkerEnd\n )\n var thisItemContentStartColumn = thisItemResult.contentStartColumn\n if (afterBlankIndent + 1 > thisItemContentStartColumn) {\n itemHasBlankLine = true\n break\n }\n }\n break\n } else if (checkIndent <= nextIndent) {\n var checkLineWithoutIndent = checkLine.slice(checkIndentInfo.charCount)\n var checkMatch = checkLineWithoutIndent.match(listItemRegex)\n if (\n checkMatch &&\n (ordered ? checkMatch[2] === delimiter : checkMatch[1] === marker)\n ) {\n break\n }\n }\n checkItemPos = skipToNextLine(source, checkLineEnd)\n }\n }\n\n // Calculate content start column\n var thisItemMarkerEnd = calculateMarkerEnd(nextMatch, ordered)\n var thisItemContentStartInSource =\n startPos + nextIndentChars + thisItemMarkerEnd\n var thisItemResult = calculateListItemContentColumn(\n source,\n thisItemContentStartInSource,\n nextLineEnd,\n nextIndent,\n thisItemMarkerEnd\n )\n var thisItemContentStartColumn = thisItemResult.contentStartColumn\n\n // Handle fenced code blocks\n var actualItemContent = itemContent\n var newCurrentPos = skipToNextLine(source, nextLineEnd)\n if (\n util.startsWith(itemContent, '```') ||\n util.startsWith(itemContent, '~~~')\n ) {\n var markerWidth = ordered\n ? nextMatch[1].length + nextMatch[2].length + 1\n : nextMatch[1].length + 1\n var expandedResult = expandMultilineFencedCodeBlock(\n source,\n itemContent,\n newCurrentPos,\n markerWidth\n )\n actualItemContent = expandedResult.content\n newCurrentPos = expandedResult.endPos\n }\n\n // Build and add item with GFM task support\n items.push(\n buildListItemContent(actualItemContent, itemHasBlankLine, state, options)\n )\n itemContentStartColumns.push(thisItemContentStartColumn)\n\n return { newCurrentPos, itemHasBlankLine }\n}\n\n// Helper function to process list item continuation lines\nfunction checkHTMLTagInterruptsList(\n source: string,\n pos: number,\n indentChars: number,\n baseIndent: number,\n indent: number,\n options: ParseOptions\n): boolean {\n if (indent > baseIndent || options.disableParsingRawHTML) return false\n const lineStartPos = pos + indentChars\n if (lineStartPos >= source.length || source[lineStartPos] !== '<')\n return false\n return isValidHTMLTagStart(source, lineStartPos)\n}\n\n// Lightweight check for HTML tag validity without full parsing\nfunction isValidHTMLTagStart(source: string, pos: number): boolean {\n if (pos >= source.length || source[pos] !== '<') return false\n const len = source.length\n let i = pos + 1\n\n // Handle closing tags\n if (i < len && source[i] === '/') {\n i++\n }\n\n // Must have at least one character for tag name\n if (i >= len) return false\n\n // First character of tag name must be letter\n const firstChar = charCode(source, i)\n if (!isAlphaCode(firstChar)) return false\n i++\n\n // Rest of tag name can be letters, digits, hyphens, underscores\n // Use early return to avoid nested conditionals\n while (i < len) {\n const ch = source[i]\n const code = charCode(source, i)\n\n // Break conditions (valid tag name terminators)\n if (\n ch === '>' ||\n ch === ' ' ||\n ch === '\\t' ||\n ch === '\\n' ||\n ch === '\\r' ||\n ch === '/'\n ) {\n break\n }\n\n // Valid tag name characters - continue\n if (\n ch === '-' ||\n ch === '_' ||\n isAlphaCode(code) ||\n (code >= 48 && code <= 57)\n ) {\n i++\n } else {\n return false // Invalid character in tag name\n }\n }\n\n // Find the end of the tag - use state machine approach to reduce branching\n let state = 0 // 0: normal, 1: in double quotes, 2: in single quotes\n while (i < len) {\n const ch = source[i]\n const code = charCode(source, i)\n\n // State machine for quote handling\n if (state === 1) {\n // in double quotes\n if (ch === '\"') state = 0\n i++\n } else if (state === 2) {\n // in single quotes\n if (ch === \"'\") state = 0\n i++\n } else if (ch === '\"') {\n state = 1\n i++\n } else if (ch === \"'\") {\n state = 2\n i++\n } else if (ch === '>') {\n return true // Found valid closing >\n } else if (ch === '/' && i + 1 < len && source[i + 1] === '>') {\n return true // Found valid self-closing />\n } else if (code === 10 || code === 13) {\n // \\n or \\r\n return false // No multiline tags in this context\n } else {\n i++\n }\n }\n\n return false // No closing > found\n}\n\nfunction processContinuation(\n source: string,\n item: MarkdownToJSX.ASTNode[],\n contentStartColumn: number,\n startPos: number,\n baseIndent: number,\n ordered: boolean,\n marker: string | undefined,\n delimiter: string | undefined,\n listItemRegex: RegExp,\n state: MarkdownToJSX.State,\n options: ParseOptions,\n allowLinkRefs?: boolean\n): number {\n let pos = startPos\n let prevLineWasBlank = false\n while (pos < source.length) {\n const lineEnd = util.findLineEnd(source, pos)\n const indentInfo = calculateIndent(source, pos, lineEnd)\n const indent = indentInfo.spaceEquivalent\n\n if (isBlankLineCheck(source, pos, lineEnd)) {\n prevLineWasBlank = true\n pos = skipToNextLine(source, lineEnd)\n continue\n }\n\n const lineWithoutIndent = source.slice(pos + indentInfo.charCount, lineEnd)\n\n if (\n indent <= baseIndent &&\n isMatchingListItem(\n lineWithoutIndent,\n indentInfo,\n ordered,\n marker,\n delimiter,\n baseIndent,\n listItemRegex\n )\n ) {\n break\n }\n\n if (indent >= contentStartColumn) {\n // Check for link reference definitions (only for first item)\n if (allowLinkRefs && prevLineWasBlank) {\n const refEndPos = skipLinkReferenceDefinition(\n source,\n pos,\n lineEnd,\n indentInfo,\n lineWithoutIndent,\n state,\n options\n )\n if (refEndPos) {\n pos = refEndPos\n prevLineWasBlank = false\n continue\n }\n }\n\n const result = processListContinuationLine(\n source,\n pos,\n lineEnd,\n indentInfo,\n contentStartColumn - 1,\n contentStartColumn,\n item,\n prevLineWasBlank,\n state,\n options,\n undefined,\n baseIndent\n )\n if (result.processed) {\n pos = result.newPos\n prevLineWasBlank = result.wasBlank\n continue\n }\n } else {\n break\n }\n }\n return pos\n}\n\n// Helper: Parse content with paragraph wrapping for tight/loose lists\nfunction parseContentWithParagraphHandling(\n content: string,\n wrapInParagraph: boolean,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): MarkdownToJSX.ASTNode[] {\n const blocks = parseBlocksWithState(content, state, options, {\n inline: false,\n list: true,\n })\n if (blocks.length > 0) {\n // Unwrap single paragraph for tight lists\n return !wrapInParagraph &&\n blocks.length === 1 &&\n blocks[0].type === RuleType.paragraph\n ? (blocks[0] as MarkdownToJSX.ParagraphNode).children\n : blocks\n }\n // Fallback to inline parsing\n const inline = parseWithInlineMode(state, true, () =>\n parseInlineSpan(content, 0, content.length, state, options)\n )\n return wrapInParagraph && inline.length > 0\n ? [\n {\n type: RuleType.paragraph,\n children: inline,\n } as MarkdownToJSX.ParagraphNode,\n ]\n : inline\n}\n\nfunction buildListItemContent(\n itemContent: string,\n itemHasBlankLine: boolean,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): MarkdownToJSX.ASTNode[] {\n const task = parseGFMTask(itemContent, 0, state)\n const hasTask =\n task &&\n (task.endPos >= itemContent.length || itemContent[task.endPos] === ' ')\n if (!hasTask) {\n return parseContentWithParagraphHandling(\n itemContent,\n itemHasBlankLine,\n state,\n options\n )\n }\n const afterTask =\n task.endPos < itemContent.length ? task.endPos + 1 : task.endPos\n const restContent = itemContent.slice(afterTask)\n const restNodes = parseContentWithParagraphHandling(\n restContent,\n itemHasBlankLine,\n state,\n options\n )\n const nodes: MarkdownToJSX.ASTNode[] = [task]\n if (task.endPos < itemContent.length) {\n nodes.push({ type: RuleType.text, text: ' ' } as MarkdownToJSX.TextNode)\n }\n nodes.push(...restNodes)\n return nodes\n}\n\nfunction checkUnicodeWhitespaceAfterMarker(\n match: RegExpMatchArray,\n marker: string\n): boolean {\n if (!match[0]) return false\n const markerInMatch = match[0].indexOf(marker)\n if (markerInMatch === -1) return false\n const afterMarkerInMatch = markerInMatch + marker.length\n if (afterMarkerInMatch >= match[0].length) return false\n const afterMarkerChar = match[0][afterMarkerInMatch]\n return afterMarkerChar ? charCode(afterMarkerChar) === $.CHAR_NBSP : false\n}\n\nfunction convertSetextHeadingInListItem(\n lastItem: MarkdownToJSX.ASTNode[],\n underlineLine: string,\n options: ParseOptions\n): boolean {\n if (lastItem.length === 0) return false\n const lastBlock = lastItem[lastItem.length - 1]\n const trimmed = underlineLine.trim()\n if (\n (!util.startsWith(trimmed, '=') && !util.startsWith(trimmed, '-')) ||\n trimmed.length < 1 ||\n !/^[=-]+[ \\t]*$/.test(trimmed)\n ) {\n return false\n }\n\n let headingChildren: MarkdownToJSX.ASTNode[] = []\n let headingContent = ''\n if (lastBlock.type === RuleType.paragraph) {\n const paragraph = lastBlock as MarkdownToJSX.ParagraphNode\n headingChildren = paragraph.children\n headingContent = paragraph.children\n .map(child =>\n child.type === RuleType.text\n ? (child as MarkdownToJSX.TextNode).text\n : ''\n )\n .join('')\n .trim()\n } else if (lastBlock.type === RuleType.text) {\n const textNodes: MarkdownToJSX.TextNode[] = []\n let i = lastItem.length - 1\n while (i >= 0 && lastItem[i].type === RuleType.text) {\n textNodes.unshift(lastItem[i] as MarkdownToJSX.TextNode)\n i--\n }\n if (textNodes.length > 0) {\n headingChildren = textNodes\n headingContent = textNodes\n .map(node => (node as MarkdownToJSX.TextNode).text)\n .join('')\n .trim()\n }\n }\n\n if (!headingContent) return false\n\n const underlineChar = trimmed[0]\n const level = underlineChar === '=' ? 1 : 2\n if (lastBlock.type === RuleType.paragraph) {\n lastItem.pop()\n } else if (lastBlock.type === RuleType.text) {\n while (\n lastItem.length > 0 &&\n lastItem[lastItem.length - 1].type === RuleType.text\n ) {\n lastItem.pop()\n }\n }\n lastItem.push(\n createHeading(level, headingChildren, headingContent, options.slugify)\n )\n return true\n}\n\nfunction processListContinuationLine(\n source: string,\n currentPos: number,\n nextLineEnd: number,\n nextIndentInfo: ReturnType<typeof calculateIndent>,\n continuationColumn: number,\n contentStartColumn: number,\n lastItem: MarkdownToJSX.ASTNode[],\n prevLineWasBlank: boolean,\n state: MarkdownToJSX.State,\n options: ParseOptions,\n unwrapParagraphs?: boolean,\n baseIndent?: number\n): { processed: boolean; newPos: number; wasBlank: boolean } {\n const nextIndent = nextIndentInfo.spaceEquivalent\n const continuationContent = source.slice(\n currentPos + nextIndentInfo.charCount,\n nextLineEnd\n )\n\n if (nextIndent >= continuationColumn + 4) {\n const blockResult = parseCodeBlock(source, currentPos, state)\n if (blockResult) {\n const codeBlockNode = blockResult as MarkdownToJSX.CodeBlockNode & {\n endPos: number\n }\n const adjustedText = removeExtraIndentFromCodeBlock(\n codeBlockNode.text || '',\n contentStartColumn\n )\n lastItem.push({\n ...codeBlockNode,\n text: adjustedText,\n } as MarkdownToJSX.CodeBlockNode)\n return {\n processed: true,\n newPos: codeBlockNode.endPos,\n wasBlank: false,\n }\n }\n }\n\n const indentRelativeToContentFenced = nextIndent - (contentStartColumn - 1)\n if (\n nextIndent + 1 >= contentStartColumn &&\n indentRelativeToContentFenced <= 3\n ) {\n const continuationStart = currentPos + nextIndentInfo.charCount\n if (continuationStart < nextLineEnd) {\n const firstCharAfterIndent = source[continuationStart]\n if (firstCharAfterIndent === '`' || firstCharAfterIndent === '~') {\n const fencedResult = parseCodeFenced(\n source,\n continuationStart,\n state,\n options\n )\n if (fencedResult) {\n const codeBlockNode = fencedResult as MarkdownToJSX.CodeBlockNode & {\n endPos: number\n }\n const adjustedText = removeExtraIndentFromCodeBlock(\n codeBlockNode.text || '',\n contentStartColumn - 1\n )\n lastItem.push({\n ...codeBlockNode,\n text: adjustedText,\n endPos: codeBlockNode.endPos,\n } as MarkdownToJSX.CodeBlockNode & { endPos: number })\n return {\n processed: true,\n newPos: codeBlockNode.endPos,\n wasBlank: false,\n }\n }\n }\n // Try parsing as table when line starts with |\n if (firstCharAfterIndent === '|') {\n const tableResult = parseTable(\n source,\n continuationStart,\n state,\n options\n )\n if (tableResult) {\n const tableNode = tableResult as MarkdownToJSX.TableNode & {\n endPos: number\n }\n lastItem.push(tableNode)\n return {\n processed: true,\n newPos: tableNode.endPos,\n wasBlank: false,\n }\n }\n }\n }\n }\n\n if (\n continuationContent.length > 0 &&\n (continuationContent[0] === '-' ||\n continuationContent[0] === '*' ||\n continuationContent[0] === '+' ||\n (continuationContent[0] >= '0' && continuationContent[0] <= '9'))\n ) {\n const listMarkerRegex = /^([-*+]|\\d{1,9}[.)])\\s+/\n if (listMarkerRegex.test(continuationContent)) {\n const inline = parseInlineWithState(\n continuationContent,\n 0,\n continuationContent.length,\n state,\n options\n )\n lastItem.push({ type: RuleType.text, text: '\\n' }, ...inline)\n return {\n processed: true,\n newPos: skipToNextLine(source, nextLineEnd),\n wasBlank: false,\n }\n }\n }\n\n const mergedPos = tryMergeBlockquoteContinuation(\n source,\n currentPos,\n lastItem,\n continuationContent,\n state,\n options\n )\n if (mergedPos !== null) {\n return { processed: true, newPos: mergedPos, wasBlank: false }\n }\n\n const continuationBlocks = parseBlocksWithState(\n continuationContent,\n state,\n options,\n { inline: false, list: true }\n )\n if (continuationBlocks.length > 0) {\n if (unwrapParagraphs && continuationBlocks[0].type === RuleType.paragraph) {\n const continuationParagraph =\n continuationBlocks[0] as MarkdownToJSX.ParagraphNode\n lastItem.push(\n { type: RuleType.text, text: '\\n' } as MarkdownToJSX.TextNode,\n ...continuationParagraph.children\n )\n if (continuationBlocks.length > 1) {\n lastItem.push(...continuationBlocks.slice(1))\n }\n } else if (\n !prevLineWasBlank &&\n continuationBlocks[0].type === RuleType.paragraph &&\n lastItem.length > 0\n ) {\n const lastBlock = lastItem[lastItem.length - 1]\n const continuationParagraph =\n continuationBlocks[0] as MarkdownToJSX.ParagraphNode\n if (lastBlock.type === RuleType.paragraph) {\n ;(lastBlock as MarkdownToJSX.ParagraphNode).children.push(\n { type: RuleType.text, text: '\\n' } as MarkdownToJSX.TextNode,\n ...continuationParagraph.children\n )\n } else if (lastBlock.type === RuleType.heading) {\n lastItem.push(...continuationParagraph.children)\n } else if (!listItemHasBlockContent(lastItem)) {\n lastItem.push(\n { type: RuleType.text, text: ' ' } as MarkdownToJSX.TextNode,\n ...continuationParagraph.children\n )\n } else {\n lastItem.push(...continuationBlocks)\n }\n if (continuationBlocks.length > 1) {\n lastItem.push(...continuationBlocks.slice(1))\n }\n } else {\n lastItem.push(...continuationBlocks)\n }\n return {\n processed: true,\n newPos: skipToNextLine(source, nextLineEnd),\n wasBlank: false,\n }\n }\n\n if (prevLineWasBlank) {\n const inline = parseWithInlineMode(state, true, () =>\n parseInlineSpan(\n continuationContent,\n 0,\n continuationContent.length,\n state,\n options\n )\n )\n lastItem.push({\n type: RuleType.paragraph,\n children: inline,\n } as MarkdownToJSX.ParagraphNode)\n } else {\n appendListContinuation(continuationContent, lastItem, state, options)\n }\n return {\n processed: true,\n newPos: skipToNextLine(source, nextLineEnd),\n wasBlank: false,\n }\n}\n\nfunction parseList(\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): ParseResult {\n if (state.inline) return null\n\n // Set inList state for proper GFM task tracking during inline parsing\n var originalInList = state.inList\n state.inList = true\n\n // Lists must start at the beginning of a line (block boundary)\n if (pos > 0) {\n var prevCharCode = charCode(source, pos - 1)\n if (prevCharCode !== $.CHAR_NEWLINE && prevCharCode !== $.CHAR_CR) {\n state.inList = originalInList\n return null\n }\n }\n\n var lineEnd = util.findLineEnd(source, pos)\n var indentInfo = calculateIndent(source, pos, lineEnd)\n // Early fail: headings/lists cannot be indented more than 3 spaces unless in list context\n if (indentInfo.spaceEquivalent > 3 && !state.inList) {\n state.inList = originalInList\n return null\n }\n var line = source.slice(pos, lineEnd)\n var indent = indentInfo.charCount\n var lineWithoutIndent = line.slice(indent)\n\n // Detect list type: ordered (digit marker) vs unordered (-/*/+ marker)\n var matchResult = matchListItem(lineWithoutIndent)\n if (!matchResult) {\n state.inList = originalInList\n return null\n }\n var match = matchResult.match\n var ordered = matchResult.ordered\n var listItemRegex = matchResult.listItemRegex\n\n var baseIndent = indentInfo.spaceEquivalent\n // Extract list-specific properties: start number and delimiter for ordered, marker for unordered\n var start = ordered ? parseInt(match[1], 10) : undefined\n var delimiter = ordered ? match[2] : undefined // '.' or ')' for ordered lists\n var marker = ordered ? undefined : match[1] // '-', '*', or '+' for unordered lists\n\n // Check if this is an empty list item (no content after marker)\n var isEmptyItem = ordered ? match[3] === '' : match[2] === ''\n\n // Helper: Check if we're at a block boundary (document start or after blank line)\n function isAtBlockBoundary(\n checkPos: number,\n requireBlankLine: boolean\n ): boolean {\n if (checkPos === 0) return true\n var prevCode = charCode(source, checkPos - 1)\n if (prevCode !== $.CHAR_NEWLINE) return false\n if (!requireBlankLine) return true\n var backPos = checkPos - 2\n while (backPos >= 0) {\n var code = charCode(source, backPos)\n if (code !== $.CHAR_SPACE && code !== $.CHAR_TAB) break\n backPos--\n }\n return backPos < 0 || charCode(source, backPos) === $.CHAR_NEWLINE\n }\n\n // Per CommonMark: empty list items cannot interrupt paragraphs (need blank line)\n if (isEmptyItem && !isAtBlockBoundary(pos, true)) {\n state.inList = originalInList\n return null\n }\n\n // Per CommonMark: only ordered lists starting with 1 can interrupt paragraphs\n if (ordered && start !== 1 && !isAtBlockBoundary(pos, false)) {\n return null\n }\n\n // For unordered lists, check that the whitespace after marker is regular space/tab, not Unicode whitespace\n if (!ordered && checkUnicodeWhitespaceAfterMarker(match, marker)) {\n return null\n }\n\n // Calculate the content start column: where the first non-whitespace character\n // after the marker delimiter actually appears in the source\n // This is needed to determine continuation indentation\n var markerStartInLine = match.index || 0\n // isEmptyItem is already set above - check if it needs updating based on spacesAfterMarkerCount\n // Empty item is different from item with whitespace but no content\n // We'll calculate spacesAfterMarkerCount later and update isEmptyItem if needed\n var markerEndInLine = ordered\n ? markerStartInLine + match[1].length + match[2].length + 1 // number + delimiter + required space\n : isEmptyItem\n ? markerStartInLine + match[1].length // marker only (no space)\n : markerStartInLine + match[1].length + 1 // marker + required space\n // Find the actual position after marker delimiter in the source\n var contentStartInSource = pos + indent + markerEndInLine\n // Count spaces/tabs before first non-whitespace in the content\n // Per CommonMark spec: marker must be followed by 1 ≤ N ≤ 4 spaces\n var contentColumnResult = calculateListItemContentColumn(\n source,\n contentStartInSource,\n lineEnd,\n baseIndent,\n markerEndInLine\n )\n var contentStartColumn = contentColumnResult.contentStartColumn\n // minimumContentStartColumn is the minimum column where content can start (for continuation checks)\n // This is the column after marker+space, regardless of how much whitespace follows\n // For empty items, it's right after the marker\n var markerBaseColumn = baseIndent + markerStartInLine + match[1].length\n var minimumContentStartColumn = ordered\n ? markerBaseColumn + match[2].length + 1 // number + delimiter + space\n : isEmptyItem\n ? markerBaseColumn // marker only (no space)\n : markerBaseColumn + 1 // marker + space\n\n var items: MarkdownToJSX.ASTNode[][] = []\n // Track contentStartColumn for each item (for nested list detection)\n var itemContentStartColumns: number[] = []\n\n // Helper: Check if a marker column is nested enough to belong to the last item\n function isMarkerNested(\n markerColumn: number,\n lastItemContentColumn: number,\n hasBlockContent: boolean\n ): boolean {\n return hasBlockContent\n ? markerColumn >= lastItemContentColumn\n : markerColumn > lastItemContentColumn\n }\n\n // Helper: Get last item\n function getLastItem(): MarkdownToJSX.ASTNode[] {\n return items[items.length - 1]\n }\n\n // Helper: Get last item's content start column\n function getLastItemContentColumn(): number {\n return (\n itemContentStartColumns[itemContentStartColumns.length - 1] ??\n contentStartColumn\n )\n }\n\n function tryParseNestedList(\n pos: number,\n lastItem: MarkdownToJSX.ASTNode[]\n ): ParseResult | null {\n const parentItem = findNestedListParent(lastItem)\n const originalList = state.inList\n state.inList = true\n const result = parseList(source, pos, state, options)\n state.inList = originalList\n if (result) {\n parentItem.push(result)\n return result\n }\n return null\n }\n\n var currentPos = skipToNextLine(source, lineEnd)\n\n // Check if this is a loose list (has blank lines)\n var checkPos = currentPos\n var hasBlankLines = false\n\n while (checkPos < source.length) {\n var nextLineEnd = util.findLineEnd(source, checkPos)\n var nextLine = source.slice(checkPos, nextLineEnd)\n if (nextLine.trim() === '') {\n // look ahead to next non-empty line\n var look = skipToNextLine(source, nextLineEnd)\n while (look < source.length) {\n var code = charCode(source, look)\n if (code === $.CHAR_NEWLINE) {\n // keep skipping\n } else if (!WHITESPACE_CHARS.has(source[look])) {\n break\n }\n look++\n }\n var lookEnd = util.findLineEnd(source, look)\n var lookLine = source.slice(look, lookEnd)\n var lookIndentInfo = calculateIndent(source, look, lookEnd)\n var lookLineWithoutIndent = lookLine.slice(lookIndentInfo.charCount)\n if (\n isMatchingListItem(\n lookLineWithoutIndent,\n lookIndentInfo,\n ordered,\n marker,\n delimiter,\n baseIndent,\n listItemRegex\n )\n ) {\n hasBlankLines = true\n } else {\n // Per CommonMark: link reference definitions can interrupt lists\n // If blank line is followed by a link reference definition, check if there's a list item after it\n var refEndPos = skipLinkReferenceDefinition(\n source,\n look,\n lookEnd,\n lookIndentInfo,\n lookLineWithoutIndent,\n state,\n options\n )\n if (refEndPos) {\n var afterRefPos = refEndPos\n while (\n afterRefPos < source.length &&\n charCode(source, afterRefPos) === $.CHAR_NEWLINE\n ) {\n afterRefPos++\n }\n if (afterRefPos < source.length) {\n var afterRefLineEnd = util.findLineEnd(source, afterRefPos)\n var afterRefLine = source.slice(afterRefPos, afterRefLineEnd)\n var afterRefIndentInfo = calculateIndent(\n source,\n afterRefPos,\n afterRefLineEnd\n )\n var afterRefLineWithoutIndent = afterRefLine.slice(\n afterRefIndentInfo.charCount\n )\n if (\n isMatchingListItem(\n afterRefLineWithoutIndent,\n afterRefIndentInfo,\n ordered,\n marker,\n delimiter,\n baseIndent,\n listItemRegex\n )\n ) {\n hasBlankLines = true\n }\n }\n }\n }\n break\n }\n var nextIndentInfo = calculateIndent(source, checkPos, nextLineEnd)\n var nextLineWithoutIndent = nextLine.slice(nextIndentInfo.charCount)\n var nextMatchResult = matchListItem(nextLineWithoutIndent)\n if (!nextMatchResult) break\n var nextMatch = nextMatchResult.match\n if (ordered) {\n if (nextMatch[2] !== delimiter) break\n } else {\n if (nextMatch[1] !== marker) break\n }\n checkPos = skipToNextLine(source, nextLineEnd)\n }\n\n // Parse the first item\n var firstItemContent = ordered ? match[3] : match[2]\n // Trim leading whitespace from content (regex now captures optional whitespace)\n firstItemContent = firstItemContent.trimStart()\n\n // Per CommonMark spec: tabs after list marker need special handling\n // For `-\\t\\tfoo`: `-` at column 0, first tab at column 1 = 3 spaces (one for marker delimiter),\n // second tab at column 4 = 4 spaces, total 6 spaces, so code block with 2 spaces remaining\n // The regex `\\s+` consumes the tabs, so match[2]/match[3] is just `foo`\n // We need to check the original source to detect tabs after the marker\n var markerStartPos = pos + indent + (match.index || 0)\n var markerEndPos = ordered\n ? markerStartPos + match[1].length + match[2].length // number + delimiter\n : markerStartPos + match[1].length // marker\n\n // Check for spaces after marker (for code blocks with 5+ spaces)\n // Per CommonMark: if there are 4+ spaces after the marker (including required space),\n // the first line is an indented code block\n var contentStartPos = markerEndPos\n // Skip the required space/tab after marker\n while (contentStartPos < source.length) {\n var code = charCode(source, contentStartPos)\n if (code !== $.CHAR_SPACE && code !== $.CHAR_TAB) break\n contentStartPos++\n }\n // Count spaces after marker (including the required one)\n var spacesAfterMarkerCount = 0\n var spacesCheckPos = markerEndPos\n while (spacesCheckPos < lineEnd) {\n var code = charCode(source, spacesCheckPos)\n if (code === $.CHAR_TAB) {\n spacesAfterMarkerCount += 4 - (spacesAfterMarkerCount % 4)\n } else if (code === $.CHAR_SPACE) {\n spacesAfterMarkerCount++\n } else {\n break\n }\n spacesCheckPos++\n }\n\n var tabsProcessed = false\n if (\n markerEndPos < source.length &&\n charCode(source, markerEndPos) === $.CHAR_TAB\n ) {\n // First tab after marker was consumed by `\\s+`\n // Tab at column 1 = 3 spaces (1 for delimiter, 2 for content)\n // Check if there's a second tab\n var tabCount = 1\n var tabCheckPos = markerEndPos + 1\n while (\n tabCheckPos < source.length &&\n charCode(source, tabCheckPos) === $.CHAR_TAB\n ) {\n tabCount++\n tabCheckPos++\n }\n\n if (tabCount >= 2) {\n // We have 2+ tabs after marker: first gives 2 spaces, second at column 4 = 4 spaces\n // Total: 6 spaces, then remove 4 for code block = 2 spaces\n firstItemContent = ' ' + firstItemContent\n tabsProcessed = true\n }\n }\n // Update isEmptyItem now that we know spacesAfterMarkerCount\n // Empty item is one with no whitespace after marker (spacesAfterMarkerCount === 0)\n // For unordered lists, also check that match[2] is empty (no content captured)\n if (!ordered) {\n isEmptyItem = isEmptyItem && spacesAfterMarkerCount === 0\n }\n // RULE_2_CODE_START: if 4+ spaces after marker, first line is indented code block\n // Skip if tabs were already processed (they already account for code block indentation)\n if (spacesAfterMarkerCount >= 4 && !tabsProcessed) {\n // Preserve the leading spaces for code blocks\n const preservedSpaces = ' '.repeat(spacesAfterMarkerCount - 1)\n firstItemContent = preservedSpaces + firstItemContent.trimStart()\n }\n\n // RULE_3_BLANK_START: check if item starts with blank line\n // If firstItemContent is empty (just whitespace), this is RULE_3_BLANK_START\n var startsWithBlankLine = firstItemContent.trim() === ''\n if (startsWithBlankLine) {\n // For RULE_3_BLANK_START, content starts after blank line(s)\n // Continuation lines need to be indented by W + 1 spaces minimum\n // W is the width of the marker (1 for '-', 2 for '10.', etc.)\n // So minimum continuation indent is markerWidth + 1\n }\n\n // Check if there will be blank lines within the first item (after currentPos)\n // by looking ahead to see if we'll encounter a blank line before the next item or end\n let firstItemHasBlankLine = hasBlankLines\n if (!hasBlankLines && currentPos < source.length) {\n var firstCheckPos = currentPos\n while (firstCheckPos < source.length) {\n var firstNextLineEnd = util.findLineEnd(source, firstCheckPos)\n var firstNextLine = source.slice(firstCheckPos, firstNextLineEnd)\n if (isBlankLineCheck(source, firstCheckPos, firstNextLineEnd)) {\n // Found blank line - check if continuation belongs to nested list or first item\n var afterBlank = skipToNextLine(source, firstNextLineEnd)\n // Skip consecutive blank lines\n while (afterBlank < source.length) {\n var blankLineEnd = util.findLineEnd(source, afterBlank)\n if (isBlankLineCheck(source, afterBlank, blankLineEnd)) {\n afterBlank = skipToNextLine(source, blankLineEnd)\n } else {\n break\n }\n }\n\n if (afterBlank < source.length) {\n var afterIndentInfo = calculateIndent(\n source,\n afterBlank,\n source.length\n )\n var afterIndent = afterIndentInfo.spaceEquivalent\n if (afterIndent >= baseIndent) {\n var afterLine = source.slice(\n afterBlank,\n util.findLineEnd(source, afterBlank)\n )\n var afterMatch = afterLine\n .slice(afterIndentInfo.charCount)\n .match(listItemRegex)\n var afterIsNewItem =\n afterMatch &&\n (ordered ? afterMatch[2] === delimiter : afterMatch[1] === marker)\n\n // Find nested item before blank line and calculate its content column\n var nestedItemContentColumn = null\n for (\n var nestedCheckPos = currentPos;\n nestedCheckPos < firstCheckPos;\n nestedCheckPos = util.findLineEnd(source, nestedCheckPos) + 1\n ) {\n var nestedCheckLineEnd = util.findLineEnd(source, nestedCheckPos)\n var nestedCheckIndentInfo = calculateIndent(\n source,\n nestedCheckPos,\n nestedCheckLineEnd\n )\n var nestedCheckMatch = source\n .slice(nestedCheckPos, nestedCheckLineEnd)\n .slice(nestedCheckIndentInfo.charCount)\n .match(listItemRegex)\n var isNestedItem =\n nestedCheckMatch &&\n nestedCheckIndentInfo.spaceEquivalent > baseIndent &&\n nestedCheckIndentInfo.spaceEquivalent >= contentStartColumn &&\n (ordered\n ? nestedCheckMatch[2] === delimiter\n : nestedCheckMatch[1] === marker)\n\n if (isNestedItem) {\n // Calculate nested item's content column (same pattern as contentStartColumn)\n var nestedMarkerStart =\n nestedCheckIndentInfo.spaceEquivalent + 1\n var nestedMarkerEnd = ordered\n ? nestedMarkerStart +\n nestedCheckMatch[1].length +\n nestedCheckMatch[2].length +\n 1\n : nestedMarkerStart + nestedCheckMatch[1].length + 1\n var nestedContentStartInSource =\n nestedCheckPos +\n nestedCheckIndentInfo.charCount +\n nestedCheckMatch[0].length\n var nestedResult = calculateListItemContentColumn(\n source,\n nestedContentStartInSource,\n nestedCheckLineEnd,\n nestedMarkerStart,\n nestedMarkerEnd - nestedMarkerStart\n )\n nestedItemContentColumn = nestedResult.contentStartColumn\n break\n }\n }\n\n var continuationCheckColumn =\n spacesAfterMarkerCount >= 5\n ? minimumContentStartColumn\n : contentStartColumn\n if (\n !afterIsNewItem &&\n afterIndent >= continuationCheckColumn &&\n (nestedItemContentColumn === null ||\n afterIndent + 1 < nestedItemContentColumn)\n ) {\n firstItemHasBlankLine = true\n }\n }\n }\n break\n }\n // Check if this line is a new list item (at same or greater indentation)\n var firstLineIndentInfo = calculateIndent(\n source,\n firstCheckPos,\n firstNextLineEnd\n )\n var firstIndent = firstLineIndentInfo.spaceEquivalent\n var firstLineWithoutIndent = firstNextLine.slice(\n firstLineIndentInfo.charCount\n )\n var firstLineMatch = firstLineWithoutIndent.match(listItemRegex)\n var firstIsNewItem =\n firstLineMatch &&\n (ordered\n ? firstLineMatch[2] === delimiter\n : firstLineMatch[1] === marker)\n // If it's a new item at baseIndent, it's the next item at same level - stop looking\n // For nested items, continue looking for blank lines after the nested list\n if (firstIsNewItem) {\n if (firstIndent <= baseIndent) {\n // Same level or higher - stop looking\n break\n }\n // Nested list - continue looking (don't break)\n }\n firstCheckPos = skipToNextLine(source, firstNextLineEnd)\n }\n }\n\n // Handle fenced code blocks that span multiple lines\n // Note: We use manual expansion here rather than parseCodeFenced because\n // we need to return a content string (with fence lines) that will be parsed later,\n // not an AST node. parseCodeFenced returns an AST node, which doesn't fit this use case.\n var actualFirstItemContent = firstItemContent\n if (\n util.startsWith(firstItemContent, '```') ||\n util.startsWith(firstItemContent, '~~~')\n ) {\n var markerWidth = ordered\n ? match[1].length + match[2].length + 1\n : match[1].length + 1\n var expandedResult = expandMultilineFencedCodeBlock(\n source,\n firstItemContent,\n currentPos,\n markerWidth\n )\n actualFirstItemContent = expandedResult.content\n currentPos = expandedResult.endPos\n }\n\n // For tight lists with whitespace-only first line, combine with continuation to avoid multiple blocks\n var hasWhitespaceButNoContent =\n !isEmptyItem &&\n firstItemContent.trim() === '' &&\n spacesAfterMarkerCount > 0 &&\n spacesAfterMarkerCount < 5\n // For ALL tight lists (no blank lines), concatenate simple text continuation lines BEFORE\n // building the item content. This is necessary to preserve hard line breaks (two trailing\n // spaces before newline) that would otherwise be lost when first line and continuation are\n // parsed separately. The broader condition (not just whitespace-only first lines) is safe\n // because we stop collecting text when we hit NEW block elements (not continuations of the\n // same block element), which ensures block-level structures are still parsed correctly.\n if (!firstItemHasBlankLine) {\n // Detect if the first line starts a blockquote (to allow continuation lines)\n var firstLineFirstChar =\n actualFirstItemContent.length > 0 ? actualFirstItemContent[0] : ''\n var firstLineStartsBlockQuote = firstLineFirstChar === '>'\n\n var pos = currentPos\n while (pos < source.length) {\n var lineEnd = util.findLineEnd(source, pos)\n var line = source.slice(pos, lineEnd)\n if (line.trim() === '') break\n var indentInfo = calculateIndent(source, pos, lineEnd)\n if (indentInfo.spaceEquivalent < minimumContentStartColumn) break\n var lineWithoutIndent = line.slice(indentInfo.charCount)\n if (\n indentInfo.spaceEquivalent <= baseIndent &&\n isMatchingListItem(\n lineWithoutIndent,\n indentInfo,\n ordered,\n marker,\n delimiter,\n baseIndent,\n listItemRegex\n )\n ) {\n break\n }\n // Check for nested list items\n if (\n isLineListItem(lineWithoutIndent) &&\n indentInfo.spaceEquivalent > baseIndent\n ) {\n break\n }\n // Check for block elements - stop collecting text if we hit a NEW block element\n // (not a continuation of the same block element started on the first line)\n var firstChar = lineWithoutIndent.length > 0 ? lineWithoutIndent[0] : ''\n // Allow blockquote continuation if first line started a blockquote\n var isBlockQuoteContinuation =\n firstChar === '>' && firstLineStartsBlockQuote\n if (\n (firstChar === '>' && !isBlockQuoteContinuation) ||\n firstChar === '#' ||\n util.startsWith(lineWithoutIndent, '```') ||\n util.startsWith(lineWithoutIndent, '~~~')\n ) {\n break\n }\n actualFirstItemContent += '\\n' + lineWithoutIndent\n currentPos = pos = skipToNextLine(source, lineEnd)\n }\n }\n\n // Build first item with GFM task support\n items.push(\n buildListItemContent(\n actualFirstItemContent,\n firstItemHasBlankLine,\n state,\n options\n )\n )\n itemContentStartColumns.push(contentStartColumn)\n\n // Process continuation lines for the first item\n // For tight lists (no blank lines), also process continuation if it's indented enough\n const shouldProcessContinuation =\n firstItemHasBlankLine &&\n (spacesAfterMarkerCount >= 5 || hasWhitespaceButNoContent)\n if (shouldProcessContinuation) {\n const lastItem = getLastItem()\n currentPos = processContinuation(\n source,\n lastItem,\n minimumContentStartColumn,\n currentPos,\n baseIndent,\n ordered,\n marker,\n delimiter,\n listItemRegex,\n state,\n options,\n true\n )\n } else if (!firstItemHasBlankLine) {\n // For tight lists (no blank lines), process continuation lines\n const continuationColumn = minimumContentStartColumn - 1\n while (currentPos < source.length) {\n const nextLineEnd = util.findLineEnd(source, currentPos)\n const nextLine = source.slice(currentPos, nextLineEnd)\n const nextIndentInfo = calculateIndent(source, currentPos, nextLineEnd)\n const nextIndent = nextIndentInfo.spaceEquivalent\n const nextLineWithoutIndent = nextLine.slice(nextIndentInfo.charCount)\n\n if (\n nextLine.trim() === '' ||\n (nextIndent <= baseIndent &&\n isMatchingListItem(\n nextLineWithoutIndent,\n nextIndentInfo,\n ordered,\n marker,\n delimiter,\n baseIndent,\n listItemRegex\n )) ||\n (isLineListItem(nextLineWithoutIndent) && nextIndent > baseIndent) ||\n nextIndent < continuationColumn\n ) {\n break\n }\n\n const lastItem = getLastItem()\n const result = processListContinuationLine(\n source,\n currentPos,\n nextLineEnd,\n nextIndentInfo,\n continuationColumn,\n contentStartColumn,\n lastItem,\n false,\n state,\n options,\n true,\n baseIndent\n )\n if (result.processed) {\n currentPos = result.newPos\n } else {\n break\n }\n }\n }\n\n // Continue parsing subsequent list items\n var prevLineWasBlank = false\n while (currentPos < source.length) {\n const nextLineEnd = util.findLineEnd(source, currentPos)\n\n const nextLine = source.slice(currentPos, nextLineEnd)\n const nextIndentInfo = calculateIndent(source, currentPos, nextLineEnd)\n const nextIndentChars = nextIndentInfo.charCount\n const nextIndent = nextIndentInfo.spaceEquivalent\n\n if (nextLine.trim() === '') {\n // Blank line - mark as loose list and continue\n hasBlankLines = true\n prevLineWasBlank = true\n currentPos = skipToNextLine(source, nextLineEnd)\n } else if (nextIndent < baseIndent) {\n const nextLineWithoutIndent = nextLine.slice(nextIndentChars)\n if (\n nextLineWithoutIndent.startsWith('<') &&\n checkHTMLTagInterruptsList(\n source,\n currentPos,\n nextIndentChars,\n baseIndent,\n nextIndent,\n options\n )\n ) {\n break\n }\n\n // Less indented - check if this is a lazy continuation line\n // Per CommonMark: lazy continuation lines can have all indentation deleted\n // They are still part of the list item if they are paragraph continuation text\n const trimmed = nextLineWithoutIndent.trim()\n if (\n trimmed.length > 0 &&\n items.length > 0 &&\n !isBlockStartChar(trimmed[0]) &&\n !isMatchingListItem(\n nextLineWithoutIndent,\n nextIndentInfo,\n ordered,\n marker,\n delimiter,\n baseIndent,\n listItemRegex\n )\n ) {\n const lastItem = getLastItem()\n if (lastItem.length > 0) {\n const lastBlock = lastItem[lastItem.length - 1]\n if (\n lastBlock.type === RuleType.paragraph ||\n lastBlock.type === RuleType.text\n ) {\n // This is a lazy continuation line - continue the paragraph\n appendListContinuation(\n nextLineWithoutIndent,\n lastItem,\n state,\n options\n )\n prevLineWasBlank = false\n currentPos = skipToNextLine(source, nextLineEnd)\n continue\n }\n }\n }\n // Not a lazy continuation - end of list\n break\n } else {\n const nextLineWithoutIndent = nextLine.slice(nextIndentChars)\n\n // Check for setext heading BEFORE thematic break\n // If last item ends with text/paragraph and this line is setext underline, convert to heading\n // Per CommonMark: setext underline must be indented enough to be continuation\n // BUT: don't check if this line is a list item marker (would be continuation of wrong item)\n if (items.length > 0) {\n const lastItemContentStartColumn =\n itemContentStartColumns[items.length - 1] || contentStartColumn\n if (\n nextIndent + 1 >= lastItemContentStartColumn &&\n !isMatchingListItem(\n nextLineWithoutIndent,\n nextIndentInfo,\n ordered,\n marker,\n delimiter,\n baseIndent,\n listItemRegex\n )\n ) {\n const lastItem = getLastItem()\n if (\n lastItem.length > 0 &&\n convertSetextHeadingInListItem(\n lastItem,\n nextLineWithoutIndent,\n options\n )\n ) {\n currentPos = skipToNextLine(source, nextLineEnd)\n continue\n }\n }\n }\n\n // Check if this line is a thematic break (per CommonMark, thematic breaks end lists)\n const thematicBreakResult = parseBreakThematic(\n source,\n currentPos,\n state,\n options\n )\n if (thematicBreakResult) {\n // Thematic break ends the list\n break\n }\n\n // Per CommonMark spec: link reference definitions interrupt list continuation\n // Check if this is a link reference definition after a blank line\n if (prevLineWasBlank) {\n const refEndPos = skipLinkReferenceDefinition(\n source,\n currentPos,\n nextLineEnd,\n nextIndentInfo,\n nextLineWithoutIndent,\n state,\n options\n )\n if (refEndPos) {\n // Skip link reference definition and continue parsing list (don't break)\n currentPos = refEndPos\n prevLineWasBlank = false\n continue\n }\n }\n\n // If line is at base indentation and not a list item, check for lazy continuation first\n if (nextIndent <= baseIndent) {\n if (\n nextLineWithoutIndent.startsWith('<') &&\n checkHTMLTagInterruptsList(\n source,\n currentPos,\n nextIndentChars,\n baseIndent,\n nextIndent,\n options\n )\n ) {\n break\n }\n\n if (\n !isMatchingListItem(\n nextLineWithoutIndent,\n nextIndentInfo,\n ordered,\n marker,\n delimiter,\n baseIndent,\n listItemRegex\n )\n ) {\n // Check for lazy continuation when nextIndent === baseIndent\n // Per CommonMark: lazy continuation lines can have all indentation deleted\n // BUT: only if there was no blank line before (lazy continuation requires no blank line)\n // AND: only if it's truly paragraph continuation text (not a block start)\n if (nextIndent === baseIndent && !prevLineWasBlank) {\n const trimmed = nextLineWithoutIndent.trim()\n if (trimmed.length > 0 && !isBlockStartChar(trimmed[0])) {\n // Check if this line would start a block (like HTML comment, thematic break, etc.)\n // If so, it should break the list, not continue it\n const blockResult = parseBlock(source, currentPos, state, options)\n if (blockResult && blockResult.type !== RuleType.paragraph) {\n break\n }\n const lastItem = getLastItem()\n if (lastItem.length > 0 && !listItemHasBlockContent(lastItem)) {\n // This is a lazy continuation line - continue the inline content\n // Lazy continuation lines don't add a newline (no space in output)\n appendListContinuation(\n nextLineWithoutIndent,\n lastItem,\n state,\n options,\n false\n )\n prevLineWasBlank = false\n currentPos = skipToNextLine(source, nextLineEnd)\n continue\n }\n }\n }\n break\n }\n }\n\n // Check for empty items with blank lines\n if (\n shouldBreakForEmptyItem(\n items,\n isEmptyItem,\n prevLineWasBlank,\n firstItemContent\n )\n )\n break\n\n const nextMatchResult = matchListItem(nextLineWithoutIndent)\n const nextMatch = nextMatchResult ? nextMatchResult.match : null\n const isSameType =\n nextMatch &&\n (ordered ? nextMatch[2] === delimiter : nextMatch[1] === marker)\n // Per CommonMark: list markers may be indented by up to 3 spaces\n // If marker is too indented (> 3 spaces), it's not a valid list item\n // If there's a blank line before such a marker, end the list (e.g., Example 313)\n if (isSameType && nextIndent > 3 && prevLineWasBlank) {\n break\n }\n // Skip list item processing and fall through to continuation check\n if (isSameType && nextIndent <= baseIndent + 3) {\n if (nextIndent >= 4 && prevLineWasBlank) break\n if (nextIndent === baseIndent) {\n // Item at same level - parse as new item\n let itemContent = ordered ? nextMatch[3] : nextMatch[2]\n itemContent = itemContent.trimStart()\n\n const result = addListItem(\n source,\n items,\n itemContentStartColumns,\n itemContent,\n currentPos,\n nextLineEnd,\n nextIndent,\n nextIndentChars,\n nextMatch,\n ordered,\n hasBlankLines,\n state,\n options\n )\n currentPos = result.newCurrentPos\n prevLineWasBlank = false\n\n // For empty items, process continuation immediately\n if (itemContent.trim() === '') {\n const newItem = items[items.length - 1]\n const thisItemContentStartColumn = getLastItemContentColumn()\n currentPos = processContinuation(\n source,\n newItem,\n thisItemContentStartColumn,\n currentPos,\n baseIndent,\n ordered,\n marker,\n delimiter,\n listItemRegex,\n state,\n options\n )\n }\n\n continue\n }\n if (nextIndent > baseIndent) {\n // Per CommonMark spec: items are only nested if indented enough to belong to previous item\n // If there was a blank line before this item, it's at the same level (not nested)\n if (prevLineWasBlank) {\n // Blank line before item means it's a new item at same level, not nested\n let itemContent = ordered ? nextMatch[3] : nextMatch[2]\n // Trim leading whitespace from content (regex now captures optional whitespace)\n itemContent = itemContent.trimStart()\n const result = addListItem(\n source,\n items,\n itemContentStartColumns,\n itemContent,\n currentPos,\n nextLineEnd,\n nextIndent,\n nextIndentChars,\n nextMatch,\n ordered,\n hasBlankLines,\n state,\n options\n )\n currentPos = result.newCurrentPos\n prevLineWasBlank = false\n continue\n }\n // Check if this item's marker position is indented enough to be continuation of previous item\n // We need to calculate the previous item's contentStartColumn, not use the first item's\n const lastItem = getLastItem()\n const markerColumn = nextIndent + 1\n const isNested = isMarkerNested(\n markerColumn,\n getLastItemContentColumn(),\n listItemHasBlockContent(lastItem)\n )\n\n if (isNested) {\n const nestedResult = tryParseNestedList(currentPos, lastItem)\n if (nestedResult) {\n currentPos = nestedResult.endPos\n prevLineWasBlank = false\n continue\n }\n }\n // Item is not indented enough to be nested - check if it's same type for same level\n if (!isNested && isSameType) {\n // This item has more indentation than baseIndent but not enough to be nested\n // It's still at the same level - parse it as a new item\n let itemContent = ordered ? nextMatch[3] : nextMatch[2]\n // Trim leading whitespace from content\n itemContent = itemContent.trimStart()\n if (!hasBlankLines) {\n // Check if this item has blank lines within it\n let checkItemPos = skipToNextLine(source, nextLineEnd)\n while (checkItemPos < source.length) {\n const checkLineEnd = util.findLineEnd(source, checkItemPos)\n const checkLine = source.slice(checkItemPos, checkLineEnd)\n const checkIndentInfo = calculateIndent(\n source,\n checkItemPos,\n checkLineEnd\n )\n const checkIndent = checkIndentInfo.spaceEquivalent\n\n if (checkLine.trim() === '') {\n const afterBlank = skipToNextLine(source, checkLineEnd)\n if (afterBlank < source.length) {\n const afterBlankIndentInfo = calculateIndent(\n source,\n afterBlank,\n source.length\n )\n const afterBlankIndent =\n afterBlankIndentInfo.spaceEquivalent\n // Calculate contentStartColumn for this item\n const thisItemMarkerStart = nextIndent\n const thisItemContentStart =\n thisItemMarkerStart +\n (ordered\n ? nextMatch[1].length + nextMatch[2].length + 1\n : nextMatch[1].length + 1)\n if (afterBlankIndent + 1 > thisItemContentStart) {\n break\n }\n }\n break\n } else if (checkIndent <= baseIndent) {\n // Check if this is the next list item at baseIndent or less\n const checkLineWithoutIndent = checkLine.slice(\n checkIndentInfo.charCount\n )\n const checkMatch = checkLineWithoutIndent.match(listItemRegex)\n const isNextItem =\n checkMatch &&\n (ordered\n ? checkMatch[2] === delimiter\n : checkMatch[1] === marker)\n if (isNextItem && checkIndent <= baseIndent) {\n break\n }\n }\n checkItemPos = skipToNextLine(source, checkLineEnd)\n }\n }\n const result = addListItem(\n source,\n items,\n itemContentStartColumns,\n itemContent,\n currentPos,\n nextLineEnd,\n nextIndent,\n nextIndentChars,\n nextMatch,\n ordered,\n hasBlankLines,\n state,\n options\n )\n currentPos = result.newCurrentPos\n prevLineWasBlank = false\n continue\n } else if (!isNested && !isSameType) {\n // Different marker type at same level - end this list\n break\n }\n // Fall through to continuation check if isNested but parseList failed\n // Check if this is continuation content\n // Per CommonMark: continuation needs to be indented to at least the content start column\n // nextIndent is space count (0-indexed), contentStartColumn is column number (1-indexed)\n // When list item has block content, exact indentation (==) continues; otherwise use >\n // For continuation checks, use minimumContentStartColumn (column after marker+space)\n // instead of contentStartColumn (which can be higher for code blocks)\n {\n const lastItem = getLastItem()\n // Check if last item is empty (no content)\n const lastItemIsEmpty = lastItem.length === 0\n // Check for empty items with blank lines\n if (\n lastItemIsEmpty &&\n shouldBreakForEmptyItem(\n items,\n isEmptyItem,\n prevLineWasBlank,\n firstItemContent\n )\n )\n break\n\n const hasBlockContent = lastItem.some(\n node =>\n node.type === RuleType.codeBlock ||\n node.type === RuleType.paragraph ||\n node.type === RuleType.blockQuote ||\n node.type === RuleType.orderedList ||\n node.type === RuleType.unorderedList ||\n node.type === RuleType.heading\n )\n // For empty items, use minimumContentStartColumn (marker + space) instead of contentStartColumn\n // which can be higher when there's extra whitespace but no content\n const continuationColumn =\n lastItemIsEmpty && items.length === 1\n ? minimumContentStartColumn\n : contentStartColumn\n const continuationCheck = hasBlockContent\n ? nextIndent >= continuationColumn\n : nextIndent > continuationColumn\n if (continuationCheck) {\n const result = processListContinuationLine(\n source,\n currentPos,\n nextLineEnd,\n nextIndentInfo,\n continuationColumn,\n contentStartColumn,\n getLastItem(),\n prevLineWasBlank,\n state,\n options,\n undefined,\n baseIndent\n )\n if (result.processed) {\n prevLineWasBlank = result.wasBlank\n currentPos = result.newPos\n continue\n }\n } else {\n break\n }\n }\n } else if (nextIndent === baseIndent) {\n // Check for Unicode whitespace after marker in unordered lists\n if (\n !ordered &&\n nextMatch &&\n checkUnicodeWhitespaceAfterMarker(nextMatch, nextMatch[1])\n ) {\n break\n }\n let itemContent = ordered ? nextMatch[3] : nextMatch[2]\n // Trim leading whitespace from content (regex now captures optional whitespace)\n itemContent = itemContent.trimStart()\n // Per CommonMark: A list is loose if items are separated by blank lines,\n // OR if an item directly contains two block-level elements with a blank line between them.\n // If list is loose (hasBlankLines = true), ALL items are wrapped.\n // Otherwise, an item is wrapped only if it has blank lines within it.\n // A blank line before this item means the PREVIOUS item was separated from this one,\n // making the list loose. For this item, we check if it has continuation after blank lines.\n // But if the list is already loose (hasBlankLines), wrap this item too.\n const result = addListItem(\n source,\n items,\n itemContentStartColumns,\n itemContent,\n currentPos,\n nextLineEnd,\n baseIndent,\n nextIndentChars,\n nextMatch,\n ordered,\n hasBlankLines,\n state,\n options\n )\n currentPos = result.newCurrentPos\n prevLineWasBlank = false\n }\n } else if (nextIndent > baseIndent) {\n // Check if this is a list item - if so, check if it should be nested or separate\n // Per CommonMark: list item markers can only be indented 0-3 spaces relative to baseIndent\n // However, nested lists can have more indentation if they're indented relative to content start\n // So we need to try parsing as nested list first, then check for paragraph continuation\n const lastItem = getLastItem()\n const isListItemResult = isLineListItem(nextLineWithoutIndent)\n if (isListItemResult) {\n // Check if marker would be properly nested (relative to content start column)\n // This handles nested lists that may have > 3 spaces indent from baseIndent\n const markerColumn = nextIndent + 1\n const isNested = isMarkerNested(\n markerColumn,\n getLastItemContentColumn(),\n listItemHasBlockContent(lastItem)\n )\n\n if (isNested) {\n // Properly nested - try parsing as nested list\n const nestedResult = tryParseNestedList(currentPos, lastItem)\n if (nestedResult) {\n currentPos = nestedResult.endPos\n prevLineWasBlank = false\n continue\n }\n }\n\n // Not properly nested - check if marker indent is valid (0-3 spaces relative to baseIndent)\n // Per CommonMark: list item markers can only be indented 0-3 spaces relative to baseIndent\n const markerIndentRelative = nextIndent - baseIndent\n if (markerIndentRelative > 3) {\n // Too much indentation (> 3 spaces from baseIndent) and not nested - not a valid list item marker\n // Check if it should be treated as paragraph continuation (if last item ends with paragraph)\n const lastBlock =\n lastItem.length > 0 ? lastItem[lastItem.length - 1] : null\n if (\n lastBlock &&\n (lastBlock.type === RuleType.paragraph ||\n lastBlock.type === RuleType.text)\n ) {\n // This is paragraph continuation text, not a code block or nested list\n appendListContinuation(\n nextLineWithoutIndent,\n lastItem,\n state,\n options\n )\n prevLineWasBlank = false\n currentPos = skipToNextLine(source, nextLineEnd)\n continue\n }\n // Not paragraph continuation - fall through to code block check\n } else {\n // Valid marker indent (0-3 spaces) but not nested - this should be a separate list\n break\n }\n } else {\n // Not a list item - try parsing as nested list (for other block types)\n const nestedResult = tryParseNestedList(currentPos, lastItem)\n if (nestedResult) {\n currentPos = nestedResult.endPos\n prevLineWasBlank = false\n continue\n }\n }\n // Check if this is continuation content\n // Per CommonMark: continuation needs to be indented to at least the content start column\n // nextIndent is space count (0-indexed), contentStartColumn is column number (1-indexed)\n // When list item has block content, exact indentation (==) continues; otherwise use >\n // For continuation checks, use minimumContentStartColumn (column after marker+space)\n // instead of contentStartColumn (which can be higher for code blocks)\n const continuationColumn = contentStartColumn\n const continuationCheck = listItemHasBlockContent(lastItem)\n ? nextIndent >= continuationColumn - 1\n : nextIndent > continuationColumn - 1\n if (continuationCheck) {\n const result = processListContinuationLine(\n source,\n currentPos,\n nextLineEnd,\n nextIndentInfo,\n continuationColumn - 1,\n contentStartColumn,\n getLastItem(),\n prevLineWasBlank,\n state,\n options,\n undefined,\n baseIndent\n )\n if (result.processed) {\n prevLineWasBlank = result.wasBlank\n currentPos = result.newPos\n continue\n }\n } else {\n break\n }\n } else {\n break\n }\n }\n }\n\n // For loose lists, ensure all items have paragraph wrappers\n // The first item may have been created before we detected that the list is loose\n if (\n hasBlankLines &&\n items.length > 1 &&\n items[0].length > 0 &&\n items[0][0].type !== RuleType.paragraph\n ) {\n // Check if list is truly loose (another item has paragraph wrapper)\n for (var j = 1; j < items.length; j++) {\n if (items[j].length > 0 && items[j][0].type === RuleType.paragraph) {\n // First item is all inline content - wrap it for loose lists\n var isBlock = false\n for (var i = 0; i < items[0].length; i++) {\n var t = items[0][i].type\n if (\n t === RuleType.codeBlock ||\n t === RuleType.heading ||\n t === RuleType.blockQuote ||\n t === RuleType.orderedList ||\n t === RuleType.unorderedList ||\n t === RuleType.htmlBlock ||\n t === RuleType.breakThematic\n ) {\n isBlock = true\n break\n }\n }\n if (!isBlock) {\n items[0] = [\n {\n type: RuleType.paragraph,\n children: items[0],\n } as MarkdownToJSX.ParagraphNode,\n ]\n }\n break\n }\n }\n }\n\n const listNode = ordered\n ? ({\n type: RuleType.orderedList,\n items,\n ordered: true,\n start,\n } as MarkdownToJSX.OrderedListNode)\n : ({\n type: RuleType.unorderedList,\n items,\n ordered: false,\n } as MarkdownToJSX.UnorderedListNode)\n\n // Restore original inList state\n state.inList = originalInList\n\n return {\n ...listNode,\n endPos: currentPos,\n } as (MarkdownToJSX.OrderedListNode | MarkdownToJSX.UnorderedListNode) & {\n endPos: number\n }\n}\n\nfunction parseTable(\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): ParseResult {\n if (state.inline) return null\n\n const lines: string[] = []\n let currentPos = pos\n\n while (currentPos < source.length) {\n const lineEnd = util.findLineEnd(source, currentPos)\n if (isBlankLineCheck(source, currentPos, lineEnd)) break\n\n const line = source.slice(currentPos, lineEnd).trim()\n const isTableLine =\n line.indexOf('|') !== -1 ||\n (lines.length >= 3 && line && !isBlockStartChar(line[0]))\n\n if (!isTableLine) break\n lines.push(line)\n currentPos = skipToNextLine(source, lineEnd)\n }\n\n if (lines.length < 2) return null\n\n // Unwrap pipes and split cells\n const unwrap = (line: string) =>\n line[0] === '|' && line[line.length - 1] === '|' ? line.slice(1, -1) : line\n\n const splitCells = (line: string) => {\n const cells: string[] = []\n let current = ''\n let inCode = false\n\n for (let i = 0; i < line.length; i++) {\n const ch = line[i]\n if (ch === '\\\\' && i + 1 < line.length && line[i + 1] === '|') {\n current += '|'\n i++\n } else if (ch === '`') {\n inCode = !inCode\n current += ch\n } else if (ch === '|' && !inCode) {\n cells.push(current.trim())\n current = ''\n } else {\n current += ch\n }\n }\n cells.push(current.trim())\n return cells\n }\n\n const headerCells = splitCells(unwrap(lines[0]))\n if (!headerCells.length) return null\n\n const separatorCells = splitCells(unwrap(lines[1]))\n if (\n separatorCells.length !== headerCells.length ||\n separatorCells.some(cell => !/^:?-+:?$/.test(cell))\n ) {\n return null\n }\n\n const alignments = separatorCells.map(cell => {\n const start = cell[0] === ':'\n const end = cell[cell.length - 1] === ':'\n return start && end ? 'center' : start ? 'left' : end ? 'right' : null\n })\n\n const parseRow = (cells: string[]) =>\n parseWithInlineMode(state, true, () =>\n cells.map(cell => parseInlineSpan(cell, 0, cell.length, state, options))\n )\n\n const header = parseRow(headerCells)\n\n const body = lines.slice(2).map(line => {\n const cells =\n line.indexOf('|') !== -1 ? splitCells(unwrap(line)) : [line.trim()]\n\n // Normalize cell count\n const count = headerCells.length\n while (cells.length < count) cells.push('')\n cells.length = count\n\n return parseRow(cells)\n })\n\n return {\n type: RuleType.table,\n header,\n cells: body,\n align: alignments,\n endPos: currentPos,\n } as MarkdownToJSX.TableNode & { endPos: number }\n}\n\n// Type 6 block-level tags - only the most common ones that matter in practice\n// Unknown tags default to type 7 (inline/non-interrupting) for safety\n// This is a pragmatic subset of the CommonMark spec's full list\nvar TYPE6_TAGS = [\n 'div',\n 'p',\n 'section',\n 'article',\n 'aside',\n 'nav',\n 'header',\n 'footer',\n 'main',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'blockquote',\n 'ul',\n 'ol',\n 'li',\n 'dl',\n 'dt',\n 'dd',\n 'table',\n 'thead',\n 'tbody',\n 'tfoot',\n 'tr',\n 'td',\n 'th',\n 'form',\n 'fieldset',\n 'hr',\n 'pre',\n 'details',\n 'summary',\n 'figure',\n 'figcaption',\n]\n\n// Type 1 block tags for fast lookup\nconst TYPE1_TAGS_SET = new Set(['pre', 'script', 'style', 'textarea'])\n\nfunction isType6Tag(tagName: string): boolean {\n return TYPE6_TAGS.indexOf(tagName.toLowerCase()) !== -1\n}\n\nexport function isType1Block(tagLower: string): boolean {\n return TYPE1_TAGS_SET.has(tagLower)\n}\n\nfunction isBlankLineCheck(\n source: string,\n lineStart: number,\n lineEnd: number\n): boolean {\n for (var i = lineStart; i < lineEnd; i++) {\n const code = charCode(source, i)\n if (code !== $.CHAR_SPACE && code !== $.CHAR_TAB && code !== $.CHAR_CR)\n return false\n }\n return true\n}\n\nfunction parseWithInlineMode<T>(\n state: MarkdownToJSX.State,\n inlineMode: boolean,\n parseFn: () => T\n): T {\n const originalInline = state.inline\n state.inline = inlineMode\n try {\n return parseFn()\n } finally {\n state.inline = originalInline\n }\n}\n\nfunction findNextBlankLine(\n source: string,\n startPos: number,\n sourceLen: number\n): number {\n var pos = startPos\n while (pos < sourceLen) {\n var nextLineEnd = util.findLineEnd(source, pos)\n if (isBlankLineCheck(source, pos, nextLineEnd)) return pos\n pos = nextLineEnd + (nextLineEnd < sourceLen ? 1 : 0)\n }\n return sourceLen\n}\n\nfunction createHTMLCommentResult(\n text: string,\n endPos: number,\n options?: { raw?: boolean; endsWithGreaterThan?: boolean }\n): MarkdownToJSX.HTMLCommentNode & {\n endPos: number\n raw?: boolean\n endsWithGreaterThan?: boolean\n} {\n return {\n type: RuleType.htmlComment,\n text,\n endPos,\n ...options,\n } as MarkdownToJSX.HTMLCommentNode & {\n endPos: number\n raw?: boolean\n endsWithGreaterThan?: boolean\n }\n}\n\nfunction createVerbatimHTMLBlock(\n tagName: string,\n text: string,\n endPos: number,\n attrs?: { [key: string]: any },\n rawAttrs?: string,\n isClosingTag?: boolean,\n canInterruptParagraph?: boolean,\n options?: ParseOptions,\n state?: MarkdownToJSX.State\n): MarkdownToJSX.HTMLNode & {\n endPos: number\n isClosingTag?: boolean\n canInterruptParagraph?: boolean\n} {\n // Detect empty unclosed HTML tags when forceBlock is used to avoid infinite recursion\n // For empty unclosed tags like <var>, the text field contains the opening tag itself\n // When forceBlock is used, this would cause recursion if the tag is parsed again\n var finalText = text\n if (options && options.forceBlock && text && !isClosingTag) {\n var openingTagPattern = new RegExp(\n '^<' + tagName.toLowerCase() + '(\\\\s[^>]*)?>$',\n 'i'\n )\n if (openingTagPattern.test(text.trim())) {\n // Empty unclosed tag detected - render as empty element to avoid recursion\n finalText = ''\n }\n }\n\n // Always parse content into children, even for verbatim blocks\n // Extract content from text (may include opening tag)\n var contentToParse = finalText\n var tagLower = tagName.toLowerCase()\n\n // If text starts with opening tag, extract just the content\n var openingTagPattern2 = new RegExp('^<' + tagLower + '[\\\\s>]', 'i')\n if (openingTagPattern2.test(contentToParse)) {\n // Find the end of opening tag\n var tagEnd = contentToParse.indexOf('>')\n if (tagEnd !== -1) {\n contentToParse = contentToParse.slice(tagEnd + 1)\n // Remove closing tag if present\n var closingTag = '</' + tagLower + '>'\n var closingIdx = contentToParse.indexOf(closingTag)\n if (closingIdx !== -1) {\n contentToParse = contentToParse.slice(0, closingIdx)\n }\n }\n } else {\n // Text might just be content, but check for closing tag\n var closingTag2 = '</' + tagLower + '>'\n var closingIdx2 = contentToParse.indexOf(closingTag2)\n if (closingIdx2 !== -1) {\n contentToParse = contentToParse.slice(0, closingIdx2)\n }\n }\n\n // Parse content into children\n var children: MarkdownToJSX.ASTNode[] = []\n if (contentToParse && options) {\n var parseState: MarkdownToJSX.State = state || {\n inline: false,\n inHTML: true,\n inAnchor: false,\n }\n\n // Determine if content should be parsed as blocks or inline\n var trimmed = contentToParse.trim()\n var hasDoubleNewline = DOUBLE_NEWLINE_R.test(trimmed)\n var hasBlockSyntax = BLOCK_SYNTAX_R.test(trimmed)\n var hasHTMLTags = HTML_BLOCK_ELEMENT_START_R.test(trimmed)\n\n if (hasDoubleNewline || hasBlockSyntax || hasHTMLTags) {\n // Parse as blocks\n var blockState = {\n ...parseState,\n inline: false,\n inHTML: true,\n inAnchor: parseState.inAnchor || tagLower === 'a',\n }\n children = parseBlocksInHTML(trimmed, blockState, options)\n } else if (trimmed) {\n // Parse as inline\n var inlineState = {\n ...parseState,\n inline: true,\n inAnchor: parseState.inAnchor || tagLower === 'a',\n }\n children = parseInlineSpan(\n trimmed,\n 0,\n trimmed.length,\n inlineState,\n options\n )\n }\n }\n\n return {\n type: RuleType.htmlBlock,\n tag: tagName as MarkdownToJSX.HTMLTags,\n attrs: attrs || {},\n rawAttrs: rawAttrs,\n children: children,\n rawText: finalText,\n text: finalText, // @deprecated - use rawText instead\n verbatim: true,\n isClosingTag: isClosingTag,\n canInterruptParagraph: canInterruptParagraph,\n endPos: endPos,\n } as MarkdownToJSX.HTMLNode & {\n endPos: number\n isClosingTag?: boolean\n canInterruptParagraph?: boolean\n }\n}\n\n/**\n * Check if content contains block-worthy elements that should be parsed\n * (explicit block syntax or blank lines not inside type 1 HTML blocks)\n */\nfunction hasBlockContent(content: string): boolean {\n const hasExplicitBlockSyntax = BLOCK_SYNTAX_R.test(content)\n const hasBlankLines = DOUBLE_NEWLINE_R.test(content)\n const hasType1Tags = TYPE1_TAG_R.test(content)\n return hasExplicitBlockSyntax || (hasBlankLines && !hasType1Tags)\n}\n\nfunction processHTMLBlock(\n tagNameOriginal: string,\n tagName: string,\n attrs: string,\n content: string,\n fullMatch: string,\n endPos: number,\n source: string,\n state: MarkdownToJSX.State,\n parentInAnchor: boolean,\n options: ParseOptions\n): MarkdownToJSX.HTMLNode & { endPos: number } {\n // Apply block-level paragraph wrapping heuristics\n if (!state.inHTML && !state.inline && !util.endsWith(fullMatch, '\\n')) {\n let checkPos = endPos\n const sourceLen = source.length\n\n while (checkPos < sourceLen) {\n const lineEnd = util.findLineEnd(source, checkPos)\n if (isBlankLineCheck(source, checkPos, lineEnd)) break\n\n const line = source.slice(checkPos, lineEnd).trim()\n if (line.length > 0 && isBlockStartChar(line[0])) {\n const htmlResult = parseHTML(source, checkPos, state, options)\n if (htmlResult) {\n checkPos = htmlResult.endPos\n continue\n }\n const selfClosingMatch = parseHTMLTag(source, checkPos)\n if (selfClosingMatch) {\n checkPos = selfClosingMatch.endPos\n continue\n }\n return null\n }\n checkPos = skipToNextLine(source, lineEnd)\n }\n }\n\n const lowerTag = tagName\n const isType1BlockTag = isType1Block(lowerTag)\n\n // Per CommonMark spec: Type 6 blocks that end at blank lines should have verbatim content\n // Check if this is a type 6 block (block-level, not type 1, not void)\n var isType6Block = !isType1BlockTag && !util.isVoidElement(tagName)\n\n // Always extract raw attributes from fullMatch if available (for consistency)\n // Per CommonMark spec Example 153: newlines and spaces between attributes should be removed\n // (not converted to spaces) when rendering. Extract raw attributes so html() can handle this.\n var rawOpeningTag: string | undefined = undefined\n // Extract raw attributes from opening tag slice if fullMatch is available\n if (fullMatch) {\n // Find the closing > of the opening tag\n var openingTagEnd = fullMatch.indexOf('>')\n if (openingTagEnd !== -1) {\n var openingTagSlice = fullMatch.slice(0, openingTagEnd + 1)\n // Check if opening tag has newlines (for rawOpeningTag preservation)\n if (openingTagSlice.indexOf('\\n') !== -1) {\n rawOpeningTag = openingTagSlice\n }\n // Always extract raw attributes from the opening tag slice for consistency\n // Find the tag name end (after <div or <div/) - first whitespace or >\n var tagNameEnd = openingTagEnd\n for (var i = 1; i < openingTagEnd; i++) {\n var ch = openingTagSlice[i]\n if (ch === ' ' || ch === '\\t' || ch === '\\n' || ch === '>') {\n tagNameEnd = i\n break\n }\n }\n // Extract attributes from after tag name to before >\n // Preserve leading whitespace for CommonMark compliance (Examples 615-616)\n attrs = openingTagSlice.slice(tagNameEnd, openingTagEnd)\n }\n }\n\n // Parse attributes, but always preserve raw attributes for consistency\n // Per CommonMark spec Example 153: newlines and spaces between attributes should be removed\n // (not converted to spaces) when rendering. Store raw attributes so html() can handle this.\n // Trim leading whitespace for parsing, but preserve full attrs (with whitespace) for rawAttrs\n var attrsTrimmed = attrs.replace(/^[\\s\\n\\r\\t]+/, '')\n var parsedAttributes = parseHTMLAttributes(\n attrsTrimmed,\n tagName,\n tagNameOriginal,\n options\n )\n var attributes: Record<string, any> = {\n ...parsedAttributes,\n }\n\n // For type 6 blocks, check if content ends with blank line or if there's no closing tag\n // Both cases mean content should be verbatim\n var endedAtBlankLine = false\n var hasClosingTagWithBlockSyntax = false\n if (isType6Block && content.length > 0) {\n // Check if there's a closing tag in the content - if so, extract content before it\n var closingTagPattern = '</' + lowerTag\n var closingTagIdx = content.indexOf(closingTagPattern)\n if (closingTagIdx >= 0) {\n var afterTag = closingTagIdx + closingTagPattern.length\n while (\n afterTag < content.length &&\n (content[afterTag] === ' ' || content[afterTag] === '\\t')\n )\n afterTag++\n if (afterTag < content.length && content[afterTag] === '>') {\n var contentBeforeClosingTag = content.slice(0, closingTagIdx)\n if (hasBlockContent(contentBeforeClosingTag)) {\n content = contentBeforeClosingTag\n hasClosingTagWithBlockSyntax = true\n } else {\n endedAtBlankLine = true\n }\n }\n }\n\n // If we didn't find a proper closing tag with block syntax, check if content ends with blank lines\n if (!hasClosingTagWithBlockSyntax) {\n // Check if content ends with blank line pattern (newline, optional whitespace, newline)\n var checkPos = content.length - 1\n // Skip trailing newline\n if (content[checkPos] === '\\n') {\n checkPos--\n // Skip whitespace\n while (\n checkPos >= 0 &&\n (content[checkPos] === ' ' ||\n content[checkPos] === '\\t' ||\n content[checkPos] === '\\r')\n ) {\n checkPos--\n }\n // If there's another newline before this, we have a blank line ending\n if (checkPos >= 0 && content[checkPos] === '\\n') {\n endedAtBlankLine = true\n }\n }\n }\n }\n\n // Determine if this block should have verbatim rendering hint\n // Type 1 blocks and Type 6 blocks ending with blank lines should be verbatim\n var shouldTreatAsVerbatim =\n isType1BlockTag ||\n (isType6Block && endedAtBlankLine && !hasBlockContent(content))\n\n // Normalize content (trim newlines for verbatim blocks)\n var normalizedContent = content\n // Store original content for text field before we modify it for parsing\n var contentForText = normalizedContent\n if (shouldTreatAsVerbatim) {\n if (normalizedContent.length > 0 && normalizedContent[0] === '\\n') {\n normalizedContent = normalizedContent.slice(1)\n contentForText = normalizedContent\n }\n if (\n normalizedContent.length > 0 &&\n normalizedContent[normalizedContent.length - 1] === '\\n'\n ) {\n normalizedContent = normalizedContent.slice(0, -1)\n contentForText = normalizedContent\n }\n // Remove closing tag from content before parsing (it should only be in text field)\n // But keep it in contentForText for the text field\n var closingTagPattern = '</' + lowerTag + '>'\n var closingTagIdx = normalizedContent.indexOf(closingTagPattern)\n if (closingTagIdx !== -1) {\n normalizedContent = normalizedContent.slice(0, closingTagIdx)\n // contentForText keeps the closing tag\n }\n }\n\n const leftTrimMatch = normalizedContent.match(/^([ \\t]*)/)\n const leftTrimAmount = leftTrimMatch ? leftTrimMatch[1] : ''\n const trimmer = new RegExp(\n `^${leftTrimAmount.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}`,\n 'gm'\n )\n const trimmed = normalizedContent.replace(trimmer, '')\n\n const hasDoubleNewline = DOUBLE_NEWLINE_R.test(trimmed)\n const hasNonParagraphBlockSyntax = BLOCK_SYNTAX_R.test(trimmed)\n const isParagraphTag = lowerTag === 'p'\n // Check if content contains HTML tags - if so, parse as blocks for proper nesting\n const hasHTMLTags = HTML_BLOCK_ELEMENT_START_R.test(trimmed)\n const hasBlockSyntax = isParagraphTag\n ? hasDoubleNewline\n : hasDoubleNewline ||\n hasNonParagraphBlockSyntax ||\n (state.inHTML && hasHTMLTags)\n\n // ALWAYS parse content into children, regardless of verbatim flag\n let children: MarkdownToJSX.ASTNode[] = []\n if (trimmed) {\n // Parse as blocks when content contains HTML tags to ensure nested HTML is parsed correctly\n if (hasBlockSyntax || hasHTMLTags) {\n const blockState = {\n ...state,\n inline: false,\n inHTML: true,\n inAnchor: state.inAnchor || lowerTag === 'a',\n }\n children = parseBlocksInHTML(trimmed, blockState, options)\n } else {\n const childState = {\n ...state,\n inline: true,\n inAnchor: parentInAnchor || state.inAnchor || lowerTag === 'a',\n }\n children = parseInlineSpan(\n trimmed,\n 0,\n trimmed.length,\n childState,\n options\n )\n }\n }\n\n // Store raw text for verbatim blocks (for CommonMark compliance in default renderer)\n var finalText: string | undefined = undefined\n if (shouldTreatAsVerbatim) {\n if (rawOpeningTag !== undefined) {\n // Type 1 block with newlines in opening tag - preserve raw opening tag + content\n // Store the full raw HTML (opening tag + content) in text field\n // The closing tag will be added by html()\n finalText = rawOpeningTag + contentForText\n } else {\n finalText = contentForText\n }\n }\n\n return {\n type: RuleType.htmlBlock,\n tag: (shouldTreatAsVerbatim\n ? tagName\n : tagNameOriginal) as MarkdownToJSX.HTMLTags,\n attrs: attributes,\n rawAttrs: attrs,\n children: children,\n rawText: finalText,\n text: finalText, // @deprecated - use rawText instead\n verbatim: shouldTreatAsVerbatim,\n canInterruptParagraph: true, // type 1-6 blocks can interrupt paragraphs\n endPos: endPos,\n } as MarkdownToJSX.HTMLNode & {\n endPos: number\n canInterruptParagraph?: boolean\n }\n}\n\nfunction parseHTML(\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): ParseResult {\n // Must start with '<'\n if (source[pos] !== '<') return null\n\n // Track attempt after cheap disqualifications but before expensive parsing work\n if (!state.inline) {}\n\n // Check for processing instructions, declarations, and comments first (before unified parser)\n if (pos + 1 < source.length) {\n if (source[pos + 1] === '?') {\n var piToken = scanRawHTML(source, pos)\n if (piToken && piToken.kind === 'pi') {\n return createHTMLCommentResult(piToken.text || '', piToken.endPos, {\n raw: true,\n })\n }\n } else if (source[pos + 1] === '!') {\n // Check for HTML comments (<!-- ... -->)\n if (pos + 3 < source.length && source.slice(pos, pos + 4) === '<!--') {\n if (state.inline) {} else {}\n var token = scanRawHTML(source, pos)\n if (token && token.kind === 'comment') {\n // Extract text content (strip <!-- and -->)\n var text = token.text || ''\n var endsWithGreaterThan = false\n if (text === '<!-->') {\n text = ''\n endsWithGreaterThan = true\n } else if (text === '<!--->') {\n text = '-'\n endsWithGreaterThan = true\n } else if (text.startsWith('<!--') && text.endsWith('-->')) {\n text = text.slice(4, -3)\n }\n // Track hit for inline mode (block mode hit tracking happens in parseMarkdown)\n if (state.inline) {}\n return createHTMLCommentResult(text, token.endPos, {\n endsWithGreaterThan,\n })\n }\n }\n var declToken = scanRawHTML(source, pos)\n if (\n declToken &&\n (declToken.kind === 'declaration' || declToken.kind === 'cdata')\n ) {\n return createHTMLCommentResult(declToken.text || '', declToken.endPos, {\n raw: true,\n })\n }\n }\n }\n\n // Check for space/newline after < (invalid HTML - should be escaped)\n if (pos + 1 < source.length) {\n const nextChar = source[pos + 1]\n if (\n nextChar === ' ' ||\n nextChar === '\\n' ||\n nextChar === '\\t' ||\n nextChar === '\\r'\n ) {\n return null\n }\n }\n\n // Check if this looks like an autolink before parsing as HTML\n var closeIdx = source.indexOf('>', pos + 1)\n if (closeIdx !== -1) {\n var contentBetween = source.slice(pos + 1, closeIdx)\n // Check for spaces - if found, might be failed autolink\n var hasSpace =\n contentBetween.indexOf(' ') !== -1 || contentBetween.indexOf('\\t') !== -1\n\n // Check for HTTP(S) URLs - these should be autolinks, not HTML tags\n if (\n !hasSpace &&\n (util.startsWith(contentBetween, 'http://') ||\n util.startsWith(contentBetween, 'https://'))\n ) {\n return null // This is an autolink, not an HTML tag\n }\n\n // Check for URI schemes (scheme:pattern) - no spaces\n if (!hasSpace && isValidUriScheme(contentBetween)) {\n return null // This is an autolink (URI scheme), not an HTML tag\n }\n }\n\n // Use unified parser\n var tagResult = parseHTMLTag(source, pos)\n\n // If parseHTMLTag returns null, it might be an incomplete tag\n // Handle incomplete/partial tags inline (previously handled by matchHTMLBlock)\n if (!tagResult && !state.inline) {\n // Check if we have < followed by a valid tag name (even without closing >)\n var sourceLen = source.length\n var firstLineEnd = util.findLineEnd(source, pos)\n var lineStart = pos\n // Skip up to 3 spaces of indentation (per spec)\n var indent = 0\n while (\n lineStart < firstLineEnd &&\n indent < 3 &&\n (source[lineStart] === ' ' || source[lineStart] === '\\t')\n ) {\n indent++\n lineStart++\n }\n if (lineStart >= firstLineEnd || source[lineStart] !== '<') return null\n\n // Try to parse tag name even if tag is incomplete\n // Only handle incomplete tags for block-level tags (type 6)\n // Non-block-level tags that parseHTMLTag can't parse are invalid, not incomplete\n if (lineStart + 1 < firstLineEnd) {\n var tagNameResult = parseHTMLTagName(source, lineStart + 1)\n if (tagNameResult) {\n var tagName = tagNameResult.tagName\n var isType6 = isType6Tag(tagName)\n // Only handle incomplete tags for block-level tags\n if (!isType6) {\n return null // Non-block-level tags that parseHTMLTag can't parse are invalid\n }\n // Find where the tag would end (end of line or before invalid char)\n var partialTagEnd = tagNameResult.nextPos\n var hasNewlineInTag = false\n var inQuotesPartial = false\n var quoteCharPartial = ''\n var checkEnd = firstLineEnd\n var foundClosingAngle = false\n // Check across multiple lines to find the end of the tag\n // Optimized: use indexOf to quickly find boundary characters\n while (checkEnd < sourceLen && !foundClosingAngle) {\n var advancedInInnerLoop = false\n while (partialTagEnd < checkEnd) {\n var c = source[partialTagEnd]\n if (inQuotesPartial) {\n if (c === quoteCharPartial) {\n inQuotesPartial = false\n quoteCharPartial = ''\n }\n if (c === '\\n' || c === '\\r') {\n hasNewlineInTag = true\n }\n partialTagEnd++\n advancedInInnerLoop = true\n } else if (c === '\"' || c === \"'\") {\n inQuotesPartial = true\n quoteCharPartial = c\n partialTagEnd++\n advancedInInnerLoop = true\n } else if (c === '\\n' || c === '\\r') {\n hasNewlineInTag = true\n partialTagEnd++\n advancedInInnerLoop = true\n var nextLineEnd = util.findLineEnd(source, partialTagEnd)\n if (nextLineEnd === partialTagEnd) break\n checkEnd = nextLineEnd\n } else if (c === '>') {\n partialTagEnd++\n foundClosingAngle = true\n break\n } else {\n partialTagEnd++\n advancedInInnerLoop = true\n }\n }\n if (foundClosingAngle) break\n if (!advancedInInnerLoop && partialTagEnd >= checkEnd) {\n var nextCheckEnd = util.findLineEnd(source, checkEnd + 1)\n if (nextCheckEnd <= checkEnd) break\n checkEnd = nextCheckEnd\n } else if (partialTagEnd >= checkEnd && checkEnd < sourceLen) {\n var nextCheckEnd = util.findLineEnd(source, checkEnd + 1)\n if (nextCheckEnd <= checkEnd) break\n checkEnd = nextCheckEnd\n } else {\n break\n }\n }\n // Only handle as incomplete tag if it has a newline (extends beyond first line)\n // OR if it extends to end of first line without closing >\n // If tag completes on first line with closing >, parseHTMLTag should have handled it\n if (!hasNewlineInTag && foundClosingAngle) {\n return null // Tag completes on first line but parseHTMLTag returned null - invalid, not incomplete\n }\n // Tag has newline - treat as incomplete and extend to end of first line if needed\n if (partialTagEnd >= firstLineEnd && firstLineEnd < sourceLen) {\n partialTagEnd = firstLineEnd\n }\n // Determine block type and find blank line\n var blockType: 'type6' | 'type7' = isType6 ? 'type6' : 'type7'\n var tagEnd = partialTagEnd\n var blockEnd = findNextBlankLine(source, firstLineEnd + 1, sourceLen)\n var blockContent = source.slice(tagEnd, blockEnd)\n var isClosingTag = pos + 1 < source.length && source[pos + 1] === '/'\n\n // For type 7 blocks with incomplete tags, preserve raw HTML\n if (blockType === 'type7' && blockContent.trim() === '') {\n var rawTagHTML = source.slice(pos, blockEnd)\n var tagLineEnd = util.findLineEnd(rawTagHTML, 0)\n if (tagLineEnd < rawTagHTML.length) tagLineEnd++\n var rawTag = rawTagHTML.slice(0, tagLineEnd)\n return createVerbatimHTMLBlock(\n tagName,\n rawTag,\n blockEnd,\n {},\n undefined,\n isClosingTag,\n false, // type 7 blocks cannot interrupt paragraphs\n options,\n state\n )\n }\n\n // For type 6/7 blocks with incomplete tags and content, preserve full raw HTML\n var fullRawHTML = source.slice(pos, blockEnd)\n return createVerbatimHTMLBlock(\n tagName,\n fullRawHTML,\n blockEnd,\n {},\n undefined,\n isClosingTag,\n blockType === 'type6', // type 6 can interrupt, type 7 cannot\n options,\n state\n )\n }\n }\n return null\n }\n\n if (!tagResult) return null\n\n // Per CommonMark spec: reject HTML tags that look like failed autolinks\n // Check if the content between < and > looks like a failed autolink\n // (HTTP(S) URLs with spaces are failed autolinks - checked above)\n if (closeIdx !== -1) {\n var contentBetweenCheck = source.slice(pos + 1, closeIdx)\n // If it starts with http:// or https:// but has spaces, it's a failed autolink\n if (\n (util.startsWith(contentBetweenCheck, 'http://') ||\n util.startsWith(contentBetweenCheck, 'https://')) &&\n (contentBetweenCheck.indexOf(' ') !== -1 ||\n contentBetweenCheck.indexOf('\\t') !== -1)\n ) {\n return null // Failed autolink - reject as HTML tag\n }\n }\n\n // If a tag name has a colon at position 1 (e.g., \"m:abc\"), it's trying to be an autolink\n // but the scheme is only 1 character (invalid). These should be escaped, not parsed as HTML.\n // Examples: <m:abc>, <x:foo> should be escaped as <m:abc>, <x:foo>\n var tagNameStart = pos + (tagResult.isClosing ? 2 : 1)\n if (tagNameStart < source.length) {\n var tagNameFirstChar = source[tagNameStart]\n var tagNameFirstCharCode = charCode(tagNameFirstChar)\n // Check if it starts with a letter\n if (\n (tagNameFirstCharCode >= 97 && tagNameFirstCharCode <= 122) ||\n (tagNameFirstCharCode >= 65 && tagNameFirstCharCode <= 90)\n ) {\n // Check if second character is a colon (making it a 1-char scheme, which is invalid)\n if (\n tagNameStart + 1 < source.length &&\n source[tagNameStart + 1] === ':'\n ) {\n // This looks like a failed autolink attempt - reject as HTML tag\n return null\n }\n }\n }\n\n // Handle closing tags\n if (tagResult.isClosing) {\n // Per CommonMark: closing tags cannot have attributes\n // If attrs is not empty (after trimming whitespace), it's invalid HTML - escape it\n var attrsTrimmed = tagResult.attrs.trim()\n if (attrsTrimmed.length > 0) {\n // Invalid closing tag with attributes - return null to allow escaping\n return null\n }\n\n // Per CommonMark spec: closing tags are type 7 HTML blocks\n // Parse as block if: (1) on its own line, or (2) followed by a block-level HTML tag\n // Per Example 148: </td></tr></table> should be block-level\n // Per Example 623: </a></foo > should be inline (wrapped in paragraph)\n if (!state.inline) {\n var sourceLen = source.length\n var firstLineEnd = util.findLineEnd(source, pos)\n var tagEnd = tagResult.endPos\n\n // Check if tag is on its own line or followed by a block-level HTML tag\n var afterTag = tagEnd\n while (\n afterTag < firstLineEnd &&\n (source[afterTag] === ' ' ||\n source[afterTag] === '\\t' ||\n source[afterTag] === '\\r')\n ) {\n afterTag++\n }\n\n var shouldParseAsBlock =\n afterTag >= firstLineEnd ||\n (source[afterTag] === '<' &&\n (function () {\n var nextTag = parseHTMLTag(source, afterTag)\n return nextTag && isType6Tag(nextTag.tagLower)\n })())\n\n if (shouldParseAsBlock) {\n var blockEnd = findNextBlankLine(source, firstLineEnd + 1, sourceLen)\n var blockContent = source.slice(tagEnd, blockEnd)\n if (blockContent.length > 0 && blockContent[0] === '\\n') {\n blockContent = blockContent.slice(1)\n }\n\n // Cache lowercase tag name to avoid repeated toLowerCase() calls\n const tagLower = tagResult.tagLower || tagResult.tagName.toLowerCase()\n return createVerbatimHTMLBlock(\n tagResult.tagName,\n blockContent,\n blockEnd,\n parseHTMLAttributes(\n tagResult.whitespaceBeforeAttrs + tagResult.attrs,\n tagLower,\n tagResult.tagName,\n options\n ),\n tagResult.whitespaceBeforeAttrs + tagResult.attrs,\n true,\n false,\n options,\n state\n )\n }\n }\n\n // Fallback: for inline context or if block parsing didn't match, parse as self-closing\n // Per CommonMark spec Example 623: closing tags should preserve raw HTML to maintain spacing (e.g., </foo >)\n // Always preserve rawText for closing tags (both inline and block level) so they can be rendered correctly\n var rawText = source.slice(pos, tagResult.endPos)\n const result: MarkdownToJSX.HTMLSelfClosingNode & {\n endPos: number\n isClosingTag?: boolean\n rawText?: string\n } = {\n type: RuleType.htmlSelfClosing,\n tag: tagResult.tagName,\n attrs: {},\n endPos: tagResult.endPos,\n isClosingTag: true,\n rawText: rawText,\n }\n return result\n }\n\n // Now use unified parser result\n // tagResult already contains parsed tag info\n\n // IMPORTANT: All validation must happen BEFORE block parsing check\n // This ensures invalid tags are rejected even if they would match as blocks\n\n // Validate tag name: cannot start with space or newline after <\n // Per CommonMark spec Example 621: < a> and <\\nfoo> are invalid\n var tagNameStart = pos + (tagResult.isClosing ? 2 : 1)\n if (tagNameStart < source.length) {\n var firstChar = source[tagNameStart]\n if (\n firstChar === ' ' ||\n firstChar === '\\t' ||\n firstChar === '\\n' ||\n firstChar === '\\r'\n ) {\n // Tag name starts with whitespace - invalid HTML\n return null\n }\n }\n\n // Attributes are passed through opaquely - no validation\n\n var tagNameLower = tagResult.tagLower\n var isVoid = util.isVoidElement(tagResult.tagName)\n\n // Check if this is a JSX component (starts with uppercase letter)\n // JSX components should be parsed as block-level HTML even with newlines\n const isJSXComponent =\n tagResult.tagName.length > 0 &&\n tagResult.tagName[0] >= 'A' &&\n tagResult.tagName[0] <= 'Z'\n\n // Self-closing tags: has /> or is void (except anchor tags which need special handling)\n // Per CommonMark spec: self-closing tags with newlines are type 7 blocks\n // Type 7 blocks don't interrupt paragraphs, so they should be parsed as inline HTML\n // IMPORTANT: Validation already happened above, so if we get here the tag is valid\n // EXCEPTION: JSX components (uppercase tags) should always be parsed as block-level HTML\n if (tagResult.isSelfClosing || (isVoid && tagNameLower !== 'a')) {\n // If tag has newline, it's a type 7 block - don't interrupt paragraphs\n // Return null to allow paragraph wrapping - parseInlineSpan will parse as raw HTML\n // But only if validation passed (which already happened above)\n // EXCEPTION: JSX components should be parsed as block-level HTML even with newlines\n if (tagResult.hasNewline && !isJSXComponent) {\n return null\n }\n\n // If we're not in HTML block context and not inline, parse as inline HTML\n // This allows them to be wrapped in paragraphs per type 7 block rules\n // Return null to allow paragraph wrapping - parseInlineSpan will parse them as raw HTML\n // EXCEPTION: JSX components should be parsed as block-level HTML even when not in HTML block context\n if (!state.inHTML && !state.inline && !isJSXComponent) {\n return null\n }\n\n var attrsTrimmedSelfClose = tagResult.attrs.replace(/\\/\\s*$/, '')\n var selfCloseAttrs = parseHTMLAttributes(\n attrsTrimmedSelfClose,\n tagNameLower,\n tagResult.tagName,\n options\n )\n // For inline context, preserve raw HTML to maintain spacing\n var rawText = state.inline ? source.slice(pos, tagResult.endPos) : undefined\n const result: MarkdownToJSX.HTMLSelfClosingNode & {\n endPos: number\n rawText?: string\n } = {\n type: RuleType.htmlSelfClosing,\n tag: tagResult.tagName,\n attrs: selfCloseAttrs,\n endPos: tagResult.endPos,\n }\n if (rawText !== undefined) {\n result.rawText = rawText\n }\n return result\n }\n\n // For inline context, parse as simple opening tag (no closing tag search)\n // IMPORTANT: Validation must happen before this check to reject invalid tags\n // Note: parseHTMLTag only returns a result if tag has closing >, so tag is complete\n // Multiline attributes are supported - newlines in tags are valid HTML\n if (state.inline) {\n // Validation already happened above, so if we get here the tag is valid\n var attrsTrimmedInline = tagResult.attrs.replace(/\\/\\s*$/, '')\n // Preserve whitespace before attributes for CommonMark compliance\n var rawAttrsWithWhitespace =\n tagResult.whitespaceBeforeAttrs + attrsTrimmedInline\n var parsedInlineAttrs = parseHTMLAttributes(\n attrsTrimmedInline,\n tagNameLower,\n tagResult.tagName,\n options\n )\n var inlineAttrs: Record<string, any> = {\n ...parsedInlineAttrs,\n }\n\n // For non-void inline tags, find matching closing tag and parse content\n var inlineEndPos = tagResult.endPos\n var children: MarkdownToJSX.ASTNode[] = []\n if (!util.isVoidElement(tagResult.tagName)) {\n var closingResult = findInlineClosingTag(\n source,\n tagResult.endPos,\n tagNameLower\n )\n if (closingResult !== null) {\n var content = source.slice(tagResult.endPos, closingResult[0])\n if (content) {\n if (\n (state.inHTML && HTML_BLOCK_ELEMENT_START_R.test(content)) ||\n hasBlockContent(content)\n ) {\n children = parseBlocksInHTML(\n content,\n {\n ...state,\n inline: false,\n inHTML: true,\n inAnchor: state.inAnchor || tagNameLower === 'a',\n },\n options\n )\n } else {\n children = parseInlineSpan(\n content,\n 0,\n content.length,\n {\n ...state,\n inline: true,\n inAnchor: state.inAnchor || tagNameLower === 'a',\n },\n options\n )\n }\n }\n inlineEndPos = closingResult[1]\n }\n }\n return {\n type: RuleType.htmlBlock,\n tag: tagResult.tagName as MarkdownToJSX.HTMLTags,\n attrs: inlineAttrs,\n rawAttrs: rawAttrsWithWhitespace,\n children: children,\n verbatim: false,\n endPos: inlineEndPos,\n } as MarkdownToJSX.HTMLNode & { endPos: number }\n }\n\n // For inline context, don't try block parsing - simple opening tags should be parsed inline\n // Block parsing is only for tags that need closing tags or are block-level\n if (!state.inline) {\n // Determine block type inline (previously handled by matchHTMLBlock)\n var sourceLen = source.length\n var firstLineEnd = util.findLineEnd(source, pos)\n var tagLower = tagResult.tagLower\n var isType1BlockVar = isType1Block(tagLower)\n var isType6Block = !isType1BlockVar && isType6Tag(tagResult.tagName)\n var tagHasClosingAngle = false\n var checkPos = pos\n while (checkPos < tagResult.endPos) {\n if (source[checkPos] === '>') {\n tagHasClosingAngle = true\n break\n }\n checkPos++\n }\n // Check if tag is followed by end of line (with optional whitespace)\n var afterTag = tagResult.endPos\n while (\n afterTag < firstLineEnd &&\n (source[afterTag] === ' ' || source[afterTag] === '\\t')\n ) {\n afterTag++\n }\n // Check if tag is complete on line\n // For type 6 blocks, they can have content on same line\n // For other tags, they must be followed by newline or end of line\n var isCompleteOnLine =\n afterTag >= firstLineEnd ||\n source[afterTag] === '\\n' ||\n source[afterTag] === '\\r' ||\n (isType6Block && afterTag < firstLineEnd) ||\n !tagHasClosingAngle\n\n // Type 1 blocks (pre, script, style, textarea) need matching closing tags\n // Handle type 1 blocks even if they have newlines in the opening tag\n if (isType1BlockVar && tagHasClosingAngle && !tagResult.isClosing) {\n // Type 1: find matching closing tag\n var type1TagName = tagResult.tagName\n var type1TagEnd = tagResult.endPos\n var type1Attrs = tagResult.attrs\n var type1ContentPos = type1TagEnd\n if (source[type1ContentPos] === '\\n') type1ContentPos++\n var type1ContentStart = type1ContentPos\n var type1ContentEnd = type1ContentPos\n var type1Depth = 1\n var type1OpenTagLen = tagLower.length + 1\n while (type1Depth > 0) {\n var type1Idx = source.indexOf('<', type1ContentPos)\n if (type1Idx === -1) {\n type1ContentEnd = sourceLen\n type1ContentPos = sourceLen\n break\n }\n var type1OpenIdx = -1\n var type1CloseIdx = -1\n if (source[type1Idx + 1] === '/') {\n type1CloseIdx = type1Idx\n } else if (\n type1Idx + type1OpenTagLen + 1 <= sourceLen &&\n (source[type1Idx + 1] === tagLower[0] ||\n source[type1Idx + 1] === type1TagName[0])\n ) {\n var type1TagCandidate = source.substring(\n type1Idx + 1,\n type1Idx + type1OpenTagLen\n )\n if (\n type1TagCandidate.toLowerCase() === tagLower &&\n (source[type1Idx + type1OpenTagLen] === ' ' ||\n source[type1Idx + type1OpenTagLen] === '>')\n ) {\n type1OpenIdx = type1Idx\n }\n }\n if (type1OpenIdx === -1 && type1CloseIdx === -1) {\n type1ContentPos = type1Idx + 1\n continue\n }\n if (\n type1OpenIdx !== -1 &&\n (type1CloseIdx === -1 || type1OpenIdx < type1CloseIdx)\n ) {\n type1ContentPos = type1OpenIdx + type1OpenTagLen + 1\n type1Depth++\n } else {\n var type1P = type1CloseIdx + 2\n while (type1P < sourceLen) {\n var type1C = source[type1P]\n if (\n type1C !== ' ' &&\n type1C !== '\\t' &&\n type1C !== '\\n' &&\n type1C !== '\\r'\n )\n break\n type1P++\n }\n if (type1P + tagLower.length > sourceLen) break\n var type1CloseTagCandidate = source.substring(\n type1P,\n type1P + tagLower.length\n )\n if (type1CloseTagCandidate.toLowerCase() !== tagLower) {\n type1ContentPos = type1P\n continue\n }\n type1P += tagLower.length\n while (type1P < sourceLen) {\n var type1C2 = source[type1P]\n if (\n type1C2 !== ' ' &&\n type1C2 !== '\\t' &&\n type1C2 !== '\\n' &&\n type1C2 !== '\\r'\n )\n break\n type1P++\n }\n if (type1P >= sourceLen || source[type1P] !== '>') {\n type1ContentPos = type1P\n continue\n }\n var type1ClosingTagEnd = type1P + 1\n var type1LineEndAfterClose = util.findLineEnd(\n source,\n type1ClosingTagEnd\n )\n type1ContentEnd = type1LineEndAfterClose\n type1ContentPos = type1LineEndAfterClose + 1\n type1Depth--\n }\n }\n var type1TrailingNl = 0\n while (\n type1ContentPos + type1TrailingNl < sourceLen &&\n source[type1ContentPos + type1TrailingNl] === '\\n'\n )\n type1TrailingNl++\n var type1FullMatch = source.slice(pos, type1ContentPos + type1TrailingNl)\n var type1Content = source.slice(type1ContentStart, type1ContentEnd)\n var type1EndPos = type1ContentPos + type1TrailingNl\n return processHTMLBlock(\n tagResult.tagName,\n tagResult.tagName,\n type1Attrs,\n type1Content,\n type1FullMatch,\n type1EndPos,\n source,\n state,\n false,\n options\n )\n }\n\n // Type 6/7 blocks end at blank lines\n if (isCompleteOnLine || !tagHasClosingAngle) {\n // Determine if type 6 or type 7\n var blockType: 'type6' | 'type7' = isType6Block ? 'type6' : 'type7'\n var tagEnd = tagResult.endPos\n var blockEnd = findNextBlankLine(source, firstLineEnd + 1, sourceLen)\n\n // For type 6 blocks, check if there's a closing tag (even beyond the blank line)\n // If there is AND there's markdown syntax, extend to include the closing tag\n // Exception: for JSX components, always extend to closing tag (proper parent-child nesting)\n if (blockType === 'type6' && !tagResult.isClosing) {\n // For JSX components, preserve case; for HTML, use lowercase\n const tagNameForClosing = isJSXComponent\n ? tagResult.tagName\n : tagResult.tagLower || tagResult.tagName.toLowerCase()\n var closingTagPattern = '</' + tagNameForClosing\n var closingIdx = source.indexOf(closingTagPattern, tagEnd)\n if (closingIdx !== -1) {\n // Found a closing tag\n // Check if it's valid\n var afterClosingTag = closingIdx + closingTagPattern.length\n while (\n afterClosingTag < sourceLen &&\n (source[afterClosingTag] === ' ' ||\n source[afterClosingTag] === '\\t')\n ) {\n afterClosingTag++\n }\n if (afterClosingTag < sourceLen && source[afterClosingTag] === '>') {\n // Valid closing tag found\n var extendedContent = source.slice(tagEnd, closingIdx)\n // For JSX components, always extend to closing tag for proper nesting\n // For HTML elements, only extend if there's block content\n var shouldExtend =\n isJSXComponent || hasBlockContent(extendedContent)\n if (shouldExtend) {\n // Extend block to include closing tag\n var closingLineEnd = util.findLineEnd(source, afterClosingTag + 1)\n blockEnd = closingLineEnd\n }\n }\n }\n }\n\n var blockContent = source.slice(tagEnd, blockEnd)\n var blockAttrs = tagResult.whitespaceBeforeAttrs + tagResult.attrs\n var isClosingTag = tagResult.isClosing\n\n // Handle type 6/7 blocks\n // For type 7 blocks with empty content (standalone tags), determine if they should be block or inline\n // Per CommonMark: Type 7 blocks cannot interrupt paragraphs, but if they're on their own line they're blocks\n // However, if the tag contains newlines in attributes (without hasNewline flag because they're in quotes),\n // it should be treated as inline and wrapped in a paragraph\n if (blockType === 'type7' && blockContent.trim() === '') {\n // Check if the tag itself contains a newline (inside the tag, not after it)\n var rawTagText = source.slice(pos, tagResult.endPos)\n var tagContainsNewline = rawTagText.indexOf('\\n') !== -1\n\n if (tagContainsNewline) {\n // Tag has newline inside it (in attribute) - should be wrapped in paragraph\n return null\n }\n\n // Tag is on its own line, treat as block\n var tagEndInSource = tagResult.endPos\n var tagLineEnd = util.findLineEnd(source, tagEndInSource)\n if (tagLineEnd < source.length) tagLineEnd++\n var rawTag = source.slice(pos, tagLineEnd)\n return createVerbatimHTMLBlock(\n tagResult.tagName,\n rawTag,\n blockEnd,\n {},\n undefined,\n isClosingTag,\n false, // type 7 blocks cannot interrupt paragraphs\n options,\n state\n )\n }\n\n // For type 7 blocks with multi-line or incomplete opening tags, preserve raw HTML\n var openingTagHasNewline = tagResult.hasNewline\n var openingTagIsIncomplete = !tagHasClosingAngle\n if (\n (openingTagHasNewline || openingTagIsIncomplete) &&\n blockType === 'type7'\n ) {\n var openingTagEnd = tagResult.endPos\n var rawOpeningTag = source.slice(pos, openingTagEnd)\n var rawContent = blockContent\n var fullRawHTML = rawOpeningTag + rawContent\n return createVerbatimHTMLBlock(\n tagResult.tagName,\n fullRawHTML,\n blockEnd,\n {},\n undefined,\n isClosingTag,\n false, // type 7 blocks cannot interrupt paragraphs\n options,\n state\n )\n }\n\n // Parse attributes, but always preserve raw attributes for consistency\n // Cache lowercase tag name to avoid repeated toLowerCase() calls\n const tagLower = tagResult.tagLower || tagResult.tagName.toLowerCase()\n var parsedBlockAttributes = parseHTMLAttributes(\n blockAttrs,\n tagLower,\n tagResult.tagName,\n options\n )\n var blockAttributes: Record<string, any> = {\n ...parsedBlockAttributes,\n }\n\n // For type 6 blocks with block syntax, parse through processHTMLBlock\n if (blockType === 'type6') {\n var contentForBlockCheck = blockContent\n var closingTagIdx = blockContent.indexOf('</' + tagLower)\n if (closingTagIdx >= 0) {\n var afterTag = closingTagIdx + 2 + tagResult.tagName.length\n while (\n afterTag < blockContent.length &&\n (blockContent[afterTag] === ' ' || blockContent[afterTag] === '\\t')\n )\n afterTag++\n if (\n afterTag < blockContent.length &&\n blockContent[afterTag] === '>'\n ) {\n contentForBlockCheck = blockContent.slice(0, closingTagIdx)\n }\n }\n\n if (hasBlockContent(contentForBlockCheck)) {\n return processHTMLBlock(\n tagResult.tagName,\n tagResult.tagName,\n blockAttrs,\n contentForBlockCheck,\n source.slice(pos, tagResult.endPos),\n blockEnd,\n source,\n state,\n false,\n options\n )\n }\n }\n\n // For type 6 and type 7 blocks, content is verbatim (raw HTML)\n // Content includes everything from after the opening tag to the blank line\n // Remove leading newline if present\n var verbatimContent = blockContent\n if (verbatimContent.length > 0 && verbatimContent[0] === '\\n') {\n verbatimContent = verbatimContent.slice(1)\n }\n // Per CommonMark spec: remove common leading whitespace from all lines\n var lines = verbatimContent.split('\\n')\n var minIndent = Infinity\n for (var lineIdx = 0; lineIdx < lines.length; lineIdx++) {\n var line = lines[lineIdx]\n if (line.trim().length === 0) continue\n var indent = 0\n while (\n indent < line.length &&\n (line[indent] === ' ' || line[indent] === '\\t')\n ) {\n indent++\n }\n if (indent < minIndent) minIndent = indent\n }\n if (minIndent > 0 && minIndent < Infinity) {\n var dedentedLines: string[] = []\n for (var lineIdx2 = 0; lineIdx2 < lines.length; lineIdx2++) {\n var line2 = lines[lineIdx2]\n if (line2.trim().length === 0) {\n dedentedLines.push(line2)\n } else {\n dedentedLines.push(line2.slice(minIndent))\n }\n }\n verbatimContent = dedentedLines.join('\\n')\n }\n\n return createVerbatimHTMLBlock(\n tagResult.tagName,\n verbatimContent,\n blockEnd,\n blockAttributes,\n blockAttrs,\n isClosingTag,\n blockType === 'type6' ? true : false, // type 6 can interrupt, type 7 cannot\n options,\n state\n )\n }\n }\n\n // If we're in inline context and didn't match simple tag parsing, return null\n // This allows the tag to be escaped or handled by other parsers\n if (state.inline) {\n return null\n }\n\n // Fallback: Try void element without /> (manual parsing)\n // Only try this if self-closing didn't match\n var tagNameResult = parseHTMLTagName(source, pos + 1)\n if (!tagNameResult) return null\n\n var tagName = tagNameResult.tagName\n if (!util.isVoidElement(tagName)) {\n return null\n }\n\n // Use tagLower from parseHTMLTagName result to avoid repeated toLowerCase() calls\n const tagLowerVoid = tagNameResult.tagLower\n\n var i = tagNameResult.nextPos\n var len = source.length\n while (i < len && isSpaceOrTab(source[i])) i++\n var attrsStart = i\n\n while (i < len && source[i] !== '>') i++\n if (i >= len) return null\n\n const attrs = source.slice(attrsStart, i).trim()\n const afterAngle = i + 1\n\n let checkIdx = afterAngle\n while (checkIdx < len && isSpaceOrTab(source[checkIdx])) checkIdx++\n const closeTagPattern = '</' + tagLowerVoid + '>'\n const foundIdx = source.toLowerCase().indexOf(closeTagPattern, checkIdx)\n if (foundIdx !== -1) {\n const between = source.slice(checkIdx, foundIdx).trim()\n if (between) {\n return null\n }\n }\n\n i++\n const endPos = i\n while (i < len && isSpaceOrTab(source[i])) i++\n if (i < len && source[i] === '\\n') i++\n\n const fallbackAttributes = parseHTMLAttributes(\n attrs,\n tagName,\n tagName,\n options\n )\n\n return {\n type: RuleType.htmlSelfClosing,\n tag: tagName,\n attrs: fallbackAttributes,\n endPos,\n } as MarkdownToJSX.HTMLSelfClosingNode & { endPos: number }\n}\n\n// ============================================================================\n// HTML Token Interface and Unified Scanner\n// Ultra-compact unified scanner for all HTML constructs\n// ============================================================================\n\nexport interface HTMLToken {\n kind: 'tag' | 'comment' | 'pi' | 'declaration' | 'cdata'\n tagNameLower?: string\n tagName?: string\n isClosing?: boolean\n isSelfClosing?: boolean\n hasNewline: boolean\n type6Candidate?: boolean\n type7Candidate?: boolean\n endPos: number\n attrs?: string\n whitespaceBeforeAttrs?: string\n text?: string\n raw?: boolean\n}\n\n/**\n * Scan tag-like constructs: </tag, <tag\n */\nfunction scanTagLike(source: string, pos: number): HTMLToken | null {\n if (source[pos] !== '<') return null\n\n var sourceLen = source.length\n\n // Check for closing tag (</tag>)\n var isClosing = false\n var tagStart = pos + 1\n if (pos + 1 < sourceLen && source[pos + 1] === '/') {\n isClosing = true\n tagStart = pos + 2\n }\n\n // Parse tag name\n var tagNameResult = parseHTMLTagName(source, tagStart)\n if (!tagNameResult) return null\n\n var tagName = tagNameResult.tagName\n var tagLower = tagNameResult.tagLower\n var attrsStart = tagNameResult.nextPos\n\n // Fast path: tags without attributes or whitespace\n if (attrsStart < sourceLen) {\n var immediateChar = source[attrsStart]\n if (immediateChar === '>' || immediateChar === '/') {\n var endPos = immediateChar === '>' ? attrsStart + 1 : attrsStart + 2\n if (\n immediateChar === '/' &&\n (attrsStart + 1 >= sourceLen || source[attrsStart + 1] !== '>')\n ) {\n return null\n }\n var isSelfClosingFast = immediateChar === '/'\n var type6CandidateFast = isType6Tag(tagName)\n var type7CandidateFast = !isType1Block(tagLower) && !type6CandidateFast\n return {\n kind: 'tag',\n tagNameLower: tagLower,\n tagName: tagName,\n isClosing: isClosing,\n isSelfClosing: isSelfClosingFast,\n hasNewline: false,\n type6Candidate: type6CandidateFast,\n type7Candidate: type7CandidateFast,\n endPos: endPos,\n attrs: '',\n whitespaceBeforeAttrs: '',\n }\n }\n }\n\n // Capture whitespace after tag name (including newlines per CommonMark spec)\n var whitespaceStart = attrsStart\n var hasNewline = false\n while (attrsStart < sourceLen) {\n var ch = source[attrsStart]\n var code = charCode(source, attrsStart)\n if (ch === ' ' || ch === '\\t') {\n // Space or tab - continue\n } else if (code === 10 || code === 13) {\n // \\n or \\r\n hasNewline = true\n } else {\n break // Not whitespace\n }\n attrsStart++\n }\n var whitespaceBeforeAttrs = source.slice(whitespaceStart, attrsStart)\n\n // Parse attributes until we find > - minimal validation only for boundary detection\n var tagEnd = attrsStart\n var inQuotes = false\n var quoteChar = ''\n var braceDepth = 0\n var hasSlash = false\n var hasSpaceBeforeSlash = false\n\n // State machine for attribute parsing: 0=normal, 1=inDoubleQuotes, 2=inSingleQuotes\n var parseState = 0\n while (tagEnd < sourceLen) {\n var char = source[tagEnd]\n var code = charCode(source, tagEnd)\n\n // Handle quotes state machine\n if (parseState === 1) {\n // in double quotes\n if (char === '\"') {\n // Check for consecutive quotes (invalid HTML)\n if (tagEnd + 1 < sourceLen && source[tagEnd + 1] === '\"') {\n return null\n }\n parseState = 0\n }\n tagEnd++\n } else if (parseState === 2) {\n // in single quotes\n if (char === \"'\") {\n parseState = 0\n }\n tagEnd++\n } else if (char === '\"') {\n parseState = 1\n tagEnd++\n } else if (char === \"'\") {\n parseState = 2\n tagEnd++\n } else if (char === '{' || (char === '}' && braceDepth > 0)) {\n // Track JSX expression brace depth\n braceDepth += char === '{' ? 1 : -1\n tagEnd++\n } else if (char === '>' && braceDepth === 0) {\n // Found closing > - check for self-closing / and space before >\n if (tagEnd > attrsStart) {\n var checkBack = tagEnd - 1\n while (checkBack >= attrsStart) {\n var backChar = source[checkBack]\n if (backChar !== ' ' && backChar !== '\\t') break\n checkBack--\n }\n if (checkBack >= attrsStart && source[checkBack] === '/') {\n hasSlash = true\n hasSpaceBeforeSlash = checkBack < tagEnd - 1\n }\n }\n tagEnd++\n break\n } else {\n // Check for invalid attribute name characters (*, #, !)\n if (char === '*' || char === '#' || char === '!') {\n var checkAhead = tagEnd + 1\n while (checkAhead < sourceLen) {\n var aheadChar = source[checkAhead]\n if (\n aheadChar === '=' ||\n aheadChar === ' ' ||\n aheadChar === '\\t' ||\n aheadChar === '\\n' ||\n aheadChar === '\\r' ||\n aheadChar === '>'\n ) {\n break\n }\n checkAhead++\n }\n if (checkAhead < sourceLen && source[checkAhead] === '=') {\n return null // Invalid char in attribute name\n }\n }\n // Track newlines\n if (code === 10 || code === 13) {\n // \\n or \\r\n hasNewline = true\n }\n tagEnd++\n }\n }\n\n // Must have found >\n if (tagEnd > sourceLen || source[tagEnd - 1] !== '>') {\n return null\n }\n\n // Reject tags with unclosed quotes\n if (parseState === 1 || parseState === 2) {\n return null\n }\n\n // Reject tags with unclosed JSX expressions\n if (braceDepth > 0) {\n return null\n }\n\n // Reject tags with space between / and > (invalid HTML structure)\n if (hasSpaceBeforeSlash) {\n return null\n }\n\n var attrsEnd = tagEnd - 1\n if (hasSlash) {\n // For self-closing tags, exclude the / from attrs\n attrsEnd--\n }\n var attrs = source.slice(attrsStart, attrsEnd)\n var isSelfClosing = hasSlash\n\n // Minimal validation: reject missing space after quoted attribute value\n var lastQuotePos = -1\n var inQuotesCheck = false\n var quoteCharCheck = ''\n var afterEquals = false\n for (var i = 0; i < attrs.length; i++) {\n var ch = attrs[i]\n if (inQuotesCheck) {\n if (ch === quoteCharCheck) {\n inQuotesCheck = false\n lastQuotePos = i\n quoteCharCheck = ''\n afterEquals = false\n }\n } else if (ch === '\"' || ch === \"'\") {\n inQuotesCheck = true\n quoteCharCheck = ch\n afterEquals = false\n } else if (ch === '=') {\n afterEquals = true\n } else if (lastQuotePos !== -1 && i === lastQuotePos + 1) {\n // Immediately after closing quote\n var code = ch.charCodeAt(0)\n if (isAlphaCode(code)) {\n // Letter immediately after quote - missing space, reject\n return null\n }\n } else if (\n afterEquals &&\n !inQuotesCheck &&\n (ch === '*' || ch === '#' || ch === '!')\n ) {\n // Invalid char in unquoted attribute value - reject\n return null\n } else if (isSpaceOrTab(ch)) {\n afterEquals = false\n }\n }\n\n // Determine type 6/7 candidates\n var type6Candidate = isType6Tag(tagName)\n var type7Candidate = !isType1Block(tagLower) && !type6Candidate\n\n return {\n kind: 'tag',\n tagNameLower: tagLower,\n tagName: tagName,\n isClosing: isClosing,\n isSelfClosing: isSelfClosing,\n hasNewline: hasNewline,\n type6Candidate: type6Candidate,\n type7Candidate: type7Candidate,\n endPos: tagEnd,\n attrs: attrs,\n whitespaceBeforeAttrs: whitespaceBeforeAttrs,\n }\n}\n\n// ============================================================================\n// Unified HTML Scanner\n// Ultra-compact unified scanner for all HTML constructs\n// ============================================================================\n\n/**\n * Unified HTML scanner - handles tags, comments, PIs, declarations, CDATA\n * Ultra-compact implementation tuned for minification\n */\nfunction scanRawHTML(s: string, p: number): HTMLToken | null {\n if (p >= s.length || s[p] !== '<') return null\n var l = s.length\n if (p + 1 >= l) return null\n var c = s[p + 1]\n if (c === '!') {\n if (p + 4 <= l && s.slice(p, p + 4) === '<!--') {\n // Comment: scan for -->\n var endPos = p + 4\n if (endPos < l && s[endPos] === '>') {\n return {\n kind: 'comment',\n hasNewline: false,\n endPos: endPos + 1,\n text: s.slice(p, endPos + 1),\n raw: true,\n }\n }\n if (endPos + 1 < l && s[endPos] === '-' && s[endPos + 1] === '>') {\n return {\n kind: 'comment',\n hasNewline: false,\n endPos: endPos + 2,\n text: s.slice(p, endPos + 2),\n raw: true,\n }\n }\n while (endPos + 2 < l) {\n if (s.slice(endPos, endPos + 3) === '-->') {\n return {\n kind: 'comment',\n hasNewline: false,\n endPos: endPos + 3,\n text: s.slice(p, endPos + 3),\n raw: true,\n }\n }\n endPos++\n }\n return null\n }\n if (p + 9 <= l && s.slice(p, p + 9) === '<![CDATA[') {\n // CDATA: scan for ]]>\n var endPos = p + 9\n while (endPos + 2 < l) {\n if (s.slice(endPos, endPos + 3) === ']]>') {\n return {\n kind: 'cdata',\n hasNewline: false,\n endPos: endPos + 3,\n text: s.slice(p, endPos + 3),\n raw: true,\n }\n }\n endPos++\n }\n return null\n }\n if (p + 2 < l && isAlphaCode(s.charCodeAt(p + 2))) {\n // Declaration: scan for >\n var endPos = p + 2\n while (endPos < l && s[endPos] !== '>') endPos++\n if (endPos >= l) return null\n return {\n kind: 'declaration',\n hasNewline: false,\n endPos: endPos + 1,\n text: s.slice(p, endPos + 1),\n raw: true,\n }\n }\n return null\n }\n if (c === '?') {\n // Processing instruction: scan for ?>\n var endPos = p + 2\n while (endPos + 1 < l) {\n if (s.slice(endPos, endPos + 2) === '?>') {\n return {\n kind: 'pi',\n hasNewline: false,\n endPos: endPos + 2,\n text: s.slice(p, endPos + 2),\n raw: true,\n }\n }\n endPos++\n }\n return null\n }\n return scanTagLike(s, p)\n}\n\ninterface DefinitionParseResult {\n endPos: number\n target: string\n title?: string\n}\n\nfunction parseRefContent(\n source: string,\n pos: number,\n urlNewlineCount: number\n): DefinitionParseResult | null {\n const len = source.length\n let i = pos\n\n // Parse URL (can be in angle brackets or plain, can span multiple lines)\n // At this point, i should be at the start of the destination (after any whitespace/newline)\n // Per CommonMark spec: destination can be on the same line or following lines\n const hasAngleBrackets = i < len && source[i] === '<'\n if (hasAngleBrackets) i++\n\n const urlStart = i\n let urlEnd = urlStart\n\n // Per CommonMark spec Example 199: empty destination after colon (just whitespace/newline)\n // is invalid - should be parsed as paragraph, not reference definition\n // Also check if we hit a blank line (two consecutive newlines) - destination ends there\n if (urlStart >= len) {\n // No destination found - invalid (except for empty <>)\n if (!hasAngleBrackets) return null\n // For angle brackets, empty destination is valid\n urlEnd = urlStart\n } else if (\n urlNewlineCount > 0 &&\n urlStart < len &&\n source[urlStart] === '\\n'\n ) {\n // We had a newline after colon, skipped whitespace, but found another newline\n // This means blank line after colon - empty destination, invalid\n return null\n } else {\n // Find end of URL - can span multiple lines\n // Per CommonMark spec: destination ends when we encounter:\n // 1. Closing > for angle-bracketed URLs\n // 2. Whitespace followed by title delimiter (\", ', or () on same or next line\n // 3. End of input or two consecutive newlines (blank line)\n while (urlEnd < len) {\n if (hasAngleBrackets && source[urlEnd] === '>') {\n break\n }\n\n if (source[urlEnd] === '\\n') {\n // Check if next line continues the URL or starts a title\n const nextLineStart = urlEnd + 1\n if (nextLineStart >= len) break\n\n // Check for blank line (two consecutive newlines)\n if (nextLineStart < len && source[nextLineStart] === '\\n') {\n // Blank line - URL ends here\n break\n }\n\n // Skip whitespace on next line\n let checkPos = nextLineStart\n while (\n checkPos < len &&\n (source[checkPos] === ' ' || source[checkPos] === '\\t')\n ) {\n checkPos++\n }\n\n // If next line starts with title delimiter, URL ends here\n if (\n checkPos < len &&\n (source[checkPos] === '\"' ||\n source[checkPos] === \"'\" ||\n source[checkPos] === '(')\n ) {\n break\n }\n\n // Per CommonMark spec: reference definitions are block-level constructs\n // If next line starts with '[', it's a new reference definition, so current one ends here\n // Stop at the newline (don't include it in the URL)\n if (checkPos < len && source[checkPos] === '[') {\n break\n }\n\n // Check if next line looks like a block-level construct or content that would terminate the ref definition\n // Per CommonMark spec: \"No further character may occur\" after title/URL\n // URLs can span multiple lines, but continuation lines should still look like URLs\n if (checkPos < len) {\n const nextChar = source[checkPos]\n // Always stop for block-level constructs\n if (\n nextChar === '=' ||\n nextChar === '-' ||\n nextChar === '_' ||\n nextChar === '*' ||\n nextChar === '#' ||\n nextChar === '>' ||\n nextChar === '`' ||\n nextChar === '~' ||\n nextChar === '[' ||\n (nextChar >= '0' && nextChar <= '9')\n ) {\n break\n }\n // Stop if next line starts with a letter (could be content, not URL continuation)\n // URLs typically start with /, http, https, <, or are indented\n // But allow if it looks like a URL scheme (letter followed by :)\n if (nextChar >= 'a' && nextChar <= 'z') {\n // Check if it's a URL scheme (e.g., \"http:\", \"ftp:\")\n let schemeEnd = checkPos + 1\n while (\n schemeEnd < len &&\n schemeEnd < checkPos + 32 &&\n ((source[schemeEnd] >= 'a' && source[schemeEnd] <= 'z') ||\n (source[schemeEnd] >= 'A' && source[schemeEnd] <= 'Z') ||\n (source[schemeEnd] >= '0' && source[schemeEnd] <= '9') ||\n source[schemeEnd] === '+' ||\n source[schemeEnd] === '.' ||\n source[schemeEnd] === '-')\n ) {\n schemeEnd++\n }\n // If followed by ':', it's a URL scheme - allow continuation\n if (schemeEnd < len && source[schemeEnd] === ':') {\n // URL scheme - allow continuation\n } else {\n // Not a URL scheme - stop here (likely content)\n break\n }\n }\n }\n\n // Otherwise, continue URL on next line (skip the newline and leading whitespace)\n urlEnd = checkPos\n continue\n }\n\n if (\n !hasAngleBrackets &&\n (source[urlEnd] === ' ' || source[urlEnd] === '\\t')\n ) {\n // Check if this whitespace is followed by a title delimiter\n let checkPos = urlEnd + 1\n while (\n checkPos < len &&\n (source[checkPos] === ' ' || source[checkPos] === '\\t')\n ) {\n checkPos++\n }\n\n // Check if next char starts a title\n if (\n checkPos < len &&\n (source[checkPos] === '\"' ||\n source[checkPos] === \"'\" ||\n source[checkPos] === '(')\n ) {\n break\n }\n\n // Check if next line starts a title\n if (checkPos < len && source[checkPos] === '\\n') {\n const nextLineStart = checkPos + 1\n if (nextLineStart < len && source[nextLineStart] === '\\n') {\n // Blank line - URL ends here\n break\n }\n let nextLineCheck = nextLineStart\n while (\n nextLineCheck < len &&\n (source[nextLineCheck] === ' ' || source[nextLineCheck] === '\\t')\n ) {\n nextLineCheck++\n }\n if (\n nextLineCheck < len &&\n (source[nextLineCheck] === '\"' ||\n source[nextLineCheck] === \"'\" ||\n source[nextLineCheck] === '(')\n ) {\n break\n }\n }\n\n // No title delimiter found - URL continues (or ends if no title)\n // Continue parsing to find title or end\n }\n\n urlEnd++\n }\n }\n\n if (hasAngleBrackets && (urlEnd >= len || source[urlEnd] !== '>')) {\n return null // No closing >\n }\n\n // Extract target and normalize whitespace\n // Per CommonMark spec: destination can span multiple lines\n // Leading/trailing whitespace on each line should be trimmed, but internal whitespace preserved\n // Also, we need to preserve newlines between continuation lines\n let target = source.slice(urlStart, urlEnd)\n\n // Normalize whitespace: trim leading/trailing whitespace from each line\n // but preserve newlines and internal whitespace\n // Per CommonMark spec: leading/trailing whitespace is trimmed from destination\n let targetLines: string[] = []\n let targetLineStart = 0\n for (let i = 0; i <= target.length; i++) {\n if (i === target.length || target[i] === '\\n') {\n let line = target.slice(targetLineStart, i)\n // Trim leading/trailing whitespace from this line\n line = line.trim()\n if (line.length > 0 || targetLines.length === 0) {\n // Only add non-empty lines, or the first line even if empty (for angle brackets)\n targetLines.push(line)\n if (i < target.length) {\n targetLines.push('\\n')\n }\n } else if (i < target.length) {\n // Empty continuation line - preserve as newline\n targetLines.push('\\n')\n }\n targetLineStart = i + 1\n }\n }\n\n target = targetLines.join('')\n\n // Trim leading/trailing whitespace from the entire target\n target = target.trim()\n\n i = hasAngleBrackets ? urlEnd + 1 : urlEnd\n\n // Check if we stopped URL parsing because next line starts with a block construct\n // (indicating the ref definition ends here)\n // Per Example 215: ref definitions end before setext headings\n // A setext heading has content on one line, then = or - on the next line\n // We need to look ahead to detect this pattern\n var stoppedAtBlock = false\n if (i < len && source[i] === '\\n') {\n var nextLineStart = i + 1\n var checkPos = nextLineStart\n while (\n checkPos < len &&\n (source[checkPos] === ' ' || source[checkPos] === '\\t')\n ) {\n checkPos++\n }\n if (checkPos < len) {\n const nextChar = source[checkPos]\n // Check for block-level constructs that terminate ref definitions\n if (\n nextChar === '[' ||\n nextChar === '=' ||\n nextChar === '-' ||\n nextChar === '_' ||\n nextChar === '*' ||\n nextChar === '#' ||\n nextChar === '>' ||\n nextChar === '`' ||\n nextChar === '~' ||\n (nextChar >= '0' && nextChar <= '9')\n ) {\n stoppedAtBlock = true\n }\n // Per Example 215: check if this looks like a setext heading\n // Pattern: content line, then line starting with = or -\n // If next line has content (not starting with block char), check if line after that starts with = or -\n if (!stoppedAtBlock && nextChar !== '=' && nextChar !== '-') {\n // Next line might be content - check if line after that starts with = or -\n var firstLineEnd = util.findLineEnd(source, checkPos)\n if (firstLineEnd < len) {\n var secondLineStart = firstLineEnd + 1\n var secondCheckPos = secondLineStart\n while (\n secondCheckPos < len &&\n (source[secondCheckPos] === ' ' || source[secondCheckPos] === '\\t')\n ) {\n secondCheckPos++\n }\n if (secondCheckPos < len) {\n var secondChar = source[secondCheckPos]\n if (secondChar === '=' || secondChar === '-') {\n // This is a setext heading pattern - ref definition should end before content line\n stoppedAtBlock = true\n }\n }\n }\n }\n }\n }\n\n // Per CommonMark spec: title delimiter must be separated by whitespace from destination\n // Check if we see a title delimiter immediately after destination (no whitespace)\n // This makes it invalid as a reference definition\n if (\n !stoppedAtBlock &&\n i < len &&\n (source[i] === '\"' || source[i] === \"'\" || source[i] === '(')\n ) {\n // Title delimiter immediately after destination without whitespace - invalid\n return null\n }\n\n // Skip whitespace between destination and title (including optional newline)\n // Per CommonMark spec: title must be separated from destination by spaces/tabs\n // The title can be on the same line or a following line\n // Per CommonMark spec: Unicode whitespace (like non-breaking space) does NOT work for separation\n // However, if we stopped because next line starts with a block construct, don't skip past the newline\n let titleNewlineCount = 0\n while (i < len && !stoppedAtBlock) {\n const c = source[i]\n if (c === '\\n') {\n titleNewlineCount++\n if (titleNewlineCount > 1) break // Only one optional newline allowed before title\n i++\n // After newline, skip leading whitespace on next line (only ASCII space/tab)\n var whitespaceStart = i\n i = util.skipWhitespace(source, i)\n // If we hit Unicode whitespace, stop\n if (\n i < len &&\n util.isUnicodeWhitespace(source[i]) &&\n source[i] !== '\\n'\n ) {\n i = whitespaceStart - 1\n break\n }\n // Check if next line starts with a block construct (ref definition ends here)\n // Per Example 215: setext headings (= or -) also terminate ref definitions\n if (i < len) {\n const nextChar = source[i]\n if (\n nextChar === '[' ||\n nextChar === '=' ||\n nextChar === '-' ||\n nextChar === '_' ||\n nextChar === '*' ||\n nextChar === '#' ||\n nextChar === '>' ||\n nextChar === '`' ||\n nextChar === '~' ||\n (nextChar >= '0' && nextChar <= '9')\n ) {\n stoppedAtBlock = true\n i = whitespaceStart - 1 // Back up to the newline\n break\n }\n // Also check if this looks like a setext heading (need to look ahead to see if there's\n // a line that starts with = or - after some content)\n // For now, just checking = or - is sufficient as they're already in the block check above\n }\n } else if (c === ' ' || c === '\\t') {\n i++\n } else if (util.isUnicodeWhitespace(c)) {\n // Unicode whitespace does NOT work for separation - stop here\n break\n } else {\n break\n }\n }\n\n // Parse optional title (can span multiple lines, but cannot contain blank lines)\n let title: string | undefined = undefined\n let titleEndPos = i\n if (i < len) {\n const titleChar = source[i]\n if (titleChar === '\"' || titleChar === \"'\") {\n // Quoted title - can span multiple lines\n i++ // skip opening quote\n const titleStart = i\n let sawBlankLine = false\n let lastWasNewline = false\n\n while (i < len && source[i] !== titleChar) {\n if (source[i] === '\\n') {\n if (lastWasNewline) {\n // Two consecutive newlines = blank line\n sawBlankLine = true\n break\n }\n lastWasNewline = true\n i++\n } else {\n lastWasNewline = false\n if (source[i] === '\\\\' && i + 1 < len) {\n i++ // skip escaped char\n }\n i++\n }\n }\n\n if (sawBlankLine) {\n // Title contains blank line - invalid\n return null\n }\n\n if (i < len && source[i] === titleChar) {\n // Extract title preserving newlines (CommonMark spec allows multi-line titles)\n title = source.slice(titleStart, i)\n titleEndPos = i + 1\n i = titleEndPos\n // Per Example 210: after closing quote, check if there's non-whitespace before newline\n // Skip whitespace after closing quote\n var afterTitlePos = i\n while (\n afterTitlePos < len &&\n (source[afterTitlePos] === ' ' || source[afterTitlePos] === '\\t')\n ) {\n afterTitlePos++\n }\n // If there's non-whitespace before newline, invalidate the ref definition\n if (\n afterTitlePos < len &&\n source[afterTitlePos] !== '\\n' &&\n source[afterTitlePos] !== '\\r'\n ) {\n // Found non-whitespace after title closing delimiter - invalid\n return null\n }\n // Update i to point to after any whitespace (before newline)\n i = afterTitlePos\n }\n } else if (titleChar === '(') {\n // Parenthesized title - can span multiple lines\n i++ // skip opening paren\n const titleStart = i\n let parenDepth = 1\n let sawBlankLine = false\n let lastWasNewline = false\n\n while (i < len && parenDepth > 0) {\n if (source[i] === '\\n') {\n if (lastWasNewline) {\n // Two consecutive newlines = blank line\n sawBlankLine = true\n break\n }\n lastWasNewline = true\n i++\n } else {\n lastWasNewline = false\n if (source[i] === '\\\\' && i + 1 < len) {\n i++ // skip escaped char\n } else if (source[i] === '(') {\n parenDepth++\n } else if (source[i] === ')') {\n parenDepth--\n }\n i++\n }\n }\n\n if (sawBlankLine) {\n // Title contains blank line - invalid\n return null\n }\n\n if (parenDepth === 0) {\n title = source.slice(titleStart, i - 1)\n titleEndPos = i\n i = titleEndPos\n }\n }\n }\n\n // Skip trailing whitespace\n i = util.skipWhitespace(source, i)\n\n // Must end at newline or end of input\n // Per CommonMark spec: no further character may occur after title\n // Per Example 210: if there's text after the title on the same line, it's invalid\n // The title parsing already handles this - if title is found, i points to after the closing delimiter\n // We just need to ensure there's no non-whitespace before the newline\n if (i < len && source[i] !== '\\n') {\n // Check if there's non-whitespace before the newline\n var checkEndPos = i\n while (checkEndPos < len && source[checkEndPos] !== '\\n') {\n if (source[checkEndPos] !== ' ' && source[checkEndPos] !== '\\t') {\n // Found non-whitespace after title - invalid reference definition\n return null\n }\n checkEndPos++\n }\n }\n\n // Also check: if no title was found, make sure we're at end of line or there's trailing text\n // Per Example 210: `[foo]: /url\\n\"title\" ok` - the \"title\" ok is trailing text, should invalidate\n if (title === undefined && i < len && source[i] !== '\\n') {\n // No title found, but there's content after destination - check if it's just whitespace\n var checkTrailingPos = i\n while (checkTrailingPos < len && source[checkTrailingPos] !== '\\n') {\n if (\n source[checkTrailingPos] !== ' ' &&\n source[checkTrailingPos] !== '\\t'\n ) {\n // Found non-whitespace after destination - invalid reference definition\n return null\n }\n checkTrailingPos++\n }\n }\n\n return {\n endPos: i < len && source[i] === '\\n' ? i + 1 : i,\n target: target,\n title: title,\n }\n}\n\nfunction parseFootnoteContent(\n source: string,\n pos: number\n): DefinitionParseResult | null {\n // pos is already after the colon and whitespace\n let contentStart = pos\n let contentEnd = contentStart\n\n // Find the end of the footnote (next footnote definition, blank line, or end of input)\n // Continuation lines are lines that:\n // 1. Start with a newline\n // 2. Don't start with [^ (unless indented with 4+ spaces)\n // 3. Can be indented with up to 4 spaces\n // 4. Stop at a blank line (two consecutive newlines) if followed by non-indented content\n let stoppedAtBlankLine = false\n while (contentEnd < source.length) {\n // Check if we're at the start of a line (after newline or at start of input)\n const isLineStart = contentEnd === 0 || source[contentEnd - 1] === '\\n'\n\n // Check for blank line (two consecutive newlines) followed by non-indented content\n // A blank line terminates the footnote if followed by content that's not indented 4+ spaces\n // We need to check if we're at a blank line: current position is \\n and next is \\n\n if (\n contentEnd + 1 < source.length &&\n source[contentEnd] === '\\n' &&\n source[contentEnd + 1] === '\\n' &&\n contentEnd > contentStart // Make sure we're past the first line\n ) {\n // Check if there's non-indented content after the blank line\n let afterBlank = contentEnd + 2\n // Skip whitespace\n while (\n afterBlank < source.length &&\n (source[afterBlank] === ' ' || source[afterBlank] === '\\t')\n ) {\n afterBlank++\n }\n // If there's content and it's not indented with 4+ spaces, stop the footnote\n if (\n afterBlank < source.length &&\n source[afterBlank] !== '\\n' &&\n afterBlank - (contentEnd + 2) < 4\n ) {\n // Blank line followed by non-indented content - stop at the blank line\n stoppedAtBlankLine = true\n break\n }\n }\n\n if (isLineStart && util.startsWith(source, '[^', contentEnd)) {\n // Check if this is a footnote definition (has ':')\n let checkPos = contentEnd + 2\n while (checkPos < source.length && source[checkPos] !== ']') {\n checkPos++\n }\n if (\n checkPos < source.length &&\n source[checkPos] === ']' &&\n checkPos + 1 < source.length &&\n source[checkPos + 1] === ':'\n ) {\n // Found next footnote definition at start of line - stop here\n break\n }\n }\n contentEnd++\n }\n\n // Extract the footnote content (from after ']:' to before next footnote or end)\n // If we stopped at a blank line, contentEnd points to the first \\n of \\n\\n\n // We want to extract up to but not including that \\n (which slice does)\n // But we also need to make sure we don't include the trailing newline from the last line\n let extractEnd = contentEnd\n\n // pos is already after the colon and whitespace, so we can use it directly\n let contentStartPos = pos\n\n // Process lines directly without splitting to avoid intermediate array allocation\n var processedParts: string[] = []\n let lineStart = contentStartPos\n let lineIndex = 0\n let prevWasBlank = false\n\n while (lineStart < extractEnd) {\n let lineEnd = lineStart\n // Find line end\n while (lineEnd < extractEnd && source[lineEnd] !== '\\n') {\n lineEnd++\n }\n\n // Extract and process line\n if (lineIndex === 0) {\n // First line - trim trailing whitespace only\n let trimmedEnd = lineEnd\n while (\n trimmedEnd > lineStart &&\n (source[trimmedEnd - 1] === ' ' || source[trimmedEnd - 1] === '\\t')\n ) {\n trimmedEnd--\n }\n // Build first line\n let firstLineStr = source.slice(lineStart, trimmedEnd)\n processedParts.push(firstLineStr)\n // Check if first line is blank\n prevWasBlank = firstLineStr.length === 0\n } else {\n // Check indentation on current line\n let leadingSpaceCount = 0\n let checkPos = lineStart\n while (\n checkPos < lineEnd &&\n checkPos < lineStart + 4 &&\n source[checkPos] === ' '\n ) {\n leadingSpaceCount++\n checkPos++\n }\n\n // Check if current line is blank\n let lineHasContent = false\n for (let k = lineStart; k < lineEnd; k++) {\n if (source[k] !== ' ' && source[k] !== '\\t' && source[k] !== '\\r') {\n lineHasContent = true\n break\n }\n }\n let currentIsBlank = !lineHasContent\n\n // Process continuation line based on indentation rules\n if (leadingSpaceCount >= 4 && prevWasBlank) {\n // 4+ spaces after a blank line - this is a paragraph, preserve indentation\n processedParts.push(source.slice(lineStart, lineEnd))\n } else if (leadingSpaceCount === 4 && !prevWasBlank) {\n // Exactly 4 spaces without blank line - remove (markdown continuation indentation)\n processedParts.push(source.slice(lineStart + 4, lineEnd))\n } else {\n // Otherwise preserve (less than 4 spaces or more than 4 spaces without blank line)\n processedParts.push(source.slice(lineStart, lineEnd))\n }\n\n // Update prevWasBlank for next iteration\n prevWasBlank = currentIsBlank\n }\n\n // Move to next line\n if (lineEnd < extractEnd && source[lineEnd] === '\\n') {\n processedParts.push('\\n')\n lineStart = lineEnd + 1\n } else {\n lineStart = extractEnd\n }\n lineIndex++\n }\n\n let footnoteContent = processedParts.join('')\n\n // Trim trailing whitespace/newlines but preserve internal structure\n // If we stopped at a blank line, remove the trailing newline from the last line\n if (stoppedAtBlankLine) {\n // Remove trailing newline if present (but preserve newlines between lines)\n footnoteContent = footnoteContent.replace(/\\n$/, '')\n }\n var contentLen = footnoteContent.length\n while (contentLen > 0) {\n var lastChar = footnoteContent[contentLen - 1]\n if (lastChar === '\\n' || lastChar === ' ') {\n contentLen--\n } else {\n break\n }\n }\n if (contentLen < footnoteContent.length) {\n footnoteContent = footnoteContent.slice(0, contentLen)\n }\n\n return {\n endPos: contentEnd,\n target: footnoteContent,\n title: undefined,\n }\n}\n\nexport function parseDefinition(\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions,\n isFootnote: boolean\n): ParseResult | null {\n if (source[pos] !== '[') return null\n var hasCaret = pos + 1 < source.length && source[pos + 1] === '^'\n if (isFootnote ? !hasCaret : hasCaret) return null\n\n var lineStart = pos\n while (lineStart > 0 && source[lineStart - 1] !== '\\n') lineStart--\n if (\n calculateIndent(source, lineStart, pos).spaceEquivalent >= 4 ||\n state.inline\n )\n return null\n\n var labelStart = pos + (isFootnote ? 2 : 1)\n var len = source.length\n var refEnd = findUnescapedChar(source, labelStart, len, ']')\n if (refEnd === -1) return null\n var ref = source.slice(labelStart, refEnd)\n if (ref.length > 999) return null\n\n var hasNonWhitespace = false,\n hasUnescapedBracket = false,\n labelHasNewlines = false\n for (var j = 0; j < ref.length; j++) {\n var c = ref[j]\n if (c === '\\\\' && j + 1 < ref.length) {\n j++\n continue\n }\n var cCode = charCode(c)\n if (cCode === $.CHAR_BRACKET_OPEN || cCode === $.CHAR_BRACKET_CLOSE) {\n hasUnescapedBracket = true\n } else if (cCode === $.CHAR_NEWLINE || cCode === $.CHAR_CR) {\n labelHasNewlines = true\n } else if (cCode !== $.CHAR_SPACE && cCode !== $.CHAR_TAB) {\n hasNonWhitespace = true\n }\n }\n if (!hasNonWhitespace || hasUnescapedBracket) return null\n\n var i = refEnd + 1\n if (labelHasNewlines) {\n var labelStartCode = charCode(source, labelStart)\n var refEndPrevCode = charCode(source, refEnd - 1)\n if (\n labelStartCode === $.CHAR_NEWLINE ||\n labelStartCode === $.CHAR_CR ||\n refEndPrevCode === $.CHAR_NEWLINE ||\n refEndPrevCode === $.CHAR_CR ||\n i >= len ||\n source[i] !== ':'\n )\n return null\n } else {\n if (i >= len || source[i] !== ':') {\n i = util.skipWhitespace(source, i)\n if (i < len && charCode(source, i) === $.CHAR_NEWLINE)\n i = util.skipWhitespace(source, i + 1)\n if (i >= len || source[i] !== ':') return null\n }\n }\n i++\n\n var urlNewlineCount = 0\n while (i < len) {\n var iCode = charCode(source, i)\n if (iCode === $.CHAR_NEWLINE) {\n if (++urlNewlineCount > 1) break\n i = util.skipWhitespace(source, i + 1)\n } else if (iCode === $.CHAR_SPACE || iCode === $.CHAR_TAB) {\n i++\n } else {\n break\n }\n }\n\n const contentResult = isFootnote\n ? parseFootnoteContent(source, i)\n : parseRefContent(source, i, urlNewlineCount)\n if (!contentResult) return null\n\n const normalizedRef = normalizeReferenceLabel(ref)\n const refs = state.refs || {}\n const storageKey = isFootnote ? `^${normalizedRef}` : normalizedRef\n if (!refs[storageKey]) {\n refs[storageKey] = {\n target: unescapeUrlOrTitle(contentResult.target.trim()),\n title: contentResult.title\n ? unescapeUrlOrTitle(contentResult.title)\n : undefined,\n }\n state.refs = refs\n }\n\n return {\n type: isFootnote ? RuleType.footnote : RuleType.ref,\n endPos: contentResult.endPos,\n } as (MarkdownToJSX.ReferenceNode | MarkdownToJSX.FootnoteNode) & {\n endPos: number\n }\n}\n\n// Delimiter stack entry for CommonMark spec delimiter stack algorithm\ninterface DelimiterEntry {\n nodeIndex: number // Index in result array where this delimiter text node is\n type: '*' | '_' | '~' | '='\n length: number // Number of delimiters in the run\n canOpen: boolean // Whether this delimiter can open emphasis\n canClose: boolean // Whether this delimiter can close emphasis\n active: boolean // Whether this delimiter is active\n sourcePos: number // Source position where this delimiter starts (for overlap detection)\n inAnchor: boolean // Whether this delimiter was collected inside a link (should not match with delimiters outside)\n}\n\n// Process emphasis using delimiter stack algorithm per CommonMark spec\nfunction processEmphasis(\n nodes: MarkdownToJSX.ASTNode[],\n delimiterStack: DelimiterEntry[],\n stackBottom: number | null\n): void {\n // openers_bottom for each delimiter type, indexed by numeric key: typeCode * 6 + (length % 3) * 2 + (canOpen ? 1 : 0)\n // Type codes: '*' = 0, '_' = 1, '~' = 2, '=' = 3\n var openersBottom: number[] = []\n\n var currentPosition = stackBottom === null ? 0 : stackBottom + 1\n\n while (currentPosition < delimiterStack.length) {\n var closer = delimiterStack[currentPosition]\n if (\n !closer ||\n (closer.type !== '*' &&\n closer.type !== '_' &&\n closer.type !== '~' &&\n closer.type !== '=')\n ) {\n currentPosition++\n continue\n }\n\n if (!closer.canClose || !closer.active) {\n currentPosition++\n continue\n }\n\n // Convert type to numeric code: '*' = 0, '_' = 1, '~' = 2, '=' = 3\n var typeCode =\n closer.type === '*'\n ? 0\n : closer.type === '_'\n ? 1\n : closer.type === '~'\n ? 2\n : 3\n var openersBottomKey =\n typeCode * 6 + (closer.length % 3) * 2 + (closer.canOpen ? 1 : 0)\n var openersBottomIndex =\n openersBottom[openersBottomKey] !== undefined\n ? openersBottom[openersBottomKey]\n : stackBottom === null\n ? -1\n : stackBottom\n\n var openerIndex = -1\n var closerType = closer.type\n var closerInAnchor = closer.inAnchor\n var closerCanOpen = closer.canOpen\n var closerLength = closer.length\n var closerLengthMod3 = closerLength % 3\n\n for (var i = currentPosition - 1; i > openersBottomIndex; i--) {\n var candidate = delimiterStack[i]\n if (\n !candidate ||\n !candidate.active ||\n candidate.type !== closerType ||\n !candidate.canOpen ||\n candidate.inAnchor !== closerInAnchor\n )\n continue\n var openerLength = candidate.length\n if (\n (!closerCanOpen && !candidate.canClose) ||\n closerLengthMod3 === 0 ||\n (openerLength + closerLength) % 3 !== 0\n ) {\n openerIndex = i\n break\n }\n }\n\n if (openerIndex >= 0) {\n var opener = delimiterStack[openerIndex]\n var openerLength = opener.length\n\n // Determine if emphasis or strong emphasis (both must have length >= 2 for strong)\n var isStrong = openerLength >= 2 && closerLength >= 2\n var delimitersToRemove = isStrong ? 2 : 1\n if (\n delimitersToRemove > openerLength ||\n delimitersToRemove > closerLength\n ) {\n currentPosition++\n continue\n }\n\n var openerNodeIndex = opener.nodeIndex\n var closerNodeIndex = closer.nodeIndex\n var contentStartIndex = openerNodeIndex + 1\n var contentEndIndex = closerNodeIndex\n var contentNodes = nodes.slice(contentStartIndex, contentEndIndex)\n\n // Remove content nodes from nodes array (they'll be in the emphasis node)\n if (contentNodes.length > 0) {\n var nodesRemoved = contentEndIndex - contentStartIndex\n nodes.splice(contentStartIndex, nodesRemoved)\n for (var k = 0; k < delimiterStack.length; k++) {\n if (delimiterStack[k].nodeIndex > contentStartIndex)\n delimiterStack[k].nodeIndex -= nodesRemoved\n }\n if (closerNodeIndex > contentStartIndex) closerNodeIndex -= nodesRemoved\n }\n\n var emphasisTag =\n opener.type === '~'\n ? 'del'\n : opener.type === '='\n ? 'mark'\n : isStrong\n ? 'strong'\n : 'em'\n var emphasisNode: MarkdownToJSX.FormattedTextNode = {\n type: RuleType.textFormatted,\n tag: emphasisTag,\n children: contentNodes,\n }\n\n var openerNode = nodes[openerNodeIndex] as MarkdownToJSX.TextNode\n if (!openerNode || !openerNode.text) {\n opener.active = closer.active = false\n continue\n }\n\n // Remove delimiters from opener text node\n var openerRemoved = openerNode.text.length <= delimitersToRemove\n if (openerRemoved) {\n nodes.splice(openerNodeIndex, 1)\n for (var k = 0; k < delimiterStack.length; k++) {\n if (delimiterStack[k].nodeIndex > openerNodeIndex)\n delimiterStack[k].nodeIndex--\n }\n if (closerNodeIndex > openerNodeIndex) closerNodeIndex--\n } else {\n openerNode.text = openerNode.text.slice(delimitersToRemove)\n }\n\n var closerNode = nodes[closerNodeIndex] as MarkdownToJSX.TextNode\n if (!closerNode || !closerNode.text) {\n opener.active = closer.active = false\n continue\n }\n var closerRemoved = closerNode.text.length <= delimitersToRemove\n if (closerRemoved) {\n nodes.splice(closerNodeIndex, 1)\n for (var k = 0; k < delimiterStack.length; k++) {\n if (delimiterStack[k].nodeIndex > closerNodeIndex)\n delimiterStack[k].nodeIndex--\n }\n } else {\n closerNode.text = closerNode.text.slice(delimitersToRemove)\n }\n\n // Insert emphasis node after opener (or at the position where opener was)\n var insertIndex = openerRemoved\n ? openerNodeIndex < closerNodeIndex\n ? closerNodeIndex - 1\n : openerNodeIndex\n : openerNodeIndex + 1\n if (insertIndex < 0 || insertIndex > nodes.length)\n insertIndex = insertIndex < 0 ? 0 : nodes.length\n nodes.splice(insertIndex, 0, emphasisNode)\n\n // Update node indices in delimiter stack after insertion\n for (var k = 0; k < delimiterStack.length; k++) {\n if (delimiterStack[k].nodeIndex >= insertIndex) {\n delimiterStack[k].nodeIndex++\n }\n }\n\n // Remove delimiters between opener and closer from stack\n for (var k = openerIndex + 1; k < currentPosition; k++) {\n delimiterStack[k].active = false\n }\n\n // Update opener and closer in stack\n if (openerRemoved) {\n opener.active = false\n } else {\n opener.length -= delimitersToRemove\n if (opener.length === 0) opener.active = false\n }\n\n if (closerRemoved) {\n closer.active = false\n currentPosition++\n } else {\n closer.length -= delimitersToRemove\n if (closer.length === 0) {\n closer.active = false\n currentPosition++\n }\n }\n } else {\n // No opener found\n openersBottom[openersBottomKey] = currentPosition - 1\n if (!closer.canOpen) {\n closer.active = false\n }\n currentPosition++\n }\n }\n\n // Remove inactive delimiters from stack (O(n) shift algorithm instead of O(n²) splice)\n var writeIndex = 0\n for (var i = 0; i < delimiterStack.length; i++) {\n if (delimiterStack[i].active) {\n delimiterStack[writeIndex++] = delimiterStack[i]\n }\n }\n delimiterStack.length = writeIndex\n}\n\nexport function parseMarkdown(\n input: string,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): MarkdownToJSX.ASTNode[] {\n var result: MarkdownToJSX.ASTNode[] = []\n var pos = 0\n var REF_CHECK_UNSET = -3\n var cachedRefCheckPos = REF_CHECK_UNSET\n\n // If inline mode, just parse the entire input as inline content\n if (state.inline)\n return parseInlineSpan(input, 0, input.length, state, options)\n\n // Block parsing mode\n\n // Check for frontmatter at the beginning (skip if doesn't start with ---)\n if (pos === 0 && input.startsWith('---')) {\n var frontmatterResult = parseFrontmatter(input, pos)\n if (frontmatterResult) {\n result.push(frontmatterResult)\n pos = frontmatterResult.endPos\n }\n }\n\n while (pos < input.length) {\n // Skip leading newlines (but preserve whitespace for indented code blocks)\n while (pos < input.length && input[pos] === '\\n') {\n pos++\n }\n\n if (pos >= input.length) break\n cachedRefCheckPos = REF_CHECK_UNSET\n\n const char = input[pos]\n\n // Try parseBlock first (handles indentation and tries all block parsers)\n // Note: Individual parsers called by parseBlock track their own attempts\n const parseResult = parseBlock(input, pos, state, options)\n if (parseResult) {\n const t = parseResult.type\n if (t === RuleType.codeBlock) {\n var isFenced = char === '`' || char === '~'\n if (!isFenced && (char === ' ' || char === '\\t')) {\n const lineEnd = util.findLineEnd(input, pos)\n const indentInfo = calculateIndent(input, pos, lineEnd)\n isFenced =\n indentInfo.spaceEquivalent <= 3 &&\n pos + indentInfo.charCount < input.length &&\n (input[pos + indentInfo.charCount] === '`' ||\n input[pos + indentInfo.charCount] === '~')\n }\n } else if (t === RuleType.breakThematic) {} else if (t === RuleType.blockQuote) {} else if (t === RuleType.heading) {} else if (t === RuleType.orderedList || t === RuleType.unorderedList) {} else if (t === RuleType.table) {} else if (t === RuleType.htmlComment) {} else if (t === RuleType.htmlBlock) {} else if (t === RuleType.ref) {}\n\n // Special handling for HTML comments with trailing content\n if (parseResult.type === RuleType.htmlComment) {\n result.push(parseResult)\n const htmlCheckPos = pos\n pos = parseResult.endPos\n\n // Per CommonMark spec Example 177: HTML comment blocks end at --> on the same line\n // If there's content after --> on the same line, it should be treated as literal text\n const commentLineEnd = util.findLineEnd(input, htmlCheckPos)\n if (pos < commentLineEnd) {\n const textContent = input.slice(pos, commentLineEnd)\n if (textContent.trim().length > 0) {\n result.push({\n type: RuleType.text,\n text: textContent,\n } as MarkdownToJSX.TextNode)\n }\n pos = commentLineEnd\n if (pos < input.length && input[pos] === '\\n') {\n pos++\n }\n }\n continue\n }\n // Special handling for HTML self-closing closing tags\n if (\n parseResult.type === RuleType.htmlBlock ||\n parseResult.type === RuleType.htmlSelfClosing\n ) {\n const isSelfClosingClosingTag =\n parseResult.type === RuleType.htmlSelfClosing &&\n parseResult.isClosingTag === true\n if (isSelfClosingClosingTag && !state.inline && !state.inHTML) {\n // Don't match, fall through to other parsers\n } else {\n result.push(parseResult)\n pos = parseResult.endPos\n continue\n }\n } else {\n result.push(parseResult)\n pos = parseResult.endPos\n continue\n }\n }\n\n // Reference definition - check BEFORE setext heading to prevent conflicts\n // Reference definitions take precedence over setext headings (e.g., [foo]: /url\\n===)\n let refCheckPos =\n cachedRefCheckPos !== REF_CHECK_UNSET ? cachedRefCheckPos : pos\n if (cachedRefCheckPos === REF_CHECK_UNSET) {\n if (isSpaceOrTab(char)) {\n const lineEnd = util.findLineEnd(input, pos)\n const indentInfo = calculateIndent(input, pos, lineEnd)\n const checkPos = pos + indentInfo.charCount\n if (\n indentInfo.spaceEquivalent <= 3 &&\n checkPos < input.length &&\n input[checkPos] === '['\n ) {\n refCheckPos = checkPos\n } else {\n refCheckPos = -1\n }\n } else if (char === '[') {\n refCheckPos = pos\n } else {\n refCheckPos = -1\n }\n cachedRefCheckPos = refCheckPos\n }\n\n if (\n refCheckPos >= 0 &&\n refCheckPos + 1 < input.length &&\n input[refCheckPos + 1] === '^'\n ) {\n refCheckPos = -1\n }\n\n if (refCheckPos >= 0) {\n const parseResult = parseDefinition(\n input,\n refCheckPos,\n state,\n options,\n false\n )\n if (parseResult) {\n result.push(parseResult)\n pos = parseResult.endPos\n continue\n }\n // parseDefinition returned null - check if this is an invalid reference definition that should be skipped\n // Per CommonMark Examples 208 and 210: certain invalid reference definitions should be skipped entirely\n const skipResult = shouldSkipInvalidReferenceDefinition(\n input,\n refCheckPos,\n pos === 0\n )\n if (skipResult.shouldSkip) {\n pos = skipResult.newPos\n continue\n }\n }\n\n // Heading (Setext style) - check after reference definitions\n const setextResult = parseHeadingSetext(input, pos, state, options)\n if (setextResult) {\n result.push(setextResult)\n pos = setextResult.endPos\n continue\n }\n\n // Footnote definition (skip leading whitespace)\n let footnoteCheckPos = pos\n if (isSpaceOrTab(input[footnoteCheckPos])) {\n const lineEnd = util.findLineEnd(input, pos)\n const indentInfo = calculateIndent(input, pos, lineEnd)\n footnoteCheckPos = pos + indentInfo.charCount\n }\n if (\n footnoteCheckPos < input.length &&\n input[footnoteCheckPos] === '[' &&\n footnoteCheckPos + 1 < input.length &&\n input[footnoteCheckPos + 1] === '^'\n ) {\n const footnoteResult = parseDefinition(\n input,\n footnoteCheckPos,\n state,\n options,\n true\n )\n if (footnoteResult) {\n pos = footnoteResult.endPos\n continue\n }\n }\n\n const paragraphResult = parseParagraph(input, pos, state, options)\n if (paragraphResult) {\n result.push(paragraphResult)\n pos = paragraphResult.endPos\n continue\n }\n\n pos++\n }\n\n // Note: Memory snapshot \"After block parsing\" is taken in compiler function\n // after parseMarkdown returns, not here\n\n // Footnotes footer is appended during rendering phase (not in AST)\n // Footnotes are stored in refs with '^' prefix and extracted during rendering\n\n // Collect all refs from state.refs (populated during parsing) and create a reference collection node\n // Reference nodes stay in their original positions, but we prepend a collection node\n // Include footnotes (keys starting with '^') so the renderer can handle them\n const allRefs = state.refs || {}\n const collectedRefs: {\n [key: string]: { target: string; title: string | undefined }\n } = {}\n for (const key in allRefs) {\n collectedRefs[key] = allRefs[key]\n }\n\n // Prepend reference collection node if we have any refs\n if (util.hasKeys(collectedRefs)) {\n const refCollectionNode: MarkdownToJSX.ReferenceCollectionNode = {\n type: RuleType.refCollection,\n refs: collectedRefs,\n }\n return [refCollectionNode, ...result]\n }\n\n return result\n}\n\n/**\n * Collect reference definitions from markdown input and populate the refs object.\n * This function scans the markdown for reference-style link and image definitions.\n *\n * @param input - The markdown string to scan\n * @param refs - Object to populate with reference definitions\n * @param options - Parser options\n */\nexport function collectReferenceDefinitions(\n input: string,\n refs: { [key: string]: { target: string; title: string | undefined } },\n options: ParseOptions\n): void {\n var pos = 0\n var canStartRef = true\n const len = input.length\n\n while (pos < len) {\n var newlines = 0\n // Count consecutive newlines more efficiently\n while (pos < len && charCode(input, pos) === $.CHAR_NEWLINE) {\n newlines++\n pos++\n }\n if (pos >= len) break\n if (newlines > 0) canStartRef = true\n\n // Skip fenced code\n const currentCharCode = charCode(input, pos)\n if (\n currentCharCode === $.CHAR_BACKTICK ||\n currentCharCode === $.CHAR_TILDE\n ) {\n var fence = parseCodeFenced(input, pos, { inline: false }, options)\n if (fence) {\n pos = fence.endPos\n canStartRef = true\n continue\n }\n }\n\n // Try parse ref (up to 3 space indent)\n var refPos = pos\n var indent = 0\n while (refPos < len && indent < 4) {\n const code = charCode(input, refPos)\n if (code === $.CHAR_SPACE) {\n indent++\n refPos++\n } else if (code === $.CHAR_TAB) {\n indent += 4 - (indent % 4)\n refPos++\n } else {\n break\n }\n }\n\n if (\n indent < 4 &&\n refPos < len &&\n charCode(input, refPos) === $.CHAR_BRACKET_OPEN &&\n canStartRef\n ) {\n if (refPos + 1 < len && charCode(input, refPos + 1) === $.CHAR_CARET) {\n canStartRef = false\n var lineEnd = util.findLineEnd(input, pos)\n pos = lineEnd >= len ? len : lineEnd + 1\n continue\n } else {\n var result = parseDefinition(\n input,\n refPos,\n { inline: false, refs },\n options,\n false\n )\n if (result) {\n pos = result.endPos\n canStartRef = true\n continue\n }\n // parseDefinition returned null - check if colon exists (invalid ref attempt) vs paragraph content\n var lineEnd = util.findLineEnd(input, pos)\n var colonPos = input.indexOf(':', refPos + 1)\n if (colonPos === -1 || colonPos >= lineEnd) {\n var indentInfo = calculateIndent(input, pos, lineEnd)\n if (\n !isBlankLineCheck(input, pos, lineEnd) &&\n currentCharCode !== $.CHAR_HASH &&\n currentCharCode !== $.CHAR_GT &&\n currentCharCode !== $.CHAR_DASH &&\n currentCharCode !== $.CHAR_EQ &&\n indentInfo.spaceEquivalent < 4\n ) {\n canStartRef = false\n }\n }\n pos = lineEnd >= len ? len : lineEnd + 1\n continue\n }\n }\n\n // Scan blockquotes for nested refs\n if (currentCharCode === $.CHAR_GT && canStartRef) {\n var bqEnd = pos\n var bqLines = []\n while (bqEnd < len) {\n var lineEnd = util.findLineEnd(input, bqEnd)\n var quotePos = bqEnd\n while (quotePos < lineEnd) {\n const code = charCode(input, quotePos)\n if (code === $.CHAR_SPACE || code === $.CHAR_TAB) {\n quotePos++\n } else {\n break\n }\n }\n if (quotePos >= lineEnd || charCode(input, quotePos) !== $.CHAR_GT)\n break\n\n var contentStart = quotePos + 1\n if (\n contentStart < lineEnd &&\n (charCode(input, contentStart) === $.CHAR_SPACE ||\n charCode(input, contentStart) === $.CHAR_TAB)\n )\n contentStart++\n bqLines.push(input.slice(contentStart, lineEnd))\n bqEnd = lineEnd + 1\n }\n if (bqLines.length) {\n collectReferenceDefinitions(bqLines.join('\\n'), refs, options)\n pos = bqEnd\n canStartRef = true\n continue\n }\n }\n\n var lineEnd = util.findLineEnd(input, pos)\n if (lineEnd >= len) {\n pos = len\n } else {\n var isCurrentLineBlank = isBlankLineCheck(input, pos, lineEnd)\n var indentInfo = calculateIndent(input, pos, lineEnd)\n pos = lineEnd + 1\n canStartRef =\n currentCharCode === $.CHAR_HASH ||\n currentCharCode === $.CHAR_GT ||\n currentCharCode === $.CHAR_DASH ||\n currentCharCode === $.CHAR_EQ ||\n isCurrentLineBlank ||\n indentInfo.spaceEquivalent >= 4\n }\n }\n}\n\n/**\n * Given a markdown string, return an abstract syntax tree (AST) of the markdown.\n *\n * The first node in the AST is a reference collection node. This node contains all the\n * reference definitions found in the markdown. These reference definitions are used to\n * resolve reference links and images in the markdown.\n *\n * @lang zh 给定一个 Markdown 字符串,返回 Markdown 的抽象语法树 (AST)。\n *\n * AST 中的第一个节点是引用集合节点。此节点包含在 Markdown 中找到的所有引用定义。这些引用定义用于解析 Markdown 中的引用链接和图像。\n * @lang hi एक Markdown स्ट्रिंग दी गई है, Markdown का अमूर्त सिंटैक्स ट्री (AST) लौटाता है।\n *\n * AST में पहला नोड संदर्भ संग्रह नोड है। यह नोड Markdown में पाई गई सभी संदर्भ परिभाषाएं शामिल करता है। ये संदर्भ परिभाषाएं Markdown में संदर्भ लिंक्स और छवियों को पार्स करने के लिए उपयोग की जाती हैं।\n *\n * @param source - The markdown string to parse.\n * @lang zh @param source - 要解析的 Markdown 字符串。\n * @lang hi @param source - पार्स करने के लिए Markdown स्ट्रिंग।\n * @param options - The options for the parser.\n * @lang zh @param options - 解析器的选项。\n * @lang hi @param options - पार्सर के लिए विकल्प।\n * @returns The AST of the markdown.\n * @lang zh @returns Markdown 的 AST。\n * @lang hi @returns Markdown का AST।\n */\nexport function parser(\n source: string,\n options?: MarkdownToJSX.Options\n): MarkdownToJSX.ASTNode[] {\n // Default state\n const defaultState: MarkdownToJSX.State = { inline: false, refs: {} }\n const finalState = { ...defaultState }\n\n // Normalize options - convert MarkdownToJSX.Options to ParseOptions\n const finalOptions: ParseOptions = {\n ...options,\n slugify: options?.slugify\n ? (input: string) => options.slugify(input, util.slugify)\n : util.slugify,\n sanitizer: options?.sanitizer || util.sanitizer,\n tagfilter: options?.tagfilter !== false,\n }\n\n // Collect reference definitions if not in inline mode\n if (!finalState.inline) {\n collectReferenceDefinitions(source, finalState.refs || {}, finalOptions)\n }\n\n // Parse markdown\n const astNodes = parseMarkdown(source, finalState, finalOptions)\n\n return astNodes\n}\n",
|
|
7
|
+
"import { NAMED_CODES_TO_UNICODE as util, decodeEntity } from '#entities'\nimport * as $ from './constants'\n\n/**\n * Parse frontmatter bounds and validate YAML\n *\n * @param input - Input string to parse\n * @returns Object with end position and YAML validity, or null if no frontmatter\n */\nexport function parseFrontmatterBounds(\n input: string\n): { endPos: number; hasValidYaml: boolean } | null {\n if (!startsWith(input, '---')) return null\n let pos = 3\n while (pos < input.length && (input[pos] === ' ' || input[pos] === '\\t'))\n pos++\n // Handle both LF and CRLF line endings\n if (pos < input.length && input[pos] === '\\r') pos++\n if (pos >= input.length || input[pos] !== '\\n') return null\n pos++\n\n let hasValidYaml = false\n while (pos < input.length) {\n const lineStart = pos\n // Find line end, handling CRLF\n while (pos < input.length && input[pos] !== '\\n' && input[pos] !== '\\r')\n pos++\n if (pos >= input.length) break\n const lineEnd = pos\n // Skip CR if present\n if (input[pos] === '\\r') pos++\n // Skip LF\n if (pos < input.length && input[pos] === '\\n') pos++\n if (startsWith(input, '---', lineStart))\n return { endPos: pos, hasValidYaml }\n // Check if line contains ':' anywhere\n // OPTIMIZATION: Use indexOf directly to avoid slice allocation\n const colonIndex = input.indexOf(':', lineStart)\n if (colonIndex !== -1 && colonIndex < lineEnd) hasValidYaml = true\n }\n return null\n}\n\n/**\n * Named HTML entity codes to unicode character mapping\n * Pre-computed from generated entity set\n * Numeric references ({ and «) are fully supported without any mapping.\n * Unknown named entities pass through as literal text (CommonMark-compliant).\n * @lang zh 命名的 HTML 实体代码到 Unicode 字符的映射\n * 从生成的实体集预计算\n * 数字引用({ 和 «)完全支持,无需映射。\n * 未知的命名实体作为字面文本传递(符合 CommonMark)。\n * @lang hi नामित HTML एंटिटी कोड से Unicode वर्णों का मैपिंग\n * जेनरेट किए गए एंटिटी सेट से पूर्व-गणना की गई\n * संख्यात्मक संदर्भ ({ और «) बिना किसी मैपिंग के पूरी तरह से समर्थित हैं।\n * अज्ञात नामित एंटिटीज़ शाब्दिक टेक्स्ट के रूप में पास होती हैं (CommonMark-अनुरूप)।\n */\nexport const NAMED_CODES_TO_UNICODE: Record<string, string> = util\n\n/**\n * Regex for matching HTML character references (&entity; or { or «)\n * Matches: & followed by entity name or # followed by decimal or hex digits, ending with ;\n * @lang zh 用于匹配 HTML 字符引用的正则表达式(&entity; 或 { 或 «)\n * 匹配:& 后跟实体名称或 # 后跟十进制或十六进制数字,以 ; 结尾\n * @lang hi HTML वर्ण संदर्भों से मिलान करने के लिए रेगेक्स (&entity; या { या «)\n * मैच: & के बाद एंटिटी नाम या # के बाद दशमलव या हेक्स अंक, ; के साथ समाप्त होता है\n */\nexport const HTML_CHAR_CODE_R: RegExp =\n /&([a-zA-Z0-9]+|#[0-9]{1,7}|#x[0-9a-fA-F]{1,6});/gi\n\n/**\n * Regex for determining if markdown content should be rendered as block-level\n * Matches: newlines, list items, headings, indented content, thematic breaks, blockquotes\n * @lang zh 用于确定 Markdown 内容是否应渲染为块级的正则表达式\n * 匹配:换行符、列表项、标题、缩进内容、分隔线、引用块\n * @lang hi यह निर्धारित करने के लिए रेगेक्स कि markdown सामग्री को ब्लॉक-स्तरीय के रूप में रेंडर किया जाना चाहिए\n * मैच: नई लाइनें, सूची आइटम्स, हेडिंग्स, इंडेंटेड सामग्री, थीमैटिक ब्रेक्स, ब्लॉककोट्स\n */\n// Mapping of lowercase HTML attributes to JSX prop names\n// Shared between React and Solid renderers (Vue uses HTML attributes directly)\nexport const HTML_TO_JSX_MAP: Record<string, string> = {\n class: 'className',\n for: 'htmlFor',\n allowfullscreen: 'allowFullScreen',\n allowtransparency: 'allowTransparency',\n autocomplete: 'autoComplete',\n autofocus: 'autoFocus',\n autoplay: 'autoPlay',\n cellpadding: 'cellPadding',\n cellspacing: 'cellSpacing',\n charset: 'charSet',\n classid: 'classId',\n colspan: 'colSpan',\n contenteditable: 'contentEditable',\n contextmenu: 'contextMenu',\n crossorigin: 'crossOrigin',\n enctype: 'encType',\n formaction: 'formAction',\n formenctype: 'formEncType',\n formmethod: 'formMethod',\n formnovalidate: 'formNoValidate',\n formtarget: 'formTarget',\n frameborder: 'frameBorder',\n hreflang: 'hrefLang',\n inputmode: 'inputMode',\n keyparams: 'keyParams',\n keytype: 'keyType',\n marginheight: 'marginHeight',\n marginwidth: 'marginWidth',\n maxlength: 'maxLength',\n mediagroup: 'mediaGroup',\n minlength: 'minLength',\n novalidate: 'noValidate',\n radiogroup: 'radioGroup',\n readonly: 'readOnly',\n rowspan: 'rowSpan',\n spellcheck: 'spellCheck',\n srcdoc: 'srcDoc',\n srclang: 'srcLang',\n srcset: 'srcSet',\n tabindex: 'tabIndex',\n usemap: 'useMap',\n}\n\n/**\n * Convert HTML attributes to JSX props\n * Maps HTML attribute names (e.g., \"class\", \"for\") to JSX prop names (e.g., \"className\", \"htmlFor\")\n *\n * @param attrs - HTML attributes object\n * @returns JSX props object\n */\nexport function htmlAttrsToJSXProps(\n attrs: Record<string, any>\n): Record<string, any> {\n var jsxProps: Record<string, any> = {}\n\n for (var key in attrs) {\n var keyLower = key.toLowerCase()\n var mappedKey = HTML_TO_JSX_MAP[keyLower]\n jsxProps[mappedKey || key] = attrs[key]\n }\n\n return jsxProps\n}\n\nexport const SHOULD_RENDER_AS_BLOCK_R: RegExp =\n /(\\n|^[-*]\\s|^#|^ {2,}|^-{2,}|^>\\s)/\n\n/**\n * Decode HTML entity references to Unicode characters\n *\n * @param text - The text containing HTML entities\n * @returns The decoded text\n */\nexport function decodeEntityReferences(text: string): string {\n if (text.indexOf('&') === -1) return text\n\n return text.replace(HTML_CHAR_CODE_R, (full, inner) => {\n // Named entity lookup via swappable decoder\n // In browser builds, this uses DOM; in Node, uses lookup table\n var entity = decodeEntity(inner)\n if (entity) return entity\n\n // Numeric entities (always computed, no lookup needed)\n if (inner[0] === '#') {\n var code =\n inner[1] === 'x' || inner[1] === 'X'\n ? parseInt(inner.slice(2), 16)\n : parseInt(inner.slice(1), 10)\n\n if (code === 0 || (code >= 0xd800 && code <= 0xdfff) || code > 0x10ffff) {\n return '\\uFFFD'\n }\n return code <= 0xffff\n ? String.fromCharCode(code)\n : String.fromCharCode(\n 0xd800 + ((code - 0x10000) >> 10),\n 0xdc00 + ((code - 0x10000) & 0x3ff)\n )\n }\n\n return full\n })\n}\n\nexport const SANITIZE_R: RegExp = /(javascript|vbscript|data(?!:image)):/i\n\n/**\n * Sanitize URLs and other input values to prevent XSS attacks.\n * Filters out javascript:, vbscript:, and data: URLs (except data:image).\n *\n * @lang zh 清理 URL 和其他输入值以防止 XSS 攻击。过滤掉 javascript:、vbscript: 和 data: URL(data:image 除外)。\n * @lang hi XSS हमलों को रोकने के लिए URLs और अन्य इनपुट मानों को सैनिटाइज़ करता है। javascript:, vbscript:, और data: URLs को फ़िल्टर करता है (data:image को छोड़कर)।\n *\n * @param input - The URL or value to sanitize\n * @lang zh @param input - 要清理的 URL 或值\n * @lang hi @param input - सैनिटाइज़ करने के लिए URL या मान\n * @returns Sanitized value, or null if unsafe\n * @lang zh @returns 清理后的值,如果不安全则返回 null\n * @lang hi @returns सैनिटाइज़ किया गया मान, या असुरक्षित होने पर null\n */\nexport function sanitizer(input: string): string | null {\n if (SANITIZE_R.test(input)) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n 'Input contains an unsafe JavaScript/VBScript/data expression, it will not be rendered.',\n input\n )\n }\n return null\n }\n\n if (input.indexOf('%') === -1) return input\n\n try {\n const decoded = decodeURIComponent(input).replace(/[^A-Za-z0-9/:]/g, '')\n if (SANITIZE_R.test(decoded)) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n 'Input contains an unsafe JavaScript/VBScript/data expression, it will not be rendered.',\n decoded\n )\n }\n return null\n }\n } catch (e) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n 'Input could not be decoded due to malformed syntax or characters, it will not be rendered.',\n input\n )\n }\n return null\n }\n\n return input\n}\n\n// Character replacement lookup table for slugify (Unicode to ASCII)\nvar slugifyReplaceTable: Record<number, string> = {}\nvar codes: number[], i: number\ncodes = [192, 193, 194, 195, 196, 197, 224, 225, 226, 227, 228, 229, 230, 198]\nfor (i = 0; i < codes.length; i++) slugifyReplaceTable[codes[i]] = 'a'\nslugifyReplaceTable[231] = slugifyReplaceTable[199] = 'c'\nslugifyReplaceTable[240] = slugifyReplaceTable[208] = 'd'\ncodes = [200, 201, 202, 203, 233, 232, 234, 235]\nfor (i = 0; i < codes.length; i++) slugifyReplaceTable[codes[i]] = 'e'\ncodes = [207, 239, 206, 238, 205, 237, 204, 236]\nfor (i = 0; i < codes.length; i++) slugifyReplaceTable[codes[i]] = 'i'\nslugifyReplaceTable[209] = slugifyReplaceTable[241] = 'n'\ncodes = [248, 216, 339, 338, 213, 245, 212, 244, 211, 243, 210, 242]\nfor (i = 0; i < codes.length; i++) slugifyReplaceTable[codes[i]] = 'o'\ncodes = [220, 252, 219, 251, 218, 250, 217, 249]\nfor (i = 0; i < codes.length; i++) slugifyReplaceTable[codes[i]] = 'u'\nslugifyReplaceTable[376] =\n slugifyReplaceTable[255] =\n slugifyReplaceTable[221] =\n slugifyReplaceTable[253] =\n 'y'\n\n/**\n * Check if a character code is alphanumeric (0-9, A-Z, a-z)\n *\n * @param code - Character code to check\n * @returns True if alphanumeric\n */\nexport function isAlnumCode(code: number): boolean {\n return (\n (code >= $.CHAR_DIGIT_0 && code <= $.CHAR_DIGIT_9) ||\n (code >= $.CHAR_A && code <= $.CHAR_Z) ||\n (code >= $.CHAR_a && code <= $.CHAR_z)\n )\n}\n\n/**\n * Convert a string to a URL-safe slug by normalizing characters and replacing spaces with hyphens.\n * Based on https://stackoverflow.com/a/18123682/1141611\n * Not complete, but probably good enough.\n *\n * @lang zh 通过规范化字符并用连字符替换空格,将字符串转换为 URL 安全的别名。不完整,但可能足够好。\n * @lang hi वर्णों को सामान्यीकृत करके और रिक्त स्थान को हाइफ़न से बदलकर स्ट्रिंग को URL-सुरक्षित slug में बदलता है। पूर्ण नहीं है, लेकिन शायद पर्याप्त है।\n *\n * @param str - String to slugify\n * @lang zh @param str - 要转换为别名的字符串\n * @lang hi @param str - slugify करने के लिए स्ट्रिंग\n * @returns URL-safe slug\n * @lang zh @returns URL 安全的别名\n * @lang hi @returns URL-सुरक्षित slug\n */\nexport function slugify(str: string): string {\n var parts: string[] = []\n for (var i = 0; i < str.length; i++) {\n var code = str.charCodeAt(i)\n if (isAlnumCode(code)) {\n if (code >= $.CHAR_A && code <= $.CHAR_Z) {\n parts.push(String.fromCharCode(code + $.CHAR_CASE_OFFSET))\n } else {\n parts.push(str[i])\n }\n } else if (code === $.CHAR_SPACE || code === $.CHAR_DASH) {\n parts.push('-')\n } else {\n var replacement = slugifyReplaceTable[code]\n if (replacement) parts.push(replacement)\n }\n }\n return parts.join('')\n}\n\n/**\n * Check if a string includes a substring\n *\n * @param str - String to search in\n * @param search - Substring to search for\n * @returns True if substring is found\n */\nexport function includes(str: string, search: string): boolean {\n return str.indexOf(search) !== -1\n}\n\n/**\n * Check if a string starts with a prefix\n *\n * @param str - String to check\n * @param prefix - Prefix to check for\n * @param pos - Optional starting position\n * @returns True if string starts with prefix\n */\nexport function startsWith(str: string, prefix: string, pos?: number): boolean {\n return str.startsWith(prefix, pos)\n}\n\n/**\n * Check if a string ends with a suffix\n *\n * @param str - String to check\n * @param suffix - Suffix to check for\n * @param pos - Optional ending position\n * @returns True if string ends with suffix\n */\nexport function endsWith(str: string, suffix: string, pos?: number): boolean {\n return str.startsWith(\n suffix,\n (pos === undefined ? str.length : pos) - suffix.length\n )\n}\n\n// Known void elements (HTML5 and SVG) that don't require closing tag or />\n// Use Set for O(1) lookups instead of O(n) array.includes()\nexport const VOID_ELEMENTS: Set<string> = new Set([\n // HTML5 void elements\n 'area',\n 'base',\n 'br',\n 'col',\n 'embed',\n 'hr',\n 'img',\n 'input',\n 'link',\n 'meta',\n 'param',\n 'source',\n 'track',\n 'wbr',\n // SVG void elements\n 'circle',\n 'ellipse',\n 'line',\n 'path',\n 'polygon',\n 'polyline',\n 'rect',\n 'use',\n 'stop',\n 'animate',\n 'animateTransform',\n 'set',\n])\n\n/**\n * Check if an element is a void element (doesn't require closing tag)\n *\n * @param tagName - HTML tag name\n * @returns True if void element\n */\nexport function isVoidElement(tagName: string): boolean {\n let lowerTag = tagName.toLowerCase()\n if (VOID_ELEMENTS.has(lowerTag)) return true\n // Handle SVG namespace prefixes like svg:circle\n const colonIndex = lowerTag.indexOf(':')\n if (colonIndex !== -1) {\n lowerTag = lowerTag.slice(colonIndex + 1)\n return VOID_ELEMENTS.has(lowerTag)\n }\n return false\n}\n\n/** Attributes that should be sanitized for security */\nexport const ATTRIBUTES_TO_SANITIZE: readonly string[] = [\n 'src',\n 'href',\n 'data',\n 'formAction',\n 'srcDoc',\n 'action',\n]\n\n// Character classification flags (bitfield)\nconst CHAR_WHITESPACE = 1\nconst CHAR_PUNCTUATION = 2\n\n// Inline character type constants\n// const INLINE_CHAR_TYPE_NORMAL = 0\nconst INLINE_CHAR_TYPE_SPECIAL = 1\nconst INLINE_CHAR_TYPE_ESCAPE = 2\nconst INLINE_CHAR_TYPE_DELIMITER = 3\nconst INLINE_CHAR_TYPE_LINK = 4\n\n// Lookup table for ASCII characters (0-127)\nexport const charClassTable: Uint8Array = (function () {\n const t = new Uint8Array(128)\n let i\n t[$.CHAR_TAB] =\n t[$.CHAR_NEWLINE] =\n t[$.CHAR_FF] =\n t[$.CHAR_CR] =\n t[$.CHAR_SPACE] =\n CHAR_WHITESPACE\n for (i = $.CHAR_EXCLAMATION; i <= $.CHAR_SLASH; i++) t[i] = CHAR_PUNCTUATION\n for (i = $.CHAR_COLON; i <= $.CHAR_AT; i++) t[i] = CHAR_PUNCTUATION\n for (i = $.CHAR_BRACKET_OPEN; i <= $.CHAR_BACKTICK; i++)\n t[i] = CHAR_PUNCTUATION\n for (i = $.CHAR_BRACE_OPEN; i <= $.CHAR_TILDE; i++) t[i] = CHAR_PUNCTUATION\n return t\n})()\n\n// Lookup table for inline character types (0-127): 0=normal, 1=special, 2=escape, 3=delimiter, 4=link\nexport const inlineCharTypeTable: Uint8Array = (function () {\n const t = new Uint8Array(128)\n t[$.CHAR_BACKSLASH] = INLINE_CHAR_TYPE_ESCAPE\n t[$.CHAR_BRACKET_OPEN] = INLINE_CHAR_TYPE_LINK\n t[$.CHAR_ASTERISK] =\n t[$.CHAR_UNDERSCORE] =\n t[$.CHAR_TILDE] =\n t[$.CHAR_EQ] =\n INLINE_CHAR_TYPE_DELIMITER\n t[$.CHAR_BACKTICK] =\n t[$.CHAR_LT] =\n t[$.CHAR_AT] =\n t[$.CHAR_BRACKET_CLOSE] =\n t[$.CHAR_NEWLINE] =\n t[$.CHAR_SPACE] =\n t[$.CHAR_EXCLAMATION] =\n INLINE_CHAR_TYPE_SPECIAL\n t[$.CHAR_f] = t[$.CHAR_H] = t[$.CHAR_W] = INLINE_CHAR_TYPE_SPECIAL\n return t\n})()\n\nexport function isASCIIPunctuation(code: number): boolean {\n return (\n code < $.CHAR_ASCII_BOUNDARY &&\n (charClassTable[code] & CHAR_PUNCTUATION) !== 0\n )\n}\n\nexport function isASCIIWhitespace(code: number): boolean {\n return (\n code < $.CHAR_ASCII_BOUNDARY &&\n (charClassTable[code] & CHAR_WHITESPACE) !== 0\n )\n}\n\n// Unicode property escapes for spec-compliant character classification\n// Per GFM spec Section 2.1: \"A punctuation character is a character in the general Unicode categories\n// Pc, Pd, Pe, Pf, Pi, Po, or Ps\" - this is \\p{P}\n// BUT also includes some currency symbols and other symbols per the spec's explicit list\nconst UNICODE_PUNCT_R = /[\\p{P}\\p{S}]/u\nconst UNICODE_WHITESPACE_R = /\\p{Zs}/u\n\nexport function isUnicodeWhitespace(c: string): boolean {\n if (!c) return true\n const code = c.charCodeAt(0)\n return code < $.CHAR_ASCII_BOUNDARY\n ? (charClassTable[code] & CHAR_WHITESPACE) !== 0\n : UNICODE_WHITESPACE_R.test(c)\n}\n\nexport function isUnicodePunctuation(c: string | number): boolean {\n if (typeof c === 'number')\n return (\n c < $.CHAR_ASCII_BOUNDARY && (charClassTable[c] & CHAR_PUNCTUATION) !== 0\n )\n if (!c) return false\n const code = c.charCodeAt(0)\n return code < $.CHAR_ASCII_BOUNDARY\n ? (charClassTable[code] & CHAR_PUNCTUATION) !== 0\n : UNICODE_PUNCT_R.test(c)\n}\n\n/**\n * Find the end of the current line\n * Optimized: Pure indexOf is faster than hybrid approach - JS engine optimizes it better\n * Handles CRLF by returning position before \\r when followed by \\n\n */\nexport function findLineEnd(source: string, startPos: number): number {\n const newlinePos = source.indexOf('\\n', startPos)\n if (newlinePos === -1) return source.length\n if (newlinePos > 0 && source.charCodeAt(newlinePos - 1) === $.CHAR_CR) {\n return newlinePos - 1\n }\n return newlinePos\n}\n\nvar crlfParts: string[] = []\n\n/**\n * Normalize CRLF and CR line endings to LF\n * Returns original string if no CR characters are present (fast path)\n */\nexport function normalizeCRLF(text: string): string {\n var firstCR = text.indexOf('\\r')\n if (firstCR === -1) return text\n\n var len = text.length\n crlfParts.length = 0\n var start = 0\n\n for (var i = firstCR; i < len; i++) {\n if (text.charCodeAt(i) === $.CHAR_CR) {\n if (start < i) crlfParts.push(text.slice(start, i))\n if (i + 1 < len && text.charCodeAt(i + 1) === $.CHAR_NEWLINE) {\n i++\n }\n crlfParts.push('\\n')\n start = i + 1\n }\n }\n if (start < len) crlfParts.push(text.slice(start))\n return crlfParts.join('')\n}\n\n/**\n * Skip whitespace characters\n */\nexport function skipWhitespace(\n source: string,\n pos: number,\n maxPos?: number\n): number {\n const end = maxPos ?? source.length\n while (pos < end && (source[pos] === ' ' || source[pos] === '\\t')) pos++\n return pos\n}\n\n/**\n * Fast check if object has any enumerable properties\n * Optimized alternative to Object.keys(obj).length > 0\n */\nexport function hasKeys(obj: Record<string, any> | null | undefined): boolean {\n if (!obj) return false\n for (var key in obj) {\n return true\n }\n return false\n}\n\n/**\n * Extract plain text from AST nodes (for image alt text, heading slugs, etc.)\n * Shared between JSX and HTML renderers\n */\n/**\n * Get nested property from object using dot notation path\n */\nexport function get(source: any, path: string, fallback: any): any {\n var result = source\n var segments = path.split('.')\n var i = 0\n while (i < segments.length) {\n result = result?.[segments[i]]\n if (result === undefined) break\n i++\n }\n return result || fallback\n}\n\n/**\n * Get tag name from override object, supporting both string and component object overrides\n */\nexport function getTag<\n T extends string | { component?: string; props?: Record<string, any> },\n>(tag: string, overrides?: Record<string, T>): string {\n if (!overrides) return tag\n const override = get(overrides, tag, undefined)\n if (typeof override === 'string') return override\n if (typeof override === 'object' && override.component)\n return override.component\n return tag\n}\n\n/**\n * Get override props from override object\n */\nexport function getOverrideProps<\n T extends string | { component?: string; props?: Record<string, any> },\n>(\n tag: string,\n overrides?: Record<string, T>\n): Record<string, string | number | boolean> {\n if (!overrides) return {}\n const override = get(overrides, tag, undefined)\n return typeof override === 'object' && override.props ? override.props : {}\n}\n\nexport function extractPlainText(nodes: Array<any>, RuleType: any): string {\n var result = ''\n for (var i = 0, len = nodes.length; i < len; i++) {\n var node = nodes[i],\n type = node.type\n if (type === RuleType.text || type === RuleType.codeInline) {\n var text = node.text\n if (text) result += text\n } else if (type === RuleType.textFormatted || type === RuleType.link) {\n if (node.children) result += extractPlainText(node.children, RuleType)\n } else if (type === RuleType.image) {\n if (node.alt) {\n result += node.alt\n }\n }\n }\n return result\n}\n\n/**\n * Check if tag should be filtered per GFM tagfilter extension\n */\nexport function shouldFilterTag(tagName: string): boolean {\n var lowerTag = tagName.toLowerCase()\n return (\n lowerTag === 'title' ||\n lowerTag === 'textarea' ||\n lowerTag === 'style' ||\n lowerTag === 'xmp' ||\n lowerTag === 'iframe' ||\n lowerTag === 'noembed' ||\n lowerTag === 'noframes' ||\n lowerTag === 'script' ||\n lowerTag === 'plaintext'\n )\n}\n\n/**\n * Apply tagfilter to text content - escape dangerous tags\n */\nexport function applyTagFilterToText(text: string): string {\n // Escape dangerous tags in raw HTML text\n // Matches opening tags like <tag> or <tag attr=\"val\">\n return text.replace(\n /<(\\/?)(title|textarea|style|xmp|iframe|noembed|noframes|script|plaintext)(\\s|>|\\/)/gi,\n function (match, slash, tagName, after) {\n // Only escape the opening <\n return '<' + slash + tagName + after\n }\n )\n}\n",
|
|
8
|
+
"import { RuleType, type MarkdownToJSX } from './types'\nimport * as $ from './constants'\nimport * as util from './utils'\n\n// NOTE: All debug and tracking functions are automatically removed by build-plugins.ts\n\n// Global parseMetrics - accessible via global.parseMetrics from all files\ndeclare global {\n var parseMetrics: {\n blockParsers: {\n [key: string]: {\n attempts: number\n hits: number\n hitTimings: number[]\n }\n }\n inlineParsers: {\n [key: string]: {\n attempts: number\n hits: number\n hitTimings: number[]\n }\n }\n totalOperations: number\n blockParseIterations: number\n inlineParseIterations: number\n } | null\n var parseMetricsStartTimes: Map<string, number> | null\n}\n\nexport {};\n\nfunction warn(message: string): void {\n console.warn(message)\n}\n\nfunction countConsecutiveChars(\n source: string,\n pos: number,\n targetChar: string,\n maxCount?: number\n): number {\n var targetCode = charCode(targetChar)\n var len = source.length\n var max = maxCount ?? len - pos\n var count = 0\n while (\n count < max &&\n pos + count < len &&\n charCode(source, pos + count) === targetCode\n )\n count++\n return count\n}\n\n// Unified flanking check: dir=0 for left, dir=1 for right\nfunction checkFlanking(\n source: string,\n delimiterStart: number,\n delimiterEnd: number,\n bound: number,\n dir: number\n): boolean {\n if (dir === 0 ? delimiterEnd >= bound : delimiterStart <= bound) return false\n\n const adjacentChar =\n dir === 0 ? source[delimiterEnd] : source[delimiterStart - 1]\n const oppositeChar =\n dir === 0\n ? delimiterStart > 0\n ? source[delimiterStart - 1]\n : null\n : delimiterEnd < source.length\n ? source[delimiterEnd]\n : null\n\n var adjacentCode = charCode(adjacentChar)\n\n if (\n adjacentCode < $.CHAR_ASCII_BOUNDARY\n ? util.isASCIIWhitespace(adjacentCode)\n : util.isUnicodeWhitespace(adjacentChar)\n ) {\n return false\n }\n\n var oppositeCode = oppositeChar ? charCode(oppositeChar) : null\n var isOppositeWS =\n oppositeChar === null ||\n oppositeChar === '\\n' ||\n oppositeChar === '\\r' ||\n (oppositeCode !== null\n ? oppositeCode < $.CHAR_ASCII_BOUNDARY\n ? util.isASCIIWhitespace(oppositeCode)\n : util.isUnicodeWhitespace(oppositeChar)\n : true)\n\n var isAdjacentPunct = isPunctuation(adjacentCode, adjacentChar)\n\n if (!isAdjacentPunct) return true\n if (isOppositeWS) return true\n\n return oppositeChar\n ? isPunctuation(charCode(oppositeChar), oppositeChar)\n : false\n}\n\n// Per CommonMark spec: backslashes escape ASCII punctuation characters in link destinations\n// For non-punctuation characters, the backslash is preserved as a literal backslash\n// Per CommonMark spec: backslash unescaping and entity reference decoding for URLs and titles\n// Any ASCII punctuation character may be backslash-escaped\n// Entity references are recognized and decoded to Unicode\nfunction unescapeUrlOrTitle(str: string): string {\n var result = '',\n i = 0\n while (i < str.length) {\n if (str[i] === '\\\\' && i + 1 < str.length) {\n var next = str[i + 1]\n result += util.isUnicodePunctuation(charCode(next)) ? next : '\\\\' + next\n i += 2\n } else {\n result += str[i++]\n }\n }\n return util.decodeEntityReferences(result)\n}\n\nfunction skipToNextLine(source: string, lineEnd: number): number {\n if (lineEnd >= source.length) return lineEnd\n if (\n source.charCodeAt(lineEnd) === $.CHAR_CR &&\n lineEnd + 1 < source.length &&\n source.charCodeAt(lineEnd + 1) === $.CHAR_NEWLINE\n ) {\n return lineEnd + 2\n }\n if (source.charCodeAt(lineEnd) === $.CHAR_NEWLINE) {\n return lineEnd + 1\n }\n return lineEnd + 1\n}\n\nfunction getCharType(code: number, skipAutoLink: boolean): number {\n if (code >= $.CHAR_ASCII_BOUNDARY) return 0\n var type = util.inlineCharTypeTable[code]\n if (\n skipAutoLink &&\n type === 1 &&\n (code === $.CHAR_f || code === $.CHAR_H || code === $.CHAR_W)\n ) {\n return 0\n }\n return type\n}\n\nfunction tryMergeBlockquoteContinuation(\n source: string,\n currentPos: number,\n lastItem: MarkdownToJSX.ASTNode[],\n continuationContent: string,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): number | null {\n if (\n !lastItem.length ||\n lastItem[lastItem.length - 1].type !== RuleType.blockQuote\n )\n return null\n const checkPos = util.skipWhitespace(\n continuationContent,\n 0,\n continuationContent.length\n )\n if (\n checkPos >= continuationContent.length ||\n continuationContent[checkPos] !== '>'\n )\n return null\n // We've already verified it starts with '>', so try blockquote directly\n // (parseBlock might match fenced code blocks first due to indentation)\n const cont = parseBlockQuote(source, currentPos, state, options)\n if (!cont) return null\n const lastBlockQuote = lastItem[\n lastItem.length - 1\n ] as MarkdownToJSX.BlockQuoteNode\n const contBlockQuote = cont as MarkdownToJSX.BlockQuoteNode & {\n endPos: number\n }\n if (contBlockQuote.children)\n lastBlockQuote.children.push(...contBlockQuote.children)\n return contBlockQuote.endPos\n}\n\nfunction createHeading(\n level: number,\n children: MarkdownToJSX.ASTNode[],\n content: string,\n slugify: (str: string) => string\n): MarkdownToJSX.HeadingNode {\n return {\n type: RuleType.heading,\n level,\n children,\n id: slugify(content),\n } as MarkdownToJSX.HeadingNode\n}\n\n// Static regex patterns for performance\nexport const UNESCAPE_R: RegExp = /\\\\(.)/g\nconst HEADING_TRAILING_HASHES_R = /\\s+#+\\s*$/\n// Unified regex for all list item patterns: ordered (digit + delimiter + content) or unordered (marker + content)\n// Groups: 1=ordered_num, 2=ordered_delim, 3=ordered_content, 4=ordered_empty_num, 5=ordered_empty_delim, 6=unordered_marker, 7=unordered_content, 8=unordered_empty_marker\nconst LIST_ITEM_R =\n /^(?:(\\d{1,9})([.)])\\s+(.*)$|(\\d{1,9})([.)])\\s*$|([-*+])\\s+(.*)$|([-*+])\\s*$)/\n// List items with content (marker + whitespace + content or end of line) - for continuation matching\nconst ORDERED_LIST_ITEM_WITH_CONTENT_R = /^(\\d{1,9})([.)])(\\s+|$)/\nconst UNORDERED_LIST_ITEM_WITH_CONTENT_R = /^([*+\\-])(\\s+|$)/\nexport const HTML_BLOCK_ELEMENT_START_R: RegExp =\n /^<([a-z][^ >/\\n\\r]*) ?([^>]*?)>/i\nexport const HTML_BLOCK_ELEMENT_START_R_ATTR: RegExp =\n /^<([a-z][^ >/]*) ?(?:[^>/]+[^/]|)>/i\n\nvar charCode = function (c: string, pos: number = 0) {\n return c.charCodeAt(pos)\n}\nvar isAlnum = function (c: string): boolean {\n return util.isAlnumCode(charCode(c))\n}\nvar isWS = function (c: string) {\n return util.isASCIIWhitespace(charCode(c))\n}\nvar isSpaceOrTab = function (c: string): boolean {\n return c === ' ' || c === '\\t'\n}\nvar isPunctuation = function (code: number, char: string): boolean {\n return util.isUnicodePunctuation(code < $.CHAR_ASCII_BOUNDARY ? code : char)\n}\nvar isNameChar = function (c: string) {\n var n = charCode(c)\n return (\n isAlnum(c) ||\n n === $.CHAR_DASH ||\n n === $.CHAR_UNDERSCORE ||\n n === $.CHAR_COLON ||\n n === $.CHAR_PERIOD\n )\n}\n\n// HTML validation functions removed - parser only recognizes boundaries, not validates syntax\n// Per GFM spec: parser's job is to identify HTML boundaries and pass content opaquely\n\nfunction parseHTMLTagName(\n source: string,\n pos: number\n): { tagName: string; tagLower: string; nextPos: number } | null {\n var sourceLen = source.length\n if (pos >= sourceLen) return null\n var firstCharCode = charCode(source[pos])\n if (!isAlphaCode(firstCharCode)) return null\n var tagNameStart = pos\n var tagNameEnd = pos\n while (tagNameEnd < sourceLen) {\n var code = charCode(source[tagNameEnd])\n if (\n (code >= $.CHAR_a && code <= $.CHAR_z) ||\n (code >= $.CHAR_A && code <= $.CHAR_Z) ||\n (code >= $.CHAR_DIGIT_0 && code <= $.CHAR_DIGIT_9) ||\n code === $.CHAR_DASH\n ) {\n tagNameEnd++\n } else {\n var tagEndCode = charCode(source[tagNameEnd])\n if (\n tagEndCode === $.CHAR_SPACE ||\n tagEndCode === $.CHAR_TAB ||\n tagEndCode === $.CHAR_NEWLINE ||\n tagEndCode === $.CHAR_CR ||\n tagEndCode === $.CHAR_GT ||\n tagEndCode === $.CHAR_SLASH\n ) {\n break\n } else {\n return null\n }\n }\n }\n if (tagNameEnd === tagNameStart) return null\n var tagName = source.slice(tagNameStart, tagNameEnd)\n\n // Validate tag name according to spec: only ASCII letters, digits, hyphens\n for (var i = 0; i < tagName.length; i++) {\n var code = charCode(tagName[i])\n if (\n !(\n (code >= $.CHAR_a && code <= $.CHAR_z) ||\n (code >= $.CHAR_A && code <= $.CHAR_Z) ||\n (code >= $.CHAR_DIGIT_0 && code <= $.CHAR_DIGIT_9) ||\n code === $.CHAR_DASH\n )\n ) {\n return null\n }\n }\n\n return { tagName, tagLower: tagName.toLowerCase(), nextPos: tagNameEnd }\n}\n\n/** Unified HTML tag parser that handles opening, closing, and self-closing tags */\nexport function parseHTMLTag(\n source: string,\n pos: number\n): {\n tagName: string\n tagLower: string\n attrs: string\n endPos: number\n isClosing: boolean\n isSelfClosing: boolean\n hasNewline: boolean\n hasSpaceBeforeSlash: boolean\n whitespaceBeforeAttrs: string\n} | null {\n var token = scanRawHTML(source, pos)\n if (!token || token.kind !== 'tag') return null\n\n // Note: hasSpaceBeforeSlash is already validated in scanner (returns null if invalid)\n return {\n tagName: token.tagName || '',\n tagLower: token.tagNameLower || '',\n attrs: token.attrs || '',\n endPos: token.endPos,\n isClosing: token.isClosing || false,\n isSelfClosing: token.isSelfClosing || false,\n hasNewline: token.hasNewline,\n hasSpaceBeforeSlash: false,\n whitespaceBeforeAttrs: token.whitespaceBeforeAttrs || '',\n }\n}\n\n/** Find matching closing tag position for inline HTML tags. Returns [contentEnd, closingTagEnd] or null */\nfunction findInlineClosingTag(\n source: string,\n startPos: number,\n tagNameLower: string\n): [number, number] | null {\n var depth = 1\n var searchPos = startPos\n while (depth > 0 && searchPos < source.length) {\n var tagIdx = source.indexOf('<', searchPos)\n if (tagIdx === -1) return null\n var tagParseResult = parseHTMLTag(source, tagIdx)\n if (!tagParseResult) {\n searchPos = tagIdx + 1\n continue\n }\n if (\n tagParseResult.isClosing &&\n tagParseResult.tagLower === tagNameLower &&\n --depth === 0\n )\n return [tagIdx, tagParseResult.endPos]\n if (\n !tagParseResult.isClosing &&\n !tagParseResult.isSelfClosing &&\n tagParseResult.tagLower === tagNameLower\n )\n depth++\n searchPos = tagParseResult.endPos\n }\n return null\n}\n\nexport const INTERPOLATION_R: RegExp = /^\\{.*\\}$/\nconst DOUBLE_NEWLINE_R = /\\n\\n/\nconst BLOCK_SYNTAX_R =\n /^(\\s{0,3}#[#\\s]|\\s{0,3}[-*+]\\s|\\s{0,3}\\d+\\.\\s|\\s{0,3}>\\s|\\s{0,3}```)/m\nconst TYPE1_TAG_R = /<\\/?(?:pre|script|style|textarea)\\b/i\nexport const UPPERCASE_TAG_R: RegExp = /^<[A-Z]/\nconst TRAILING_NEWLINE_R = /\\n$/\nconst BLOCK_START_CHARS_SET = new Set([\n '#',\n '>',\n '-',\n '*',\n '+',\n '`',\n '|',\n '0',\n '1',\n '2',\n '3',\n '4',\n '5',\n '6',\n '7',\n '8',\n '9',\n])\n\n/** Find the next occurrence of a character, ignoring escaped versions */\nfunction findUnescapedChar(\n source: string,\n startPos: number,\n endPos: number,\n targetChar: string\n): number {\n let i = startPos\n while (i < endPos) {\n if (source[i] === '\\\\' && i + 1 < endPos) {\n i += 2\n continue\n }\n if (source[i] === targetChar) return i\n i++\n }\n return -1\n}\n\ntype StyleTuple = [key: string, value: string]\n\nfunction addStyleToCollection(styles: StyleTuple[], buffer: string): void {\n var colonIndex = buffer.indexOf(':')\n if (colonIndex > 0) {\n var value = buffer.slice(colonIndex + 1).trim()\n var len = value.length\n if (len >= 2) {\n var first = value[0]\n if ((first === '\"' || first === \"'\") && value[len - 1] === first) {\n value = value.slice(1, -1)\n }\n }\n styles.push([buffer.slice(0, colonIndex).trim(), value])\n }\n}\n\nexport function parseStyleAttribute(styleString: string): StyleTuple[] {\n var styles: StyleTuple[] = []\n if (!styleString) return styles\n\n var buffer = ''\n var depth = 0\n var quoteChar = ''\n\n for (var i = 0; i < styleString.length; i++) {\n var char = styleString[i]\n\n if (char === '\"' || char === \"'\") {\n if (!quoteChar) {\n quoteChar = char\n depth++\n } else if (char === quoteChar) {\n quoteChar = ''\n depth--\n }\n } else if (char === '(' && util.endsWith(buffer, 'url')) {\n depth++\n } else if (char === ')' && depth > 0) {\n depth--\n } else if (char === ';' && depth === 0) {\n addStyleToCollection(styles, buffer)\n buffer = ''\n continue\n }\n\n buffer += char\n }\n\n addStyleToCollection(styles, buffer)\n\n return styles\n}\n\nfunction attributeValueToJSXPropValue(\n tag: MarkdownToJSX.HTMLTags,\n key: string,\n value: string,\n sanitizeUrlFn: (\n value: string,\n tag: string,\n attribute: string\n ) => string | null,\n options: ParseOptions\n): any {\n if (key === 'style') {\n return parseStyleAttribute(value).reduce(\n function (styles, [k, v]) {\n const sanitized = sanitizeUrlFn(v, tag, k)\n if (sanitized != null) {\n styles[k.replace(/(-[a-z])/g, substr => substr[1].toUpperCase())] =\n sanitized\n }\n return styles\n },\n {} as { [key: string]: any }\n );\n }\n\n // Handle JSX expressions (braces) before sanitization\n // This allows parsing of arrays/objects in JSX props\n if (value.match(INTERPOLATION_R)) {\n value = value.slice(1, value.length - 1)\n value = value ? value.replace(UNESCAPE_R, '$1') : value\n\n // Try to parse as JSON for arrays/objects (best effort)\n // Keep as raw string for functions and complex expressions\n if (value.length > 0) {\n const firstChar = value[0]\n // Check if it looks like an array or object literal\n if (firstChar === '[' || firstChar === '{') {\n try {\n return JSON.parse(value)\n } catch (e) {\n // Not valid JSON, keep as string (e.g., functions, JSX expressions)\n return value\n }\n }\n }\n // For other expressions (functions, variables, etc.), keep as string by default\n // Only eval if explicitly opted-in (NOT recommended for user inputs)\n if (value === 'true') return true\n if (value === 'false') return false\n\n // Attempt to eval unserializable expressions only if explicitly enabled\n // ⚠️ WARNING: This uses eval() and should only be used with trusted content\n if (options.evalUnserializableExpressions) {\n try {\n // Try to evaluate as an expression (function, variable, etc.)\n // eslint-disable-next-line no-eval\n return eval(`(${value})`)\n } catch (e) {\n // If eval fails, return as string\n return value\n }\n }\n\n // Don't apply sanitization to JSX expressions\n // Keep as string - can be handled via renderRule on a case-by-case basis\n return value\n }\n\n if (util.ATTRIBUTES_TO_SANITIZE.indexOf(key) !== -1) {\n return sanitizeUrlFn(\n value ? value.replace(UNESCAPE_R, '$1') : value,\n tag,\n key\n )\n }\n\n return value === 'true' ? true : value === 'false' ? false : value\n}\n\nfunction parseHTMLAttributes(\n attrs: string,\n tagName: string,\n tagNameOriginal: string,\n options: ParseOptions\n): { [key: string]: any } {\n const result: { [key: string]: any } = {}\n if (!attrs || !attrs.trim()) return result\n\n const attrMatches: string[] = []\n let i = 0\n const len = attrs.length\n while (i < len) {\n while (i < len && isSpaceOrTab(attrs[i])) i++\n if (i >= len) break\n const nameStart = i\n while (i < len && isNameChar(attrs[i])) i++\n if (i === nameStart) {\n i++\n continue\n }\n const name = attrs.slice(nameStart, i)\n while (i < len && isSpaceOrTab(attrs[i])) i++\n if (i >= len || attrs[i] !== '=') {\n attrMatches.push(name)\n continue\n }\n i++\n while (i < len && isSpaceOrTab(attrs[i])) i++\n if (i >= len) {\n attrMatches.push(name + '=')\n break\n }\n const valueStart = i\n const q = attrs[i]\n if (q === '\"' || q === \"'\") {\n i++\n while (i < len) {\n if (attrs[i] === q) {\n if (i + 1 >= len) {\n i++\n break\n }\n const nextChar = attrs[i + 1]\n if (isSpaceOrTab(nextChar) || nextChar === '/') {\n i++\n break\n }\n }\n i++\n }\n } else if (q === '{') {\n let depth = 1\n i++\n while (i < len && depth > 0) {\n if (attrs[i] === '{') depth++\n else if (attrs[i] === '}') {\n depth--\n if (depth === 0) {\n i++\n break\n }\n }\n i++\n }\n } else {\n while (i < len && !isSpaceOrTab(attrs[i])) i++\n }\n attrMatches.push(name + '=' + attrs.slice(valueStart, i))\n }\n\n if (!attrMatches?.length) return result\n const tagNameLower = tagName.toLowerCase(),\n isJSXComponent =\n tagNameOriginal.length > 0 &&\n tagNameOriginal[0] >= 'A' &&\n tagNameOriginal[0] <= 'Z'\n for (let i = 0; i < attrMatches.length; i++) {\n const rawAttr = attrMatches[i],\n delimiterIdx = rawAttr.indexOf('=')\n if (delimiterIdx !== -1) {\n const key = rawAttr.slice(0, delimiterIdx).trim(),\n keyLower = key.toLowerCase()\n if (keyLower === 'ref') continue\n const attrKey = isJSXComponent ? key : keyLower,\n rawValue = rawAttr.slice(delimiterIdx + 1).trim(),\n value = ((str: string) => {\n const first = str[0]\n if (\n (first === '\"' || first === \"'\") &&\n str.length >= 2 &&\n str[str.length - 1] === first\n )\n return str.slice(1, -1)\n return str\n })(rawValue)\n\n if (\n (keyLower === 'href' && tagNameLower === 'a') ||\n (keyLower === 'src' && tagNameLower === 'img')\n ) {\n const safe = options.sanitizer(\n value,\n tagNameLower as MarkdownToJSX.HTMLTags,\n keyLower\n )\n if (safe == null) {\n warn(`Stripped unsafe ${keyLower} on <${tagNameOriginal}>`)\n continue\n }\n result[attrKey] = safe\n } else {\n const normalizedValue = attributeValueToJSXPropValue(\n tagNameLower as MarkdownToJSX.HTMLTags,\n keyLower,\n value,\n options.sanitizer,\n options\n )\n result[attrKey] = normalizedValue\n }\n } else if (rawAttr !== 'style')\n result[isJSXComponent ? rawAttr : rawAttr.toLowerCase()] = true\n }\n // Check for URI-encoded malicious content in the raw attributes string\n // Only decode if % is present (performance optimization)\n if (attrs.indexOf('%') !== -1) {\n try {\n if (util.SANITIZE_R.test(decodeURIComponent(attrs)))\n for (var key in result) delete result[key]\n } catch (e) {\n // Invalid URI encoding (e.g., \"100%\") - skip the check\n // Individual attributes were already sanitized above\n }\n } else if (util.SANITIZE_R.test(attrs)) {\n for (var key in result) delete result[key]\n }\n return result\n}\n\nexport type ParseResult = (MarkdownToJSX.ASTNode & { endPos: number }) | null\n\n/** Options passed to parsers */\nexport type ParseOptions = Omit<MarkdownToJSX.Options, 'slugify'> & {\n slugify: (input: string) => string\n}\n\nvar isBlockStartChar = function (c: string): boolean {\n return BLOCK_START_CHARS_SET.has(c)\n}\n\ninterface BracketEntry {\n type: 'link' | 'image'\n pos: number\n resultIdx: number\n inAnchor: boolean\n}\n\n// Check if an invalid reference definition should be skipped per CommonMark Examples 208 and 210\nfunction shouldSkipInvalidReferenceDefinition(\n input: string,\n refCheckPos: number,\n isAtDocumentStart: boolean\n): { shouldSkip: boolean; newPos: number } {\n // Find closing ']' handling escapes\n let bracketEnd = refCheckPos + 1\n while (bracketEnd < input.length && input[bracketEnd] !== ']') {\n if (input[bracketEnd] === '\\\\' && bracketEnd + 1 < input.length) {\n bracketEnd += 2\n continue\n }\n bracketEnd++\n }\n if (bracketEnd >= input.length) return { shouldSkip: false, newPos: 0 }\n\n // Check if label starts/ends with newline (Example 208 pattern)\n const labelStart = refCheckPos + 1\n const labelEnd = bracketEnd\n const labelStartsWithNewline =\n labelStart < labelEnd &&\n (input[labelStart] === '\\n' || input[labelStart] === '\\r')\n const labelEndsWithNewline =\n labelEnd > labelStart &&\n (input[labelEnd - 1] === '\\n' || input[labelEnd - 1] === '\\r')\n\n let afterBracket = bracketEnd + 1\n // Skip whitespace after ']'\n afterBracket = util.skipWhitespace(input, afterBracket)\n\n // Check for colon\n if (afterBracket >= input.length || input[afterBracket] !== ':') {\n return { shouldSkip: false, newPos: 0 }\n }\n\n // Found colon - check for Example 208 pattern (label starts/ends with newline at document start)\n if ((labelStartsWithNewline || labelEndsWithNewline) && isAtDocumentStart) {\n // Invalid ref definition per Example 208 - skip to next line after URL\n let skipPos = afterBracket + 1\n skipPos = util.skipWhitespace(input, skipPos)\n // Skip optional newline\n if (skipPos < input.length && input[skipPos] === '\\n') {\n skipPos = util.skipWhitespace(input, skipPos + 1)\n }\n // Find end of URL line (next newline)\n while (skipPos < input.length && input[skipPos] !== '\\n') {\n skipPos++\n }\n if (skipPos < input.length) {\n skipPos++\n }\n return { shouldSkip: true, newPos: skipPos }\n }\n\n // Check for Example 210 pattern (trailing text after title)\n return checkExample210Pattern(input, afterBracket)\n}\n\n// Helper for Example 210: trailing text after title\nfunction checkExample210Pattern(\n input: string,\n colonPos: number\n): { shouldSkip: boolean; newPos: number } {\n let urlEnd = colonPos + 1\n urlEnd = util.skipWhitespace(input, urlEnd)\n // Skip optional newline\n if (urlEnd < input.length && input[urlEnd] === '\\n') {\n urlEnd = util.skipWhitespace(input, urlEnd + 1)\n }\n // Find end of URL (next newline)\n while (urlEnd < input.length && input[urlEnd] !== '\\n') {\n urlEnd++\n }\n if (urlEnd >= input.length) return { shouldSkip: false, newPos: 0 }\n\n urlEnd++\n // Check for title delimiter on next line\n let titleLineStart = util.skipWhitespace(input, urlEnd)\n if (\n titleLineStart >= input.length ||\n (input[titleLineStart] !== '\"' && input[titleLineStart] !== \"'\")\n ) {\n return { shouldSkip: false, newPos: 0 }\n }\n\n // Has title delimiter - check for trailing text (Example 210)\n const titleChar = input[titleLineStart]\n let titleEnd = titleLineStart + 1\n while (\n titleEnd < input.length &&\n input[titleEnd] !== titleChar &&\n input[titleEnd] !== '\\n'\n ) {\n if (input[titleEnd] === '\\\\' && titleEnd + 1 < input.length) {\n titleEnd += 2\n continue\n }\n titleEnd++\n }\n if (titleEnd >= input.length || input[titleEnd] !== titleChar) {\n return { shouldSkip: false, newPos: 0 }\n }\n\n // Found closing quote - check for trailing text\n let afterTitle = util.skipWhitespace(input, titleEnd + 1)\n if (\n afterTitle < input.length &&\n input[afterTitle] !== '\\n' &&\n input[afterTitle] !== '\\r'\n ) {\n // Trailing text found - invalid ref definition per Example 210\n return { shouldSkip: true, newPos: urlEnd }\n }\n\n return { shouldSkip: false, newPos: 0 }\n}\n\n// Check if nodes contain a link (prevents nested links per CommonMark)\nfunction containsLink(nodes: MarkdownToJSX.ASTNode[]): boolean {\n for (var i = 0; i < nodes.length; i++) {\n var node = nodes[i]\n if (node.type === RuleType.link) return true\n if (node.type === RuleType.textFormatted) {\n var formattedNode = node as MarkdownToJSX.FormattedTextNode\n if (formattedNode.children && containsLink(formattedNode.children))\n return true\n }\n }\n return false\n}\n\nfunction extractAllTextFromNodes(nodes: MarkdownToJSX.ASTNode[]): string {\n var text = ''\n for (var i = 0, len = nodes.length; i < len; i++) {\n var node = nodes[i]\n var type = node.type\n if (type === RuleType.text) {\n text += (node as MarkdownToJSX.TextNode).text\n } else if (type === RuleType.image) {\n var imgNode = node as MarkdownToJSX.ImageNode\n if (imgNode.alt) text += imgNode.alt\n } else if (type === RuleType.textFormatted) {\n var formattedNode = node as MarkdownToJSX.FormattedTextNode\n if (formattedNode.children) {\n text += extractAllTextFromNodes(formattedNode.children)\n }\n } else if (type === RuleType.link) {\n var linkNode = node as MarkdownToJSX.LinkNode\n if (linkNode.children) {\n text += extractAllTextFromNodes(linkNode.children)\n }\n }\n }\n return text\n}\n\nconst WHITESPACE_CHARS = new Set([' ', '\\t', '\\r', '\\n', '\\f', '\\v'])\n\n/**\n * Single pass, no recursion, eliminates parseLink/parseImage/parseRefLink/parseRefImage functions\n */\nfunction parseInlineSpan(\n source: string,\n start: number,\n end: number,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): MarkdownToJSX.ASTNode[] {\n var result: MarkdownToJSX.ASTNode[] = []\n var delimiterStack: DelimiterEntry[] = []\n var bracketStack: BracketEntry[] = []\n\n var pos = start\n var textStart = start\n var skipAutoLink = options.disableAutoLink || state.inAnchor\n var hasAmpersand = false\n var inAnchor = !!state.inAnchor\n var disableParsingRawHTML = !!options.disableParsingRawHTML\n\n // Helper: handle HTML tag parsing (angle brace autolinks, comments, tags, type 7 blocks)\n var handleHTMLTag = function (\n checkType7Block: boolean,\n respectDisableAutoLink: boolean\n ): boolean {\n if (!inAnchor && (!respectDisableAutoLink || !options.disableAutoLink)) {\n var angleBraceResult = parseLinkOrImage(source, pos, state, options, '<')\n if (angleBraceResult) {\n flushText(pos)\n result.push(angleBraceResult)\n pos = angleBraceResult.endPos\n textStart = pos\n return true\n }\n }\n\n // Skip HTML parsing if disableParsingRawHTML is enabled\n if (disableParsingRawHTML) {\n return false\n }\n\n var htmlResult = parseHTML(source, pos, state, options)\n if (htmlResult) {\n flushText(pos)\n result.push(htmlResult)\n pos = htmlResult.endPos\n textStart = pos\n return true\n }\n\n if (!checkType7Block) return false\n var tagCheckResult = parseHTMLTag(source, pos)\n if (!tagCheckResult) return false\n var tagNameStart = pos + (tagCheckResult.isClosing ? 2 : 1)\n if (tagNameStart >= source.length || isSpaceOrTab(source[tagNameStart]))\n return false\n var closeIdx = source.indexOf('>', pos + 1)\n if (closeIdx !== -1) {\n var contentStart = pos + 1\n var contentLen = closeIdx - contentStart\n if (contentLen >= 7) {\n var isHttp = util.startsWith(source, 'http://', contentStart)\n if (isHttp || util.startsWith(source, 'https://', contentStart)) {\n for (var j = contentStart; j < closeIdx; j++) {\n if (isSpaceOrTab(source[j])) return false\n }\n }\n }\n }\n var tagFirstCharCode = charCode(source, tagNameStart)\n if (\n isAlphaCode(tagFirstCharCode) &&\n tagNameStart + 1 < source.length &&\n source[tagNameStart + 1] === ':'\n )\n return false\n if (tagCheckResult.isClosing && tagCheckResult.attrs.trim().length)\n return false\n\n if (tagCheckResult.attrs.length) {\n var inQuotes = false\n var quoteChar = ''\n for (var i = 0; i < tagCheckResult.attrs.length; i++) {\n var ch = tagCheckResult.attrs[i]\n if (inQuotes && ch === quoteChar) {\n inQuotes = false\n } else if (!inQuotes && (ch === '\"' || ch === \"'\")) {\n inQuotes = true\n quoteChar = ch\n } else if (ch === '*' || ch === '#' || ch === '!') {\n var checkAhead = i + 1\n while (\n checkAhead < tagCheckResult.attrs.length &&\n tagCheckResult.attrs[checkAhead] !== '=' &&\n tagCheckResult.attrs[checkAhead] !== ' ' &&\n tagCheckResult.attrs[checkAhead] !== '\\t'\n )\n checkAhead++\n if (\n checkAhead < tagCheckResult.attrs.length &&\n tagCheckResult.attrs[checkAhead] === '='\n )\n return false\n }\n }\n }\n\n // Valid tag with newline - type 7 block, preserve as raw HTML\n // But still parse content into children\n var rawText = source.slice(pos, tagCheckResult.endPos)\n var tagName = tagCheckResult.tagName.toLowerCase()\n var contentToParse = rawText\n // Extract content if rawText includes opening tag\n var tagEnd = contentToParse.indexOf('>')\n if (tagEnd !== -1) {\n contentToParse = contentToParse.slice(tagEnd + 1)\n var closingTag = '</' + tagName + '>'\n var closingIdx = contentToParse.indexOf(closingTag)\n if (closingIdx !== -1) {\n contentToParse = contentToParse.slice(0, closingIdx)\n }\n }\n var children: MarkdownToJSX.ASTNode[] = []\n if (contentToParse.trim() && options) {\n var parseState: MarkdownToJSX.State = {\n ...state,\n inline: false,\n inHTML: true,\n }\n var trimmed = contentToParse.trim()\n if (\n DOUBLE_NEWLINE_R.test(trimmed) ||\n BLOCK_SYNTAX_R.test(trimmed) ||\n HTML_BLOCK_ELEMENT_START_R.test(trimmed)\n ) {\n children = parseBlocksInHTML(trimmed, parseState, options)\n } else if (trimmed) {\n parseState.inline = true\n children = parseInlineSpan(\n trimmed,\n 0,\n trimmed.length,\n parseState,\n options\n )\n }\n }\n var htmlBlockResult = {\n type: RuleType.htmlBlock,\n tag: tagCheckResult.tagName as MarkdownToJSX.HTMLTags,\n attrs: {},\n children: children,\n rawText: rawText,\n text: rawText, // @deprecated - use rawText instead\n verbatim: true,\n endPos: tagCheckResult.endPos,\n } as MarkdownToJSX.HTMLNode & { endPos: number }\n flushText(pos)\n result.push(htmlBlockResult)\n pos = htmlBlockResult.endPos\n textStart = pos\n return true\n }\n\n var flushText = function (endPos: number) {\n if (endPos > textStart) {\n var text = source.slice(textStart, endPos)\n result.push({\n type: RuleType.text,\n text: hasAmpersand ? util.decodeEntityReferences(text) : text,\n } as MarkdownToJSX.TextNode)\n textStart = endPos\n hasAmpersand = false\n }\n }\n\n while (pos < end) {\n var code = charCode(source, pos)\n var charType = getCharType(code, skipAutoLink)\n\n if (charType === 0) {\n if (code === $.CHAR_AMPERSAND) hasAmpersand = true\n pos++\n // Fast path for ASCII text - avoid repeated charCode calls and lookups\n while (pos < end) {\n code = charCode(source, pos)\n if (code >= $.CHAR_ASCII_BOUNDARY) break\n if (code === $.CHAR_AMPERSAND) hasAmpersand = true\n var lookupCharType = util.inlineCharTypeTable[code]\n if (lookupCharType !== 0) {\n // Check for autolink exception\n if (\n skipAutoLink &&\n lookupCharType === 1 &&\n (code === $.CHAR_f || code === $.CHAR_H || code === $.CHAR_W)\n ) {\n pos++\n continue\n }\n break\n }\n pos++\n }\n continue\n }\n\n // CODE SPANS (highest priority, no nesting)\n if (code === $.CHAR_BACKTICK) {\n var backtickStart = pos\n var backtickCount = 0\n while (pos + backtickCount < end) {\n if (charCode(source, pos + backtickCount) !== $.CHAR_BACKTICK) break\n backtickCount++\n }\n\n if (backtickCount > 0) {\n var contentStart = pos + backtickCount\n var contentEnd = -1\n var i = contentStart\n // Scan character by character for closing backticks - faster than indexOf\n while (i < end) {\n // Find next backtick\n while (i < end && charCode(source, i) !== $.CHAR_BACKTICK) i++\n if (i >= end) break\n\n // Count consecutive backticks\n var closingCount = 0\n while (\n i + closingCount < end &&\n charCode(source, i + closingCount) === $.CHAR_BACKTICK\n ) {\n closingCount++\n }\n if (closingCount > backtickCount) closingCount = backtickCount\n var j = i + closingCount\n\n // Check if this is a valid closing sequence\n if (\n closingCount === backtickCount &&\n (i <= contentStart ||\n charCode(source, i - 1) !== $.CHAR_BACKTICK) &&\n (j >= end || charCode(source, j) !== $.CHAR_BACKTICK)\n ) {\n contentEnd = i\n i = j\n break\n }\n i++\n }\n\n if (contentEnd !== -1) {\n var rawContent = source.slice(contentStart, contentEnd)\n var hasNewline = false\n for (var k = 0; k < rawContent.length; k++) {\n var nlCode = charCode(rawContent, k)\n if (nlCode === $.CHAR_NEWLINE || nlCode === $.CHAR_CR) {\n hasNewline = true\n break\n }\n }\n var content = rawContent\n if (hasNewline) {\n // Optimize newline replacement by avoiding regex\n content = rawContent\n .replace(/\\r\\n/g, ' ')\n .replace(/\\r/g, ' ')\n .replace(/\\n/g, ' ')\n }\n if (content.length > 0) {\n var firstChar = charCode(content, 0)\n var lastChar = charCode(content, content.length - 1)\n if (firstChar === $.CHAR_SPACE && lastChar === $.CHAR_SPACE) {\n for (var idx = 1; idx < content.length - 1; idx++) {\n if (charCode(content, idx) !== $.CHAR_SPACE) {\n content = content.slice(1, content.length - 1)\n break\n }\n }\n }\n }\n\n flushText(backtickStart)\n result.push({\n type: RuleType.codeInline,\n text: content,\n } as MarkdownToJSX.CodeInlineNode)\n pos = i\n textStart = pos\n continue\n }\n pos = contentStart\n continue\n }\n }\n\n // AUTOLINKS: BARE URLS AND EMAIL (check BEFORE escapes to preserve backslashes in URLs)\n if (\n !inAnchor &&\n !skipAutoLink &&\n (code === $.CHAR_f || code === $.CHAR_H || code === $.CHAR_W)\n ) {\n var autolinkType: 'h' | 'w' | 'f' | null = null\n // Cache character codes to avoid repeated function calls\n var c1 = pos + 1 < end ? charCode(source, pos + 1) : 0\n var c2 = pos + 2 < end ? charCode(source, pos + 2) : 0\n var c3 = pos + 3 < end ? charCode(source, pos + 3) : 0\n var c4 = pos + 4 < end ? charCode(source, pos + 4) : 0\n var c5 = pos + 5 < end ? charCode(source, pos + 5) : 0\n\n if (\n code === $.CHAR_H &&\n c1 === $.CHAR_t &&\n c2 === $.CHAR_t &&\n c3 === $.CHAR_p\n ) {\n autolinkType = 'h'\n } else if (\n code === $.CHAR_W &&\n c1 === $.CHAR_W &&\n c2 === $.CHAR_W &&\n c3 === $.CHAR_PERIOD\n ) {\n autolinkType = 'w'\n } else if (\n code === $.CHAR_f &&\n c1 === $.CHAR_t &&\n c2 === $.CHAR_p &&\n c3 === $.CHAR_COLON &&\n c4 === $.CHAR_SLASH &&\n c5 === $.CHAR_SLASH\n ) {\n autolinkType = 'f'\n }\n if (autolinkType) {\n var bareUrlResult = parseLinkOrImage(\n source,\n pos,\n state,\n options,\n autolinkType\n )\n if (bareUrlResult) {\n flushText(pos)\n result.push(bareUrlResult)\n pos = bareUrlResult.endPos\n textStart = pos\n continue\n }\n }\n }\n\n if (!inAnchor && !skipAutoLink && code === $.CHAR_AT) {\n var emailResult = parseLinkOrImage(source, pos, state, options, '@')\n if (emailResult && 'emailStart' in emailResult) {\n var emailStart = (\n emailResult as MarkdownToJSX.LinkNode & {\n endPos: number\n emailStart: number\n }\n ).emailStart\n var emailEnd = emailResult.endPos\n var removedIndices: number[] = []\n for (var j = delimiterStack.length - 1; j >= 0; j--) {\n var delim = delimiterStack[j]\n if (delim.sourcePos >= emailStart && delim.sourcePos < emailEnd) {\n if (delim.nodeIndex >= 0 && delim.nodeIndex < result.length) {\n result.splice(delim.nodeIndex, 1)\n removedIndices.push(delim.nodeIndex)\n }\n delimiterStack.splice(j, 1)\n }\n }\n if (emailStart < textStart) {\n for (var i = result.length - 1; i >= 0; i--) {\n if (result[i].type === RuleType.text) {\n result.splice(i, 1)\n removedIndices.push(i)\n break\n }\n }\n textStart = emailStart\n }\n // Batch update delimiter indices after all removals (O(n+m) instead of O(n*m))\n if (removedIndices.length) {\n removedIndices.sort(function (a, b) {\n return a - b\n })\n var removedIdx = 0\n for (var m = 0; m < delimiterStack.length; m++) {\n var delim = delimiterStack[m]\n while (\n removedIdx < removedIndices.length &&\n removedIndices[removedIdx] < delim.nodeIndex\n )\n removedIdx++\n delim.nodeIndex -= removedIdx\n }\n }\n flushText(emailStart)\n result.push(emailResult)\n pos = emailEnd\n textStart = pos\n continue\n }\n }\n\n // HTML TAGS AND AUTOLINKS (check BEFORE escapes to preserve backslashes in autolinks)\n if (code === $.CHAR_LT) {\n if (handleHTMLTag(true, false)) continue\n }\n\n // BACKSLASH ESCAPES\n if (code === $.CHAR_BACKSLASH) {\n if (pos + 1 < end && charCode(source, pos + 1) === $.CHAR_NEWLINE) {\n var afterNewline = pos + 2\n while (\n afterNewline < end &&\n charCode(source, afterNewline) === $.CHAR_SPACE\n )\n afterNewline++\n if (afterNewline >= end) {\n pos++\n continue\n }\n flushText(pos)\n result.push({ type: RuleType.breakLine } as MarkdownToJSX.BreakLineNode)\n pos += 2\n while (pos < end && charCode(source, pos) === $.CHAR_SPACE) pos++\n textStart = pos\n continue\n }\n\n var nextChar = pos + 1 < end ? source[pos + 1] : ''\n if (\n nextChar &&\n '!\"#$%&\\'()*+,-./:;<=>?@[\\\\]^_`{|}~'.indexOf(nextChar) !== -1\n ) {\n flushText(pos)\n result.push({\n type: RuleType.text,\n text: nextChar === '&' ? '&\\u200B' : nextChar,\n } as MarkdownToJSX.TextNode)\n pos += 2\n textStart = pos\n continue\n }\n }\n\n // LINKS AND IMAGES - OPENING BRACKET\n if (code === $.CHAR_BRACKET_OPEN) {\n if (!inAnchor) {\n if (pos + 1 < end && source[pos + 1] === '^') {\n var footnoteEndPos = pos + 2\n while (footnoteEndPos < end && source[footnoteEndPos] !== ']')\n footnoteEndPos++\n if (footnoteEndPos < end) {\n var identifier = source.slice(pos + 2, footnoteEndPos)\n flushText(pos)\n result.push({\n type: RuleType.footnoteReference,\n target: `#${options.slugify(identifier)}`,\n text: identifier,\n } as MarkdownToJSX.FootnoteReferenceNode)\n pos = footnoteEndPos + 1\n textStart = pos\n continue\n }\n }\n\n if (\n state.inList &&\n pos + 2 < end &&\n charCode(source, pos + 2) === $.CHAR_BRACKET_CLOSE\n ) {\n var nextCode = charCode(source, pos + 1)\n if (\n nextCode === $.CHAR_SPACE ||\n nextCode === $.CHAR_x ||\n nextCode === $.CHAR_X\n ) {\n flushText(pos)\n result.push({\n type: RuleType.gfmTask,\n completed: nextCode === $.CHAR_x || nextCode === $.CHAR_X,\n } as MarkdownToJSX.GFMTaskNode)\n pos += 3\n textStart = pos\n continue\n }\n }\n }\n\n var isImage = false\n if (pos > start && source[pos - 1] === '!') {\n var backslashCount = 0\n for (\n var checkPos = pos - 2;\n checkPos >= start && source[checkPos] === '\\\\';\n checkPos--\n )\n backslashCount++\n if ((backslashCount & 1) === 0) {\n isImage = true\n if (textStart < pos - 1) flushText(pos - 1)\n if (\n result.length > 0 &&\n result[result.length - 1].type === RuleType.text\n ) {\n var lastText = result[result.length - 1] as MarkdownToJSX.TextNode\n if (lastText.text.endsWith('!')) {\n lastText.text = lastText.text.slice(0, -1)\n if (!lastText.text) result.pop()\n }\n }\n }\n }\n if (!isImage) flushText(pos)\n textStart = pos + 1\n if (!inAnchor || isImage) {\n bracketStack.push({\n type: isImage ? 'image' : 'link',\n pos: isImage ? pos - 1 : pos,\n resultIdx: result.length,\n inAnchor: inAnchor,\n })\n }\n\n pos++\n continue\n }\n\n // LINKS AND IMAGES - CLOSING BRACKET\n if (code === $.CHAR_BRACKET_CLOSE && bracketStack.length > 0) {\n var bracket = bracketStack[bracketStack.length - 1]\n var linkTextStart = bracket.pos + (bracket.type === 'image' ? 2 : 1)\n var linkTextEnd = pos\n flushText(pos)\n var afterBracket = pos + 1\n var linkChildren = buildLinkChildren(result, bracket)\n var hasNestedLink = bracket.type === 'link' && containsLink(linkChildren)\n var foundRefBrackets = false\n\n if (\n !hasNestedLink &&\n afterBracket < end &&\n source[afterBracket] === '('\n ) {\n var urlResult = parseUrlAndTitle(source, afterBracket + 1, true)\n if (urlResult) {\n finalizeLinkOrImageNode(\n result,\n delimiterStack,\n bracketStack,\n bracket,\n linkTextStart,\n linkTextEnd,\n options.sanitizer(\n unescapeUrlOrTitle(urlResult.target),\n 'a',\n 'href'\n ),\n urlResult.title ? unescapeUrlOrTitle(urlResult.title) : undefined\n )\n pos = urlResult.endPos\n textStart = pos\n continue\n }\n }\n\n var refs = state.refs || {}\n util.hasKeys(refs);\n var refLabel: string | null = null\n var refEnd = pos\n if (afterBracket < end && source[afterBracket] === '[') {\n var refStart = afterBracket + 1\n var i = refStart\n while (i < end && source[i] !== ']') i++\n if (i < end) {\n refLabel = source.slice(refStart, i)\n refEnd = i\n foundRefBrackets = true\n }\n }\n if (!foundRefBrackets || refLabel === '')\n refLabel = source.slice(linkTextStart, linkTextEnd)\n var normalizedRef = normalizeReferenceLabel(refLabel)\n if (!hasNestedLink && refs && refs[normalizedRef]) {\n var ref = refs[normalizedRef]\n finalizeLinkOrImageNode(\n result,\n delimiterStack,\n bracketStack,\n bracket,\n linkTextStart,\n linkTextEnd,\n ref.target,\n ref.title\n )\n pos = refEnd + 1\n textStart = pos\n continue\n }\n\n var bracketResultIdx = bracket.resultIdx\n bracketStack.pop()\n result.length = bracketResultIdx\n if (bracket.type === 'image')\n result.push({\n type: RuleType.text,\n text: '!',\n } as MarkdownToJSX.TextNode)\n result.push(\n { type: RuleType.text, text: '[' } as MarkdownToJSX.TextNode,\n ...linkChildren,\n { type: RuleType.text, text: ']' } as MarkdownToJSX.TextNode\n )\n for (var k = 0; k < delimiterStack.length; k++) {\n if (delimiterStack[k].nodeIndex >= bracketResultIdx)\n delimiterStack[k].nodeIndex++\n }\n pos++\n textStart = pos\n continue\n }\n\n // ========================================\n // EMPHASIS AND STRIKETHROUGH DELIMITERS (*, _, ~~, ==)\n // ========================================\n if (\n code === $.CHAR_ASTERISK ||\n code === $.CHAR_UNDERSCORE ||\n code === $.CHAR_TILDE ||\n code === $.CHAR_EQ\n ) {\n var delimChar = source[pos]\n var delimStart = pos\n var delimCount = countConsecutiveChars(source, pos, delimChar)\n\n // GFM strikethrough (~~) and marked text (==) require exactly 2 delimiters\n if ((delimChar === '~' || delimChar === '=') && delimCount !== 2) {\n pos++\n continue\n }\n\n var delimiterEnd = delimStart + delimCount\n var leftFlanking = checkFlanking(source, delimStart, delimiterEnd, end, 0)\n var rightFlanking = checkFlanking(\n source,\n delimStart,\n delimiterEnd,\n start,\n 1\n )\n var canOpen = leftFlanking\n var canClose = rightFlanking\n if (delimChar === '_' && leftFlanking && rightFlanking) {\n if (delimStart > 0) {\n var precedingChar = source[delimStart - 1]\n var precedingCode = charCode(precedingChar)\n canOpen = isPunctuation(precedingCode, precedingChar)\n }\n if (delimiterEnd < end) {\n var followingChar = source[delimiterEnd]\n var followingCode = charCode(followingChar)\n canClose = isPunctuation(followingCode, followingChar)\n }\n }\n flushText(delimStart)\n delimiterStack.push({\n nodeIndex: result.length,\n type: delimChar as '*' | '_' | '~' | '=',\n length: delimCount,\n canOpen: canOpen,\n canClose: canClose,\n active: true,\n sourcePos: delimStart,\n inAnchor: inAnchor,\n })\n result.push({\n type: RuleType.text,\n text: source.slice(delimStart, delimStart + delimCount),\n } as MarkdownToJSX.TextNode)\n\n pos = delimStart + delimCount\n textStart = pos\n continue\n }\n\n // ========================================\n // LINE BREAKS\n // ========================================\n if (code === $.CHAR_NEWLINE) {\n var checkPos = pos - 1\n var spaceCount = 0\n while (\n checkPos >= textStart &&\n charCode(source, checkPos) === $.CHAR_SPACE\n ) {\n spaceCount++\n checkPos--\n }\n if (spaceCount >= 2) {\n var afterNewline = pos + 1\n while (\n afterNewline < end &&\n charCode(source, afterNewline) === $.CHAR_SPACE\n )\n afterNewline++\n if (afterNewline >= end) {\n flushText(checkPos + 1)\n pos = end\n textStart = end\n continue\n }\n flushText(checkPos + 1)\n result.push({ type: RuleType.breakLine } as MarkdownToJSX.BreakLineNode)\n pos++\n while (pos < end && charCode(source, pos) === $.CHAR_SPACE) pos++\n textStart = pos\n continue\n }\n\n var prevCode = pos > textStart ? charCode(source, pos - 1) : 0\n var nextCode = pos + 1 < end ? charCode(source, pos + 1) : 0\n var flushPos =\n pos > textStart &&\n prevCode === $.CHAR_SPACE &&\n nextCode === $.CHAR_SPACE\n ? pos - 1\n : pos\n flushText(flushPos)\n result.push({ type: RuleType.text, text: '\\n' } as MarkdownToJSX.TextNode)\n textStart = pos + 1\n if (\n pos > start &&\n prevCode === $.CHAR_SPACE &&\n textStart < end &&\n charCode(source, textStart) === $.CHAR_SPACE\n )\n textStart++\n pos = textStart\n continue\n }\n\n if (code === $.CHAR_AMPERSAND) hasAmpersand = true\n pos++\n while (pos < end) {\n var code = charCode(source, pos)\n if (code >= $.CHAR_ASCII_BOUNDARY) break\n if (code === $.CHAR_AMPERSAND) hasAmpersand = true\n var lookupCharType = util.inlineCharTypeTable[code]\n if (lookupCharType === 0) {\n pos++\n continue\n }\n if (\n lookupCharType === 1 &&\n (code === $.CHAR_f || code === $.CHAR_H || code === $.CHAR_W) &&\n skipAutoLink\n ) {\n pos++\n continue\n }\n break\n }\n }\n\n flushText(pos)\n\n // Process emphasis using delimiter stack algorithm\n if (delimiterStack.length) {\n processEmphasis(result, delimiterStack, null)\n }\n\n // Insert bracket text nodes in forward order (more efficient than reverse splices)\n if (bracketStack.length) {\n bracketStack.sort(function (a, b) {\n return a.resultIdx - b.resultIdx\n })\n for (var i = 0; i < bracketStack.length; i++) {\n result.splice(bracketStack[i].resultIdx + i, 0, {\n type: RuleType.text,\n text: bracketStack[i].type === 'image' ? '![' : '[',\n } as MarkdownToJSX.TextNode)\n }\n }\n\n return result\n}\n\n// Helper: Process emphasis within link/image text and update delimiter stack\nfunction processEmphasisInLinkText(\n result: MarkdownToJSX.ASTNode[],\n delimiterStack: DelimiterEntry[],\n bracket: BracketEntry,\n linkTextStart: number,\n linkTextEnd: number\n): void {\n var hasDelims = false\n for (var di = 0; di < delimiterStack.length; di++) {\n if (\n delimiterStack[di].sourcePos >= linkTextStart &&\n delimiterStack[di].sourcePos < linkTextEnd\n ) {\n hasDelims = true\n break\n }\n }\n if (!hasDelims) return\n\n var tempNodes = buildLinkChildren(result, bracket)\n var tempDelims: DelimiterEntry[] = []\n for (var di = 0; di < delimiterStack.length; di++) {\n var delim = delimiterStack[di]\n if (delim.sourcePos >= linkTextStart && delim.sourcePos < linkTextEnd) {\n tempDelims.push({\n nodeIndex: delim.nodeIndex - bracket.resultIdx,\n type: delim.type,\n length: delim.length,\n canOpen: delim.canOpen,\n canClose: delim.canClose,\n active: delim.active,\n sourcePos: delim.sourcePos,\n inAnchor: delim.inAnchor,\n })\n }\n }\n processEmphasis(tempNodes, tempDelims, null)\n result.length = bracket.resultIdx\n for (var i = 0; i < tempNodes.length; i++) result.push(tempNodes[i])\n var newDelimStack: DelimiterEntry[] = []\n for (var di = 0; di < delimiterStack.length; di++) {\n if (\n delimiterStack[di].sourcePos < linkTextStart ||\n delimiterStack[di].sourcePos >= linkTextEnd\n ) {\n newDelimStack.push(delimiterStack[di])\n }\n }\n delimiterStack.length = 0\n for (var i = 0; i < newDelimStack.length; i++)\n delimiterStack.push(newDelimStack[i])\n}\n\n// Helper: Create link or image node from children and target/title\nfunction createLinkOrImageNode(\n bracket: BracketEntry,\n linkChildren: MarkdownToJSX.ASTNode[],\n target: string | null,\n title: string | undefined\n): MarkdownToJSX.ASTNode {\n if (bracket.type === 'link') {\n return {\n type: RuleType.link,\n target: target,\n title: title,\n children: linkChildren,\n } as MarkdownToJSX.LinkNode\n }\n return {\n type: RuleType.image,\n target: target || '',\n alt: extractAllTextFromNodes(linkChildren),\n title: title,\n } as MarkdownToJSX.ImageNode\n}\n\nfunction buildLinkChildren(\n result: MarkdownToJSX.ASTNode[],\n bracket: BracketEntry\n): MarkdownToJSX.ASTNode[] {\n return result.slice(bracket.resultIdx)\n}\n\nfunction finalizeLinkOrImageNode(\n result: MarkdownToJSX.ASTNode[],\n delimiterStack: DelimiterEntry[],\n bracketStack: BracketEntry[],\n bracket: BracketEntry,\n linkTextStart: number,\n linkTextEnd: number,\n target: string | null,\n title: string | undefined\n): void {\n processEmphasisInLinkText(\n result,\n delimiterStack,\n bracket,\n linkTextStart,\n linkTextEnd\n )\n var linkChildren = buildLinkChildren(result, bracket)\n bracketStack.pop()\n result.length = bracket.resultIdx\n result.push(createLinkOrImageNode(bracket, linkChildren, target, title))\n}\n\n/** Parse URL and optional title from parentheses: (url \"title\") */\n// Parse link destination (URL) - handles angle brackets and regular URLs\nfunction parseLinkDestination(\n source: string,\n start: number,\n allowNestedParens: boolean\n): { target: string; endPos: number; hadSpace: boolean } | null {\n let i = util.skipWhitespace(source, start)\n const hasAngleBrackets = i < source.length && source[i] === '<'\n if (hasAngleBrackets) i++\n const actualUrlStart = i\n\n // Handle empty angle brackets <>\n if (hasAngleBrackets && i < source.length && source[i] === '>') {\n return { target: '', endPos: i + 1, hadSpace: false }\n }\n\n let target: string\n let urlEnd: number\n var foundSpace = false\n\n if (hasAngleBrackets) {\n // For angle bracket URLs, parse until '>', allowing spaces and handling escapes\n urlEnd = i\n while (urlEnd < source.length && source[urlEnd] !== '>') {\n const c = source[urlEnd]\n if (c === '\\n' || c === '\\r' || c === '<') return null\n if (c === '\\\\') {\n urlEnd += 2\n continue\n }\n urlEnd++\n }\n if (urlEnd >= source.length || source[urlEnd] !== '>') return null\n urlEnd++\n // Trim leading and trailing whitespace inside < >\n let actualStart = actualUrlStart\n while (actualStart < urlEnd - 1 && isSpaceOrTab(source[actualStart]))\n actualStart++\n let actualEnd = urlEnd - 1\n while (actualEnd > actualStart && isSpaceOrTab(source[actualEnd - 1]))\n actualEnd--\n target = source.slice(actualStart, actualEnd)\n i = urlEnd\n } else {\n // Non-angle bracket URL: break on whitespace, newline\n let parenDepth = 0\n urlEnd = i\n while (urlEnd < source.length) {\n const c = source[urlEnd]\n if (c === ' ' || c === '\\t' || c === '\\n') {\n foundSpace = true\n break\n }\n if (!allowNestedParens && c === ')') break\n if (allowNestedParens && c === '(') {\n if (urlEnd > 0 && source[urlEnd - 1] === '\\\\') {\n urlEnd++\n continue\n }\n parenDepth++\n urlEnd++\n continue\n }\n if (allowNestedParens && c === ')') {\n if (urlEnd > 0 && source[urlEnd - 1] === '\\\\') {\n urlEnd++\n continue\n }\n if (parenDepth === 0) break\n parenDepth--\n urlEnd++\n continue\n }\n urlEnd++\n }\n target = source.slice(actualUrlStart, urlEnd)\n i = urlEnd\n }\n\n return { target, endPos: i, hadSpace: foundSpace }\n}\n\n// Parse link title - handles quoted and parenthesized titles\nfunction parseLinkTitle(\n source: string,\n start: number,\n hadSpaceInUrl: boolean,\n hasAngleBrackets: boolean\n): { title: string | undefined; endPos: number } {\n let i = start\n // Skip whitespace after URL\n let newlineCount = 0\n while (i < source.length) {\n const c = source[i]\n if (isSpaceOrTab(c)) {\n i++\n } else if (c === '\\n') {\n if (newlineCount >= 1) break\n newlineCount++\n i++\n } else if (util.isUnicodeWhitespace(c)) {\n break\n } else {\n break\n }\n }\n\n // If URL contained spaces and there's no title delimiter, the link is invalid\n if (hadSpaceInUrl && !hasAngleBrackets) {\n if (\n i >= source.length ||\n (source[i] !== '\"' && source[i] !== \"'\" && source[i] !== '(')\n ) {\n return { title: undefined, endPos: i }\n }\n }\n let title: string | undefined = undefined\n if (i < source.length) {\n const titleChar = source[i]\n if (titleChar === '\"' || titleChar === \"'\") {\n i++\n const titleStart = i\n while (i < source.length && source[i] !== titleChar) {\n if (source[i] === '\\\\') i++\n i++\n }\n if (i < source.length) {\n title = source.slice(titleStart, i)\n i++\n }\n } else if (titleChar === '(') {\n i++\n const titleStart = i\n let parenDepth = 1\n while (i < source.length && parenDepth > 0) {\n if (source[i] === '\\\\' && i + 1 < source.length) i++\n else if (source[i] === '(') parenDepth++\n else if (source[i] === ')') parenDepth--\n i++\n }\n if (parenDepth === 0) {\n title = source.slice(titleStart, i - 1)\n }\n }\n }\n\n i = util.skipWhitespace(source, i)\n return { title, endPos: i }\n}\n\nfunction parseUrlAndTitle(\n source: string,\n urlStart: number,\n allowNestedParens: boolean\n): { target: string; title: string | undefined; endPos: number } | null {\n const destResult = parseLinkDestination(source, urlStart, allowNestedParens)\n if (!destResult) return null\n\n let i = urlStart\n i = util.skipWhitespace(source, i)\n const hasAngleBrackets = i < source.length && source[i] === '<'\n\n // Handle empty angle brackets <>\n if (\n hasAngleBrackets &&\n destResult.target === '' &&\n destResult.endPos === i + 2\n ) {\n const titleResult = parseLinkTitle(\n source,\n destResult.endPos,\n false,\n hasAngleBrackets\n )\n if (\n titleResult.endPos >= source.length ||\n source[titleResult.endPos] !== ')'\n )\n return null\n return {\n target: '',\n title: titleResult.title,\n endPos: titleResult.endPos + 1,\n }\n }\n\n const titleResult = parseLinkTitle(\n source,\n destResult.endPos,\n destResult.hadSpace,\n hasAngleBrackets\n )\n if (titleResult.endPos >= source.length || source[titleResult.endPos] !== ')')\n return null\n\n return {\n target: destResult.target,\n title: titleResult.title,\n endPos: titleResult.endPos + 1,\n }\n}\n\nenum AutolinkMode {\n URI,\n EMAIL,\n ANGLE,\n}\n\nfunction isAlphaCode(code: number): boolean {\n return (\n (code >= $.CHAR_A && code <= $.CHAR_Z) ||\n (code >= $.CHAR_a && code <= $.CHAR_z)\n )\n}\n\nfunction isValidUriScheme(content: string): boolean {\n const colonPos = content.indexOf(':')\n if (colonPos < 2 || colonPos > 32) return false\n\n const firstCharCode = charCode(content)\n if (!isAlphaCode(firstCharCode)) {\n return false\n }\n\n // Check if all chars before colon are valid scheme chars\n for (let j = 1; j < colonPos; j++) {\n const c = content[j]\n const cCode = charCode(c)\n if (!isAlnum(c) && c !== '+' && c !== '.' && c !== '-') {\n return false\n }\n }\n return true\n}\n\nfunction isValidAutolinkContext(\n source: string,\n start: number,\n includeCR: boolean\n): boolean {\n if (start === 0) return true\n let validChars = includeCR ? ' \\t\\n\\r*_~(' : ' \\t\\n*_~('\n return validChars.indexOf(source[start - 1]) !== -1\n}\n\nfunction sanitizeAndCreate(\n target: string,\n linkText: string,\n endPos: number,\n sanitizer: (url: string, tag: string, attr: string) => string | null,\n emailStart?: number\n): ParseResult | null {\n let safe = sanitizer(target, 'a', 'href')\n if (!safe) return null\n return {\n type: RuleType.link,\n target: safe,\n children: [{ type: RuleType.text, text: linkText }],\n endPos: endPos,\n ...(emailStart !== undefined ? { emailStart } : {}),\n } as MarkdownToJSX.LinkNode & { endPos: number; emailStart?: number }\n}\n\nfunction parseAutolink(\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions,\n mode: AutolinkMode\n): ParseResult | null {\n if (\n state.inAnchor ||\n (mode !== AutolinkMode.ANGLE && options.disableAutoLink)\n )\n return null\n\n if (mode === AutolinkMode.ANGLE) {\n if (source[pos] !== '<') return null\n let end = pos + 1\n while (end < source.length && source[end] !== '>') {\n const endCode = charCode(source, end)\n if (\n endCode === $.CHAR_SPACE ||\n endCode === $.CHAR_TAB ||\n endCode === $.CHAR_NEWLINE ||\n endCode === $.CHAR_CR ||\n endCode < $.CHAR_SPACE\n )\n return null\n end++\n }\n if (end >= source.length || source[end] !== '>') return null\n let content = source.slice(pos + 1, end)\n if (!content.length) return null\n\n let hasBackslash = content.indexOf('\\\\') !== -1\n let hasValidUriScheme = isValidUriScheme(content)\n let isHttp =\n util.startsWith(content, 'http://') ||\n util.startsWith(content, 'https://')\n let isMailto = false\n if (!hasValidUriScheme && !isHttp && content.length >= 7) {\n const firstChar = content[0]\n if (firstChar === 'm' || firstChar === 'M') {\n const contentLower = content.toLowerCase()\n if (util.startsWith(contentLower, 'mailto:')) {\n isMailto = true\n let colonPos = contentLower.indexOf(':')\n let mailtoText = content.slice(colonPos + 1)\n return sanitizeAndCreate(\n 'mailto:' + mailtoText,\n content,\n end + 1,\n options.sanitizer\n )\n }\n }\n }\n let isEmailLike =\n !hasBackslash &&\n content.indexOf('@') !== -1 &&\n content.indexOf('//') === -1 &&\n !hasValidUriScheme\n\n if (!isHttp && !isMailto && !isEmailLike && !hasValidUriScheme) return null\n\n let target = content,\n linkText = content\n if (!isMailto && !hasValidUriScheme && !isHttp && isEmailLike) {\n target = 'mailto:' + content\n }\n\n return sanitizeAndCreate(target, linkText, end + 1, options.sanitizer)\n }\n\n if (mode === AutolinkMode.EMAIL) {\n let emailStart = pos\n while (\n emailStart > 0 &&\n (isAlnum(source[emailStart - 1]) ||\n '.+-_'.indexOf(source[emailStart - 1]) !== -1)\n )\n emailStart--\n if (emailStart >= pos || !isValidAutolinkContext(source, emailStart, true))\n return null\n\n let emailEnd = pos + 1\n let hasDot = false\n while (emailEnd < source.length) {\n let c = source[emailEnd]\n if (c === '.') {\n hasDot = true\n emailEnd++\n } else if (isAlnum(c) || c === '-' || c === '_') emailEnd++\n else break\n }\n\n if (!hasDot || emailEnd <= pos + 1) return null\n while (emailEnd > pos + 1 && source[emailEnd - 1] === '.') emailEnd--\n if (\n emailEnd > pos + 1 &&\n (source[emailEnd - 1] === '-' || source[emailEnd - 1] === '_')\n )\n return null\n // Check if email contains at least one dot\n // For large documents, prefer slice+includes to avoid scanning entire document\n const emailLength = emailEnd - (pos + 1)\n if (emailLength < 10000) {\n if (\n source.indexOf('.', pos + 1) >= emailEnd ||\n source.indexOf('.', pos + 1) === -1\n )\n return null\n } else {\n if (source.slice(pos + 1, emailEnd).indexOf('.') === -1) return null\n }\n\n let email = source.slice(emailStart, emailEnd)\n return sanitizeAndCreate(\n 'mailto:' + email,\n email,\n emailEnd,\n options.sanitizer,\n emailStart\n )\n }\n\n let isHttp =\n util.startsWith(source, 'http://', pos) ||\n util.startsWith(source, 'https://', pos)\n let isFtp = !isHttp && util.startsWith(source, 'ftp://', pos)\n let isWww = !isHttp && !isFtp && util.startsWith(source, 'www.', pos)\n if (\n !(isHttp || isFtp || isWww) ||\n !isValidAutolinkContext(source, pos, false)\n )\n return null\n\n var urlEnd =\n pos +\n (isHttp ? (charCode(source, pos + 4) === $.CHAR_s ? 8 : 7) : isFtp ? 6 : 4)\n var domainStart = urlEnd\n // Inline scanDomain\n while (urlEnd < source.length) {\n const code = charCode(source, urlEnd)\n if (\n code === $.CHAR_SPACE ||\n code === $.CHAR_TAB ||\n code === $.CHAR_NEWLINE ||\n code === $.CHAR_LT ||\n code === $.CHAR_GT\n )\n break\n urlEnd++\n }\n if (urlEnd <= domainStart) return null\n // Inline trimTrailingPunct\n let trimmed = urlEnd\n while (trimmed > domainStart) {\n let lastChar = source[trimmed - 1]\n if (trimmed > domainStart + 1 && source[trimmed - 2] === '\\\\') break\n if (\n lastChar === '?' ||\n lastChar === '!' ||\n lastChar === '.' ||\n lastChar === ',' ||\n lastChar === ':' ||\n lastChar === '*' ||\n lastChar === '_' ||\n lastChar === '~'\n ) {\n trimmed--\n } else if (lastChar === ';') {\n let ampPos = trimmed - 2\n while (\n ampPos >= domainStart &&\n source[ampPos] !== '&' &&\n source[ampPos] !== ' '\n )\n ampPos--\n if (ampPos >= domainStart && source[ampPos] === '&') {\n let entityName = source.slice(ampPos + 1, trimmed - 1)\n if (\n entityName.length >= 2 &&\n entityName.length <= 10 &&\n /^[a-zA-Z0-9]+$/.test(entityName) &&\n (entityName === 'lt' ||\n entityName === 'gt' ||\n (entityName.length >= 3 &&\n (util.startsWith(entityName, 'amp') ||\n util.startsWith(entityName, 'apos') ||\n util.startsWith(entityName, 'quot') ||\n util.startsWith(entityName, 'nbsp') ||\n /^[a-z]{3,10}$/.test(entityName))))\n )\n break\n trimmed = ampPos\n break\n }\n trimmed--\n } else if (lastChar === ')') {\n let openCount = 0,\n closeCount = 0\n for (let i = domainStart; i < trimmed; i++) {\n if (source[i] === '(') openCount++\n if (source[i] === ')') closeCount++\n }\n if (closeCount > openCount) trimmed--\n else break\n } else break\n }\n urlEnd = trimmed\n if (urlEnd <= domainStart) return null\n\n var domainEnd = domainStart\n var lastDot = -1\n var secondLastDot = -1\n while (domainEnd < urlEnd) {\n const domainCode = charCode(source, domainEnd)\n if (\n (domainCode >= $.CHAR_A && domainCode <= $.CHAR_Z) ||\n (domainCode >= $.CHAR_a && domainCode <= $.CHAR_z) ||\n (domainCode >= $.CHAR_DIGIT_0 && domainCode <= $.CHAR_DIGIT_9) ||\n domainCode === $.CHAR_DASH ||\n domainCode === $.CHAR_UNDERSCORE ||\n domainCode === $.CHAR_PERIOD\n ) {\n if (domainCode === $.CHAR_PERIOD) {\n secondLastDot = lastDot\n lastDot = domainEnd\n }\n domainEnd++\n continue\n }\n break\n }\n if (domainEnd === domainStart || lastDot === -1) return null\n if (secondLastDot === -1) secondLastDot = domainStart - 1\n for (let i = secondLastDot + 1; i < lastDot; i++) {\n if (source[i] === '_') return null\n }\n for (let i = lastDot + 1; i < domainEnd; i++) {\n if (source[i] === '_') return null\n }\n\n let linkText = source.slice(pos, urlEnd)\n return sanitizeAndCreate(\n isWww ? 'http://' + linkText : linkText,\n linkText,\n urlEnd,\n options.sanitizer\n )\n}\n\n// Unified link/image parser - handles all link/image types based on starting character\nfunction parseLinkOrImage(\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions,\n startChar: '[' | '!' | '<' | 'h' | 'f' | 'w' | '@'\n): ParseResult | null {\n // Angle brace autolink: <url>\n if (startChar === '<') {\n return parseAutolink(\n source,\n pos,\n state,\n options,\n AutolinkMode.ANGLE\n ) as ParseResult\n }\n\n // Bare URL autolink: http://, https://, ftp://, www.\n if (startChar === 'h' || startChar === 'f' || startChar === 'w') {\n return parseAutolink(\n source,\n pos,\n state,\n options,\n AutolinkMode.URI\n ) as ParseResult\n }\n\n // Email autolink: @example.com\n if (startChar === '@') {\n return parseAutolink(\n source,\n pos,\n state,\n options,\n AutolinkMode.EMAIL\n ) as ParseResult | null\n }\n\n // Bracket-based links/images are handled inline in parseInlineSpan\n // This function only handles autolinks\n return null\n}\n\nfunction normalizeReferenceLabel(label: string): string {\n var trimmed = label.trim()\n var normalized = trimmed.replace(/[\\s\\t\\n\\r]+/g, ' ')\n if (normalized.indexOf('\\u1E9E') !== -1) {\n return normalized.replace(/\\u1E9E/g, 'ss').toLowerCase();\n }\n return normalized.toLowerCase()\n}\n\nfunction parseGFMTask(\n source: string,\n pos: number,\n state: MarkdownToJSX.State\n): ParseResult {\n if (pos + 3 >= source.length || source[pos] !== '[') return null\n const marker = source[pos + 1]\n if (marker !== ' ' && marker !== 'x' && marker !== 'X') return null\n if (source[pos + 2] !== ']') return null\n return {\n type: RuleType.gfmTask,\n completed: marker.toLowerCase() === 'x',\n endPos: pos + 3,\n } as MarkdownToJSX.GFMTaskNode & { endPos: number }\n}\n\nfunction parseBlocksWithState(\n content: string,\n state: MarkdownToJSX.State,\n options: ParseOptions,\n config: { inline?: boolean; list?: boolean; inBlockQuote?: boolean }\n): MarkdownToJSX.ASTNode[] {\n const originalInline = state.inline\n const originalList = state.inList\n const originalInBlockQuote = state.inBlockQuote\n if (config.inline !== undefined) state.inline = config.inline\n if (config.list !== undefined) state.inList = config.list\n if (config.inBlockQuote !== undefined)\n state.inBlockQuote = config.inBlockQuote\n const blocks = parseBlocksInHTML(content, state, options)\n state.inline = originalInline\n state.inList = originalList\n state.inBlockQuote = originalInBlockQuote\n return blocks\n}\n\nfunction parseInlineWithState(\n content: string,\n start: number,\n end: number,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): MarkdownToJSX.ASTNode[] {\n return parseWithInlineMode(state, true, () =>\n parseInlineSpan(content, start, end, state, options)\n )\n}\n\ntype BlockParserFn = (\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions\n) => ParseResult | null\n\nfunction parseBlock(\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): ParseResult | null {\n var char = source[pos]\n if (char === undefined) return null\n var effectivePos = pos\n var indentInfo: ReturnType<typeof calculateIndent> | null = null\n var firstChar = char\n var lineEnd: number | null = null\n\n var charCodeVal = charCode(char)\n var isIndentChar = charCodeVal === $.CHAR_SPACE || charCodeVal === $.CHAR_TAB\n if (isIndentChar) {\n lineEnd = util.findLineEnd(source, pos)\n indentInfo = calculateIndent(source, pos, lineEnd)\n effectivePos = pos + indentInfo.charCount\n if (effectivePos >= source.length) return parseCodeBlock(source, pos, state)\n firstChar = source[effectivePos]\n }\n var spaceEquivalent = indentInfo ? indentInfo.spaceEquivalent : 0\n if (spaceEquivalent >= 4) {\n if (isIndentChar) return parseCodeBlock(source, pos, state)\n return null\n }\n var firstCharCode = charCode(firstChar)\n if (firstCharCode === $.CHAR_GT) {\n var blockQuoteResult = parseBlockQuote(source, pos, state, options)\n if (blockQuoteResult) return blockQuoteResult\n } else if (firstCharCode === $.CHAR_UNDERSCORE) {\n return parseBreakThematic(source, pos, state, options)\n } else if (\n firstCharCode === $.CHAR_DASH ||\n firstCharCode === $.CHAR_ASTERISK ||\n firstCharCode === $.CHAR_PLUS\n ) {\n var thematicBreakResult = parseBreakThematic(source, pos, state, options)\n if (thematicBreakResult) return thematicBreakResult\n var listResult = parseList(source, pos, state, options)\n if (listResult) return listResult\n } else if (\n firstCharCode >= $.CHAR_DIGIT_0 &&\n firstCharCode <= $.CHAR_DIGIT_9\n ) {\n var listResult = parseList(source, pos, state, options)\n if (listResult) return listResult\n } else if (firstCharCode === $.CHAR_HASH) {\n return parseHeading(source, effectivePos, state, options)\n } else if (firstCharCode === $.CHAR_BRACKET_OPEN) {\n return parseDefinition(\n source,\n effectivePos,\n state,\n options,\n effectivePos + 1 < source.length &&\n charCode(source, effectivePos + 1) === $.CHAR_CARET\n )\n } else if (firstCharCode === $.CHAR_LT && !options.disableParsingRawHTML) {\n return parseHTML(source, effectivePos, state, options)\n } else if (\n firstCharCode === $.CHAR_BACKTICK ||\n firstCharCode === $.CHAR_TILDE\n ) {\n if (!lineEnd) lineEnd = util.findLineEnd(source, pos)\n if (!indentInfo) indentInfo = calculateIndent(source, pos, lineEnd)\n if (indentInfo.spaceEquivalent <= 3)\n return parseCodeFenced(source, effectivePos, state, options)\n } else if (firstCharCode === $.CHAR_PIPE) {\n return parseTable(source, pos, state, options)\n }\n if (isIndentChar) return parseCodeBlock(source, pos, state)\n return null\n}\n\n/** Parse blocks inside HTML content */\nfunction parseBlocksInHTML(\n input: string,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): MarkdownToJSX.ASTNode[] {\n const result: MarkdownToJSX.ASTNode[] = []\n let pos = 0\n\n while (pos < input.length) {\n while (pos < input.length && input[pos] === '\\n') {\n pos++\n }\n\n if (pos >= input.length) break\n\n var char = input[pos]\n\n // Fast path: check for setext heading in list context\n // Per CommonMark: setext headings take precedence over thematic breaks\n if (state.inList && result.length > 0) {\n var lastBlock = result[result.length - 1]\n if (lastBlock?.type === RuleType.paragraph) {\n var paragraph = lastBlock as MarkdownToJSX.ParagraphNode\n // Quick check for potential setext underline characters\n var code = charCode(char)\n if (\n code === $.CHAR_DASH ||\n code === $.CHAR_EQ ||\n code === $.CHAR_SPACE ||\n code === $.CHAR_TAB\n ) {\n var lineEnd = util.findLineEnd(input, pos)\n var lineContent = input.slice(pos, lineEnd)\n\n // Check indentation (up to 3 spaces allowed for setext headings)\n var indentInfo = calculateIndent(input, pos, lineEnd)\n if (indentInfo.spaceEquivalent < 4) {\n var trimmed = lineContent.slice(indentInfo.charCount).trim()\n // Use convertSetextHeadingInListItem helper to check and convert\n if (convertSetextHeadingInListItem(result, trimmed, options)) {\n pos =\n lineEnd +\n (lineEnd < input.length && input[lineEnd] === '\\n' ? 1 : 0)\n continue\n }\n }\n }\n }\n }\n\n // Try parseBlock first (handles most block types)\n var blockResult = parseBlock(input, pos, state, options)\n if (blockResult) {\n result.push(blockResult)\n pos = blockResult.endPos\n continue\n }\n\n // Try setext heading (not handled by parseBlock)\n var setextResult = parseHeadingSetext(input, pos, state, options)\n if (setextResult) {\n result.push(setextResult)\n pos = setextResult.endPos\n continue\n }\n\n var remaining = input.slice(pos).trim()\n if (remaining) {\n // Per CommonMark spec example 293: Before parsing a paragraph, check if there's\n // a blockquote ending with a paragraph in recent blocks that this should merge into\n if (state.inBlockQuote && result.length > 0) {\n // Find the deepest blockquote ending with a paragraph in recent blocks\n // (may be nested inside list items)\n function findBlockquoteWithParagraphEnd(\n node: MarkdownToJSX.ASTNode\n ): MarkdownToJSX.ParagraphNode | null {\n if (node.type === RuleType.blockQuote) {\n var blockQuote = node as MarkdownToJSX.BlockQuoteNode\n if (blockQuote.children && blockQuote.children.length > 0) {\n var lastChild =\n blockQuote.children[blockQuote.children.length - 1]\n if (lastChild.type === RuleType.paragraph) {\n return lastChild as MarkdownToJSX.ParagraphNode\n }\n }\n } else if (\n node.type === RuleType.orderedList ||\n node.type === RuleType.unorderedList\n ) {\n var list = node as\n | MarkdownToJSX.OrderedListNode\n | MarkdownToJSX.UnorderedListNode\n if (list.items && list.items.length > 0) {\n var lastItem = list.items[list.items.length - 1]\n if (lastItem && lastItem.length > 0) {\n var lastItemChild = lastItem[lastItem.length - 1]\n var found = findBlockquoteWithParagraphEnd(lastItemChild)\n if (found) return found\n }\n }\n }\n return null\n }\n\n // Check recent blocks (from end) for blockquote ending with paragraph\n for (var i = result.length - 1; i >= 0; i--) {\n var paragraph = findBlockquoteWithParagraphEnd(result[i])\n if (paragraph) {\n var parseResult = parseParagraph(input, pos, state, options)\n if (parseResult) {\n var newParagraph = parseResult as MarkdownToJSX.ParagraphNode\n // Merge the new paragraph's children into the blockquote's paragraph\n if (paragraph.children && newParagraph.children) {\n paragraph.children.push(\n { type: RuleType.text, text: '\\n' } as MarkdownToJSX.TextNode,\n ...newParagraph.children\n )\n }\n pos = parseResult.endPos\n continue\n }\n }\n }\n }\n\n var parseResult = parseParagraph(input, pos, state, options)\n if (parseResult) {\n result.push(parseResult)\n pos = parseResult.endPos\n continue\n }\n }\n\n pos++\n }\n\n return result\n}\n\nfunction parseHeading(\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): ParseResult {\n if (state.inline) return null\n\n // Find line end to limit expensive indentation scan\n const lineEnd = util.findLineEnd(source, pos)\n const indentResult = calculateIndent(source, pos, lineEnd, 3)\n if (indentResult.spaceEquivalent > 3 && !state.inList) return null\n var i = pos + indentResult.charCount\n\n if (i >= source.length || source[i] !== '#') return null\n\n const level = countConsecutiveChars(source, i, '#', 6)\n i += level\n\n if (i >= source.length) return null\n const afterHash = source[i]\n if (afterHash === '\\n' || afterHash === '\\r') {\n const lineEnd = util.findLineEnd(source, i)\n return {\n ...createHeading(level, [], '', options.slugify),\n endPos: lineEnd + (lineEnd < source.length ? 1 : 0),\n } as MarkdownToJSX.HeadingNode & { endPos: number }\n }\n if (afterHash !== ' ' && afterHash !== '\\t') return null\n\n const contentStart = i\n const contentEnd = util.findLineEnd(source, contentStart)\n var content = source\n .slice(contentStart, contentEnd)\n .replace(HEADING_TRAILING_HASHES_R, '')\n .trim()\n\n const children = parseInlineWithState(\n content,\n 0,\n content.length,\n state,\n options\n )\n\n return {\n ...createHeading(level, children, content, options.slugify),\n endPos: contentEnd + (contentEnd < source.length ? 1 : 0),\n } as MarkdownToJSX.HeadingNode & { endPos: number }\n}\n\nfunction parseHeadingSetext(\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): ParseResult {\n if (state.inline || state.inBlockQuote || state.inList) return null\n\n const firstLineEnd = util.findLineEnd(source, pos)\n if (firstLineEnd >= source.length) return null\n\n // Find underline pattern first, then validate backwards\n let underlineLineStart = skipToNextLine(source, firstLineEnd),\n underlineLineEnd = -1,\n underlineChar: string | null = null\n\n // Scan forward for underline (= or - with up to 3 spaces indentation)\n for (\n var linesScanned = 0;\n underlineLineStart < source.length && linesScanned < 10;\n linesScanned++\n ) {\n const lineEnd = util.findLineEnd(source, underlineLineStart)\n if (lineEnd >= source.length) break\n\n // Check if blank line (stops setext headings)\n var i = underlineLineStart\n while (\n i < lineEnd &&\n (charCode(source, i) === $.CHAR_SPACE ||\n charCode(source, i) === $.CHAR_TAB ||\n charCode(source, i) === $.CHAR_CR)\n )\n i++\n if (i >= lineEnd) break\n\n // Check indentation (up to 3 spaces) and first char\n var indentCount = 0,\n checkPos = underlineLineStart\n while (\n checkPos < lineEnd &&\n indentCount < 3 &&\n charCode(source, checkPos) === $.CHAR_SPACE\n ) {\n indentCount++\n checkPos++\n }\n\n if (checkPos < lineEnd) {\n const code = charCode(source, checkPos)\n if (code === $.CHAR_EQ || code === $.CHAR_DASH) {\n // Validate underline: only = or - with optional trailing spaces, no internal spaces\n const char = source[checkPos]\n var underlineCount = 0,\n hasSeenWS = false,\n p = checkPos\n while (p < lineEnd) {\n const c = charCode(source, p)\n if (c === code) {\n if (hasSeenWS) {\n underlineCount = 0\n break\n }\n underlineCount++\n } else if (c === $.CHAR_SPACE || c === $.CHAR_TAB) {\n hasSeenWS = true\n } else {\n underlineCount = 0\n break\n }\n p++\n }\n\n if (underlineCount >= 1) {\n underlineLineEnd = lineEnd\n underlineChar = char\n break\n }\n }\n }\n\n underlineLineStart = skipToNextLine(source, lineEnd)\n }\n\n if (!underlineChar) return null\n\n // Quick validation: content cannot start with certain block characters\n const firstCharCode = charCode(source, pos)\n if (\n firstCharCode === $.CHAR_HASH ||\n firstCharCode === $.CHAR_GT ||\n source[pos] === '|'\n )\n return null\n\n // Collect content lines forward to underline\n let contentEnd = pos\n var currentPos = pos,\n hasContent = false\n\n while (currentPos < underlineLineStart) {\n const lineEnd = util.findLineEnd(source, currentPos)\n if (lineEnd >= underlineLineStart) break\n\n // Check if line has non-whitespace content\n var j = currentPos\n while (\n j < lineEnd &&\n (charCode(source, j) === $.CHAR_SPACE ||\n charCode(source, j) === $.CHAR_TAB ||\n charCode(source, j) === $.CHAR_CR)\n )\n j++\n if (j < lineEnd) {\n // Line has content\n hasContent = true\n contentEnd = lineEnd\n }\n\n currentPos = skipToNextLine(source, lineEnd)\n }\n\n if (!hasContent) return null\n\n // Extract and trim content\n const rawContent = source.slice(pos, contentEnd)\n var startTrim = 0,\n endTrim = rawContent.length\n while (\n startTrim < endTrim &&\n (rawContent.charCodeAt(startTrim) === $.CHAR_SPACE ||\n rawContent.charCodeAt(startTrim) === $.CHAR_TAB ||\n rawContent.charCodeAt(startTrim) === $.CHAR_CR ||\n rawContent.charCodeAt(startTrim) === $.CHAR_NEWLINE)\n )\n startTrim++\n while (\n endTrim > startTrim &&\n (rawContent.charCodeAt(endTrim - 1) === $.CHAR_SPACE ||\n rawContent.charCodeAt(endTrim - 1) === $.CHAR_TAB ||\n rawContent.charCodeAt(endTrim - 1) === $.CHAR_CR ||\n rawContent.charCodeAt(endTrim - 1) === $.CHAR_NEWLINE)\n )\n endTrim--\n const content = rawContent.slice(startTrim, endTrim)\n\n if (!content) return null\n\n const level = underlineChar === '=' ? 1 : 2\n const children = parseInlineWithState(\n content,\n 0,\n content.length,\n state,\n options\n )\n\n return {\n ...createHeading(level, children, content, options.slugify),\n endPos: underlineLineEnd + (underlineLineEnd < source.length ? 1 : 0),\n } as MarkdownToJSX.HeadingNode & { endPos: number }\n}\n\nfunction parseParagraph(\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): ParseResult {\n // Note: We don't check isBlockStartChar here because this is called as a fallback\n // after other block parsers have already tried and failed\n if (state.inline) return null\n let endPos = pos\n const sourceLen = source.length\n\n while (endPos < sourceLen) {\n let lineEnd = util.findLineEnd(source, endPos)\n let isEmptyLine = true\n\n for (let i = endPos; i < lineEnd; i++) {\n const code = charCode(source, i)\n if (code !== $.CHAR_SPACE && code !== $.CHAR_TAB && code !== $.CHAR_CR) {\n isEmptyLine = false\n break\n }\n }\n\n if (isEmptyLine) {\n endPos = lineEnd\n break\n }\n\n if (lineEnd >= sourceLen) {\n endPos = sourceLen\n break\n }\n\n const nextLineStart = skipToNextLine(source, lineEnd)\n if (nextLineStart >= sourceLen) {\n endPos = sourceLen\n break\n }\n\n let nextLineEnd = util.findLineEnd(source, nextLineStart)\n let nextLineIsEmpty = true\n let nextLineFirstChar = ''\n\n for (let i = nextLineStart; i < nextLineEnd; i++) {\n const code = charCode(source, i)\n if (code !== $.CHAR_SPACE && code !== $.CHAR_TAB && code !== $.CHAR_CR) {\n nextLineIsEmpty = false\n if (nextLineFirstChar === '') nextLineFirstChar = source[i]\n break\n }\n }\n\n if (nextLineIsEmpty) {\n endPos = lineEnd\n break\n }\n\n // Check if next line starts with a block element\n // BUT: per CommonMark, lines indented by exactly 4 spaces are paragraph continuation,\n // not code blocks or other blocks, even if they start with block-starting characters.\n let shouldBreak = false\n const nextIndentInfo = calculateIndent(source, nextLineStart, nextLineEnd)\n const isExact4SpaceIndent =\n nextIndentInfo.spaceEquivalent === 4 && nextIndentInfo.charCount === 4\n\n // Check for HTML blocks first (types 1-6 can interrupt paragraphs)\n // Per CommonMark spec: HTML blocks of types 1-6 can interrupt paragraphs\n if (\n nextLineFirstChar === '<' &&\n !isExact4SpaceIndent &&\n !options.disableParsingRawHTML\n ) {\n const htmlCheckPos = nextLineStart\n let htmlLineStart = htmlCheckPos\n let htmlIndent = 0\n while (htmlLineStart < nextLineEnd && htmlIndent < 3) {\n const code = charCode(source, htmlLineStart)\n if (code === $.CHAR_SPACE || code === $.CHAR_TAB) {\n htmlIndent++\n htmlLineStart++\n } else {\n break\n }\n }\n if (htmlLineStart < nextLineEnd && source[htmlLineStart] === '<') {\n var htmlResult = parseHTML(\n source,\n htmlLineStart,\n { ...state, inline: false },\n options\n )\n if (htmlResult) {\n shouldBreak =\n !('canInterruptParagraph' in htmlResult) ||\n (htmlResult.canInterruptParagraph as boolean)\n }\n }\n }\n\n // In list context, lines indented to the content start column are also continuation\n // For now, treat 4-space indented lines as continuation regardless of context\n if (isExact4SpaceIndent) {\n // Line is indented exactly 4 spaces - this is paragraph continuation\n // Per CommonMark spec: lines indented by exactly 4 spaces are paragraph continuation,\n // not code blocks or other blocks, even if they start with block-starting characters.\n // Don't break, continue paragraph across this line\n shouldBreak = false\n } else if (\n !shouldBreak &&\n nextLineFirstChar &&\n isBlockStartChar(nextLineFirstChar)\n ) {\n // Reference definitions don't break paragraphs - skip them\n if (nextLineFirstChar === '[') {\n // Check if it's a reference definition (not a footnote)\n const checkPos = nextLineStart\n if (checkPos + 1 >= sourceLen || source[checkPos + 1] !== '^') {\n // Could be a reference definition - don't break paragraph\n shouldBreak = false\n } else {\n // Footnote definition - break paragraph\n shouldBreak = true\n }\n } else if (nextLineFirstChar === '*' || nextLineFirstChar === '+') {\n // Asterisk/plus is only a block start for lists (*/+ followed by space/tab) or thematic breaks (3+ alone)\n // But thematic breaks can have up to 3 spaces indentation, so check for thematic break first\n const thematicBreakResult = parseBreakThematic(\n source,\n nextLineStart,\n state,\n options\n )\n if (thematicBreakResult) {\n shouldBreak = true\n } else {\n // Check if it's a list (followed by space/tab)\n const secondChar =\n nextLineStart + 1 < sourceLen ? source[nextLineStart + 1] : ''\n if (secondChar && isSpaceOrTab(secondChar)) {\n shouldBreak = true\n } else {\n // Not a list or thematic break - don't break paragraph\n shouldBreak = false\n }\n }\n } else {\n // Use parseBlock to check if next line starts a block\n // Special handling needed for setext headings and ordered lists\n const blockResult = parseBlock(source, nextLineStart, state, options)\n\n if (blockResult) {\n // Check if it's a code block from 4+ space indentation (paragraph continuation)\n if (blockResult.type === RuleType.codeBlock) {\n const blockIndentInfo = calculateIndent(\n source,\n nextLineStart,\n nextLineEnd\n )\n if (blockIndentInfo.spaceEquivalent >= 4) {\n // 4+ space indentation is paragraph continuation, not a block start\n shouldBreak = false\n } else {\n // Fenced code block - break paragraph\n shouldBreak = true\n }\n } else if (\n blockResult.type === RuleType.unorderedList ||\n blockResult.type === RuleType.orderedList\n ) {\n // Lists can interrupt paragraphs, but ordered lists starting with numbers other than 1 cannot\n if (blockResult.type === RuleType.orderedList) {\n const orderedList = blockResult as MarkdownToJSX.OrderedListNode\n // Only ordered lists starting with 1 can interrupt paragraphs\n shouldBreak = orderedList.start === 1\n } else {\n shouldBreak = true\n }\n } else if (nextLineFirstChar === '-') {\n // Dash could be setext heading underline if preceded by content\n // Per CommonMark: setext headings take precedence over thematic breaks\n if (endPos > pos) {\n // We have content - break paragraph to let setext heading parser check\n shouldBreak = true\n } else {\n // No content - use the block result (thematic break or list)\n shouldBreak = true\n }\n } else if (blockResult.type === RuleType.ref) {\n // Reference definitions don't break paragraphs\n shouldBreak = false\n } else {\n // Other block types break paragraphs\n shouldBreak = true\n }\n }\n }\n } else {\n // Next line doesn't start with a block-starting character\n // Per CommonMark: in paragraph context, lines indented by exactly 4 spaces\n // are paragraph continuation, not code blocks. Only 4+ spaces at document\n // start (not in paragraph) are code blocks.\n // So we don't break on 4-space indentation in paragraph continuation.\n }\n\n if (shouldBreak) {\n endPos = lineEnd\n break\n }\n\n // Continue paragraph across single newline\n endPos = skipToNextLine(source, lineEnd)\n }\n\n if (endPos <= pos) return null\n\n // Per CommonMark: lines indented by exactly 4 spaces in paragraph context\n // are continuation, not code blocks. We need to remove the 4-space indentation\n // from continuation lines but preserve them as part of the paragraph.\n var contentStart = pos\n var contentEnd = endPos\n\n while (contentStart < contentEnd) {\n const code = charCode(source, contentStart)\n if (code === $.CHAR_SPACE || code === $.CHAR_TAB) {\n contentStart++\n } else {\n break\n }\n }\n\n // Fast path: if no newlines, use content directly (common case)\n // Check if there's a newline between contentStart and contentEnd\n // We can optimize by checking if contentEnd is beyond the first line\n const firstLineEnd = util.findLineEnd(source, contentStart)\n var hasNewline = contentEnd > firstLineEnd\n\n var processedContent\n if (!hasNewline) {\n // Single line - no processing needed\n processedContent = source.slice(contentStart, contentEnd)\n } else {\n // Multi-line: process 4-space indentation\n var processedParts: string[] = []\n var lineStart = contentStart\n var lineIndex = 0\n\n while (lineStart < contentEnd) {\n var lineEnd = util.findLineEnd(source, lineStart)\n if (lineEnd > contentEnd) lineEnd = contentEnd\n\n if (lineIndex === 0) {\n processedParts.push(source.slice(lineStart, lineEnd))\n } else {\n // Check for exactly 4 leading spaces\n var spaceCount = 0\n while (spaceCount < 4 && lineStart + spaceCount < lineEnd) {\n if (charCode(source, lineStart + spaceCount) === $.CHAR_SPACE) {\n spaceCount++\n } else {\n break\n }\n }\n var start = spaceCount === 4 ? lineStart + 4 : lineStart\n processedParts.push(source.slice(start, lineEnd))\n }\n\n if (lineEnd < contentEnd) {\n const charAtEnd = charCode(source, lineEnd)\n if (charAtEnd === $.CHAR_CR || charAtEnd === $.CHAR_NEWLINE) {\n processedParts.push('\\n')\n lineStart = skipToNextLine(source, lineEnd)\n } else {\n lineStart = contentEnd\n }\n } else {\n lineStart = contentEnd\n }\n lineIndex++\n }\n processedContent = processedParts.join('')\n }\n\n var processedContentEnd = processedContent.length\n while (processedContentEnd > 0) {\n var c = processedContent.charCodeAt(processedContentEnd - 1)\n if (c === $.CHAR_SPACE || c === $.CHAR_TAB) {\n processedContentEnd--\n } else {\n break\n }\n }\n if (processedContentEnd < processedContent.length) {\n processedContent = processedContent.slice(0, processedContentEnd)\n }\n\n // Check if processed content has actual content\n let hasProcessedContent = false\n for (let i = 0; i < processedContent.length; i++) {\n const code = processedContent.charCodeAt(i)\n if (\n code !== $.CHAR_SPACE &&\n code !== $.CHAR_TAB &&\n code !== $.CHAR_NEWLINE &&\n code !== $.CHAR_CR\n ) {\n hasProcessedContent = true\n break\n }\n }\n if (!hasProcessedContent) return null\n\n // Per CommonMark spec: Extract link reference definitions from paragraph content\n // Reference definitions can appear at the end of paragraph content\n // They should be extracted and stored, not parsed as inline content\n // Scan backwards from endPos in source to find reference definitions\n var extractedContent = processedContent\n var extractedEndPos = endPos\n // Find the last newline in the source before endPos (optimized: manual scan instead of lastIndexOf)\n var lastNewlinePos = -1\n var searchPos = endPos - 1\n while (searchPos >= contentStart) {\n if (charCode(source, searchPos) === $.CHAR_NEWLINE) {\n lastNewlinePos = searchPos\n break\n }\n searchPos--\n }\n if (lastNewlinePos >= 0) {\n // Per CommonMark spec: \"A link reference definition cannot interrupt a paragraph.\"\n // Only extract reference definitions if they're at the START of the paragraph (no content before them)\n // Check if there's any non-whitespace content before the last newline\n var hasContentBeforeNewline = false\n for (var checkPos = contentStart; checkPos < lastNewlinePos; checkPos++) {\n const code = charCode(source, checkPos)\n if (\n code !== $.CHAR_SPACE &&\n code !== $.CHAR_TAB &&\n code !== $.CHAR_NEWLINE &&\n code !== $.CHAR_CR\n ) {\n hasContentBeforeNewline = true\n break\n }\n }\n\n // Only extract reference definition if there's no content before the newline\n // (i.e., it's at the start of the paragraph)\n if (!hasContentBeforeNewline) {\n // Check if the content after the last newline is a reference definition\n var refDefStartPos = lastNewlinePos + 1\n // Skip any leading whitespace\n while (refDefStartPos < source.length) {\n const code = charCode(source, refDefStartPos)\n if (code === $.CHAR_SPACE || code === $.CHAR_TAB) {\n refDefStartPos++\n } else {\n break\n }\n }\n // Check indentation - reference definitions can't be indented 4+ spaces\n var refDefIndent = refDefStartPos - (lastNewlinePos + 1)\n if (\n refDefIndent < 4 &&\n refDefStartPos < source.length &&\n source[refDefStartPos] === '['\n ) {\n var refDefState = { ...state, inline: false }\n var refDefResult = parseDefinition(\n source,\n refDefStartPos,\n refDefState,\n options,\n false\n )\n if (refDefResult) {\n // Reference definition was successfully parsed - exclude it from paragraph content\n // Find the corresponding position in processedContent\n // Count newlines from contentStart to lastNewlinePos\n var newlineCount = 0\n var searchPos = contentStart\n while (searchPos <= lastNewlinePos) {\n const nlPos = source.indexOf('\\n', searchPos)\n if (nlPos === -1 || nlPos > lastNewlinePos) break\n newlineCount++\n searchPos = nlPos + 1\n }\n // Find the corresponding position in processedContent\n var newlinePosInProcessed = 0\n var newlinesFound = 0\n searchPos = 0\n while (searchPos < processedContent.length) {\n const nlPos = processedContent.indexOf('\\n', searchPos)\n if (nlPos === -1) break\n newlinesFound++\n if (newlinesFound === newlineCount) {\n newlinePosInProcessed = nlPos + 1\n break\n }\n searchPos = nlPos + 1\n }\n if (newlinePosInProcessed > 0) {\n extractedContent = processedContent.slice(\n 0,\n newlinePosInProcessed - 1\n )\n }\n extractedEndPos = refDefResult.endPos\n // Update state.refs from the parsed reference\n state.refs = refDefState.refs\n }\n }\n }\n }\n\n // Parse as inline (newlines are preserved by default)\n const children = parseInlineWithState(\n extractedContent,\n 0,\n extractedContent.length,\n state,\n options\n )\n\n var result: MarkdownToJSX.ParagraphNode & {\n endPos: number\n removedClosingTags?: MarkdownToJSX.ASTNode[]\n } = {\n type: RuleType.paragraph,\n children,\n endPos: extractedEndPos,\n }\n\n // Per CommonMark spec Example 148: when paragraphs contain multiple closing tags at the end,\n // only the first closing tag should be kept in the paragraph, the rest should be removed\n // This handles cases where closing tags are part of HTML block structures\n // Heuristic: if there are 3+ consecutive closing tags, remove all but the first one\n // Example 148: <p><em>world</em>.</pre></p> should keep </pre> but remove </td>, </tr>, </table> (4 tags)\n // Example 623: <p></a></foo ></p> should keep both </a> and </foo > (2 tags, not removed)\n if (children.length > 0) {\n // Find closing tags at the end of paragraph children (ignoring whitespace-only text nodes)\n // Keep the first closing tag but remove the rest\n var closingTagIndices: number[] = []\n for (var i = children.length - 1; i >= 0; i--) {\n var child = children[i]\n if (\n child.type === RuleType.htmlSelfClosing &&\n child.isClosingTag === true\n ) {\n closingTagIndices.push(i)\n } else if (child.type === RuleType.text) {\n var textNode = child as MarkdownToJSX.TextNode\n // Skip whitespace-only text nodes when looking for consecutive closing tags\n if (textNode.text && textNode.text.trim().length > 0) {\n break\n }\n } else {\n // Stop at first non-closing-tag, non-whitespace node\n break\n }\n }\n // If we found 3+ consecutive closing tags at the end, remove all but the first one\n // Store the removed closing tags on the paragraph node so html() can render them separately\n // Heuristic: 3+ tags indicates HTML block structure (like </pre></td></tr></table>)\n // 2 tags might be standalone (like </a></foo >) - keep both\n if (closingTagIndices.length >= 3) {\n // Keep only the first closing tag (earliest in array), remove the rest\n var firstClosingTagIdx = closingTagIndices[closingTagIndices.length - 1]\n var removedClosingTags = children.slice(firstClosingTagIdx + 1)\n children.splice(firstClosingTagIdx + 1)\n result.removedClosingTags = removedClosingTags\n }\n }\n\n return result\n}\n\nfunction parseFrontmatter(source: string, pos: number): ParseResult {\n if (pos !== 0) return null\n const bounds = util.parseFrontmatterBounds(source)\n if (!bounds?.hasValidYaml) return null\n let sliceEnd = bounds.endPos - 1\n if (sliceEnd > 0 && source[sliceEnd - 1] === '\\r') sliceEnd--\n let text = util.normalizeCRLF(source.slice(0, sliceEnd))\n return {\n type: RuleType.frontmatter,\n text,\n endPos: bounds.endPos,\n } as MarkdownToJSX.FrontmatterNode & { endPos: number }\n}\n\nfunction parseBreakThematic(\n source: string,\n pos: number,\n state?: MarkdownToJSX.State,\n options?: ParseOptions\n): ParseResult {\n // Find the end of the line\n const lineEnd = util.findLineEnd(source, pos)\n\n // Per CommonMark: up to 3 spaces of indentation allowed\n // Count indentation, checking if it exceeds 3 spaces\n // OPTIMIZATION: Work directly on source string to avoid slice allocation\n const indentResult = calculateIndent(source, pos, lineEnd, 3)\n if (indentResult.spaceEquivalent > 3) return null\n var checkPos = pos + indentResult.charCount\n\n // Now check for thematic break character (-, *, or _)\n if (checkPos >= lineEnd) return null\n const startChar = source[checkPos]\n if (startChar !== '-' && startChar !== '*' && startChar !== '_') return null\n\n // OPTIMIZATION: Fast path - count matching characters before full validation\n // This eliminates 96% of failed attempts (102 attempts -> ~4 attempts)\n // Thematic break requires 3+ matching chars per CommonMark spec\n var charCount = 0\n var scanPos = checkPos\n while (scanPos < lineEnd) {\n var char = source[scanPos]\n if (char === startChar) {\n charCount++\n } else if (char !== ' ' && char !== '\\t') {\n // Non-matching non-whitespace character - not a thematic break\n return null\n }\n scanPos++\n }\n\n if (charCount < 3) {\n return null // Need at least 3 matching characters per CommonMark spec\n }\n\n return {\n type: RuleType.breakThematic,\n endPos: skipToNextLine(source, lineEnd),\n } as MarkdownToJSX.BreakThematicNode & { endPos: number }\n}\n\n/** Calculate the space-equivalent indentation at a position (tabs = 4 spaces) */\nexport function calculateIndent(\n source: string,\n pos: number,\n maxPos: number,\n maxSpaces?: number\n): { spaceEquivalent: number; charCount: number } {\n let spaceEquivalent = 0\n let charCount = 0\n let i = pos\n while (i < maxPos) {\n var iCode = charCode(source, i)\n if (iCode !== $.CHAR_SPACE && iCode !== $.CHAR_TAB) break\n if (maxSpaces !== undefined && spaceEquivalent >= maxSpaces) break\n if (iCode === $.CHAR_TAB) {\n spaceEquivalent += 4 - (spaceEquivalent % 4)\n } else {\n spaceEquivalent += 1\n }\n charCount++\n i++\n }\n return { spaceEquivalent, charCount }\n}\n\nfunction extractCodeBlockLineContent(\n source: string,\n lineStart: number,\n lineEnd: number,\n startColumn: number\n): string {\n let indentChars = 0\n let indentSpaceEquivalent = 0\n let currentColumn = startColumn\n for (let i = lineStart; i < lineEnd && indentSpaceEquivalent < 4; i++) {\n var iCode = charCode(source, i)\n if (iCode === $.CHAR_TAB) {\n const spaces = 4 - (currentColumn % 4)\n indentSpaceEquivalent += spaces\n indentChars++\n currentColumn += spaces\n if (indentSpaceEquivalent >= 4) break\n } else if (iCode === $.CHAR_SPACE) {\n indentSpaceEquivalent++\n indentChars++\n currentColumn++\n if (indentSpaceEquivalent >= 4) break\n } else {\n break\n }\n }\n\n let content = source.slice(lineStart + indentChars, lineEnd)\n var tabCount = 0\n for (var tc = lineStart; tc < lineEnd; tc++) {\n if (source[tc] === '\\t') tabCount++\n if (tabCount >= 2) break\n }\n if (tabCount >= 2 && util.startsWith(content, '\\t') && startColumn > 0) {\n content = ' ' + content.slice(1)\n }\n return content\n}\n\nfunction parseCodeBlock(\n source: string,\n pos: number,\n state: MarkdownToJSX.State\n): ParseResult {\n // Limit indentation scan to current line\n const lineEndForIndent = util.findLineEnd(source, pos)\n const indentInfo = calculateIndent(source, pos, lineEndForIndent)\n if (indentInfo.spaceEquivalent < 4) return null\n\n const initialIndent = indentInfo.spaceEquivalent\n const lineEnd = util.findLineEnd(source, pos + indentInfo.charCount)\n const lineStart = pos\n\n let column = 0\n var i = lineStart - 1\n while (i >= 0 && source[i] !== '\\n' && source[i] !== '\\r') {\n i--\n }\n i++\n while (i < lineStart) {\n if (source[i] === '\\t') {\n column = column + 4 - (column % 4)\n } else {\n column++\n }\n i++\n }\n\n let firstLineContent = extractCodeBlockLineContent(\n source,\n lineStart,\n lineEnd,\n column\n )\n const contentStart = skipToNextLine(source, lineEnd)\n if (contentStart >= source.length) {\n if (!firstLineContent.trim()) return null\n return {\n type: RuleType.codeBlock,\n text: firstLineContent,\n endPos: contentStart,\n } as MarkdownToJSX.CodeBlockNode & { endPos: number }\n }\n\n var parts: string[] = []\n parts.push(firstLineContent)\n let endPos = contentStart\n\n while (endPos < source.length) {\n const nextLineEnd = util.findLineEnd(source, endPos)\n if (isBlankLineCheck(source, endPos, nextLineEnd)) {\n const nextLinePos = nextLineEnd + 1\n if (nextLinePos < source.length) {\n const nextLineEnd = util.findLineEnd(source, nextLinePos)\n const nextIndentInfo = calculateIndent(source, nextLinePos, nextLineEnd)\n const nextChar = source[nextLinePos + nextIndentInfo.charCount]\n if (\n nextChar &&\n nextChar !== '\\n' &&\n (nextIndentInfo.spaceEquivalent < 4 ||\n (nextChar === '>' &&\n nextIndentInfo.spaceEquivalent < initialIndent))\n ) {\n break\n }\n }\n parts.push('\\n')\n } else {\n const currentIndentInfo = calculateIndent(source, endPos, nextLineEnd)\n if (currentIndentInfo.spaceEquivalent < 4) {\n break\n }\n\n let lineContent = extractCodeBlockLineContent(\n source,\n endPos,\n nextLineEnd,\n 0\n )\n parts.push('\\n')\n parts.push(lineContent)\n }\n\n endPos = skipToNextLine(source, nextLineEnd)\n }\n\n let content = parts.join('')\n content = content.replace(TRAILING_NEWLINE_R, '')\n if (!content.trim()) return null\n\n return {\n type: RuleType.codeBlock,\n text: content,\n endPos,\n } as MarkdownToJSX.CodeBlockNode & { endPos: number }\n}\n\nexport function parseCodeFenced(\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): ParseResult {\n const fenceChar = source[pos]\n if (fenceChar !== '`' && fenceChar !== '~') return null\n\n // Fast check: must have at least 3 consecutive fence chars\n const fenceLength = countConsecutiveChars(source, pos, fenceChar)\n if (fenceLength < 3) return null\n\n // Find line start for indentation calculation\n let lineStart = pos\n while (lineStart > 0 && charCode(source, lineStart - 1) !== $.CHAR_NEWLINE)\n lineStart--\n\n // Calculate indentation (caller already verified <= 3, but we need exact value)\n const indentInfo = calculateIndent(source, lineStart, pos)\n let openingIndent = indentInfo.spaceEquivalent\n let contentIndentToRemove = openingIndent\n\n // Handle 4-space indentation special case (simplified)\n if (openingIndent === 4 && indentInfo.charCount === 4) {\n // All 4 chars before pos are spaces/tabs, so this is indented code block\n openingIndent = 0\n contentIndentToRemove = 4\n }\n\n // Should not happen since caller checks indent <= 3, but keep for safety\n if (openingIndent >= 4) return null\n\n let i = util.skipWhitespace(source, pos + fenceLength)\n const lineEnd = util.findLineEnd(source, i)\n let langAndAttrs = source.slice(i, lineEnd).trim()\n\n if (fenceChar === '`' && langAndAttrs.indexOf('`') !== -1) return null\n\n langAndAttrs = langAndAttrs.replace(UNESCAPE_R, '$1')\n const langSpaceIdx = langAndAttrs.indexOf(' ')\n const lang =\n langSpaceIdx > 0 ? langAndAttrs.slice(0, langSpaceIdx) : langAndAttrs\n const attrsString =\n langSpaceIdx > 0 ? langAndAttrs.slice(langSpaceIdx + 1).trim() : ''\n const attrs =\n attrsString && /=\\s*[\"']/.test(attrsString)\n ? parseHTMLAttributes(attrsString, 'code', 'code', options)\n : undefined\n\n let contentStart = skipToNextLine(source, lineEnd)\n let endPos = contentStart\n\n while (endPos < source.length) {\n let lineEndPos = util.findLineEnd(source, endPos)\n\n let fenceStart = endPos\n let indentCount = 0\n while (fenceStart < lineEndPos) {\n const code = charCode(source, fenceStart)\n if (code === $.CHAR_SPACE) {\n indentCount++\n fenceStart++\n if (indentCount >= 4) break\n } else if (code === $.CHAR_TAB) {\n indentCount += 4 - (indentCount % 4)\n fenceStart++\n if (indentCount >= 4) break\n } else {\n break\n }\n }\n\n if (indentCount < 4) {\n let closeLen = countConsecutiveChars(\n source,\n fenceStart,\n fenceChar,\n lineEndPos - fenceStart\n )\n if (closeLen >= fenceLength) {\n let afterFence = fenceStart + closeLen\n while (afterFence < lineEndPos) {\n const code = charCode(source, afterFence)\n if (code === $.CHAR_SPACE || code === $.CHAR_TAB) {\n afterFence++\n } else {\n break\n }\n }\n if (afterFence === lineEndPos) {\n break\n }\n }\n } else if (\n contentIndentToRemove === 4 &&\n openingIndent === 0 &&\n indentCount === 4\n ) {\n let closeLen = countConsecutiveChars(\n source,\n fenceStart,\n fenceChar,\n lineEndPos - fenceStart\n )\n if (\n closeLen >= fenceLength &&\n isBlankLineCheck(source, fenceStart + closeLen, lineEndPos)\n ) {\n break\n }\n }\n\n endPos = skipToNextLine(source, lineEndPos)\n }\n\n let contentEnd =\n endPos > contentStart && source[endPos - 1] === '\\n' ? endPos - 1 : endPos\n if (contentEnd > contentStart && source[contentEnd - 1] === '\\r') {\n contentEnd--\n }\n let rawContent = util.normalizeCRLF(source.slice(contentStart, contentEnd))\n if (contentIndentToRemove) {\n rawContent = removeExtraIndentFromCodeBlock(\n rawContent,\n contentIndentToRemove\n )\n }\n\n let finalEndPos =\n endPos < source.length\n ? skipToNextLine(source, util.findLineEnd(source, endPos))\n : endPos\n\n return {\n type: RuleType.codeBlock,\n text: rawContent,\n lang: lang,\n attrs: attrs,\n endPos: finalEndPos,\n } as MarkdownToJSX.CodeBlockNode & { endPos: number }\n}\n\nfunction parseBlockQuoteChildren(\n content: string,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): MarkdownToJSX.ASTNode[] {\n // Fast check: if content is empty or only whitespace, return early\n for (var i = 0; i < content.length; i++) {\n if (!isWS(content[i])) {\n // Parse all blocks using parseBlocksWithState (which uses parseBlock via parseBlocksInHTML)\n const blockChildren = parseBlocksWithState(content, state, options, {\n inline: false,\n inBlockQuote: true,\n })\n // Remove endPos property efficiently without creating intermediate objects\n for (var j = 0; j < blockChildren.length; j++) {\n const node = blockChildren[j] as MarkdownToJSX.ASTNode & {\n endPos?: number\n }\n if ('endPos' in node) {\n delete node.endPos\n }\n }\n return blockChildren\n }\n }\n return []\n}\n\nfunction parseBlockQuote(\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): ParseResult {\n if (state.inline) return null\n\n let checkPos = pos\n while (\n checkPos < source.length &&\n (source[checkPos] === ' ' || source[checkPos] === '\\t')\n ) {\n checkPos++\n }\n if (checkPos >= source.length || source[checkPos] !== '>') return null\n\n // Find the end of the blockquote and process content in single pass\n let endPos = pos\n var processedParts: string[] = []\n var alertType: string | undefined = undefined\n var hasContent = false\n var firstLineStart = -1\n\n // Track if we're currently in a code block (indented or fenced) that requires > prefix\n var inCodeBlock = false\n var codeBlockType: 'indented' | 'fenced' | null = null\n var fencedFenceChar: string | null = null\n var fencedFenceLength = 0\n var previousLineWasEmpty = false\n\n while (endPos < source.length) {\n const lineEnd = util.findLineEnd(source, endPos)\n\n // Check if this line starts a blockquote\n let lineStart = endPos\n // Skip leading whitespace\n while (\n lineStart < lineEnd &&\n (source[lineStart] === ' ' || source[lineStart] === '\\t')\n ) {\n lineStart++\n }\n\n // If line starts with '>', it's part of the blockquote\n if (lineStart < lineEnd && source[lineStart] === '>') {\n let contentStart = lineStart + 1\n if (contentStart < lineEnd && source[contentStart] === ' ') contentStart++\n\n // Inline code block detection (was detectCodeBlockInBlockQuote)\n const indentInfo = calculateIndent(source, contentStart, lineEnd)\n const isIndented = indentInfo.spaceEquivalent >= 4\n let isFenced = false\n let fenceChar: string | null = null\n let fenceLen = 0\n if (contentStart < lineEnd) {\n const firstChar = source[contentStart]\n if (firstChar === '`' || firstChar === '~') {\n let len = 0\n let i = contentStart\n while (i < lineEnd && source[i] === firstChar && len < 20) {\n len++\n i++\n }\n if (len >= 3) {\n isFenced = true\n fenceChar = firstChar\n fenceLen = len\n }\n }\n }\n\n // Update code block state\n if (\n inCodeBlock &&\n codeBlockType === 'fenced' &&\n fenceChar === fencedFenceChar &&\n fenceLen >= fencedFenceLength\n ) {\n inCodeBlock = false\n codeBlockType = null\n fencedFenceChar = null\n fencedFenceLength = 0\n } else if (isIndented || isFenced) {\n inCodeBlock = true\n codeBlockType = isIndented ? 'indented' : 'fenced'\n fencedFenceChar = fenceChar\n fencedFenceLength = fenceLen\n }\n\n // Inline blank line check (was isBlankLineCheck)\n var isBlankLine = !isIndented && !isFenced\n if (isBlankLine) {\n for (var i = contentStart; i < lineEnd; i++) {\n if (!isWS(source[i])) {\n isBlankLine = false\n break\n }\n }\n }\n previousLineWasEmpty = isBlankLine\n\n // Track first line for alert extraction\n if (firstLineStart === -1 && !isBlankLine) {\n firstLineStart = processedParts.length\n }\n if (!isBlankLine) hasContent = true\n\n // Process line content: remove > marker and optional space, handle tabs\n const afterMarkerStart = lineStart + 1\n\n // Check if first char after > is a tab (needs special handling)\n if (afterMarkerStart < lineEnd && source[afterMarkerStart] === '\\t') {\n // Expand tabs to spaces\n processedParts.push(' ') // First tab after > becomes 2 spaces\n let col = 4\n for (let k = afterMarkerStart + 1; k < lineEnd; k++) {\n const char = source[k]\n var code = charCode(char)\n if (code === $.CHAR_TAB) {\n const spaces = 4 - (col % 4)\n // Use fixed strings for common cases\n if (spaces === 1) processedParts.push(' ')\n else if (spaces === 2) processedParts.push(' ')\n else if (spaces === 3) processedParts.push(' ')\n else processedParts.push(' '.repeat(spaces))\n col += spaces\n } else {\n processedParts.push(char)\n col++\n }\n }\n if (lineEnd < source.length) processedParts.push('\\n')\n } else {\n // Fast path: no tab immediately after > (common case)\n let processedContentStart = afterMarkerStart\n if (\n processedContentStart < lineEnd &&\n source[processedContentStart] === ' '\n ) {\n processedContentStart++\n }\n processedParts.push(source.slice(processedContentStart, lineEnd))\n if (lineEnd < source.length) processedParts.push('\\n')\n }\n } else {\n // Check for lazy continuation line (line without > that continues blockquote)\n // Inline blank line check\n var isEmptyLine = true\n for (var i = endPos; i < lineEnd; i++) {\n if (!isWS(source[i])) {\n isEmptyLine = false\n break\n }\n }\n\n // Stop blockquote if: empty line, or in code block (code blocks require > prefix)\n if (isEmptyLine || inCodeBlock) {\n break\n }\n\n const lazyIndentInfo = calculateIndent(source, endPos, lineEnd)\n if (lazyIndentInfo.spaceEquivalent === 0) {\n // Check if this line starts a block (excluding reference definitions which don't break blockquotes)\n const blockResult = parseBlock(source, endPos, state, options)\n if (\n blockResult &&\n blockResult.type !== RuleType.ref &&\n blockResult.type !== RuleType.codeBlock\n ) {\n break\n }\n if (previousLineWasEmpty) {\n break\n }\n }\n processedParts.push(source.slice(endPos, lineEnd))\n if (lineEnd < source.length) processedParts.push('\\n')\n }\n\n endPos = skipToNextLine(source, lineEnd)\n }\n\n // Empty blockquotes are valid (e.g., \">\\n\" or \">\\n> \\n> \\n\")\n // Only reject if we didn't process any lines at all\n if (endPos === pos) return null\n\n // Remove trailing newline if present (avoid endsWith check by tracking)\n if (\n processedParts.length > 0 &&\n processedParts[processedParts.length - 1] === '\\n'\n ) {\n processedParts.pop()\n }\n\n let processedContent = processedParts.join('')\n\n // Extract alert type (check start of content for [!...]\\n pattern)\n if (\n processedContent.length >= 4 &&\n processedContent.charCodeAt(0) === $.CHAR_BRACKET_OPEN &&\n processedContent.charCodeAt(1) === $.CHAR_EXCLAMATION\n ) {\n const alertEnd = processedContent.indexOf(']\\n', 2)\n if (alertEnd > 2) {\n alertType = processedContent.slice(2, alertEnd)\n processedContent = processedContent.slice(alertEnd + 2)\n }\n }\n\n const children = parseBlockQuoteChildren(processedContent, state, options)\n\n const result: MarkdownToJSX.BlockQuoteNode & { endPos: number } = {\n type: RuleType.blockQuote,\n children,\n endPos,\n }\n if (alertType) {\n result.alert = alertType\n }\n return result\n}\n\n/** Remove extra indentation from code block text when used in list items */\nfunction removeExtraIndentFromCodeBlock(\n codeBlockText: string,\n extraIndent: number\n): string {\n return codeBlockText\n .split('\\n')\n .map(function (line) {\n if (line.length === 0) return line\n let toRemove = extraIndent\n let removed = 0\n let i = 0\n let currentColumn = 0\n while (i < line.length && removed < toRemove) {\n if (line[i] === ' ') {\n removed++\n currentColumn++\n i++\n } else if (line[i] === '\\t') {\n const spacesFromTab = 4 - (currentColumn % 4)\n if (removed + spacesFromTab <= toRemove) {\n removed += spacesFromTab\n currentColumn += spacesFromTab\n i++\n } else {\n const remainingToRemove = toRemove - removed\n const spacesToKeep = Math.max(0, spacesFromTab - remainingToRemove)\n return ' '.repeat(spacesToKeep) + line.slice(i + 1)\n }\n } else {\n break\n }\n }\n return line.slice(i)\n })\n .join('\\n')\n}\n\nfunction appendListContinuation(\n continuationContent: string,\n lastItem: MarkdownToJSX.ASTNode[],\n state: MarkdownToJSX.State,\n options: ParseOptions,\n addNewline: boolean = true\n): void {\n const sourceToParse = (addNewline ? '\\n' : '') + continuationContent\n const continuationInline = parseInlineWithState(\n sourceToParse,\n 0,\n sourceToParse.length,\n state,\n options\n )\n if (\n lastItem.length > 0 &&\n lastItem[lastItem.length - 1].type === RuleType.paragraph\n ) {\n ;(\n lastItem[lastItem.length - 1] as MarkdownToJSX.ParagraphNode\n ).children.push(...continuationInline)\n } else {\n lastItem.push(...continuationInline)\n }\n}\n\n// Helper: Check if list item contains block-level content\nfunction listItemHasBlockContent(item: MarkdownToJSX.ASTNode[]): boolean {\n return item.some(function (node) {\n return (\n node.type === RuleType.codeBlock ||\n node.type === RuleType.paragraph ||\n node.type === RuleType.blockQuote ||\n node.type === RuleType.orderedList ||\n node.type === RuleType.unorderedList ||\n node.type === RuleType.heading\n )\n })\n}\n\n// Helper: Check if line matches any list item pattern\nfunction isLineListItem(line: string): boolean {\n return !!line.match(LIST_ITEM_R)\n}\n\n// Helper: Find deepest nested list parent in item hierarchy\nfunction findNestedListParent(\n item: MarkdownToJSX.ASTNode[]\n): MarkdownToJSX.ASTNode[] {\n if (item.length === 0) return item\n var lastBlock = item[item.length - 1]\n if (\n (lastBlock.type === RuleType.orderedList ||\n lastBlock.type === RuleType.unorderedList) &&\n (\n lastBlock as\n | MarkdownToJSX.OrderedListNode\n | MarkdownToJSX.UnorderedListNode\n ).items?.length > 0\n ) {\n return findNestedListParent(\n (\n lastBlock as\n | MarkdownToJSX.OrderedListNode\n | MarkdownToJSX.UnorderedListNode\n ).items.slice(-1)[0]\n )\n }\n return item\n}\n\n// Helper: Skip link reference definition if present\nfunction skipLinkReferenceDefinition(\n source: string,\n linePos: number,\n lineEnd: number,\n indentInfo: ReturnType<typeof calculateIndent>,\n lineWithoutIndent: string,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): number | null {\n if (!util.startsWith(lineWithoutIndent, '[')) return null\n var refCheckState = { inline: false, list: false, refs: state.refs || {} }\n var refResult = parseDefinition(\n source,\n linePos + indentInfo.charCount,\n refCheckState,\n options,\n false\n )\n return refResult ? refResult.endPos : null\n}\n\n// Helper: Check if we should break list due to empty item after blank line\nfunction shouldBreakForEmptyItem(\n items: MarkdownToJSX.ASTNode[][],\n isEmptyItem: boolean,\n prevLineWasBlank: boolean,\n firstItemContent: string\n): boolean {\n if (items.length !== 1 || !prevLineWasBlank) return false\n const lastItem = items[0] // Since items.length === 1, this is the only item\n if (lastItem.length !== 0) return false\n if (isEmptyItem) return true\n if (!isEmptyItem && firstItemContent.trim() === '') return true\n return false\n}\n\n// Helper: Calculate content start column for a list item\n// Helper: Calculate marker end position from match\nfunction calculateMarkerEnd(match: RegExpMatchArray, ordered: boolean): number {\n var markerStart = match.index || 0\n return ordered\n ? markerStart + match[1].length + match[2].length + 1\n : markerStart + match[1].length + 1\n}\n\nfunction calculateListItemContentColumn(\n source: string,\n contentStartInSource: number,\n lineEnd: number,\n baseIndent: number,\n markerEndInLine: number\n): { contentStartColumn: number; contentStartPos: number } {\n var spacesAfterMarker = 0\n var col = baseIndent + markerEndInLine\n var contentCheckPos = contentStartInSource\n while (contentCheckPos < lineEnd && spacesAfterMarker < 4) {\n var code = charCode(source, contentCheckPos)\n if (code === $.CHAR_SPACE) {\n spacesAfterMarker++\n col++\n } else if (code === $.CHAR_TAB) {\n var spaces = 4 - (col % 4)\n if (spacesAfterMarker + spaces > 4) break\n spacesAfterMarker += spaces\n col += spaces\n } else {\n break\n }\n contentCheckPos++\n }\n return { contentStartColumn: col, contentStartPos: contentCheckPos }\n}\n\nfunction matchListItem(\n lineWithoutIndent: string\n): { match: RegExpMatchArray; ordered: boolean; listItemRegex: RegExp } | null {\n var match = lineWithoutIndent.match(LIST_ITEM_R)\n if (!match) return null\n\n // Groups: 1=ordered_num, 2=ordered_delim, 3=ordered_content, 4=ordered_empty_num, 5=ordered_empty_delim, 6=unordered_marker, 7=unordered_content, 8=unordered_empty_marker\n if (match[1]) {\n // Ordered with content: (\\d{1,9})([.)])\\s+(.*)\n return {\n match: [lineWithoutIndent, match[1], match[2], match[3]],\n ordered: true,\n listItemRegex: ORDERED_LIST_ITEM_WITH_CONTENT_R,\n }\n }\n if (match[4]) {\n // Ordered empty: (\\d{1,9})([.)])\\s*\n return {\n match: [lineWithoutIndent, match[4], match[5], ''],\n ordered: true,\n listItemRegex: ORDERED_LIST_ITEM_WITH_CONTENT_R,\n }\n }\n if (match[6]) {\n // Unordered with content: ([-*+])\\s+(.*)\n return {\n match: [lineWithoutIndent, match[6], match[7]],\n ordered: false,\n listItemRegex: UNORDERED_LIST_ITEM_WITH_CONTENT_R,\n }\n }\n if (match[8]) {\n // Unordered empty: ([-*+])\\s*\n return {\n match: [lineWithoutIndent, match[8], ''],\n ordered: false,\n listItemRegex: UNORDERED_LIST_ITEM_WITH_CONTENT_R,\n }\n }\n return null\n}\n\n// Helper: Check if a line is a matching list item for the current list\nfunction isMatchingListItem(\n lineWithoutIndent: string,\n indentInfo: ReturnType<typeof calculateIndent>,\n ordered: boolean,\n marker: string | undefined,\n delimiter: string | undefined,\n baseIndent: number,\n listItemRegex: RegExp\n): boolean {\n if (indentInfo.spaceEquivalent !== baseIndent) return false\n var match = lineWithoutIndent.match(listItemRegex)\n if (match) {\n return ordered ? match[2] === delimiter : match[1] === marker\n }\n var emptyMatch = lineWithoutIndent.match(LIST_ITEM_R)\n if (!emptyMatch) return false\n if (ordered) {\n return emptyMatch[4] && emptyMatch[5] === delimiter\n } else {\n return emptyMatch[8] === marker\n }\n}\n\n// Helper: Handle fenced code blocks that span multiple lines in list items\nfunction expandMultilineFencedCodeBlock(\n source: string,\n itemContent: string,\n startPos: number,\n markerWidth: number\n): { content: string; endPos: number } {\n var content = itemContent\n var pos = startPos\n var fenceChar = itemContent[0]\n while (pos < source.length) {\n var lineEnd = util.findLineEnd(source, pos)\n var line = source.slice(pos, lineEnd)\n var processedLine = util.startsWith(line, ' '.repeat(markerWidth))\n ? line.slice(markerWidth)\n : line\n if (\n util.startsWith(processedLine.trim(), fenceChar) &&\n countConsecutiveChars(processedLine.trim(), 0, fenceChar) >= 3\n ) {\n return { content: content, endPos: skipToNextLine(source, lineEnd) }\n }\n content += '\\n' + processedLine\n pos = skipToNextLine(source, lineEnd)\n }\n return { content: content, endPos: pos }\n}\n\n// Helper function to add a new list item with all standard processing\nfunction addListItem(\n source: string,\n items: MarkdownToJSX.ASTNode[][],\n itemContentStartColumns: number[],\n itemContent: string,\n startPos: number,\n nextLineEnd: number,\n nextIndent: number,\n nextIndentChars: number,\n nextMatch: RegExpMatchArray,\n ordered: boolean,\n hasBlankLines: boolean,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): { newCurrentPos: number; itemHasBlankLine: boolean } {\n // Derive marker/delimiter/regex (cheap to recompute vs passing 3 extra params)\n var marker = ordered ? undefined : nextMatch[1]\n var delimiter = ordered ? nextMatch[2] : undefined\n var listItemRegex = ordered\n ? ORDERED_LIST_ITEM_WITH_CONTENT_R\n : UNORDERED_LIST_ITEM_WITH_CONTENT_R\n\n // Check if item has blank lines\n var itemHasBlankLine = hasBlankLines\n if (!hasBlankLines) {\n var startCheckPos = skipToNextLine(source, nextLineEnd)\n var checkItemPos = startCheckPos\n while (checkItemPos < source.length) {\n var checkLineEnd = util.findLineEnd(source, checkItemPos)\n var checkLine = source.slice(checkItemPos, checkLineEnd)\n var checkIndentInfo = calculateIndent(source, checkItemPos, checkLineEnd)\n var checkIndent = checkIndentInfo.spaceEquivalent\n if (isBlankLineCheck(source, checkItemPos, checkLineEnd)) {\n var afterBlank = skipToNextLine(source, checkLineEnd)\n if (afterBlank < source.length) {\n var afterBlankLineEnd = util.findLineEnd(source, afterBlank)\n var afterBlankIndentInfo = calculateIndent(\n source,\n afterBlank,\n afterBlankLineEnd\n )\n var afterBlankIndent = afterBlankIndentInfo.spaceEquivalent\n var thisItemMarkerEnd = calculateMarkerEnd(nextMatch, ordered)\n var thisItemContentStartInSource =\n startPos + nextIndentChars + thisItemMarkerEnd\n var thisItemResult = calculateListItemContentColumn(\n source,\n thisItemContentStartInSource,\n nextLineEnd,\n nextIndent,\n thisItemMarkerEnd\n )\n var thisItemContentStartColumn = thisItemResult.contentStartColumn\n if (afterBlankIndent + 1 > thisItemContentStartColumn) {\n itemHasBlankLine = true\n break\n }\n }\n break\n } else if (checkIndent <= nextIndent) {\n var checkLineWithoutIndent = checkLine.slice(checkIndentInfo.charCount)\n var checkMatch = checkLineWithoutIndent.match(listItemRegex)\n if (\n checkMatch &&\n (ordered ? checkMatch[2] === delimiter : checkMatch[1] === marker)\n ) {\n break\n }\n }\n checkItemPos = skipToNextLine(source, checkLineEnd)\n }\n }\n\n // Calculate content start column\n var thisItemMarkerEnd = calculateMarkerEnd(nextMatch, ordered)\n var thisItemContentStartInSource =\n startPos + nextIndentChars + thisItemMarkerEnd\n var thisItemResult = calculateListItemContentColumn(\n source,\n thisItemContentStartInSource,\n nextLineEnd,\n nextIndent,\n thisItemMarkerEnd\n )\n var thisItemContentStartColumn = thisItemResult.contentStartColumn\n\n // Handle fenced code blocks\n var actualItemContent = itemContent\n var newCurrentPos = skipToNextLine(source, nextLineEnd)\n if (\n util.startsWith(itemContent, '```') ||\n util.startsWith(itemContent, '~~~')\n ) {\n var markerWidth = ordered\n ? nextMatch[1].length + nextMatch[2].length + 1\n : nextMatch[1].length + 1\n var expandedResult = expandMultilineFencedCodeBlock(\n source,\n itemContent,\n newCurrentPos,\n markerWidth\n )\n actualItemContent = expandedResult.content\n newCurrentPos = expandedResult.endPos\n }\n\n // Build and add item with GFM task support\n items.push(\n buildListItemContent(actualItemContent, itemHasBlankLine, state, options)\n )\n itemContentStartColumns.push(thisItemContentStartColumn)\n\n return { newCurrentPos, itemHasBlankLine }\n}\n\n// Helper function to process list item continuation lines\nfunction checkHTMLTagInterruptsList(\n source: string,\n pos: number,\n indentChars: number,\n baseIndent: number,\n indent: number,\n options: ParseOptions\n): boolean {\n if (indent > baseIndent || options.disableParsingRawHTML) return false\n const lineStartPos = pos + indentChars\n if (lineStartPos >= source.length || source[lineStartPos] !== '<')\n return false\n return isValidHTMLTagStart(source, lineStartPos)\n}\n\n// Lightweight check for HTML tag validity without full parsing\nfunction isValidHTMLTagStart(source: string, pos: number): boolean {\n if (pos >= source.length || source[pos] !== '<') return false\n const len = source.length\n let i = pos + 1\n\n // Handle closing tags\n if (i < len && source[i] === '/') {\n i++\n }\n\n // Must have at least one character for tag name\n if (i >= len) return false\n\n // First character of tag name must be letter\n const firstChar = charCode(source, i)\n if (!isAlphaCode(firstChar)) return false\n i++\n\n // Rest of tag name can be letters, digits, hyphens, underscores\n // Use early return to avoid nested conditionals\n while (i < len) {\n const ch = source[i]\n const code = charCode(source, i)\n\n // Break conditions (valid tag name terminators)\n if (\n ch === '>' ||\n ch === ' ' ||\n ch === '\\t' ||\n ch === '\\n' ||\n ch === '\\r' ||\n ch === '/'\n ) {\n break\n }\n\n // Valid tag name characters - continue\n if (\n ch === '-' ||\n ch === '_' ||\n isAlphaCode(code) ||\n (code >= 48 && code <= 57)\n ) {\n i++\n } else {\n return false // Invalid character in tag name\n }\n }\n\n // Find the end of the tag - use state machine approach to reduce branching\n let state = 0 // 0: normal, 1: in double quotes, 2: in single quotes\n while (i < len) {\n const ch = source[i]\n const code = charCode(source, i)\n\n // State machine for quote handling\n if (state === 1) {\n // in double quotes\n if (ch === '\"') state = 0\n i++\n } else if (state === 2) {\n // in single quotes\n if (ch === \"'\") state = 0\n i++\n } else if (ch === '\"') {\n state = 1\n i++\n } else if (ch === \"'\") {\n state = 2\n i++\n } else if (ch === '>') {\n return true // Found valid closing >\n } else if (ch === '/' && i + 1 < len && source[i + 1] === '>') {\n return true // Found valid self-closing />\n } else if (code === 10 || code === 13) {\n // \\n or \\r\n return false // No multiline tags in this context\n } else {\n i++\n }\n }\n\n return false // No closing > found\n}\n\nfunction processContinuation(\n source: string,\n item: MarkdownToJSX.ASTNode[],\n contentStartColumn: number,\n startPos: number,\n baseIndent: number,\n ordered: boolean,\n marker: string | undefined,\n delimiter: string | undefined,\n listItemRegex: RegExp,\n state: MarkdownToJSX.State,\n options: ParseOptions,\n allowLinkRefs?: boolean\n): number {\n let pos = startPos\n let prevLineWasBlank = false\n while (pos < source.length) {\n const lineEnd = util.findLineEnd(source, pos)\n const indentInfo = calculateIndent(source, pos, lineEnd)\n const indent = indentInfo.spaceEquivalent\n\n if (isBlankLineCheck(source, pos, lineEnd)) {\n prevLineWasBlank = true\n pos = skipToNextLine(source, lineEnd)\n continue\n }\n\n const lineWithoutIndent = source.slice(pos + indentInfo.charCount, lineEnd)\n\n if (\n indent <= baseIndent &&\n isMatchingListItem(\n lineWithoutIndent,\n indentInfo,\n ordered,\n marker,\n delimiter,\n baseIndent,\n listItemRegex\n )\n ) {\n break\n }\n\n if (indent >= contentStartColumn) {\n // Check for link reference definitions (only for first item)\n if (allowLinkRefs && prevLineWasBlank) {\n const refEndPos = skipLinkReferenceDefinition(\n source,\n pos,\n lineEnd,\n indentInfo,\n lineWithoutIndent,\n state,\n options\n )\n if (refEndPos) {\n pos = refEndPos\n prevLineWasBlank = false\n continue\n }\n }\n\n const result = processListContinuationLine(\n source,\n pos,\n lineEnd,\n indentInfo,\n contentStartColumn - 1,\n contentStartColumn,\n item,\n prevLineWasBlank,\n state,\n options,\n undefined,\n baseIndent\n )\n if (result.processed) {\n pos = result.newPos\n prevLineWasBlank = result.wasBlank\n continue\n }\n } else {\n break\n }\n }\n return pos\n}\n\n// Helper: Parse content with paragraph wrapping for tight/loose lists\nfunction parseContentWithParagraphHandling(\n content: string,\n wrapInParagraph: boolean,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): MarkdownToJSX.ASTNode[] {\n const blocks = parseBlocksWithState(content, state, options, {\n inline: false,\n list: true,\n })\n if (blocks.length > 0) {\n // Unwrap single paragraph for tight lists\n return !wrapInParagraph &&\n blocks.length === 1 &&\n blocks[0].type === RuleType.paragraph\n ? (blocks[0] as MarkdownToJSX.ParagraphNode).children\n : blocks\n }\n // Fallback to inline parsing\n const inline = parseWithInlineMode(state, true, () =>\n parseInlineSpan(content, 0, content.length, state, options)\n )\n return wrapInParagraph && inline.length > 0\n ? [\n {\n type: RuleType.paragraph,\n children: inline,\n } as MarkdownToJSX.ParagraphNode,\n ]\n : inline\n}\n\nfunction buildListItemContent(\n itemContent: string,\n itemHasBlankLine: boolean,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): MarkdownToJSX.ASTNode[] {\n const task = parseGFMTask(itemContent, 0, state)\n const hasTask =\n task &&\n (task.endPos >= itemContent.length || itemContent[task.endPos] === ' ')\n if (!hasTask) {\n return parseContentWithParagraphHandling(\n itemContent,\n itemHasBlankLine,\n state,\n options\n )\n }\n const afterTask =\n task.endPos < itemContent.length ? task.endPos + 1 : task.endPos\n const restContent = itemContent.slice(afterTask)\n const restNodes = parseContentWithParagraphHandling(\n restContent,\n itemHasBlankLine,\n state,\n options\n )\n const nodes: MarkdownToJSX.ASTNode[] = [task]\n if (task.endPos < itemContent.length) {\n nodes.push({ type: RuleType.text, text: ' ' } as MarkdownToJSX.TextNode)\n }\n nodes.push(...restNodes)\n return nodes\n}\n\nfunction checkUnicodeWhitespaceAfterMarker(\n match: RegExpMatchArray,\n marker: string\n): boolean {\n if (!match[0]) return false\n const markerInMatch = match[0].indexOf(marker)\n if (markerInMatch === -1) return false\n const afterMarkerInMatch = markerInMatch + marker.length\n if (afterMarkerInMatch >= match[0].length) return false\n const afterMarkerChar = match[0][afterMarkerInMatch]\n return afterMarkerChar ? charCode(afterMarkerChar) === $.CHAR_NBSP : false\n}\n\nfunction convertSetextHeadingInListItem(\n lastItem: MarkdownToJSX.ASTNode[],\n underlineLine: string,\n options: ParseOptions\n): boolean {\n if (lastItem.length === 0) return false\n const lastBlock = lastItem[lastItem.length - 1]\n const trimmed = underlineLine.trim()\n if (\n (!util.startsWith(trimmed, '=') && !util.startsWith(trimmed, '-')) ||\n trimmed.length < 1 ||\n !/^[=-]+[ \\t]*$/.test(trimmed)\n ) {\n return false\n }\n\n let headingChildren: MarkdownToJSX.ASTNode[] = []\n let headingContent = ''\n if (lastBlock.type === RuleType.paragraph) {\n const paragraph = lastBlock as MarkdownToJSX.ParagraphNode\n headingChildren = paragraph.children\n headingContent = paragraph.children\n .map(child =>\n child.type === RuleType.text\n ? (child as MarkdownToJSX.TextNode).text\n : ''\n )\n .join('')\n .trim()\n } else if (lastBlock.type === RuleType.text) {\n const textNodes: MarkdownToJSX.TextNode[] = []\n let i = lastItem.length - 1\n while (i >= 0 && lastItem[i].type === RuleType.text) {\n textNodes.unshift(lastItem[i] as MarkdownToJSX.TextNode)\n i--\n }\n if (textNodes.length > 0) {\n headingChildren = textNodes\n headingContent = textNodes\n .map(node => (node as MarkdownToJSX.TextNode).text)\n .join('')\n .trim()\n }\n }\n\n if (!headingContent) return false\n\n const underlineChar = trimmed[0]\n const level = underlineChar === '=' ? 1 : 2\n if (lastBlock.type === RuleType.paragraph) {\n lastItem.pop()\n } else if (lastBlock.type === RuleType.text) {\n while (\n lastItem.length > 0 &&\n lastItem[lastItem.length - 1].type === RuleType.text\n ) {\n lastItem.pop()\n }\n }\n lastItem.push(\n createHeading(level, headingChildren, headingContent, options.slugify)\n )\n return true\n}\n\nfunction processListContinuationLine(\n source: string,\n currentPos: number,\n nextLineEnd: number,\n nextIndentInfo: ReturnType<typeof calculateIndent>,\n continuationColumn: number,\n contentStartColumn: number,\n lastItem: MarkdownToJSX.ASTNode[],\n prevLineWasBlank: boolean,\n state: MarkdownToJSX.State,\n options: ParseOptions,\n unwrapParagraphs?: boolean,\n baseIndent?: number\n): { processed: boolean; newPos: number; wasBlank: boolean } {\n const nextIndent = nextIndentInfo.spaceEquivalent\n const continuationContent = source.slice(\n currentPos + nextIndentInfo.charCount,\n nextLineEnd\n )\n\n if (nextIndent >= continuationColumn + 4) {\n const blockResult = parseCodeBlock(source, currentPos, state)\n if (blockResult) {\n const codeBlockNode = blockResult as MarkdownToJSX.CodeBlockNode & {\n endPos: number\n }\n const adjustedText = removeExtraIndentFromCodeBlock(\n codeBlockNode.text || '',\n contentStartColumn\n )\n lastItem.push({\n ...codeBlockNode,\n text: adjustedText,\n } as MarkdownToJSX.CodeBlockNode)\n return {\n processed: true,\n newPos: codeBlockNode.endPos,\n wasBlank: false,\n }\n }\n }\n\n const indentRelativeToContentFenced = nextIndent - (contentStartColumn - 1)\n if (\n nextIndent + 1 >= contentStartColumn &&\n indentRelativeToContentFenced <= 3\n ) {\n const continuationStart = currentPos + nextIndentInfo.charCount\n if (continuationStart < nextLineEnd) {\n const firstCharAfterIndent = source[continuationStart]\n if (firstCharAfterIndent === '`' || firstCharAfterIndent === '~') {\n const fencedResult = parseCodeFenced(\n source,\n continuationStart,\n state,\n options\n )\n if (fencedResult) {\n const codeBlockNode = fencedResult as MarkdownToJSX.CodeBlockNode & {\n endPos: number\n }\n const adjustedText = removeExtraIndentFromCodeBlock(\n codeBlockNode.text || '',\n contentStartColumn - 1\n )\n lastItem.push({\n ...codeBlockNode,\n text: adjustedText,\n endPos: codeBlockNode.endPos,\n } as MarkdownToJSX.CodeBlockNode & { endPos: number })\n return {\n processed: true,\n newPos: codeBlockNode.endPos,\n wasBlank: false,\n }\n }\n }\n // Try parsing as table when line starts with |\n if (firstCharAfterIndent === '|') {\n const tableResult = parseTable(\n source,\n continuationStart,\n state,\n options\n )\n if (tableResult) {\n const tableNode = tableResult as MarkdownToJSX.TableNode & {\n endPos: number\n }\n lastItem.push(tableNode)\n return {\n processed: true,\n newPos: tableNode.endPos,\n wasBlank: false,\n }\n }\n }\n }\n }\n\n if (\n continuationContent.length > 0 &&\n (continuationContent[0] === '-' ||\n continuationContent[0] === '*' ||\n continuationContent[0] === '+' ||\n (continuationContent[0] >= '0' && continuationContent[0] <= '9'))\n ) {\n const listMarkerRegex = /^([-*+]|\\d{1,9}[.)])\\s+/\n if (listMarkerRegex.test(continuationContent)) {\n const inline = parseInlineWithState(\n continuationContent,\n 0,\n continuationContent.length,\n state,\n options\n )\n lastItem.push({ type: RuleType.text, text: '\\n' }, ...inline)\n return {\n processed: true,\n newPos: skipToNextLine(source, nextLineEnd),\n wasBlank: false,\n }\n }\n }\n\n const mergedPos = tryMergeBlockquoteContinuation(\n source,\n currentPos,\n lastItem,\n continuationContent,\n state,\n options\n )\n if (mergedPos !== null) {\n return { processed: true, newPos: mergedPos, wasBlank: false }\n }\n\n const continuationBlocks = parseBlocksWithState(\n continuationContent,\n state,\n options,\n { inline: false, list: true }\n )\n if (continuationBlocks.length > 0) {\n if (unwrapParagraphs && continuationBlocks[0].type === RuleType.paragraph) {\n const continuationParagraph =\n continuationBlocks[0] as MarkdownToJSX.ParagraphNode\n lastItem.push(\n { type: RuleType.text, text: '\\n' } as MarkdownToJSX.TextNode,\n ...continuationParagraph.children\n )\n if (continuationBlocks.length > 1) {\n lastItem.push(...continuationBlocks.slice(1))\n }\n } else if (\n !prevLineWasBlank &&\n continuationBlocks[0].type === RuleType.paragraph &&\n lastItem.length > 0\n ) {\n const lastBlock = lastItem[lastItem.length - 1]\n const continuationParagraph =\n continuationBlocks[0] as MarkdownToJSX.ParagraphNode\n if (lastBlock.type === RuleType.paragraph) {\n ;(lastBlock as MarkdownToJSX.ParagraphNode).children.push(\n { type: RuleType.text, text: '\\n' } as MarkdownToJSX.TextNode,\n ...continuationParagraph.children\n )\n } else if (lastBlock.type === RuleType.heading) {\n lastItem.push(...continuationParagraph.children)\n } else if (!listItemHasBlockContent(lastItem)) {\n lastItem.push(\n { type: RuleType.text, text: ' ' } as MarkdownToJSX.TextNode,\n ...continuationParagraph.children\n )\n } else {\n lastItem.push(...continuationBlocks)\n }\n if (continuationBlocks.length > 1) {\n lastItem.push(...continuationBlocks.slice(1))\n }\n } else {\n lastItem.push(...continuationBlocks)\n }\n return {\n processed: true,\n newPos: skipToNextLine(source, nextLineEnd),\n wasBlank: false,\n }\n }\n\n if (prevLineWasBlank) {\n const inline = parseWithInlineMode(state, true, () =>\n parseInlineSpan(\n continuationContent,\n 0,\n continuationContent.length,\n state,\n options\n )\n )\n lastItem.push({\n type: RuleType.paragraph,\n children: inline,\n } as MarkdownToJSX.ParagraphNode)\n } else {\n appendListContinuation(continuationContent, lastItem, state, options)\n }\n return {\n processed: true,\n newPos: skipToNextLine(source, nextLineEnd),\n wasBlank: false,\n }\n}\n\nfunction parseList(\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): ParseResult {\n if (state.inline) return null\n\n // Set inList state for proper GFM task tracking during inline parsing\n var originalInList = state.inList\n state.inList = true\n\n // Lists must start at the beginning of a line (block boundary)\n if (pos > 0) {\n var prevCharCode = charCode(source, pos - 1)\n if (prevCharCode !== $.CHAR_NEWLINE && prevCharCode !== $.CHAR_CR) {\n state.inList = originalInList\n return null\n }\n }\n\n var lineEnd = util.findLineEnd(source, pos)\n var indentInfo = calculateIndent(source, pos, lineEnd)\n // Early fail: headings/lists cannot be indented more than 3 spaces unless in list context\n if (indentInfo.spaceEquivalent > 3 && !state.inList) {\n state.inList = originalInList\n return null\n }\n var line = source.slice(pos, lineEnd)\n var indent = indentInfo.charCount\n var lineWithoutIndent = line.slice(indent)\n\n // Detect list type: ordered (digit marker) vs unordered (-/*/+ marker)\n var matchResult = matchListItem(lineWithoutIndent)\n if (!matchResult) {\n state.inList = originalInList\n return null\n }\n var match = matchResult.match\n var ordered = matchResult.ordered\n var listItemRegex = matchResult.listItemRegex\n\n var baseIndent = indentInfo.spaceEquivalent\n // Extract list-specific properties: start number and delimiter for ordered, marker for unordered\n var start = ordered ? parseInt(match[1], 10) : undefined\n var delimiter = ordered ? match[2] : undefined // '.' or ')' for ordered lists\n var marker = ordered ? undefined : match[1] // '-', '*', or '+' for unordered lists\n\n // Check if this is an empty list item (no content after marker)\n var isEmptyItem = ordered ? match[3] === '' : match[2] === ''\n\n // Helper: Check if we're at a block boundary (document start or after blank line)\n function isAtBlockBoundary(\n checkPos: number,\n requireBlankLine: boolean\n ): boolean {\n if (checkPos === 0) return true\n var prevCode = charCode(source, checkPos - 1)\n if (prevCode !== $.CHAR_NEWLINE) return false\n if (!requireBlankLine) return true\n var backPos = checkPos - 2\n while (backPos >= 0) {\n var code = charCode(source, backPos)\n if (code !== $.CHAR_SPACE && code !== $.CHAR_TAB) break\n backPos--\n }\n return backPos < 0 || charCode(source, backPos) === $.CHAR_NEWLINE\n }\n\n // Per CommonMark: empty list items cannot interrupt paragraphs (need blank line)\n if (isEmptyItem && !isAtBlockBoundary(pos, true)) {\n state.inList = originalInList\n return null\n }\n\n // Per CommonMark: only ordered lists starting with 1 can interrupt paragraphs\n if (ordered && start !== 1 && !isAtBlockBoundary(pos, false)) {\n return null\n }\n\n // For unordered lists, check that the whitespace after marker is regular space/tab, not Unicode whitespace\n if (!ordered && checkUnicodeWhitespaceAfterMarker(match, marker)) {\n return null\n }\n\n // Calculate the content start column: where the first non-whitespace character\n // after the marker delimiter actually appears in the source\n // This is needed to determine continuation indentation\n var markerStartInLine = match.index || 0\n // isEmptyItem is already set above - check if it needs updating based on spacesAfterMarkerCount\n // Empty item is different from item with whitespace but no content\n // We'll calculate spacesAfterMarkerCount later and update isEmptyItem if needed\n var markerEndInLine = ordered\n ? markerStartInLine + match[1].length + match[2].length + 1 // number + delimiter + required space\n : isEmptyItem\n ? markerStartInLine + match[1].length // marker only (no space)\n : markerStartInLine + match[1].length + 1 // marker + required space\n // Find the actual position after marker delimiter in the source\n var contentStartInSource = pos + indent + markerEndInLine\n // Count spaces/tabs before first non-whitespace in the content\n // Per CommonMark spec: marker must be followed by 1 ≤ N ≤ 4 spaces\n var contentColumnResult = calculateListItemContentColumn(\n source,\n contentStartInSource,\n lineEnd,\n baseIndent,\n markerEndInLine\n )\n var contentStartColumn = contentColumnResult.contentStartColumn\n // minimumContentStartColumn is the minimum column where content can start (for continuation checks)\n // This is the column after marker+space, regardless of how much whitespace follows\n // For empty items, it's right after the marker\n var markerBaseColumn = baseIndent + markerStartInLine + match[1].length\n var minimumContentStartColumn = ordered\n ? markerBaseColumn + match[2].length + 1 // number + delimiter + space\n : isEmptyItem\n ? markerBaseColumn // marker only (no space)\n : markerBaseColumn + 1 // marker + space\n\n var items: MarkdownToJSX.ASTNode[][] = []\n // Track contentStartColumn for each item (for nested list detection)\n var itemContentStartColumns: number[] = []\n\n // Helper: Check if a marker column is nested enough to belong to the last item\n function isMarkerNested(\n markerColumn: number,\n lastItemContentColumn: number,\n hasBlockContent: boolean\n ): boolean {\n return hasBlockContent\n ? markerColumn >= lastItemContentColumn\n : markerColumn > lastItemContentColumn\n }\n\n // Helper: Get last item\n function getLastItem(): MarkdownToJSX.ASTNode[] {\n return items[items.length - 1]\n }\n\n // Helper: Get last item's content start column\n function getLastItemContentColumn(): number {\n return (\n itemContentStartColumns[itemContentStartColumns.length - 1] ??\n contentStartColumn\n )\n }\n\n function tryParseNestedList(\n pos: number,\n lastItem: MarkdownToJSX.ASTNode[]\n ): ParseResult | null {\n const parentItem = findNestedListParent(lastItem)\n const originalList = state.inList\n state.inList = true\n const result = parseList(source, pos, state, options)\n state.inList = originalList\n if (result) {\n parentItem.push(result)\n return result\n }\n return null\n }\n\n var currentPos = skipToNextLine(source, lineEnd)\n\n // Check if this is a loose list (has blank lines)\n var checkPos = currentPos\n var hasBlankLines = false\n\n while (checkPos < source.length) {\n var nextLineEnd = util.findLineEnd(source, checkPos)\n var nextLine = source.slice(checkPos, nextLineEnd)\n if (nextLine.trim() === '') {\n // look ahead to next non-empty line\n var look = skipToNextLine(source, nextLineEnd)\n while (look < source.length) {\n var code = charCode(source, look)\n if (code === $.CHAR_NEWLINE) {\n // keep skipping\n } else if (!WHITESPACE_CHARS.has(source[look])) {\n break\n }\n look++\n }\n var lookEnd = util.findLineEnd(source, look)\n var lookLine = source.slice(look, lookEnd)\n var lookIndentInfo = calculateIndent(source, look, lookEnd)\n var lookLineWithoutIndent = lookLine.slice(lookIndentInfo.charCount)\n if (\n isMatchingListItem(\n lookLineWithoutIndent,\n lookIndentInfo,\n ordered,\n marker,\n delimiter,\n baseIndent,\n listItemRegex\n )\n ) {\n hasBlankLines = true\n } else {\n // Per CommonMark: link reference definitions can interrupt lists\n // If blank line is followed by a link reference definition, check if there's a list item after it\n var refEndPos = skipLinkReferenceDefinition(\n source,\n look,\n lookEnd,\n lookIndentInfo,\n lookLineWithoutIndent,\n state,\n options\n )\n if (refEndPos) {\n var afterRefPos = refEndPos\n while (\n afterRefPos < source.length &&\n charCode(source, afterRefPos) === $.CHAR_NEWLINE\n ) {\n afterRefPos++\n }\n if (afterRefPos < source.length) {\n var afterRefLineEnd = util.findLineEnd(source, afterRefPos)\n var afterRefLine = source.slice(afterRefPos, afterRefLineEnd)\n var afterRefIndentInfo = calculateIndent(\n source,\n afterRefPos,\n afterRefLineEnd\n )\n var afterRefLineWithoutIndent = afterRefLine.slice(\n afterRefIndentInfo.charCount\n )\n if (\n isMatchingListItem(\n afterRefLineWithoutIndent,\n afterRefIndentInfo,\n ordered,\n marker,\n delimiter,\n baseIndent,\n listItemRegex\n )\n ) {\n hasBlankLines = true\n }\n }\n }\n }\n break\n }\n var nextIndentInfo = calculateIndent(source, checkPos, nextLineEnd)\n var nextLineWithoutIndent = nextLine.slice(nextIndentInfo.charCount)\n var nextMatchResult = matchListItem(nextLineWithoutIndent)\n if (!nextMatchResult) break\n var nextMatch = nextMatchResult.match\n if (ordered) {\n if (nextMatch[2] !== delimiter) break\n } else {\n if (nextMatch[1] !== marker) break\n }\n checkPos = skipToNextLine(source, nextLineEnd)\n }\n\n // Parse the first item\n var firstItemContent = ordered ? match[3] : match[2]\n // Trim leading whitespace from content (regex now captures optional whitespace)\n firstItemContent = firstItemContent.trimStart()\n\n // Per CommonMark spec: tabs after list marker need special handling\n // For `-\\t\\tfoo`: `-` at column 0, first tab at column 1 = 3 spaces (one for marker delimiter),\n // second tab at column 4 = 4 spaces, total 6 spaces, so code block with 2 spaces remaining\n // The regex `\\s+` consumes the tabs, so match[2]/match[3] is just `foo`\n // We need to check the original source to detect tabs after the marker\n var markerStartPos = pos + indent + (match.index || 0)\n var markerEndPos = ordered\n ? markerStartPos + match[1].length + match[2].length // number + delimiter\n : markerStartPos + match[1].length // marker\n\n // Check for spaces after marker (for code blocks with 5+ spaces)\n // Per CommonMark: if there are 4+ spaces after the marker (including required space),\n // the first line is an indented code block\n var contentStartPos = markerEndPos\n // Skip the required space/tab after marker\n while (contentStartPos < source.length) {\n var code = charCode(source, contentStartPos)\n if (code !== $.CHAR_SPACE && code !== $.CHAR_TAB) break\n contentStartPos++\n }\n // Count spaces after marker (including the required one)\n var spacesAfterMarkerCount = 0\n var spacesCheckPos = markerEndPos\n while (spacesCheckPos < lineEnd) {\n var code = charCode(source, spacesCheckPos)\n if (code === $.CHAR_TAB) {\n spacesAfterMarkerCount += 4 - (spacesAfterMarkerCount % 4)\n } else if (code === $.CHAR_SPACE) {\n spacesAfterMarkerCount++\n } else {\n break\n }\n spacesCheckPos++\n }\n\n var tabsProcessed = false\n if (\n markerEndPos < source.length &&\n charCode(source, markerEndPos) === $.CHAR_TAB\n ) {\n // First tab after marker was consumed by `\\s+`\n // Tab at column 1 = 3 spaces (1 for delimiter, 2 for content)\n // Check if there's a second tab\n var tabCount = 1\n var tabCheckPos = markerEndPos + 1\n while (\n tabCheckPos < source.length &&\n charCode(source, tabCheckPos) === $.CHAR_TAB\n ) {\n tabCount++\n tabCheckPos++\n }\n\n if (tabCount >= 2) {\n // We have 2+ tabs after marker: first gives 2 spaces, second at column 4 = 4 spaces\n // Total: 6 spaces, then remove 4 for code block = 2 spaces\n firstItemContent = ' ' + firstItemContent\n tabsProcessed = true\n }\n }\n // Update isEmptyItem now that we know spacesAfterMarkerCount\n // Empty item is one with no whitespace after marker (spacesAfterMarkerCount === 0)\n // For unordered lists, also check that match[2] is empty (no content captured)\n if (!ordered) {\n isEmptyItem = isEmptyItem && spacesAfterMarkerCount === 0\n }\n // RULE_2_CODE_START: if 4+ spaces after marker, first line is indented code block\n // Skip if tabs were already processed (they already account for code block indentation)\n if (spacesAfterMarkerCount >= 4 && !tabsProcessed) {\n // Preserve the leading spaces for code blocks\n const preservedSpaces = ' '.repeat(spacesAfterMarkerCount - 1)\n firstItemContent = preservedSpaces + firstItemContent.trimStart()\n }\n\n // RULE_3_BLANK_START: check if item starts with blank line\n // If firstItemContent is empty (just whitespace), this is RULE_3_BLANK_START\n var startsWithBlankLine = firstItemContent.trim() === ''\n if (startsWithBlankLine) {\n // For RULE_3_BLANK_START, content starts after blank line(s)\n // Continuation lines need to be indented by W + 1 spaces minimum\n // W is the width of the marker (1 for '-', 2 for '10.', etc.)\n // So minimum continuation indent is markerWidth + 1\n }\n\n // Check if there will be blank lines within the first item (after currentPos)\n // by looking ahead to see if we'll encounter a blank line before the next item or end\n let firstItemHasBlankLine = hasBlankLines\n if (!hasBlankLines && currentPos < source.length) {\n var firstCheckPos = currentPos\n while (firstCheckPos < source.length) {\n var firstNextLineEnd = util.findLineEnd(source, firstCheckPos)\n var firstNextLine = source.slice(firstCheckPos, firstNextLineEnd)\n if (isBlankLineCheck(source, firstCheckPos, firstNextLineEnd)) {\n // Found blank line - check if continuation belongs to nested list or first item\n var afterBlank = skipToNextLine(source, firstNextLineEnd)\n // Skip consecutive blank lines\n while (afterBlank < source.length) {\n var blankLineEnd = util.findLineEnd(source, afterBlank)\n if (isBlankLineCheck(source, afterBlank, blankLineEnd)) {\n afterBlank = skipToNextLine(source, blankLineEnd)\n } else {\n break\n }\n }\n\n if (afterBlank < source.length) {\n var afterIndentInfo = calculateIndent(\n source,\n afterBlank,\n source.length\n )\n var afterIndent = afterIndentInfo.spaceEquivalent\n if (afterIndent >= baseIndent) {\n var afterLine = source.slice(\n afterBlank,\n util.findLineEnd(source, afterBlank)\n )\n var afterMatch = afterLine\n .slice(afterIndentInfo.charCount)\n .match(listItemRegex)\n var afterIsNewItem =\n afterMatch &&\n (ordered ? afterMatch[2] === delimiter : afterMatch[1] === marker)\n\n // Find nested item before blank line and calculate its content column\n var nestedItemContentColumn = null\n for (\n var nestedCheckPos = currentPos;\n nestedCheckPos < firstCheckPos;\n nestedCheckPos = util.findLineEnd(source, nestedCheckPos) + 1\n ) {\n var nestedCheckLineEnd = util.findLineEnd(source, nestedCheckPos)\n var nestedCheckIndentInfo = calculateIndent(\n source,\n nestedCheckPos,\n nestedCheckLineEnd\n )\n var nestedCheckMatch = source\n .slice(nestedCheckPos, nestedCheckLineEnd)\n .slice(nestedCheckIndentInfo.charCount)\n .match(listItemRegex)\n var isNestedItem =\n nestedCheckMatch &&\n nestedCheckIndentInfo.spaceEquivalent > baseIndent &&\n nestedCheckIndentInfo.spaceEquivalent >= contentStartColumn &&\n (ordered\n ? nestedCheckMatch[2] === delimiter\n : nestedCheckMatch[1] === marker)\n\n if (isNestedItem) {\n // Calculate nested item's content column (same pattern as contentStartColumn)\n var nestedMarkerStart =\n nestedCheckIndentInfo.spaceEquivalent + 1\n var nestedMarkerEnd = ordered\n ? nestedMarkerStart +\n nestedCheckMatch[1].length +\n nestedCheckMatch[2].length +\n 1\n : nestedMarkerStart + nestedCheckMatch[1].length + 1\n var nestedContentStartInSource =\n nestedCheckPos +\n nestedCheckIndentInfo.charCount +\n nestedCheckMatch[0].length\n var nestedResult = calculateListItemContentColumn(\n source,\n nestedContentStartInSource,\n nestedCheckLineEnd,\n nestedMarkerStart,\n nestedMarkerEnd - nestedMarkerStart\n )\n nestedItemContentColumn = nestedResult.contentStartColumn\n break\n }\n }\n\n var continuationCheckColumn =\n spacesAfterMarkerCount >= 5\n ? minimumContentStartColumn\n : contentStartColumn\n if (\n !afterIsNewItem &&\n afterIndent >= continuationCheckColumn &&\n (nestedItemContentColumn === null ||\n afterIndent + 1 < nestedItemContentColumn)\n ) {\n firstItemHasBlankLine = true\n }\n }\n }\n break\n }\n // Check if this line is a new list item (at same or greater indentation)\n var firstLineIndentInfo = calculateIndent(\n source,\n firstCheckPos,\n firstNextLineEnd\n )\n var firstIndent = firstLineIndentInfo.spaceEquivalent\n var firstLineWithoutIndent = firstNextLine.slice(\n firstLineIndentInfo.charCount\n )\n var firstLineMatch = firstLineWithoutIndent.match(listItemRegex)\n var firstIsNewItem =\n firstLineMatch &&\n (ordered\n ? firstLineMatch[2] === delimiter\n : firstLineMatch[1] === marker)\n // If it's a new item at baseIndent, it's the next item at same level - stop looking\n // For nested items, continue looking for blank lines after the nested list\n if (firstIsNewItem) {\n if (firstIndent <= baseIndent) {\n // Same level or higher - stop looking\n break\n }\n // Nested list - continue looking (don't break)\n }\n firstCheckPos = skipToNextLine(source, firstNextLineEnd)\n }\n }\n\n // Handle fenced code blocks that span multiple lines\n // Note: We use manual expansion here rather than parseCodeFenced because\n // we need to return a content string (with fence lines) that will be parsed later,\n // not an AST node. parseCodeFenced returns an AST node, which doesn't fit this use case.\n var actualFirstItemContent = firstItemContent\n if (\n util.startsWith(firstItemContent, '```') ||\n util.startsWith(firstItemContent, '~~~')\n ) {\n var markerWidth = ordered\n ? match[1].length + match[2].length + 1\n : match[1].length + 1\n var expandedResult = expandMultilineFencedCodeBlock(\n source,\n firstItemContent,\n currentPos,\n markerWidth\n )\n actualFirstItemContent = expandedResult.content\n currentPos = expandedResult.endPos\n }\n\n // For tight lists with whitespace-only first line, combine with continuation to avoid multiple blocks\n var hasWhitespaceButNoContent =\n !isEmptyItem &&\n firstItemContent.trim() === '' &&\n spacesAfterMarkerCount > 0 &&\n spacesAfterMarkerCount < 5\n // For ALL tight lists (no blank lines), concatenate simple text continuation lines BEFORE\n // building the item content. This is necessary to preserve hard line breaks (two trailing\n // spaces before newline) that would otherwise be lost when first line and continuation are\n // parsed separately. The broader condition (not just whitespace-only first lines) is safe\n // because we stop collecting text when we hit NEW block elements (not continuations of the\n // same block element), which ensures block-level structures are still parsed correctly.\n if (!firstItemHasBlankLine) {\n // Detect if the first line starts a blockquote (to allow continuation lines)\n var firstLineFirstChar =\n actualFirstItemContent.length > 0 ? actualFirstItemContent[0] : ''\n var firstLineStartsBlockQuote = firstLineFirstChar === '>'\n\n var pos = currentPos\n while (pos < source.length) {\n var lineEnd = util.findLineEnd(source, pos)\n var line = source.slice(pos, lineEnd)\n if (line.trim() === '') break\n var indentInfo = calculateIndent(source, pos, lineEnd)\n if (indentInfo.spaceEquivalent < minimumContentStartColumn) break\n var lineWithoutIndent = line.slice(indentInfo.charCount)\n if (\n indentInfo.spaceEquivalent <= baseIndent &&\n isMatchingListItem(\n lineWithoutIndent,\n indentInfo,\n ordered,\n marker,\n delimiter,\n baseIndent,\n listItemRegex\n )\n ) {\n break\n }\n // Check for nested list items\n if (\n isLineListItem(lineWithoutIndent) &&\n indentInfo.spaceEquivalent > baseIndent\n ) {\n break\n }\n // Check for block elements - stop collecting text if we hit a NEW block element\n // (not a continuation of the same block element started on the first line)\n var firstChar = lineWithoutIndent.length > 0 ? lineWithoutIndent[0] : ''\n // Allow blockquote continuation if first line started a blockquote\n var isBlockQuoteContinuation =\n firstChar === '>' && firstLineStartsBlockQuote\n if (\n (firstChar === '>' && !isBlockQuoteContinuation) ||\n firstChar === '#' ||\n util.startsWith(lineWithoutIndent, '```') ||\n util.startsWith(lineWithoutIndent, '~~~')\n ) {\n break\n }\n actualFirstItemContent += '\\n' + lineWithoutIndent\n currentPos = pos = skipToNextLine(source, lineEnd)\n }\n }\n\n // Build first item with GFM task support\n items.push(\n buildListItemContent(\n actualFirstItemContent,\n firstItemHasBlankLine,\n state,\n options\n )\n )\n itemContentStartColumns.push(contentStartColumn)\n\n // Process continuation lines for the first item\n // For tight lists (no blank lines), also process continuation if it's indented enough\n const shouldProcessContinuation =\n firstItemHasBlankLine &&\n (spacesAfterMarkerCount >= 5 || hasWhitespaceButNoContent)\n if (shouldProcessContinuation) {\n const lastItem = getLastItem()\n currentPos = processContinuation(\n source,\n lastItem,\n minimumContentStartColumn,\n currentPos,\n baseIndent,\n ordered,\n marker,\n delimiter,\n listItemRegex,\n state,\n options,\n true\n )\n } else if (!firstItemHasBlankLine) {\n // For tight lists (no blank lines), process continuation lines\n const continuationColumn = minimumContentStartColumn - 1\n while (currentPos < source.length) {\n const nextLineEnd = util.findLineEnd(source, currentPos)\n const nextLine = source.slice(currentPos, nextLineEnd)\n const nextIndentInfo = calculateIndent(source, currentPos, nextLineEnd)\n const nextIndent = nextIndentInfo.spaceEquivalent\n const nextLineWithoutIndent = nextLine.slice(nextIndentInfo.charCount)\n\n if (\n nextLine.trim() === '' ||\n (nextIndent <= baseIndent &&\n isMatchingListItem(\n nextLineWithoutIndent,\n nextIndentInfo,\n ordered,\n marker,\n delimiter,\n baseIndent,\n listItemRegex\n )) ||\n (isLineListItem(nextLineWithoutIndent) && nextIndent > baseIndent) ||\n nextIndent < continuationColumn\n ) {\n break\n }\n\n const lastItem = getLastItem()\n const result = processListContinuationLine(\n source,\n currentPos,\n nextLineEnd,\n nextIndentInfo,\n continuationColumn,\n contentStartColumn,\n lastItem,\n false,\n state,\n options,\n true,\n baseIndent\n )\n if (result.processed) {\n currentPos = result.newPos\n } else {\n break\n }\n }\n }\n\n // Continue parsing subsequent list items\n var prevLineWasBlank = false\n while (currentPos < source.length) {\n const nextLineEnd = util.findLineEnd(source, currentPos)\n\n const nextLine = source.slice(currentPos, nextLineEnd)\n const nextIndentInfo = calculateIndent(source, currentPos, nextLineEnd)\n const nextIndentChars = nextIndentInfo.charCount\n const nextIndent = nextIndentInfo.spaceEquivalent\n\n if (nextLine.trim() === '') {\n // Blank line - mark as loose list and continue\n hasBlankLines = true\n prevLineWasBlank = true\n currentPos = skipToNextLine(source, nextLineEnd)\n } else if (nextIndent < baseIndent) {\n const nextLineWithoutIndent = nextLine.slice(nextIndentChars)\n if (\n nextLineWithoutIndent.startsWith('<') &&\n checkHTMLTagInterruptsList(\n source,\n currentPos,\n nextIndentChars,\n baseIndent,\n nextIndent,\n options\n )\n ) {\n break\n }\n\n // Less indented - check if this is a lazy continuation line\n // Per CommonMark: lazy continuation lines can have all indentation deleted\n // They are still part of the list item if they are paragraph continuation text\n const trimmed = nextLineWithoutIndent.trim()\n if (\n trimmed.length > 0 &&\n items.length > 0 &&\n !isBlockStartChar(trimmed[0]) &&\n !isMatchingListItem(\n nextLineWithoutIndent,\n nextIndentInfo,\n ordered,\n marker,\n delimiter,\n baseIndent,\n listItemRegex\n )\n ) {\n const lastItem = getLastItem()\n if (lastItem.length > 0) {\n const lastBlock = lastItem[lastItem.length - 1]\n if (\n !prevLineWasBlank &&\n (lastBlock.type === RuleType.paragraph ||\n lastBlock.type === RuleType.text)\n ) {\n // This is a lazy continuation line - continue the paragraph\n // Per CommonMark: lazy continuation only applies when there's no blank line\n appendListContinuation(\n nextLineWithoutIndent,\n lastItem,\n state,\n options\n )\n prevLineWasBlank = false\n currentPos = skipToNextLine(source, nextLineEnd)\n continue\n }\n }\n }\n // Not a lazy continuation - end of list\n break\n } else {\n const nextLineWithoutIndent = nextLine.slice(nextIndentChars)\n\n // Check for setext heading BEFORE thematic break\n // If last item ends with text/paragraph and this line is setext underline, convert to heading\n // Per CommonMark: setext underline must be indented enough to be continuation\n // BUT: don't check if this line is a list item marker (would be continuation of wrong item)\n if (items.length > 0) {\n const lastItemContentStartColumn =\n itemContentStartColumns[items.length - 1] || contentStartColumn\n if (\n nextIndent + 1 >= lastItemContentStartColumn &&\n !isMatchingListItem(\n nextLineWithoutIndent,\n nextIndentInfo,\n ordered,\n marker,\n delimiter,\n baseIndent,\n listItemRegex\n )\n ) {\n const lastItem = getLastItem()\n if (\n lastItem.length > 0 &&\n convertSetextHeadingInListItem(\n lastItem,\n nextLineWithoutIndent,\n options\n )\n ) {\n currentPos = skipToNextLine(source, nextLineEnd)\n continue\n }\n }\n }\n\n // Check if this line is a thematic break (per CommonMark, thematic breaks end lists)\n const thematicBreakResult = parseBreakThematic(\n source,\n currentPos,\n state,\n options\n )\n if (thematicBreakResult) {\n // Thematic break ends the list\n break\n }\n\n // Per CommonMark spec: link reference definitions interrupt list continuation\n // Check if this is a link reference definition after a blank line\n if (prevLineWasBlank) {\n const refEndPos = skipLinkReferenceDefinition(\n source,\n currentPos,\n nextLineEnd,\n nextIndentInfo,\n nextLineWithoutIndent,\n state,\n options\n )\n if (refEndPos) {\n // Skip link reference definition and continue parsing list (don't break)\n currentPos = refEndPos\n prevLineWasBlank = false\n continue\n }\n }\n\n // If line is at base indentation and not a list item, check for lazy continuation first\n if (nextIndent <= baseIndent) {\n if (\n nextLineWithoutIndent.startsWith('<') &&\n checkHTMLTagInterruptsList(\n source,\n currentPos,\n nextIndentChars,\n baseIndent,\n nextIndent,\n options\n )\n ) {\n break\n }\n\n if (\n !isMatchingListItem(\n nextLineWithoutIndent,\n nextIndentInfo,\n ordered,\n marker,\n delimiter,\n baseIndent,\n listItemRegex\n )\n ) {\n // Check for lazy continuation when nextIndent === baseIndent\n // Per CommonMark: lazy continuation lines can have all indentation deleted\n // BUT: only if there was no blank line before (lazy continuation requires no blank line)\n // AND: only if it's truly paragraph continuation text (not a block start)\n if (nextIndent === baseIndent && !prevLineWasBlank) {\n const trimmed = nextLineWithoutIndent.trim()\n if (trimmed.length > 0 && !isBlockStartChar(trimmed[0])) {\n // Check if this line would start a block (like HTML comment, thematic break, etc.)\n // If so, it should break the list, not continue it\n const blockResult = parseBlock(source, currentPos, state, options)\n if (blockResult && blockResult.type !== RuleType.paragraph) {\n break\n }\n const lastItem = getLastItem()\n if (lastItem.length > 0 && !listItemHasBlockContent(lastItem)) {\n // This is a lazy continuation line - continue the inline content\n // Lazy continuation lines don't add a newline (no space in output)\n appendListContinuation(\n nextLineWithoutIndent,\n lastItem,\n state,\n options,\n false\n )\n prevLineWasBlank = false\n currentPos = skipToNextLine(source, nextLineEnd)\n continue\n }\n }\n }\n break\n }\n }\n\n // Check for empty items with blank lines\n if (\n shouldBreakForEmptyItem(\n items,\n isEmptyItem,\n prevLineWasBlank,\n firstItemContent\n )\n )\n break\n\n const nextMatchResult = matchListItem(nextLineWithoutIndent)\n const nextMatch = nextMatchResult ? nextMatchResult.match : null\n const isSameType =\n nextMatch &&\n (ordered ? nextMatch[2] === delimiter : nextMatch[1] === marker)\n // Per CommonMark: list markers may be indented by up to 3 spaces\n // If marker is too indented (> 3 spaces), it's not a valid list item\n // If there's a blank line before such a marker, end the list (e.g., Example 313)\n if (isSameType && nextIndent > 3 && prevLineWasBlank) {\n break\n }\n // Skip list item processing and fall through to continuation check\n if (isSameType && nextIndent <= baseIndent + 3) {\n if (nextIndent >= 4 && prevLineWasBlank) break\n if (nextIndent === baseIndent) {\n // Item at same level - parse as new item\n let itemContent = ordered ? nextMatch[3] : nextMatch[2]\n itemContent = itemContent.trimStart()\n\n const result = addListItem(\n source,\n items,\n itemContentStartColumns,\n itemContent,\n currentPos,\n nextLineEnd,\n nextIndent,\n nextIndentChars,\n nextMatch,\n ordered,\n hasBlankLines,\n state,\n options\n )\n currentPos = result.newCurrentPos\n prevLineWasBlank = false\n\n // For empty items, process continuation immediately\n if (itemContent.trim() === '') {\n const newItem = items[items.length - 1]\n const thisItemContentStartColumn = getLastItemContentColumn()\n currentPos = processContinuation(\n source,\n newItem,\n thisItemContentStartColumn,\n currentPos,\n baseIndent,\n ordered,\n marker,\n delimiter,\n listItemRegex,\n state,\n options\n )\n }\n\n continue\n }\n if (nextIndent > baseIndent) {\n // Per CommonMark spec: items are only nested if indented enough to belong to previous item\n // If there was a blank line before this item, it's at the same level (not nested)\n if (prevLineWasBlank) {\n // Blank line before item means it's a new item at same level, not nested\n let itemContent = ordered ? nextMatch[3] : nextMatch[2]\n // Trim leading whitespace from content (regex now captures optional whitespace)\n itemContent = itemContent.trimStart()\n const result = addListItem(\n source,\n items,\n itemContentStartColumns,\n itemContent,\n currentPos,\n nextLineEnd,\n nextIndent,\n nextIndentChars,\n nextMatch,\n ordered,\n hasBlankLines,\n state,\n options\n )\n currentPos = result.newCurrentPos\n prevLineWasBlank = false\n continue\n }\n // Check if this item's marker position is indented enough to be continuation of previous item\n // We need to calculate the previous item's contentStartColumn, not use the first item's\n const lastItem = getLastItem()\n const markerColumn = nextIndent + 1\n const isNested = isMarkerNested(\n markerColumn,\n getLastItemContentColumn(),\n listItemHasBlockContent(lastItem)\n )\n\n if (isNested) {\n const nestedResult = tryParseNestedList(currentPos, lastItem)\n if (nestedResult) {\n currentPos = nestedResult.endPos\n prevLineWasBlank = false\n continue\n }\n }\n // Item is not indented enough to be nested - check if it's same type for same level\n if (!isNested && isSameType) {\n // This item has more indentation than baseIndent but not enough to be nested\n // It's still at the same level - parse it as a new item\n let itemContent = ordered ? nextMatch[3] : nextMatch[2]\n // Trim leading whitespace from content\n itemContent = itemContent.trimStart()\n if (!hasBlankLines) {\n // Check if this item has blank lines within it\n let checkItemPos = skipToNextLine(source, nextLineEnd)\n while (checkItemPos < source.length) {\n const checkLineEnd = util.findLineEnd(source, checkItemPos)\n const checkLine = source.slice(checkItemPos, checkLineEnd)\n const checkIndentInfo = calculateIndent(\n source,\n checkItemPos,\n checkLineEnd\n )\n const checkIndent = checkIndentInfo.spaceEquivalent\n\n if (checkLine.trim() === '') {\n const afterBlank = skipToNextLine(source, checkLineEnd)\n if (afterBlank < source.length) {\n const afterBlankIndentInfo = calculateIndent(\n source,\n afterBlank,\n source.length\n )\n const afterBlankIndent =\n afterBlankIndentInfo.spaceEquivalent\n // Calculate contentStartColumn for this item\n const thisItemMarkerStart = nextIndent\n const thisItemContentStart =\n thisItemMarkerStart +\n (ordered\n ? nextMatch[1].length + nextMatch[2].length + 1\n : nextMatch[1].length + 1)\n if (afterBlankIndent + 1 > thisItemContentStart) {\n break\n }\n }\n break\n } else if (checkIndent <= baseIndent) {\n // Check if this is the next list item at baseIndent or less\n const checkLineWithoutIndent = checkLine.slice(\n checkIndentInfo.charCount\n )\n const checkMatch = checkLineWithoutIndent.match(listItemRegex)\n const isNextItem =\n checkMatch &&\n (ordered\n ? checkMatch[2] === delimiter\n : checkMatch[1] === marker)\n if (isNextItem && checkIndent <= baseIndent) {\n break\n }\n }\n checkItemPos = skipToNextLine(source, checkLineEnd)\n }\n }\n const result = addListItem(\n source,\n items,\n itemContentStartColumns,\n itemContent,\n currentPos,\n nextLineEnd,\n nextIndent,\n nextIndentChars,\n nextMatch,\n ordered,\n hasBlankLines,\n state,\n options\n )\n currentPos = result.newCurrentPos\n prevLineWasBlank = false\n continue\n } else if (!isNested && !isSameType) {\n // Different marker type at same level - end this list\n break\n }\n // Fall through to continuation check if isNested but parseList failed\n // Check if this is continuation content\n // Per CommonMark: continuation needs to be indented to at least the content start column\n // nextIndent is space count (0-indexed), contentStartColumn is column number (1-indexed)\n // When list item has block content, exact indentation (==) continues; otherwise use >\n // For continuation checks, use minimumContentStartColumn (column after marker+space)\n // instead of contentStartColumn (which can be higher for code blocks)\n {\n const lastItem = getLastItem()\n // Check if last item is empty (no content)\n const lastItemIsEmpty = lastItem.length === 0\n // Check for empty items with blank lines\n if (\n lastItemIsEmpty &&\n shouldBreakForEmptyItem(\n items,\n isEmptyItem,\n prevLineWasBlank,\n firstItemContent\n )\n )\n break\n\n const hasBlockContent = lastItem.some(\n node =>\n node.type === RuleType.codeBlock ||\n node.type === RuleType.paragraph ||\n node.type === RuleType.blockQuote ||\n node.type === RuleType.orderedList ||\n node.type === RuleType.unorderedList ||\n node.type === RuleType.heading\n )\n // For empty items, use minimumContentStartColumn (marker + space) instead of contentStartColumn\n // which can be higher when there's extra whitespace but no content\n const continuationColumn =\n lastItemIsEmpty && items.length === 1\n ? minimumContentStartColumn\n : contentStartColumn\n const continuationCheck = hasBlockContent\n ? nextIndent >= continuationColumn\n : nextIndent > continuationColumn\n if (continuationCheck) {\n const result = processListContinuationLine(\n source,\n currentPos,\n nextLineEnd,\n nextIndentInfo,\n continuationColumn,\n contentStartColumn,\n getLastItem(),\n prevLineWasBlank,\n state,\n options,\n undefined,\n baseIndent\n )\n if (result.processed) {\n prevLineWasBlank = result.wasBlank\n currentPos = result.newPos\n continue\n }\n } else {\n break\n }\n }\n } else if (nextIndent === baseIndent) {\n // Check for Unicode whitespace after marker in unordered lists\n if (\n !ordered &&\n nextMatch &&\n checkUnicodeWhitespaceAfterMarker(nextMatch, nextMatch[1])\n ) {\n break\n }\n let itemContent = ordered ? nextMatch[3] : nextMatch[2]\n // Trim leading whitespace from content (regex now captures optional whitespace)\n itemContent = itemContent.trimStart()\n // Per CommonMark: A list is loose if items are separated by blank lines,\n // OR if an item directly contains two block-level elements with a blank line between them.\n // If list is loose (hasBlankLines = true), ALL items are wrapped.\n // Otherwise, an item is wrapped only if it has blank lines within it.\n // A blank line before this item means the PREVIOUS item was separated from this one,\n // making the list loose. For this item, we check if it has continuation after blank lines.\n // But if the list is already loose (hasBlankLines), wrap this item too.\n const result = addListItem(\n source,\n items,\n itemContentStartColumns,\n itemContent,\n currentPos,\n nextLineEnd,\n baseIndent,\n nextIndentChars,\n nextMatch,\n ordered,\n hasBlankLines,\n state,\n options\n )\n currentPos = result.newCurrentPos\n prevLineWasBlank = false\n }\n } else if (nextIndent > baseIndent) {\n // Check if this is a list item - if so, check if it should be nested or separate\n // Per CommonMark: list item markers can only be indented 0-3 spaces relative to baseIndent\n // However, nested lists can have more indentation if they're indented relative to content start\n // So we need to try parsing as nested list first, then check for paragraph continuation\n const lastItem = getLastItem()\n const isListItemResult = isLineListItem(nextLineWithoutIndent)\n if (isListItemResult) {\n // Check if marker would be properly nested (relative to content start column)\n // This handles nested lists that may have > 3 spaces indent from baseIndent\n const markerColumn = nextIndent + 1\n const isNested = isMarkerNested(\n markerColumn,\n getLastItemContentColumn(),\n listItemHasBlockContent(lastItem)\n )\n\n if (isNested) {\n // Properly nested - try parsing as nested list\n const nestedResult = tryParseNestedList(currentPos, lastItem)\n if (nestedResult) {\n currentPos = nestedResult.endPos\n prevLineWasBlank = false\n continue\n }\n }\n\n // Not properly nested - check if marker indent is valid (0-3 spaces relative to baseIndent)\n // Per CommonMark: list item markers can only be indented 0-3 spaces relative to baseIndent\n const markerIndentRelative = nextIndent - baseIndent\n if (markerIndentRelative > 3) {\n // Too much indentation (> 3 spaces from baseIndent) and not nested - not a valid list item marker\n // Check if it should be treated as paragraph continuation (if last item ends with paragraph)\n const lastBlock =\n lastItem.length > 0 ? lastItem[lastItem.length - 1] : null\n if (\n lastBlock &&\n (lastBlock.type === RuleType.paragraph ||\n lastBlock.type === RuleType.text)\n ) {\n // This is paragraph continuation text, not a code block or nested list\n appendListContinuation(\n nextLineWithoutIndent,\n lastItem,\n state,\n options\n )\n prevLineWasBlank = false\n currentPos = skipToNextLine(source, nextLineEnd)\n continue\n }\n // Not paragraph continuation - fall through to code block check\n } else {\n // Valid marker indent (0-3 spaces) but not nested - this should be a separate list\n break\n }\n } else {\n // Not a list item - try parsing as nested list (for other block types)\n const nestedResult = tryParseNestedList(currentPos, lastItem)\n if (nestedResult) {\n currentPos = nestedResult.endPos\n prevLineWasBlank = false\n continue\n }\n }\n // Check if this is continuation content\n // Per CommonMark: continuation needs to be indented to at least the content start column\n // nextIndent is space count (0-indexed), contentStartColumn is column number (1-indexed)\n // When list item has block content, exact indentation (==) continues; otherwise use >\n // For continuation checks, use minimumContentStartColumn (column after marker+space)\n // instead of contentStartColumn (which can be higher for code blocks)\n const continuationColumn = contentStartColumn\n const continuationCheck = listItemHasBlockContent(lastItem)\n ? nextIndent >= continuationColumn - 1\n : nextIndent > continuationColumn - 1\n if (continuationCheck) {\n const result = processListContinuationLine(\n source,\n currentPos,\n nextLineEnd,\n nextIndentInfo,\n continuationColumn - 1,\n contentStartColumn,\n getLastItem(),\n prevLineWasBlank,\n state,\n options,\n undefined,\n baseIndent\n )\n if (result.processed) {\n prevLineWasBlank = result.wasBlank\n currentPos = result.newPos\n continue\n }\n } else {\n break\n }\n } else {\n break\n }\n }\n }\n\n // For loose lists, ensure all items have paragraph wrappers\n // The first item may have been created before we detected that the list is loose\n if (\n hasBlankLines &&\n items.length > 1 &&\n items[0].length > 0 &&\n items[0][0].type !== RuleType.paragraph\n ) {\n // Check if list is truly loose (another item has paragraph wrapper)\n for (var j = 1; j < items.length; j++) {\n if (items[j].length > 0 && items[j][0].type === RuleType.paragraph) {\n // First item is all inline content - wrap it for loose lists\n var isBlock = false\n for (var i = 0; i < items[0].length; i++) {\n var t = items[0][i].type\n if (\n t === RuleType.codeBlock ||\n t === RuleType.heading ||\n t === RuleType.blockQuote ||\n t === RuleType.orderedList ||\n t === RuleType.unorderedList ||\n t === RuleType.htmlBlock ||\n t === RuleType.breakThematic\n ) {\n isBlock = true\n break\n }\n }\n if (!isBlock) {\n items[0] = [\n {\n type: RuleType.paragraph,\n children: items[0],\n } as MarkdownToJSX.ParagraphNode,\n ]\n }\n break\n }\n }\n }\n\n const listNode = ordered\n ? ({\n type: RuleType.orderedList,\n items,\n ordered: true,\n start,\n } as MarkdownToJSX.OrderedListNode)\n : ({\n type: RuleType.unorderedList,\n items,\n ordered: false,\n } as MarkdownToJSX.UnorderedListNode)\n\n // Restore original inList state\n state.inList = originalInList\n\n return {\n ...listNode,\n endPos: currentPos,\n } as (MarkdownToJSX.OrderedListNode | MarkdownToJSX.UnorderedListNode) & {\n endPos: number\n }\n}\n\nfunction parseTable(\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): ParseResult {\n if (state.inline) return null\n\n const lines: string[] = []\n let currentPos = pos\n\n while (currentPos < source.length) {\n const lineEnd = util.findLineEnd(source, currentPos)\n if (isBlankLineCheck(source, currentPos, lineEnd)) break\n\n const line = source.slice(currentPos, lineEnd).trim()\n const isTableLine =\n line.indexOf('|') !== -1 ||\n (lines.length >= 3 && line && !isBlockStartChar(line[0]))\n\n if (!isTableLine) break\n lines.push(line)\n currentPos = skipToNextLine(source, lineEnd)\n }\n\n if (lines.length < 2) return null\n\n // Unwrap pipes and split cells\n const unwrap = (line: string) =>\n line[0] === '|' && line[line.length - 1] === '|' ? line.slice(1, -1) : line\n\n const splitCells = (line: string) => {\n const cells: string[] = []\n let current = ''\n let inCode = false\n\n for (let i = 0; i < line.length; i++) {\n const ch = line[i]\n if (ch === '\\\\' && i + 1 < line.length && line[i + 1] === '|') {\n current += '|'\n i++\n } else if (ch === '`') {\n inCode = !inCode\n current += ch\n } else if (ch === '|' && !inCode) {\n cells.push(current.trim())\n current = ''\n } else {\n current += ch\n }\n }\n cells.push(current.trim())\n return cells\n }\n\n const headerCells = splitCells(unwrap(lines[0]))\n if (!headerCells.length) return null\n\n const separatorCells = splitCells(unwrap(lines[1]))\n if (\n separatorCells.length !== headerCells.length ||\n separatorCells.some(cell => !/^:?-+:?$/.test(cell))\n ) {\n return null\n }\n\n const alignments = separatorCells.map(cell => {\n const start = cell[0] === ':'\n const end = cell[cell.length - 1] === ':'\n return start && end ? 'center' : start ? 'left' : end ? 'right' : null\n })\n\n const parseRow = (cells: string[]) =>\n parseWithInlineMode(state, true, () =>\n cells.map(cell => parseInlineSpan(cell, 0, cell.length, state, options))\n )\n\n const header = parseRow(headerCells)\n\n const body = lines.slice(2).map(line => {\n const cells =\n line.indexOf('|') !== -1 ? splitCells(unwrap(line)) : [line.trim()]\n\n // Normalize cell count\n const count = headerCells.length\n while (cells.length < count) cells.push('')\n cells.length = count\n\n return parseRow(cells)\n })\n\n return {\n type: RuleType.table,\n header,\n cells: body,\n align: alignments,\n endPos: currentPos,\n } as MarkdownToJSX.TableNode & { endPos: number }\n}\n\n// Type 6 block-level tags - only the most common ones that matter in practice\n// Unknown tags default to type 7 (inline/non-interrupting) for safety\n// This is a pragmatic subset of the CommonMark spec's full list\nvar TYPE6_TAGS = [\n 'div',\n 'p',\n 'section',\n 'article',\n 'aside',\n 'nav',\n 'header',\n 'footer',\n 'main',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'blockquote',\n 'ul',\n 'ol',\n 'li',\n 'dl',\n 'dt',\n 'dd',\n 'table',\n 'thead',\n 'tbody',\n 'tfoot',\n 'tr',\n 'td',\n 'th',\n 'form',\n 'fieldset',\n 'hr',\n 'pre',\n 'details',\n 'summary',\n 'figure',\n 'figcaption',\n]\n\n// Type 1 block tags for fast lookup\nconst TYPE1_TAGS_SET = new Set(['pre', 'script', 'style', 'textarea'])\n\nfunction isType6Tag(tagName: string): boolean {\n return TYPE6_TAGS.indexOf(tagName.toLowerCase()) !== -1\n}\n\nexport function isType1Block(tagLower: string): boolean {\n return TYPE1_TAGS_SET.has(tagLower)\n}\n\nfunction isBlankLineCheck(\n source: string,\n lineStart: number,\n lineEnd: number\n): boolean {\n for (var i = lineStart; i < lineEnd; i++) {\n const code = charCode(source, i)\n if (code !== $.CHAR_SPACE && code !== $.CHAR_TAB && code !== $.CHAR_CR)\n return false\n }\n return true\n}\n\nfunction parseWithInlineMode<T>(\n state: MarkdownToJSX.State,\n inlineMode: boolean,\n parseFn: () => T\n): T {\n const originalInline = state.inline\n state.inline = inlineMode\n try {\n return parseFn()\n } finally {\n state.inline = originalInline\n }\n}\n\nfunction findNextBlankLine(\n source: string,\n startPos: number,\n sourceLen: number\n): number {\n var pos = startPos\n while (pos < sourceLen) {\n var nextLineEnd = util.findLineEnd(source, pos)\n if (isBlankLineCheck(source, pos, nextLineEnd)) return pos\n pos = skipToNextLine(source, nextLineEnd)\n }\n return sourceLen\n}\n\nfunction createHTMLCommentResult(\n text: string,\n endPos: number,\n options?: { raw?: boolean; endsWithGreaterThan?: boolean }\n): MarkdownToJSX.HTMLCommentNode & {\n endPos: number\n raw?: boolean\n endsWithGreaterThan?: boolean\n} {\n return {\n type: RuleType.htmlComment,\n text: util.normalizeCRLF(text),\n endPos,\n ...options,\n } as MarkdownToJSX.HTMLCommentNode & {\n endPos: number\n raw?: boolean\n endsWithGreaterThan?: boolean\n }\n}\n\nfunction createVerbatimHTMLBlock(\n tagName: string,\n text: string,\n endPos: number,\n attrs?: { [key: string]: any },\n rawAttrs?: string,\n isClosingTag?: boolean,\n canInterruptParagraph?: boolean,\n options?: ParseOptions,\n state?: MarkdownToJSX.State\n): MarkdownToJSX.HTMLNode & {\n endPos: number\n isClosingTag?: boolean\n canInterruptParagraph?: boolean\n} {\n var normalizedText = util.normalizeCRLF(text)\n // Detect empty unclosed HTML tags when forceBlock is used to avoid infinite recursion\n // For empty unclosed tags like <var>, the text field contains the opening tag itself\n // When forceBlock is used, this would cause recursion if the tag is parsed again\n var finalText = normalizedText\n if (options && options.forceBlock && text && !isClosingTag) {\n var openingTagPattern = new RegExp(\n '^<' + tagName.toLowerCase() + '(\\\\s[^>]*)?>$',\n 'i'\n )\n if (openingTagPattern.test(text.trim())) {\n // Empty unclosed tag detected - render as empty element to avoid recursion\n finalText = ''\n }\n }\n\n // Always parse content into children, even for verbatim blocks\n // Extract content from text (may include opening tag)\n var contentToParse = finalText\n var tagLower = tagName.toLowerCase()\n\n // If text starts with opening tag, extract just the content\n var openingTagPattern2 = new RegExp('^<' + tagLower + '[\\\\s>]', 'i')\n if (openingTagPattern2.test(contentToParse)) {\n // Find the end of opening tag\n var tagEnd = contentToParse.indexOf('>')\n if (tagEnd !== -1) {\n contentToParse = contentToParse.slice(tagEnd + 1)\n // Remove closing tag if present\n var closingTag = '</' + tagLower + '>'\n var closingIdx = contentToParse.indexOf(closingTag)\n if (closingIdx !== -1) {\n contentToParse = contentToParse.slice(0, closingIdx)\n }\n }\n } else {\n // Text might just be content, but check for closing tag\n var closingTag2 = '</' + tagLower + '>'\n var closingIdx2 = contentToParse.indexOf(closingTag2)\n if (closingIdx2 !== -1) {\n contentToParse = contentToParse.slice(0, closingIdx2)\n }\n }\n\n // Parse content into children\n var children: MarkdownToJSX.ASTNode[] = []\n if (contentToParse && options) {\n var parseState: MarkdownToJSX.State = state || {\n inline: false,\n inHTML: true,\n inAnchor: false,\n }\n\n // Determine if content should be parsed as blocks or inline\n var trimmed = contentToParse.trim()\n var hasDoubleNewline = DOUBLE_NEWLINE_R.test(trimmed)\n var hasBlockSyntax = BLOCK_SYNTAX_R.test(trimmed)\n var hasHTMLTags = HTML_BLOCK_ELEMENT_START_R.test(trimmed)\n\n if (hasDoubleNewline || hasBlockSyntax || hasHTMLTags) {\n // Parse as blocks\n var blockState = {\n ...parseState,\n inline: false,\n inHTML: true,\n inAnchor: parseState.inAnchor || tagLower === 'a',\n }\n children = parseBlocksInHTML(trimmed, blockState, options)\n } else if (trimmed) {\n // Parse as inline\n var inlineState = {\n ...parseState,\n inline: true,\n inAnchor: parseState.inAnchor || tagLower === 'a',\n }\n children = parseInlineSpan(\n trimmed,\n 0,\n trimmed.length,\n inlineState,\n options\n )\n }\n }\n\n return {\n type: RuleType.htmlBlock,\n tag: tagName as MarkdownToJSX.HTMLTags,\n attrs: attrs || {},\n rawAttrs: rawAttrs,\n children: children,\n rawText: finalText,\n text: finalText, // @deprecated - use rawText instead\n verbatim: true,\n isClosingTag: isClosingTag,\n canInterruptParagraph: canInterruptParagraph,\n endPos: endPos,\n } as MarkdownToJSX.HTMLNode & {\n endPos: number\n isClosingTag?: boolean\n canInterruptParagraph?: boolean\n }\n}\n\n/**\n * Check if content contains block-worthy elements that should be parsed\n * (explicit block syntax or blank lines not inside type 1 HTML blocks)\n */\nfunction hasBlockContent(content: string): boolean {\n const hasExplicitBlockSyntax = BLOCK_SYNTAX_R.test(content)\n const hasBlankLines = DOUBLE_NEWLINE_R.test(content)\n const hasType1Tags = TYPE1_TAG_R.test(content)\n return hasExplicitBlockSyntax || (hasBlankLines && !hasType1Tags)\n}\n\nfunction processHTMLBlock(\n tagNameOriginal: string,\n tagName: string,\n attrs: string,\n content: string,\n fullMatch: string,\n endPos: number,\n source: string,\n state: MarkdownToJSX.State,\n parentInAnchor: boolean,\n options: ParseOptions\n): MarkdownToJSX.HTMLNode & { endPos: number } {\n // Apply block-level paragraph wrapping heuristics\n if (!state.inHTML && !state.inline && !util.endsWith(fullMatch, '\\n')) {\n let checkPos = endPos\n const sourceLen = source.length\n\n while (checkPos < sourceLen) {\n const lineEnd = util.findLineEnd(source, checkPos)\n if (isBlankLineCheck(source, checkPos, lineEnd)) break\n\n const line = source.slice(checkPos, lineEnd).trim()\n if (line.length > 0 && isBlockStartChar(line[0])) {\n const htmlResult = parseHTML(source, checkPos, state, options)\n if (htmlResult) {\n checkPos = htmlResult.endPos\n continue\n }\n const selfClosingMatch = parseHTMLTag(source, checkPos)\n if (selfClosingMatch) {\n checkPos = selfClosingMatch.endPos\n continue\n }\n return null\n }\n checkPos = skipToNextLine(source, lineEnd)\n }\n }\n\n const lowerTag = tagName\n const isType1BlockTag = isType1Block(lowerTag)\n\n // Per CommonMark spec: Type 6 blocks that end at blank lines should have verbatim content\n // Check if this is a type 6 block (block-level, not type 1, not void)\n var isType6Block = !isType1BlockTag && !util.isVoidElement(tagName)\n\n // Always extract raw attributes from fullMatch if available (for consistency)\n // Per CommonMark spec Example 153: newlines and spaces between attributes should be removed\n // (not converted to spaces) when rendering. Extract raw attributes so html() can handle this.\n var rawOpeningTag: string | undefined = undefined\n // Extract raw attributes from opening tag slice if fullMatch is available\n if (fullMatch) {\n // Find the closing > of the opening tag\n var openingTagEnd = fullMatch.indexOf('>')\n if (openingTagEnd !== -1) {\n var openingTagSlice = fullMatch.slice(0, openingTagEnd + 1)\n // Check if opening tag has newlines (for rawOpeningTag preservation)\n if (openingTagSlice.indexOf('\\n') !== -1) {\n rawOpeningTag = openingTagSlice\n }\n // Always extract raw attributes from the opening tag slice for consistency\n // Find the tag name end (after <div or <div/) - first whitespace or >\n var tagNameEnd = openingTagEnd\n for (var i = 1; i < openingTagEnd; i++) {\n var ch = openingTagSlice[i]\n if (ch === ' ' || ch === '\\t' || ch === '\\n' || ch === '>') {\n tagNameEnd = i\n break\n }\n }\n // Extract attributes from after tag name to before >\n // Preserve leading whitespace for CommonMark compliance (Examples 615-616)\n attrs = openingTagSlice.slice(tagNameEnd, openingTagEnd)\n }\n }\n\n // Parse attributes, but always preserve raw attributes for consistency\n // Per CommonMark spec Example 153: newlines and spaces between attributes should be removed\n // (not converted to spaces) when rendering. Store raw attributes so html() can handle this.\n // Trim leading whitespace for parsing, but preserve full attrs (with whitespace) for rawAttrs\n var attrsTrimmed = attrs.replace(/^[\\s\\n\\r\\t]+/, '')\n var parsedAttributes = parseHTMLAttributes(\n attrsTrimmed,\n tagName,\n tagNameOriginal,\n options\n )\n var attributes: Record<string, any> = {\n ...parsedAttributes,\n }\n\n // For type 6 blocks, check if content ends with blank line or if there's no closing tag\n // Both cases mean content should be verbatim\n var endedAtBlankLine = false\n var hasClosingTagWithBlockSyntax = false\n if (isType6Block && content.length > 0) {\n // Check if there's a closing tag in the content - if so, extract content before it\n var closingTagPattern = '</' + lowerTag\n var closingTagIdx = content.indexOf(closingTagPattern)\n if (closingTagIdx >= 0) {\n var afterTag = closingTagIdx + closingTagPattern.length\n while (\n afterTag < content.length &&\n (content[afterTag] === ' ' || content[afterTag] === '\\t')\n )\n afterTag++\n if (afterTag < content.length && content[afterTag] === '>') {\n var contentBeforeClosingTag = content.slice(0, closingTagIdx)\n if (hasBlockContent(contentBeforeClosingTag)) {\n content = contentBeforeClosingTag\n hasClosingTagWithBlockSyntax = true\n } else {\n endedAtBlankLine = true\n }\n }\n }\n\n // If we didn't find a proper closing tag with block syntax, check if content ends with blank lines\n if (!hasClosingTagWithBlockSyntax) {\n // Check if content ends with blank line pattern (newline, optional whitespace, newline)\n var checkPos = content.length - 1\n // Skip trailing newline\n if (content[checkPos] === '\\n') {\n checkPos--\n // Skip whitespace\n while (\n checkPos >= 0 &&\n (content[checkPos] === ' ' ||\n content[checkPos] === '\\t' ||\n content[checkPos] === '\\r')\n ) {\n checkPos--\n }\n // If there's another newline before this, we have a blank line ending\n if (checkPos >= 0 && content[checkPos] === '\\n') {\n endedAtBlankLine = true\n }\n }\n }\n }\n\n // Determine if this block should have verbatim rendering hint\n // Type 1 blocks and Type 6 blocks ending with blank lines should be verbatim\n var shouldTreatAsVerbatim =\n isType1BlockTag ||\n (isType6Block && endedAtBlankLine && !hasBlockContent(content))\n\n var normalizedContent = util.normalizeCRLF(content)\n // Store original content for text field before we modify it for parsing\n var contentForText = normalizedContent\n if (shouldTreatAsVerbatim) {\n if (normalizedContent.length > 0 && normalizedContent[0] === '\\n') {\n normalizedContent = normalizedContent.slice(1)\n contentForText = normalizedContent\n }\n if (\n normalizedContent.length > 0 &&\n normalizedContent[normalizedContent.length - 1] === '\\n'\n ) {\n normalizedContent = normalizedContent.slice(0, -1)\n contentForText = normalizedContent\n }\n // Remove closing tag from content before parsing (it should only be in text field)\n // But keep it in contentForText for the text field\n var closingTagPattern = '</' + lowerTag + '>'\n var closingTagIdx = normalizedContent.indexOf(closingTagPattern)\n if (closingTagIdx !== -1) {\n normalizedContent = normalizedContent.slice(0, closingTagIdx)\n // contentForText keeps the closing tag\n }\n }\n\n const leftTrimMatch = normalizedContent.match(/^([ \\t]*)/)\n const leftTrimAmount = leftTrimMatch ? leftTrimMatch[1] : ''\n const trimmer = new RegExp(\n `^${leftTrimAmount.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}`,\n 'gm'\n )\n const trimmed = normalizedContent.replace(trimmer, '')\n\n const hasDoubleNewline = DOUBLE_NEWLINE_R.test(trimmed)\n const hasNonParagraphBlockSyntax = BLOCK_SYNTAX_R.test(trimmed)\n const isParagraphTag = lowerTag === 'p'\n // Check if content contains HTML tags - if so, parse as blocks for proper nesting\n const hasHTMLTags = HTML_BLOCK_ELEMENT_START_R.test(trimmed)\n const hasBlockSyntax = isParagraphTag\n ? hasDoubleNewline\n : hasDoubleNewline ||\n hasNonParagraphBlockSyntax ||\n (state.inHTML && hasHTMLTags)\n\n // ALWAYS parse content into children, regardless of verbatim flag\n let children: MarkdownToJSX.ASTNode[] = []\n if (trimmed) {\n // Parse as blocks when content contains HTML tags to ensure nested HTML is parsed correctly\n if (hasBlockSyntax || hasHTMLTags) {\n const blockState = {\n ...state,\n inline: false,\n inHTML: true,\n inAnchor: state.inAnchor || lowerTag === 'a',\n }\n children = parseBlocksInHTML(trimmed, blockState, options)\n } else {\n const childState = {\n ...state,\n inline: true,\n inAnchor: parentInAnchor || state.inAnchor || lowerTag === 'a',\n }\n children = parseInlineSpan(\n trimmed,\n 0,\n trimmed.length,\n childState,\n options\n )\n }\n }\n\n // Store raw text for verbatim blocks (for CommonMark compliance in default renderer)\n var finalText: string | undefined = undefined\n if (shouldTreatAsVerbatim) {\n if (rawOpeningTag !== undefined) {\n // Type 1 block with newlines in opening tag - preserve raw opening tag + content\n // Store the full raw HTML (opening tag + content) in text field\n // The closing tag will be added by html()\n finalText = rawOpeningTag + contentForText\n } else {\n finalText = contentForText\n }\n }\n\n return {\n type: RuleType.htmlBlock,\n tag: (shouldTreatAsVerbatim\n ? tagName\n : tagNameOriginal) as MarkdownToJSX.HTMLTags,\n attrs: attributes,\n rawAttrs: attrs,\n children: children,\n rawText: finalText,\n text: finalText, // @deprecated - use rawText instead\n verbatim: shouldTreatAsVerbatim,\n canInterruptParagraph: true, // type 1-6 blocks can interrupt paragraphs\n endPos: endPos,\n } as MarkdownToJSX.HTMLNode & {\n endPos: number\n canInterruptParagraph?: boolean\n }\n}\n\nfunction parseHTML(\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): ParseResult {\n // Must start with '<'\n if (source[pos] !== '<') return null\n\n // Track attempt after cheap disqualifications but before expensive parsing work\n if (!state.inline) {}\n\n // Check for processing instructions, declarations, and comments first (before unified parser)\n if (pos + 1 < source.length) {\n if (source[pos + 1] === '?') {\n var piToken = scanRawHTML(source, pos)\n if (piToken && piToken.kind === 'pi') {\n return createHTMLCommentResult(piToken.text || '', piToken.endPos, {\n raw: true,\n })\n }\n } else if (source[pos + 1] === '!') {\n // Check for HTML comments (<!-- ... -->)\n if (pos + 3 < source.length && source.slice(pos, pos + 4) === '<!--') {\n if (state.inline) {} else {}\n var token = scanRawHTML(source, pos)\n if (token && token.kind === 'comment') {\n // Extract text content (strip <!-- and -->)\n var text = token.text || ''\n var endsWithGreaterThan = false\n if (text === '<!-->') {\n text = ''\n endsWithGreaterThan = true\n } else if (text === '<!--->') {\n text = '-'\n endsWithGreaterThan = true\n } else if (text.startsWith('<!--') && text.endsWith('-->')) {\n text = text.slice(4, -3)\n }\n // Track hit for inline mode (block mode hit tracking happens in parseMarkdown)\n if (state.inline) {}\n return createHTMLCommentResult(text, token.endPos, {\n endsWithGreaterThan,\n })\n }\n }\n var declToken = scanRawHTML(source, pos)\n if (\n declToken &&\n (declToken.kind === 'declaration' || declToken.kind === 'cdata')\n ) {\n return createHTMLCommentResult(declToken.text || '', declToken.endPos, {\n raw: true,\n })\n }\n }\n }\n\n // Check for space/newline after < (invalid HTML - should be escaped)\n if (pos + 1 < source.length) {\n const nextChar = source[pos + 1]\n if (\n nextChar === ' ' ||\n nextChar === '\\n' ||\n nextChar === '\\t' ||\n nextChar === '\\r'\n ) {\n return null\n }\n }\n\n // Check if this looks like an autolink before parsing as HTML\n var closeIdx = source.indexOf('>', pos + 1)\n if (closeIdx !== -1) {\n var contentBetween = source.slice(pos + 1, closeIdx)\n // Check for spaces - if found, might be failed autolink\n var hasSpace =\n contentBetween.indexOf(' ') !== -1 || contentBetween.indexOf('\\t') !== -1\n\n // Check for HTTP(S) URLs - these should be autolinks, not HTML tags\n if (\n !hasSpace &&\n (util.startsWith(contentBetween, 'http://') ||\n util.startsWith(contentBetween, 'https://'))\n ) {\n return null // This is an autolink, not an HTML tag\n }\n\n // Check for URI schemes (scheme:pattern) - no spaces\n if (!hasSpace && isValidUriScheme(contentBetween)) {\n return null // This is an autolink (URI scheme), not an HTML tag\n }\n }\n\n // Use unified parser\n var tagResult = parseHTMLTag(source, pos)\n\n // If parseHTMLTag returns null, it might be an incomplete tag\n // Handle incomplete/partial tags inline (previously handled by matchHTMLBlock)\n if (!tagResult && !state.inline) {\n // Check if we have < followed by a valid tag name (even without closing >)\n var sourceLen = source.length\n var firstLineEnd = util.findLineEnd(source, pos)\n var lineStart = pos\n // Skip up to 3 spaces of indentation (per spec)\n var indent = 0\n while (\n lineStart < firstLineEnd &&\n indent < 3 &&\n (source[lineStart] === ' ' || source[lineStart] === '\\t')\n ) {\n indent++\n lineStart++\n }\n if (lineStart >= firstLineEnd || source[lineStart] !== '<') return null\n\n // Try to parse tag name even if tag is incomplete\n // Only handle incomplete tags for block-level tags (type 6)\n // Non-block-level tags that parseHTMLTag can't parse are invalid, not incomplete\n if (lineStart + 1 < firstLineEnd) {\n var tagNameResult = parseHTMLTagName(source, lineStart + 1)\n if (tagNameResult) {\n var tagName = tagNameResult.tagName\n var isType6 = isType6Tag(tagName)\n // Only handle incomplete tags for block-level tags\n if (!isType6) {\n return null // Non-block-level tags that parseHTMLTag can't parse are invalid\n }\n // Find where the tag would end (end of line or before invalid char)\n var partialTagEnd = tagNameResult.nextPos\n var hasNewlineInTag = false\n var inQuotesPartial = false\n var quoteCharPartial = ''\n var checkEnd = firstLineEnd\n var foundClosingAngle = false\n // Check across multiple lines to find the end of the tag\n // Optimized: use indexOf to quickly find boundary characters\n while (checkEnd < sourceLen && !foundClosingAngle) {\n var advancedInInnerLoop = false\n while (partialTagEnd < checkEnd) {\n var c = source[partialTagEnd]\n if (inQuotesPartial) {\n if (c === quoteCharPartial) {\n inQuotesPartial = false\n quoteCharPartial = ''\n }\n if (c === '\\n' || c === '\\r') {\n hasNewlineInTag = true\n }\n partialTagEnd++\n advancedInInnerLoop = true\n } else if (c === '\"' || c === \"'\") {\n inQuotesPartial = true\n quoteCharPartial = c\n partialTagEnd++\n advancedInInnerLoop = true\n } else if (c === '\\n' || c === '\\r') {\n hasNewlineInTag = true\n partialTagEnd++\n advancedInInnerLoop = true\n var nextLineEnd = util.findLineEnd(source, partialTagEnd)\n if (nextLineEnd === partialTagEnd) break\n checkEnd = nextLineEnd\n } else if (c === '>') {\n partialTagEnd++\n foundClosingAngle = true\n break\n } else {\n partialTagEnd++\n advancedInInnerLoop = true\n }\n }\n if (foundClosingAngle) break\n if (!advancedInInnerLoop && partialTagEnd >= checkEnd) {\n var nextCheckEnd = util.findLineEnd(source, checkEnd + 1)\n if (nextCheckEnd <= checkEnd) break\n checkEnd = nextCheckEnd\n } else if (partialTagEnd >= checkEnd && checkEnd < sourceLen) {\n var nextCheckEnd = util.findLineEnd(source, checkEnd + 1)\n if (nextCheckEnd <= checkEnd) break\n checkEnd = nextCheckEnd\n } else {\n break\n }\n }\n // Only handle as incomplete tag if it has a newline (extends beyond first line)\n // OR if it extends to end of first line without closing >\n // If tag completes on first line with closing >, parseHTMLTag should have handled it\n if (!hasNewlineInTag && foundClosingAngle) {\n return null // Tag completes on first line but parseHTMLTag returned null - invalid, not incomplete\n }\n // Tag has newline - treat as incomplete and extend to end of first line if needed\n if (partialTagEnd >= firstLineEnd && firstLineEnd < sourceLen) {\n partialTagEnd = firstLineEnd\n }\n // Determine block type and find blank line\n var blockType: 'type6' | 'type7' = isType6 ? 'type6' : 'type7'\n var tagEnd = partialTagEnd\n var blockEnd = findNextBlankLine(\n source,\n skipToNextLine(source, firstLineEnd),\n sourceLen\n )\n var blockContent = source.slice(tagEnd, blockEnd)\n var isClosingTag = pos + 1 < source.length && source[pos + 1] === '/'\n\n // For type 7 blocks with incomplete tags, preserve raw HTML\n if (blockType === 'type7' && blockContent.trim() === '') {\n var rawTagHTML = source.slice(pos, blockEnd)\n var tagLineEnd = util.findLineEnd(rawTagHTML, 0)\n if (tagLineEnd < rawTagHTML.length) tagLineEnd++\n var rawTag = rawTagHTML.slice(0, tagLineEnd)\n return createVerbatimHTMLBlock(\n tagName,\n rawTag,\n blockEnd,\n {},\n undefined,\n isClosingTag,\n false, // type 7 blocks cannot interrupt paragraphs\n options,\n state\n )\n }\n\n // For type 6/7 blocks with incomplete tags and content, preserve full raw HTML\n var fullRawHTML = source.slice(pos, blockEnd)\n return createVerbatimHTMLBlock(\n tagName,\n fullRawHTML,\n blockEnd,\n {},\n undefined,\n isClosingTag,\n blockType === 'type6', // type 6 can interrupt, type 7 cannot\n options,\n state\n )\n }\n }\n return null\n }\n\n if (!tagResult) return null\n\n // Per CommonMark spec: reject HTML tags that look like failed autolinks\n // Check if the content between < and > looks like a failed autolink\n // (HTTP(S) URLs with spaces are failed autolinks - checked above)\n if (closeIdx !== -1) {\n var contentBetweenCheck = source.slice(pos + 1, closeIdx)\n // If it starts with http:// or https:// but has spaces, it's a failed autolink\n if (\n (util.startsWith(contentBetweenCheck, 'http://') ||\n util.startsWith(contentBetweenCheck, 'https://')) &&\n (contentBetweenCheck.indexOf(' ') !== -1 ||\n contentBetweenCheck.indexOf('\\t') !== -1)\n ) {\n return null // Failed autolink - reject as HTML tag\n }\n }\n\n // If a tag name has a colon at position 1 (e.g., \"m:abc\"), it's trying to be an autolink\n // but the scheme is only 1 character (invalid). These should be escaped, not parsed as HTML.\n // Examples: <m:abc>, <x:foo> should be escaped as <m:abc>, <x:foo>\n var tagNameStart = pos + (tagResult.isClosing ? 2 : 1)\n if (tagNameStart < source.length) {\n var tagNameFirstChar = source[tagNameStart]\n var tagNameFirstCharCode = charCode(tagNameFirstChar)\n // Check if it starts with a letter\n if (\n (tagNameFirstCharCode >= 97 && tagNameFirstCharCode <= 122) ||\n (tagNameFirstCharCode >= 65 && tagNameFirstCharCode <= 90)\n ) {\n // Check if second character is a colon (making it a 1-char scheme, which is invalid)\n if (\n tagNameStart + 1 < source.length &&\n source[tagNameStart + 1] === ':'\n ) {\n // This looks like a failed autolink attempt - reject as HTML tag\n return null\n }\n }\n }\n\n // Handle closing tags\n if (tagResult.isClosing) {\n // Per CommonMark: closing tags cannot have attributes\n // If attrs is not empty (after trimming whitespace), it's invalid HTML - escape it\n var attrsTrimmed = tagResult.attrs.trim()\n if (attrsTrimmed.length > 0) {\n // Invalid closing tag with attributes - return null to allow escaping\n return null\n }\n\n // Per CommonMark spec: closing tags are type 7 HTML blocks\n // Parse as block if: (1) on its own line, or (2) followed by a block-level HTML tag\n // Per Example 148: </td></tr></table> should be block-level\n // Per Example 623: </a></foo > should be inline (wrapped in paragraph)\n if (!state.inline) {\n var sourceLen = source.length\n var firstLineEnd = util.findLineEnd(source, pos)\n var tagEnd = tagResult.endPos\n\n // Check if tag is on its own line or followed by a block-level HTML tag\n var afterTag = tagEnd\n while (\n afterTag < firstLineEnd &&\n (source[afterTag] === ' ' ||\n source[afterTag] === '\\t' ||\n source[afterTag] === '\\r')\n ) {\n afterTag++\n }\n\n var shouldParseAsBlock =\n afterTag >= firstLineEnd ||\n (source[afterTag] === '<' &&\n (function () {\n var nextTag = parseHTMLTag(source, afterTag)\n return nextTag && isType6Tag(nextTag.tagLower)\n })())\n\n if (shouldParseAsBlock) {\n var blockEnd = findNextBlankLine(\n source,\n skipToNextLine(source, firstLineEnd),\n sourceLen\n )\n var blockContent = source.slice(tagEnd, blockEnd)\n if (blockContent.length > 0) {\n if (blockContent[0] === '\\r' && blockContent[1] === '\\n') {\n blockContent = blockContent.slice(2)\n } else if (blockContent[0] === '\\n' || blockContent[0] === '\\r') {\n blockContent = blockContent.slice(1)\n }\n }\n\n // Cache lowercase tag name to avoid repeated toLowerCase() calls\n const tagLower = tagResult.tagLower || tagResult.tagName.toLowerCase()\n return createVerbatimHTMLBlock(\n tagResult.tagName,\n blockContent,\n blockEnd,\n parseHTMLAttributes(\n tagResult.whitespaceBeforeAttrs + tagResult.attrs,\n tagLower,\n tagResult.tagName,\n options\n ),\n tagResult.whitespaceBeforeAttrs + tagResult.attrs,\n true,\n false,\n options,\n state\n )\n }\n }\n\n // Fallback: for inline context or if block parsing didn't match, parse as self-closing\n // Per CommonMark spec Example 623: closing tags should preserve raw HTML to maintain spacing (e.g., </foo >)\n // Always preserve rawText for closing tags (both inline and block level) so they can be rendered correctly\n var rawText = source.slice(pos, tagResult.endPos)\n const result: MarkdownToJSX.HTMLSelfClosingNode & {\n endPos: number\n isClosingTag?: boolean\n rawText?: string\n } = {\n type: RuleType.htmlSelfClosing,\n tag: tagResult.tagName,\n attrs: {},\n endPos: tagResult.endPos,\n isClosingTag: true,\n rawText: rawText,\n }\n return result\n }\n\n // Now use unified parser result\n // tagResult already contains parsed tag info\n\n // IMPORTANT: All validation must happen BEFORE block parsing check\n // This ensures invalid tags are rejected even if they would match as blocks\n\n // Validate tag name: cannot start with space or newline after <\n // Per CommonMark spec Example 621: < a> and <\\nfoo> are invalid\n var tagNameStart = pos + (tagResult.isClosing ? 2 : 1)\n if (tagNameStart < source.length) {\n var firstChar = source[tagNameStart]\n if (\n firstChar === ' ' ||\n firstChar === '\\t' ||\n firstChar === '\\n' ||\n firstChar === '\\r'\n ) {\n // Tag name starts with whitespace - invalid HTML\n return null\n }\n }\n\n // Attributes are passed through opaquely - no validation\n\n var tagNameLower = tagResult.tagLower\n var isVoid = util.isVoidElement(tagResult.tagName)\n\n // Check if this is a JSX component (starts with uppercase letter)\n // JSX components should be parsed as block-level HTML even with newlines\n const isJSXComponent =\n tagResult.tagName.length > 0 &&\n tagResult.tagName[0] >= 'A' &&\n tagResult.tagName[0] <= 'Z'\n\n // Self-closing tags: has /> or is void (except anchor tags which need special handling)\n // Per CommonMark spec: self-closing tags with newlines are type 7 blocks\n // Type 7 blocks don't interrupt paragraphs, so they should be parsed as inline HTML\n // IMPORTANT: Validation already happened above, so if we get here the tag is valid\n // EXCEPTION: JSX components (uppercase tags) should always be parsed as block-level HTML\n if (tagResult.isSelfClosing || (isVoid && tagNameLower !== 'a')) {\n // If tag has newline, it's a type 7 block - don't interrupt paragraphs\n // Return null to allow paragraph wrapping - parseInlineSpan will parse as raw HTML\n // But only if validation passed (which already happened above)\n // EXCEPTION: JSX components should be parsed as block-level HTML even with newlines\n if (tagResult.hasNewline && !isJSXComponent) {\n return null\n }\n\n // If we're not in HTML block context and not inline, parse as inline HTML\n // This allows them to be wrapped in paragraphs per type 7 block rules\n // Return null to allow paragraph wrapping - parseInlineSpan will parse them as raw HTML\n // EXCEPTION: JSX components should be parsed as block-level HTML even when not in HTML block context\n if (!state.inHTML && !state.inline && !isJSXComponent) {\n return null\n }\n\n var attrsTrimmedSelfClose = tagResult.attrs.replace(/\\/\\s*$/, '')\n var selfCloseAttrs = parseHTMLAttributes(\n attrsTrimmedSelfClose,\n tagNameLower,\n tagResult.tagName,\n options\n )\n // For inline context, preserve raw HTML to maintain spacing\n var rawText = state.inline ? source.slice(pos, tagResult.endPos) : undefined\n const result: MarkdownToJSX.HTMLSelfClosingNode & {\n endPos: number\n rawText?: string\n } = {\n type: RuleType.htmlSelfClosing,\n tag: tagResult.tagName,\n attrs: selfCloseAttrs,\n endPos: tagResult.endPos,\n }\n if (rawText !== undefined) {\n result.rawText = rawText\n }\n return result\n }\n\n // For inline context, parse as simple opening tag (no closing tag search)\n // IMPORTANT: Validation must happen before this check to reject invalid tags\n // Note: parseHTMLTag only returns a result if tag has closing >, so tag is complete\n // Multiline attributes are supported - newlines in tags are valid HTML\n if (state.inline) {\n // Validation already happened above, so if we get here the tag is valid\n var attrsTrimmedInline = tagResult.attrs.replace(/\\/\\s*$/, '')\n // Preserve whitespace before attributes for CommonMark compliance\n var rawAttrsWithWhitespace =\n tagResult.whitespaceBeforeAttrs + attrsTrimmedInline\n var parsedInlineAttrs = parseHTMLAttributes(\n attrsTrimmedInline,\n tagNameLower,\n tagResult.tagName,\n options\n )\n var inlineAttrs: Record<string, any> = {\n ...parsedInlineAttrs,\n }\n\n // For non-void inline tags, find matching closing tag and parse content\n var inlineEndPos = tagResult.endPos\n var children: MarkdownToJSX.ASTNode[] = []\n if (!util.isVoidElement(tagResult.tagName)) {\n var closingResult = findInlineClosingTag(\n source,\n tagResult.endPos,\n tagNameLower\n )\n if (closingResult !== null) {\n var content = source.slice(tagResult.endPos, closingResult[0])\n if (content) {\n if (\n (state.inHTML && HTML_BLOCK_ELEMENT_START_R.test(content)) ||\n hasBlockContent(content)\n ) {\n children = parseBlocksInHTML(\n content,\n {\n ...state,\n inline: false,\n inHTML: true,\n inAnchor: state.inAnchor || tagNameLower === 'a',\n },\n options\n )\n } else {\n children = parseInlineSpan(\n content,\n 0,\n content.length,\n {\n ...state,\n inline: true,\n inAnchor: state.inAnchor || tagNameLower === 'a',\n },\n options\n )\n }\n }\n inlineEndPos = closingResult[1]\n }\n }\n return {\n type: RuleType.htmlBlock,\n tag: tagResult.tagName as MarkdownToJSX.HTMLTags,\n attrs: inlineAttrs,\n rawAttrs: rawAttrsWithWhitespace,\n children: children,\n verbatim: false,\n endPos: inlineEndPos,\n } as MarkdownToJSX.HTMLNode & { endPos: number }\n }\n\n // For inline context, don't try block parsing - simple opening tags should be parsed inline\n // Block parsing is only for tags that need closing tags or are block-level\n if (!state.inline) {\n // Determine block type inline (previously handled by matchHTMLBlock)\n var sourceLen = source.length\n var firstLineEnd = util.findLineEnd(source, pos)\n var tagLower = tagResult.tagLower\n var isType1BlockVar = isType1Block(tagLower)\n var isType6Block = !isType1BlockVar && isType6Tag(tagResult.tagName)\n var tagHasClosingAngle = false\n var checkPos = pos\n while (checkPos < tagResult.endPos) {\n if (source[checkPos] === '>') {\n tagHasClosingAngle = true\n break\n }\n checkPos++\n }\n // Check if tag is followed by end of line (with optional whitespace)\n var afterTag = tagResult.endPos\n while (\n afterTag < firstLineEnd &&\n (source[afterTag] === ' ' || source[afterTag] === '\\t')\n ) {\n afterTag++\n }\n // Check if tag is complete on line\n // For type 6 blocks, they can have content on same line\n // For other tags, they must be followed by newline or end of line\n var isCompleteOnLine =\n afterTag >= firstLineEnd ||\n source[afterTag] === '\\n' ||\n source[afterTag] === '\\r' ||\n (isType6Block && afterTag < firstLineEnd) ||\n !tagHasClosingAngle\n\n // Type 1 blocks (pre, script, style, textarea) need matching closing tags\n // Handle type 1 blocks even if they have newlines in the opening tag\n if (isType1BlockVar && tagHasClosingAngle && !tagResult.isClosing) {\n // Type 1: find matching closing tag\n var type1TagName = tagResult.tagName\n var type1TagEnd = tagResult.endPos\n var type1Attrs = tagResult.attrs\n var type1ContentPos = type1TagEnd\n if (source[type1ContentPos] === '\\n') type1ContentPos++\n var type1ContentStart = type1ContentPos\n var type1ContentEnd = type1ContentPos\n var type1Depth = 1\n var type1OpenTagLen = tagLower.length + 1\n while (type1Depth > 0) {\n var type1Idx = source.indexOf('<', type1ContentPos)\n if (type1Idx === -1) {\n type1ContentEnd = sourceLen\n type1ContentPos = sourceLen\n break\n }\n var type1OpenIdx = -1\n var type1CloseIdx = -1\n if (source[type1Idx + 1] === '/') {\n type1CloseIdx = type1Idx\n } else if (\n type1Idx + type1OpenTagLen + 1 <= sourceLen &&\n (source[type1Idx + 1] === tagLower[0] ||\n source[type1Idx + 1] === type1TagName[0])\n ) {\n var type1TagCandidate = source.substring(\n type1Idx + 1,\n type1Idx + type1OpenTagLen\n )\n if (\n type1TagCandidate.toLowerCase() === tagLower &&\n (source[type1Idx + type1OpenTagLen] === ' ' ||\n source[type1Idx + type1OpenTagLen] === '>')\n ) {\n type1OpenIdx = type1Idx\n }\n }\n if (type1OpenIdx === -1 && type1CloseIdx === -1) {\n type1ContentPos = type1Idx + 1\n continue\n }\n if (\n type1OpenIdx !== -1 &&\n (type1CloseIdx === -1 || type1OpenIdx < type1CloseIdx)\n ) {\n type1ContentPos = type1OpenIdx + type1OpenTagLen + 1\n type1Depth++\n } else {\n var type1P = type1CloseIdx + 2\n while (type1P < sourceLen) {\n var type1C = source[type1P]\n if (\n type1C !== ' ' &&\n type1C !== '\\t' &&\n type1C !== '\\n' &&\n type1C !== '\\r'\n )\n break\n type1P++\n }\n if (type1P + tagLower.length > sourceLen) break\n var type1CloseTagCandidate = source.substring(\n type1P,\n type1P + tagLower.length\n )\n if (type1CloseTagCandidate.toLowerCase() !== tagLower) {\n type1ContentPos = type1P\n continue\n }\n type1P += tagLower.length\n while (type1P < sourceLen) {\n var type1C2 = source[type1P]\n if (\n type1C2 !== ' ' &&\n type1C2 !== '\\t' &&\n type1C2 !== '\\n' &&\n type1C2 !== '\\r'\n )\n break\n type1P++\n }\n if (type1P >= sourceLen || source[type1P] !== '>') {\n type1ContentPos = type1P\n continue\n }\n var type1ClosingTagEnd = type1P + 1\n var type1LineEndAfterClose = util.findLineEnd(\n source,\n type1ClosingTagEnd\n )\n type1ContentEnd = type1LineEndAfterClose\n type1ContentPos = type1LineEndAfterClose + 1\n type1Depth--\n }\n }\n var type1TrailingNl = 0\n while (\n type1ContentPos + type1TrailingNl < sourceLen &&\n source[type1ContentPos + type1TrailingNl] === '\\n'\n )\n type1TrailingNl++\n var type1FullMatch = source.slice(pos, type1ContentPos + type1TrailingNl)\n var type1Content = source.slice(type1ContentStart, type1ContentEnd)\n var type1EndPos = type1ContentPos + type1TrailingNl\n return processHTMLBlock(\n tagResult.tagName,\n tagResult.tagName,\n type1Attrs,\n type1Content,\n type1FullMatch,\n type1EndPos,\n source,\n state,\n false,\n options\n )\n }\n\n // Type 6/7 blocks end at blank lines\n if (isCompleteOnLine || !tagHasClosingAngle) {\n // Determine if type 6 or type 7\n var blockType: 'type6' | 'type7' = isType6Block ? 'type6' : 'type7'\n var tagEnd = tagResult.endPos\n var blockEnd = findNextBlankLine(\n source,\n skipToNextLine(source, firstLineEnd),\n sourceLen\n )\n\n // For type 6 blocks, check if there's a closing tag (even beyond the blank line)\n // If there is AND there's markdown syntax, extend to include the closing tag\n // Exception: for JSX components, always extend to closing tag (proper parent-child nesting)\n if (blockType === 'type6' && !tagResult.isClosing) {\n // For JSX components, preserve case; for HTML, use lowercase\n const tagNameForClosing = isJSXComponent\n ? tagResult.tagName\n : tagResult.tagLower || tagResult.tagName.toLowerCase()\n var closingTagPattern = '</' + tagNameForClosing\n var closingIdx = source.indexOf(closingTagPattern, tagEnd)\n if (closingIdx !== -1) {\n // Found a closing tag\n // Check if it's valid\n var afterClosingTag = closingIdx + closingTagPattern.length\n while (\n afterClosingTag < sourceLen &&\n (source[afterClosingTag] === ' ' ||\n source[afterClosingTag] === '\\t')\n ) {\n afterClosingTag++\n }\n if (afterClosingTag < sourceLen && source[afterClosingTag] === '>') {\n // Valid closing tag found\n var extendedContent = source.slice(tagEnd, closingIdx)\n // For JSX components, always extend to closing tag for proper nesting\n // For HTML elements, only extend if there's block content\n var shouldExtend =\n isJSXComponent || hasBlockContent(extendedContent)\n if (shouldExtend) {\n // Extend block to include closing tag\n var closingLineEnd = util.findLineEnd(source, afterClosingTag + 1)\n blockEnd = closingLineEnd\n }\n }\n }\n }\n\n var blockContent = source.slice(tagEnd, blockEnd)\n var blockAttrs = tagResult.whitespaceBeforeAttrs + tagResult.attrs\n var isClosingTag = tagResult.isClosing\n\n // Handle type 6/7 blocks\n // For type 7 blocks with empty content (standalone tags), determine if they should be block or inline\n // Per CommonMark: Type 7 blocks cannot interrupt paragraphs, but if they're on their own line they're blocks\n // However, if the tag contains newlines in attributes (without hasNewline flag because they're in quotes),\n // it should be treated as inline and wrapped in a paragraph\n if (blockType === 'type7' && blockContent.trim() === '') {\n // Check if the tag itself contains a newline (inside the tag, not after it)\n var rawTagText = source.slice(pos, tagResult.endPos)\n var tagContainsNewline = rawTagText.indexOf('\\n') !== -1\n\n if (tagContainsNewline) {\n // Tag has newline inside it (in attribute) - should be wrapped in paragraph\n return null\n }\n\n // Tag is on its own line, treat as block\n var tagEndInSource = tagResult.endPos\n var tagLineEnd = util.findLineEnd(source, tagEndInSource)\n if (tagLineEnd < source.length) tagLineEnd++\n var rawTag = source.slice(pos, tagLineEnd)\n return createVerbatimHTMLBlock(\n tagResult.tagName,\n rawTag,\n blockEnd,\n {},\n undefined,\n isClosingTag,\n false, // type 7 blocks cannot interrupt paragraphs\n options,\n state\n )\n }\n\n // For type 7 blocks with multi-line or incomplete opening tags, preserve raw HTML\n var openingTagHasNewline = tagResult.hasNewline\n var openingTagIsIncomplete = !tagHasClosingAngle\n if (\n (openingTagHasNewline || openingTagIsIncomplete) &&\n blockType === 'type7'\n ) {\n var openingTagEnd = tagResult.endPos\n var rawOpeningTag = source.slice(pos, openingTagEnd)\n var rawContent = blockContent\n var fullRawHTML = rawOpeningTag + rawContent\n return createVerbatimHTMLBlock(\n tagResult.tagName,\n fullRawHTML,\n blockEnd,\n {},\n undefined,\n isClosingTag,\n false, // type 7 blocks cannot interrupt paragraphs\n options,\n state\n )\n }\n\n // Parse attributes, but always preserve raw attributes for consistency\n // Cache lowercase tag name to avoid repeated toLowerCase() calls\n const tagLower = tagResult.tagLower || tagResult.tagName.toLowerCase()\n var parsedBlockAttributes = parseHTMLAttributes(\n blockAttrs,\n tagLower,\n tagResult.tagName,\n options\n )\n var blockAttributes: Record<string, any> = {\n ...parsedBlockAttributes,\n }\n\n // For type 6 blocks with block syntax, parse through processHTMLBlock\n if (blockType === 'type6') {\n var contentForBlockCheck = blockContent\n var closingTagIdx = blockContent.indexOf('</' + tagLower)\n if (closingTagIdx >= 0) {\n var afterTag = closingTagIdx + 2 + tagResult.tagName.length\n while (\n afterTag < blockContent.length &&\n (blockContent[afterTag] === ' ' || blockContent[afterTag] === '\\t')\n )\n afterTag++\n if (\n afterTag < blockContent.length &&\n blockContent[afterTag] === '>'\n ) {\n contentForBlockCheck = blockContent.slice(0, closingTagIdx)\n }\n }\n\n if (hasBlockContent(contentForBlockCheck)) {\n return processHTMLBlock(\n tagResult.tagName,\n tagResult.tagName,\n blockAttrs,\n contentForBlockCheck,\n source.slice(pos, tagResult.endPos),\n blockEnd,\n source,\n state,\n false,\n options\n )\n }\n }\n\n var verbatimContent = blockContent\n if (verbatimContent.length > 0) {\n if (verbatimContent[0] === '\\r' && verbatimContent[1] === '\\n') {\n verbatimContent = verbatimContent.slice(2)\n } else if (verbatimContent[0] === '\\n' || verbatimContent[0] === '\\r') {\n verbatimContent = verbatimContent.slice(1)\n }\n }\n // Per CommonMark spec: remove common leading whitespace from all lines\n var lines = verbatimContent.split('\\n')\n var minIndent = Infinity\n for (var lineIdx = 0; lineIdx < lines.length; lineIdx++) {\n var line = lines[lineIdx]\n if (line.trim().length === 0) continue\n var indent = 0\n while (\n indent < line.length &&\n (line[indent] === ' ' || line[indent] === '\\t')\n ) {\n indent++\n }\n if (indent < minIndent) minIndent = indent\n }\n if (minIndent > 0 && minIndent < Infinity) {\n var dedentedLines: string[] = []\n for (var lineIdx2 = 0; lineIdx2 < lines.length; lineIdx2++) {\n var line2 = lines[lineIdx2]\n if (line2.trim().length === 0) {\n dedentedLines.push(line2)\n } else {\n dedentedLines.push(line2.slice(minIndent))\n }\n }\n verbatimContent = dedentedLines.join('\\n')\n }\n\n return createVerbatimHTMLBlock(\n tagResult.tagName,\n verbatimContent,\n blockEnd,\n blockAttributes,\n blockAttrs,\n isClosingTag,\n blockType === 'type6' ? true : false, // type 6 can interrupt, type 7 cannot\n options,\n state\n )\n }\n }\n\n // If we're in inline context and didn't match simple tag parsing, return null\n // This allows the tag to be escaped or handled by other parsers\n if (state.inline) {\n return null\n }\n\n // Fallback: Try void element without /> (manual parsing)\n // Only try this if self-closing didn't match\n var tagNameResult = parseHTMLTagName(source, pos + 1)\n if (!tagNameResult) return null\n\n var tagName = tagNameResult.tagName\n if (!util.isVoidElement(tagName)) {\n return null\n }\n\n // Use tagLower from parseHTMLTagName result to avoid repeated toLowerCase() calls\n const tagLowerVoid = tagNameResult.tagLower\n\n var i = tagNameResult.nextPos\n var len = source.length\n while (i < len && isSpaceOrTab(source[i])) i++\n var attrsStart = i\n\n while (i < len && source[i] !== '>') i++\n if (i >= len) return null\n\n const attrs = source.slice(attrsStart, i).trim()\n const afterAngle = i + 1\n\n let checkIdx = afterAngle\n while (checkIdx < len && isSpaceOrTab(source[checkIdx])) checkIdx++\n const closeTagPattern = '</' + tagLowerVoid + '>'\n const foundIdx = source.toLowerCase().indexOf(closeTagPattern, checkIdx)\n if (foundIdx !== -1) {\n const between = source.slice(checkIdx, foundIdx).trim()\n if (between) {\n return null\n }\n }\n\n i++\n const endPos = i\n while (i < len && isSpaceOrTab(source[i])) i++\n if (i < len && source[i] === '\\n') i++\n\n const fallbackAttributes = parseHTMLAttributes(\n attrs,\n tagName,\n tagName,\n options\n )\n\n return {\n type: RuleType.htmlSelfClosing,\n tag: tagName,\n attrs: fallbackAttributes,\n endPos,\n } as MarkdownToJSX.HTMLSelfClosingNode & { endPos: number }\n}\n\n// ============================================================================\n// HTML Token Interface and Unified Scanner\n// Ultra-compact unified scanner for all HTML constructs\n// ============================================================================\n\nexport interface HTMLToken {\n kind: 'tag' | 'comment' | 'pi' | 'declaration' | 'cdata'\n tagNameLower?: string\n tagName?: string\n isClosing?: boolean\n isSelfClosing?: boolean\n hasNewline: boolean\n type6Candidate?: boolean\n type7Candidate?: boolean\n endPos: number\n attrs?: string\n whitespaceBeforeAttrs?: string\n text?: string\n raw?: boolean\n}\n\n/**\n * Scan tag-like constructs: </tag, <tag\n */\nfunction scanTagLike(source: string, pos: number): HTMLToken | null {\n if (source[pos] !== '<') return null\n\n var sourceLen = source.length\n\n // Check for closing tag (</tag>)\n var isClosing = false\n var tagStart = pos + 1\n if (pos + 1 < sourceLen && source[pos + 1] === '/') {\n isClosing = true\n tagStart = pos + 2\n }\n\n // Parse tag name\n var tagNameResult = parseHTMLTagName(source, tagStart)\n if (!tagNameResult) return null\n\n var tagName = tagNameResult.tagName\n var tagLower = tagNameResult.tagLower\n var attrsStart = tagNameResult.nextPos\n\n // Fast path: tags without attributes or whitespace\n if (attrsStart < sourceLen) {\n var immediateChar = source[attrsStart]\n if (immediateChar === '>' || immediateChar === '/') {\n var endPos = immediateChar === '>' ? attrsStart + 1 : attrsStart + 2\n if (\n immediateChar === '/' &&\n (attrsStart + 1 >= sourceLen || source[attrsStart + 1] !== '>')\n ) {\n return null\n }\n var isSelfClosingFast = immediateChar === '/'\n var type6CandidateFast = isType6Tag(tagName)\n var type7CandidateFast = !isType1Block(tagLower) && !type6CandidateFast\n return {\n kind: 'tag',\n tagNameLower: tagLower,\n tagName: tagName,\n isClosing: isClosing,\n isSelfClosing: isSelfClosingFast,\n hasNewline: false,\n type6Candidate: type6CandidateFast,\n type7Candidate: type7CandidateFast,\n endPos: endPos,\n attrs: '',\n whitespaceBeforeAttrs: '',\n }\n }\n }\n\n // Capture whitespace after tag name (including newlines per CommonMark spec)\n var whitespaceStart = attrsStart\n var hasNewline = false\n while (attrsStart < sourceLen) {\n var ch = source[attrsStart]\n var code = charCode(source, attrsStart)\n if (ch === ' ' || ch === '\\t') {\n // Space or tab - continue\n } else if (code === 10 || code === 13) {\n // \\n or \\r\n hasNewline = true\n } else {\n break // Not whitespace\n }\n attrsStart++\n }\n var whitespaceBeforeAttrs = source.slice(whitespaceStart, attrsStart)\n\n // Parse attributes until we find > - minimal validation only for boundary detection\n var tagEnd = attrsStart\n var inQuotes = false\n var quoteChar = ''\n var braceDepth = 0\n var hasSlash = false\n var hasSpaceBeforeSlash = false\n\n // State machine for attribute parsing: 0=normal, 1=inDoubleQuotes, 2=inSingleQuotes\n var parseState = 0\n while (tagEnd < sourceLen) {\n var char = source[tagEnd]\n var code = charCode(source, tagEnd)\n\n // Handle quotes state machine\n if (parseState === 1) {\n // in double quotes\n if (char === '\"') {\n // Check for consecutive quotes (invalid HTML)\n if (tagEnd + 1 < sourceLen && source[tagEnd + 1] === '\"') {\n return null\n }\n parseState = 0\n }\n tagEnd++\n } else if (parseState === 2) {\n // in single quotes\n if (char === \"'\") {\n parseState = 0\n }\n tagEnd++\n } else if (char === '\"') {\n parseState = 1\n tagEnd++\n } else if (char === \"'\") {\n parseState = 2\n tagEnd++\n } else if (char === '{' || (char === '}' && braceDepth > 0)) {\n // Track JSX expression brace depth\n braceDepth += char === '{' ? 1 : -1\n tagEnd++\n } else if (char === '>' && braceDepth === 0) {\n // Found closing > - check for self-closing / and space before >\n if (tagEnd > attrsStart) {\n var checkBack = tagEnd - 1\n while (checkBack >= attrsStart) {\n var backChar = source[checkBack]\n if (backChar !== ' ' && backChar !== '\\t') break\n checkBack--\n }\n if (checkBack >= attrsStart && source[checkBack] === '/') {\n hasSlash = true\n hasSpaceBeforeSlash = checkBack < tagEnd - 1\n }\n }\n tagEnd++\n break\n } else {\n // Check for invalid attribute name characters (*, #, !)\n if (char === '*' || char === '#' || char === '!') {\n var checkAhead = tagEnd + 1\n while (checkAhead < sourceLen) {\n var aheadChar = source[checkAhead]\n if (\n aheadChar === '=' ||\n aheadChar === ' ' ||\n aheadChar === '\\t' ||\n aheadChar === '\\n' ||\n aheadChar === '\\r' ||\n aheadChar === '>'\n ) {\n break\n }\n checkAhead++\n }\n if (checkAhead < sourceLen && source[checkAhead] === '=') {\n return null // Invalid char in attribute name\n }\n }\n // Track newlines\n if (code === 10 || code === 13) {\n // \\n or \\r\n hasNewline = true\n }\n tagEnd++\n }\n }\n\n // Must have found >\n if (tagEnd > sourceLen || source[tagEnd - 1] !== '>') {\n return null\n }\n\n // Reject tags with unclosed quotes\n if (parseState === 1 || parseState === 2) {\n return null\n }\n\n // Reject tags with unclosed JSX expressions\n if (braceDepth > 0) {\n return null\n }\n\n // Reject tags with space between / and > (invalid HTML structure)\n if (hasSpaceBeforeSlash) {\n return null\n }\n\n var attrsEnd = tagEnd - 1\n if (hasSlash) {\n // For self-closing tags, exclude the / from attrs\n attrsEnd--\n }\n var attrs = source.slice(attrsStart, attrsEnd)\n var isSelfClosing = hasSlash\n\n // Minimal validation: reject missing space after quoted attribute value\n var lastQuotePos = -1\n var inQuotesCheck = false\n var quoteCharCheck = ''\n var afterEquals = false\n for (var i = 0; i < attrs.length; i++) {\n var ch = attrs[i]\n if (inQuotesCheck) {\n if (ch === quoteCharCheck) {\n inQuotesCheck = false\n lastQuotePos = i\n quoteCharCheck = ''\n afterEquals = false\n }\n } else if (ch === '\"' || ch === \"'\") {\n inQuotesCheck = true\n quoteCharCheck = ch\n afterEquals = false\n } else if (ch === '=') {\n afterEquals = true\n } else if (lastQuotePos !== -1 && i === lastQuotePos + 1) {\n // Immediately after closing quote\n var code = ch.charCodeAt(0)\n if (isAlphaCode(code)) {\n // Letter immediately after quote - missing space, reject\n return null\n }\n } else if (\n afterEquals &&\n !inQuotesCheck &&\n (ch === '*' || ch === '#' || ch === '!')\n ) {\n // Invalid char in unquoted attribute value - reject\n return null\n } else if (isSpaceOrTab(ch)) {\n afterEquals = false\n }\n }\n\n // Determine type 6/7 candidates\n var type6Candidate = isType6Tag(tagName)\n var type7Candidate = !isType1Block(tagLower) && !type6Candidate\n\n return {\n kind: 'tag',\n tagNameLower: tagLower,\n tagName: tagName,\n isClosing: isClosing,\n isSelfClosing: isSelfClosing,\n hasNewline: hasNewline,\n type6Candidate: type6Candidate,\n type7Candidate: type7Candidate,\n endPos: tagEnd,\n attrs: attrs,\n whitespaceBeforeAttrs: whitespaceBeforeAttrs,\n }\n}\n\n// ============================================================================\n// Unified HTML Scanner\n// Ultra-compact unified scanner for all HTML constructs\n// ============================================================================\n\n/**\n * Unified HTML scanner - handles tags, comments, PIs, declarations, CDATA\n * Ultra-compact implementation tuned for minification\n */\nfunction scanRawHTML(s: string, p: number): HTMLToken | null {\n if (p >= s.length || s[p] !== '<') return null\n var l = s.length\n if (p + 1 >= l) return null\n var c = s[p + 1]\n if (c === '!') {\n if (p + 4 <= l && s.slice(p, p + 4) === '<!--') {\n // Comment: scan for -->\n var endPos = p + 4\n if (endPos < l && s[endPos] === '>') {\n return {\n kind: 'comment',\n hasNewline: false,\n endPos: endPos + 1,\n text: s.slice(p, endPos + 1),\n raw: true,\n }\n }\n if (endPos + 1 < l && s[endPos] === '-' && s[endPos + 1] === '>') {\n return {\n kind: 'comment',\n hasNewline: false,\n endPos: endPos + 2,\n text: s.slice(p, endPos + 2),\n raw: true,\n }\n }\n while (endPos + 2 < l) {\n if (s.slice(endPos, endPos + 3) === '-->') {\n return {\n kind: 'comment',\n hasNewline: false,\n endPos: endPos + 3,\n text: s.slice(p, endPos + 3),\n raw: true,\n }\n }\n endPos++\n }\n return null\n }\n if (p + 9 <= l && s.slice(p, p + 9) === '<![CDATA[') {\n // CDATA: scan for ]]>\n var endPos = p + 9\n while (endPos + 2 < l) {\n if (s.slice(endPos, endPos + 3) === ']]>') {\n return {\n kind: 'cdata',\n hasNewline: false,\n endPos: endPos + 3,\n text: s.slice(p, endPos + 3),\n raw: true,\n }\n }\n endPos++\n }\n return null\n }\n if (p + 2 < l && isAlphaCode(s.charCodeAt(p + 2))) {\n // Declaration: scan for >\n var endPos = p + 2\n while (endPos < l && s[endPos] !== '>') endPos++\n if (endPos >= l) return null\n return {\n kind: 'declaration',\n hasNewline: false,\n endPos: endPos + 1,\n text: s.slice(p, endPos + 1),\n raw: true,\n }\n }\n return null\n }\n if (c === '?') {\n // Processing instruction: scan for ?>\n var endPos = p + 2\n while (endPos + 1 < l) {\n if (s.slice(endPos, endPos + 2) === '?>') {\n return {\n kind: 'pi',\n hasNewline: false,\n endPos: endPos + 2,\n text: s.slice(p, endPos + 2),\n raw: true,\n }\n }\n endPos++\n }\n return null\n }\n return scanTagLike(s, p)\n}\n\ninterface DefinitionParseResult {\n endPos: number\n target: string\n title?: string\n}\n\nfunction isBlockStartAt(s: string, p: number): boolean {\n if (p >= s.length) return false\n var c = s[p]\n return (\n c === '=' ||\n c === '-' ||\n c === '_' ||\n c === '*' ||\n c === '#' ||\n c === '>' ||\n c === '`' ||\n c === '~' ||\n c === '[' ||\n (c >= '0' && c <= '9')\n )\n}\n\nfunction isTitleDelimiter(s: string, p: number): boolean {\n if (p >= s.length) return false\n var c = s[p]\n return c === '\"' || c === \"'\" || c === '('\n}\n\nfunction parseQuotedTitle(\n s: string,\n p: number,\n closeChar: string\n): { value: string; endPos: number } | null {\n var len = s.length\n if (p >= len || s[p] !== closeChar) return null\n p++\n var start = p\n var lastWasNewline = false\n while (p < len && s[p] !== closeChar) {\n var c = s.charCodeAt(p)\n if (c === $.CHAR_NEWLINE) {\n if (lastWasNewline) return null\n lastWasNewline = true\n p++\n } else if (c === $.CHAR_CR) {\n if (p + 1 < len && s.charCodeAt(p + 1) === $.CHAR_NEWLINE) {\n if (lastWasNewline) return null\n lastWasNewline = true\n p += 2\n } else {\n lastWasNewline = false\n p++\n }\n } else {\n lastWasNewline = false\n if (c === $.CHAR_BACKSLASH && p + 1 < len) p++\n p++\n }\n }\n if (p >= len) return null\n return { value: s.slice(start, p), endPos: p + 1 }\n}\n\nfunction parseParenTitle(\n s: string,\n p: number\n): { value: string; endPos: number } | null {\n var len = s.length\n if (p >= len || s[p] !== '(') return null\n p++\n var start = p\n var depth = 1\n var lastWasNewline = false\n while (p < len && depth > 0) {\n var c = s.charCodeAt(p)\n if (c === $.CHAR_NEWLINE) {\n if (lastWasNewline) return null\n lastWasNewline = true\n p++\n } else if (c === $.CHAR_CR) {\n if (p + 1 < len && s.charCodeAt(p + 1) === $.CHAR_NEWLINE) {\n if (lastWasNewline) return null\n lastWasNewline = true\n p += 2\n } else {\n lastWasNewline = false\n p++\n }\n } else {\n lastWasNewline = false\n if (c === $.CHAR_BACKSLASH && p + 1 < len) {\n p++\n } else if (c === $.CHAR_PAREN_OPEN) {\n depth++\n } else if (c === $.CHAR_PAREN_CLOSE) {\n depth--\n }\n p++\n }\n }\n if (depth !== 0) return null\n return { value: s.slice(start, p - 1), endPos: p }\n}\n\nfunction scanFootnoteEnd(s: string, p: number): number {\n var len = s.length\n var pos = p\n while (pos < len) {\n var isLineStart = pos === 0 || s[pos - 1] === '\\n'\n var c = s.charCodeAt(pos)\n if (c === $.CHAR_NEWLINE && pos > p) {\n var nextPos = pos + 1\n if (nextPos < len && s.charCodeAt(nextPos) === $.CHAR_CR) nextPos++\n if (nextPos < len && s.charCodeAt(nextPos) === $.CHAR_NEWLINE) {\n var afterBlank = nextPos + 1\n while (\n afterBlank < len &&\n (s[afterBlank] === ' ' || s[afterBlank] === '\\t')\n ) {\n afterBlank++\n }\n var blankLineLen = afterBlank - (pos + 1)\n if (s.charCodeAt(pos + 1) === $.CHAR_CR) blankLineLen--\n if (\n afterBlank < len &&\n s.charCodeAt(afterBlank) !== $.CHAR_NEWLINE &&\n s.charCodeAt(afterBlank) !== $.CHAR_CR &&\n blankLineLen < 4\n ) {\n return pos\n }\n }\n }\n if (isLineStart && util.startsWith(s, '[^', pos)) {\n var checkPos = pos + 2\n while (checkPos < len && s[checkPos] !== ']') {\n checkPos++\n }\n if (\n checkPos < len &&\n s[checkPos] === ']' &&\n checkPos + 1 < len &&\n s[checkPos + 1] === ':'\n ) {\n return pos\n }\n }\n pos++\n }\n return len\n}\n\nfunction parseRefContent(\n source: string,\n pos: number,\n urlNewlineCount: number\n): DefinitionParseResult | null {\n const len = source.length\n let i = pos\n\n // Parse URL (can be in angle brackets or plain, can span multiple lines)\n // At this point, i should be at the start of the destination (after any whitespace/newline)\n // Per CommonMark spec: destination can be on the same line or following lines\n const hasAngleBrackets = i < len && source[i] === '<'\n if (hasAngleBrackets) i++\n\n const urlStart = i\n let urlEnd = urlStart\n\n // Per CommonMark spec Example 199: empty destination after colon (just whitespace/newline)\n // is invalid - should be parsed as paragraph, not reference definition\n // Also check if we hit a blank line (two consecutive newlines) - destination ends there\n if (urlStart >= len) {\n // No destination found - invalid (except for empty <>)\n if (!hasAngleBrackets) return null\n // For angle brackets, empty destination is valid\n urlEnd = urlStart\n } else if (\n urlNewlineCount > 0 &&\n urlStart < len &&\n source[urlStart] === '\\n'\n ) {\n // We had a newline after colon, skipped whitespace, but found another newline\n // This means blank line after colon - empty destination, invalid\n return null\n } else {\n // Find end of URL - can span multiple lines\n // Per CommonMark spec: destination ends when we encounter:\n // 1. Closing > for angle-bracketed URLs\n // 2. Whitespace followed by title delimiter (\", ', or () on same or next line\n // 3. End of input or two consecutive newlines (blank line)\n while (urlEnd < len) {\n if (hasAngleBrackets && source[urlEnd] === '>') {\n break\n }\n\n if (source[urlEnd] === '\\n') {\n // Check if next line continues the URL or starts a title\n const nextLineStart = urlEnd + 1\n if (nextLineStart >= len) break\n\n // Check for blank line (two consecutive newlines)\n if (nextLineStart < len && source[nextLineStart] === '\\n') {\n // Blank line - URL ends here\n break\n }\n\n // Skip whitespace on next line\n let checkPos = nextLineStart\n while (\n checkPos < len &&\n (source[checkPos] === ' ' || source[checkPos] === '\\t')\n ) {\n checkPos++\n }\n\n // If next line starts with title delimiter, URL ends here\n if (checkPos < len && isTitleDelimiter(source, checkPos)) {\n break\n }\n\n // Per CommonMark spec: reference definitions are block-level constructs\n // If next line starts with '[', it's a new reference definition, so current one ends here\n // Stop at the newline (don't include it in the URL)\n if (checkPos < len && source[checkPos] === '[') {\n break\n }\n\n // Check if next line looks like a block-level construct or content that would terminate the ref definition\n // Per CommonMark spec: \"No further character may occur\" after title/URL\n // URLs can span multiple lines, but continuation lines should still look like URLs\n if (checkPos < len) {\n const nextChar = source[checkPos]\n if (isBlockStartAt(source, checkPos)) {\n break\n }\n // Stop if next line starts with a letter (could be content, not URL continuation)\n // URLs typically start with /, http, https, <, or are indented\n // But allow if it looks like a URL scheme (letter followed by :)\n if (nextChar >= 'a' && nextChar <= 'z') {\n // Check if it's a URL scheme (e.g., \"http:\", \"ftp:\")\n let schemeEnd = checkPos + 1\n while (\n schemeEnd < len &&\n schemeEnd < checkPos + 32 &&\n ((source[schemeEnd] >= 'a' && source[schemeEnd] <= 'z') ||\n (source[schemeEnd] >= 'A' && source[schemeEnd] <= 'Z') ||\n (source[schemeEnd] >= '0' && source[schemeEnd] <= '9') ||\n source[schemeEnd] === '+' ||\n source[schemeEnd] === '.' ||\n source[schemeEnd] === '-')\n ) {\n schemeEnd++\n }\n // If followed by ':', it's a URL scheme - allow continuation\n if (schemeEnd < len && source[schemeEnd] === ':') {\n // URL scheme - allow continuation\n } else {\n // Not a URL scheme - stop here (likely content)\n break\n }\n }\n }\n\n // Otherwise, continue URL on next line (skip the newline and leading whitespace)\n urlEnd = checkPos\n continue\n }\n\n if (\n !hasAngleBrackets &&\n (source[urlEnd] === ' ' || source[urlEnd] === '\\t')\n ) {\n // Check if this whitespace is followed by a title delimiter\n let checkPos = urlEnd + 1\n while (\n checkPos < len &&\n (source[checkPos] === ' ' || source[checkPos] === '\\t')\n ) {\n checkPos++\n }\n\n // Check if next char starts a title\n if (checkPos < len && isTitleDelimiter(source, checkPos)) {\n break\n }\n\n // Check if next line starts a title\n if (checkPos < len && source[checkPos] === '\\n') {\n const nextLineStart = checkPos + 1\n if (nextLineStart < len && source[nextLineStart] === '\\n') {\n // Blank line - URL ends here\n break\n }\n let nextLineCheck = nextLineStart\n while (\n nextLineCheck < len &&\n (source[nextLineCheck] === ' ' || source[nextLineCheck] === '\\t')\n ) {\n nextLineCheck++\n }\n if (nextLineCheck < len && isTitleDelimiter(source, nextLineCheck)) {\n break\n }\n }\n\n // No title delimiter found - URL continues (or ends if no title)\n // Continue parsing to find title or end\n }\n\n urlEnd++\n }\n }\n\n if (hasAngleBrackets && (urlEnd >= len || source[urlEnd] !== '>')) {\n return null // No closing >\n }\n\n // Extract target and normalize whitespace\n // Per CommonMark spec: destination can span multiple lines\n // Leading/trailing whitespace on each line should be trimmed, but internal whitespace preserved\n // Also, we need to preserve newlines between continuation lines\n let target = source.slice(urlStart, urlEnd)\n\n // Normalize whitespace: trim leading/trailing whitespace from each line\n // but preserve newlines and internal whitespace\n // Per CommonMark spec: leading/trailing whitespace is trimmed from destination\n let targetLines: string[] = []\n let targetLineStart = 0\n for (let i = 0; i <= target.length; i++) {\n if (i === target.length || target[i] === '\\n') {\n let line = target.slice(targetLineStart, i)\n // Trim leading/trailing whitespace from this line\n line = line.trim()\n if (line.length > 0 || targetLines.length === 0) {\n // Only add non-empty lines, or the first line even if empty (for angle brackets)\n targetLines.push(line)\n if (i < target.length) {\n targetLines.push('\\n')\n }\n } else if (i < target.length) {\n // Empty continuation line - preserve as newline\n targetLines.push('\\n')\n }\n targetLineStart = i + 1\n }\n }\n\n target = targetLines.join('')\n\n // Trim leading/trailing whitespace from the entire target\n target = target.trim()\n\n i = hasAngleBrackets ? urlEnd + 1 : urlEnd\n\n // Check if we stopped URL parsing because next line starts with a block construct\n // (indicating the ref definition ends here)\n // Per Example 215: ref definitions end before setext headings\n // A setext heading has content on one line, then = or - on the next line\n // We need to look ahead to detect this pattern\n var stoppedAtBlock = false\n if (i < len && source[i] === '\\n') {\n var nextLineStart = i + 1\n var checkPos = nextLineStart\n while (\n checkPos < len &&\n (source[checkPos] === ' ' || source[checkPos] === '\\t')\n ) {\n checkPos++\n }\n if (checkPos < len) {\n const nextChar = source[checkPos]\n if (isBlockStartAt(source, checkPos)) {\n stoppedAtBlock = true\n }\n // Per Example 215: check if this looks like a setext heading\n // Pattern: content line, then line starting with = or -\n // If next line has content (not starting with block char), check if line after that starts with = or -\n if (!stoppedAtBlock && nextChar !== '=' && nextChar !== '-') {\n // Next line might be content - check if line after that starts with = or -\n var firstLineEnd = util.findLineEnd(source, checkPos)\n if (firstLineEnd < len) {\n var secondLineStart = skipToNextLine(source, firstLineEnd)\n var secondCheckPos = secondLineStart\n while (\n secondCheckPos < len &&\n (source[secondCheckPos] === ' ' || source[secondCheckPos] === '\\t')\n ) {\n secondCheckPos++\n }\n if (secondCheckPos < len) {\n var secondChar = source[secondCheckPos]\n if (secondChar === '=' || secondChar === '-') {\n // This is a setext heading pattern - ref definition should end before content line\n stoppedAtBlock = true\n }\n }\n }\n }\n }\n }\n\n // Per CommonMark spec: title delimiter must be separated by whitespace from destination\n // Check if we see a title delimiter immediately after destination (no whitespace)\n // This makes it invalid as a reference definition\n if (!stoppedAtBlock && i < len && isTitleDelimiter(source, i)) {\n // Title delimiter immediately after destination without whitespace - invalid\n return null\n }\n\n // Skip whitespace between destination and title (including optional newline)\n // Per CommonMark spec: title must be separated from destination by spaces/tabs\n // The title can be on the same line or a following line\n // Per CommonMark spec: Unicode whitespace (like non-breaking space) does NOT work for separation\n // However, if we stopped because next line starts with a block construct, don't skip past the newline\n let titleNewlineCount = 0\n while (i < len && !stoppedAtBlock) {\n const c = source[i]\n if (c === '\\n') {\n titleNewlineCount++\n if (titleNewlineCount > 1) break // Only one optional newline allowed before title\n i++\n // After newline, skip leading whitespace on next line (only ASCII space/tab)\n var whitespaceStart = i\n i = util.skipWhitespace(source, i)\n // If we hit Unicode whitespace, stop\n if (\n i < len &&\n util.isUnicodeWhitespace(source[i]) &&\n source[i] !== '\\n'\n ) {\n i = whitespaceStart - 1\n break\n }\n // Check if next line starts with a block construct (ref definition ends here)\n // Per Example 215: setext headings (= or -) also terminate ref definitions\n if (i < len) {\n const nextChar = source[i]\n if (isBlockStartAt(source, i)) {\n stoppedAtBlock = true\n i = whitespaceStart - 1 // Back up to the newline\n break\n }\n // Also check if this looks like a setext heading (need to look ahead to see if there's\n // a line that starts with = or - after some content)\n // For now, just checking = or - is sufficient as they're already in the block check above\n }\n } else if (c === ' ' || c === '\\t') {\n i++\n } else if (util.isUnicodeWhitespace(c)) {\n // Unicode whitespace does NOT work for separation - stop here\n break\n } else {\n break\n }\n }\n\n // Parse optional title (can span multiple lines, but cannot contain blank lines)\n let title: string | undefined = undefined\n if (i < len) {\n const titleChar = source[i]\n var titleResult =\n titleChar === '('\n ? parseParenTitle(source, i)\n : titleChar === '\"' || titleChar === \"'\"\n ? parseQuotedTitle(source, i, titleChar)\n : null\n if (\n titleResult === null &&\n (titleChar === '\"' || titleChar === \"'\" || titleChar === '(')\n ) {\n return null\n }\n if (titleResult) {\n title = titleResult.value\n i = titleResult.endPos\n var afterTitlePos = i\n while (\n afterTitlePos < len &&\n (source[afterTitlePos] === ' ' || source[afterTitlePos] === '\\t')\n ) {\n afterTitlePos++\n }\n if (\n afterTitlePos < len &&\n source[afterTitlePos] !== '\\n' &&\n source[afterTitlePos] !== '\\r'\n ) {\n return null\n }\n i = afterTitlePos\n }\n }\n\n // Skip trailing whitespace\n i = util.skipWhitespace(source, i)\n\n // Must end at newline or end of input\n // Per CommonMark spec: no further character may occur after title\n // Per Example 210: if there's text after the title on the same line, it's invalid\n // The title parsing already handles this - if title is found, i points to after the closing delimiter\n // We just need to ensure there's no non-whitespace before the newline\n if (i < len && source[i] !== '\\n') {\n // Check if there's non-whitespace before the newline\n var checkEndPos = i\n while (checkEndPos < len && source[checkEndPos] !== '\\n') {\n if (source[checkEndPos] !== ' ' && source[checkEndPos] !== '\\t') {\n // Found non-whitespace after title - invalid reference definition\n return null\n }\n checkEndPos++\n }\n }\n\n // Also check: if no title was found, make sure we're at end of line or there's trailing text\n // Per Example 210: `[foo]: /url\\n\"title\" ok` - the \"title\" ok is trailing text, should invalidate\n if (title === undefined && i < len && source[i] !== '\\n') {\n // No title found, but there's content after destination - check if it's just whitespace\n var checkTrailingPos = i\n while (checkTrailingPos < len && source[checkTrailingPos] !== '\\n') {\n if (\n source[checkTrailingPos] !== ' ' &&\n source[checkTrailingPos] !== '\\t'\n ) {\n // Found non-whitespace after destination - invalid reference definition\n return null\n }\n checkTrailingPos++\n }\n }\n\n return {\n endPos: i < len && source[i] === '\\n' ? i + 1 : i,\n target: target,\n title: title,\n }\n}\n\nfunction parseFootnoteContent(\n source: string,\n pos: number\n): DefinitionParseResult | null {\n // pos is already after the colon and whitespace\n let contentStart = pos\n let contentEnd = scanFootnoteEnd(source, pos)\n let stoppedAtBlankLine =\n contentEnd < source.length &&\n source[contentEnd] === '\\n' &&\n source[contentEnd + 1] === '\\n'\n\n // Extract the footnote content (from after ']:' to before next footnote or end)\n let extractEnd = contentEnd\n\n // pos is already after the colon and whitespace, so we can use it directly\n let contentStartPos = pos\n\n // Process lines directly without splitting to avoid intermediate array allocation\n var processedParts: string[] = []\n let lineStart = contentStartPos\n let lineIndex = 0\n let prevWasBlank = false\n\n while (lineStart < extractEnd) {\n // Find line end - use findLineEnd to properly handle CRLF\n let lineEnd = util.findLineEnd(source, lineStart)\n if (lineEnd > extractEnd) lineEnd = extractEnd\n\n // Extract and process line\n if (lineIndex === 0) {\n // First line - trim trailing whitespace only\n let trimmedEnd = lineEnd\n while (\n trimmedEnd > lineStart &&\n (source[trimmedEnd - 1] === ' ' || source[trimmedEnd - 1] === '\\t')\n ) {\n trimmedEnd--\n }\n // Build first line\n let firstLineStr = source.slice(lineStart, trimmedEnd)\n processedParts.push(firstLineStr)\n // Check if first line is blank\n prevWasBlank = firstLineStr.length === 0\n } else {\n // Check indentation on current line\n let leadingSpaceCount = 0\n let checkPos = lineStart\n while (\n checkPos < lineEnd &&\n checkPos < lineStart + 4 &&\n source[checkPos] === ' '\n ) {\n leadingSpaceCount++\n checkPos++\n }\n\n // Check if current line is blank\n let lineHasContent = false\n for (let k = lineStart; k < lineEnd; k++) {\n if (source[k] !== ' ' && source[k] !== '\\t' && source[k] !== '\\r') {\n lineHasContent = true\n break\n }\n }\n let currentIsBlank = !lineHasContent\n\n // Process continuation line based on indentation rules\n if (leadingSpaceCount >= 4 && prevWasBlank) {\n // 4+ spaces after a blank line - this is a paragraph, preserve indentation\n processedParts.push(source.slice(lineStart, lineEnd))\n } else if (leadingSpaceCount === 4 && !prevWasBlank) {\n // Exactly 4 spaces without blank line - remove (markdown continuation indentation)\n processedParts.push(source.slice(lineStart + 4, lineEnd))\n } else {\n // Otherwise preserve (less than 4 spaces or more than 4 spaces without blank line)\n processedParts.push(source.slice(lineStart, lineEnd))\n }\n\n // Update prevWasBlank for next iteration\n prevWasBlank = currentIsBlank\n }\n\n // Move to next line\n if (lineEnd < extractEnd) {\n const charAtEnd = charCode(source, lineEnd)\n if (charAtEnd === $.CHAR_CR || charAtEnd === $.CHAR_NEWLINE) {\n processedParts.push('\\n')\n lineStart = skipToNextLine(source, lineEnd)\n } else {\n lineStart = extractEnd\n }\n } else {\n lineStart = extractEnd\n }\n lineIndex++\n }\n\n let footnoteContent = processedParts.join('')\n\n // Trim trailing whitespace/newlines but preserve internal structure\n // If we stopped at a blank line, remove the trailing newline from the last line\n if (stoppedAtBlankLine) {\n // Remove trailing newline if present (but preserve newlines between lines)\n footnoteContent = footnoteContent.replace(/\\n$/, '')\n }\n var contentLen = footnoteContent.length\n while (contentLen > 0) {\n var lastChar = footnoteContent[contentLen - 1]\n if (lastChar === '\\n' || lastChar === ' ') {\n contentLen--\n } else {\n break\n }\n }\n if (contentLen < footnoteContent.length) {\n footnoteContent = footnoteContent.slice(0, contentLen)\n }\n\n return {\n endPos: contentEnd,\n target: footnoteContent,\n title: undefined,\n }\n}\n\nexport function parseDefinition(\n source: string,\n pos: number,\n state: MarkdownToJSX.State,\n options: ParseOptions,\n isFootnote: boolean\n): ParseResult | null {\n if (source[pos] !== '[') return null\n var hasCaret = pos + 1 < source.length && source[pos + 1] === '^'\n if (isFootnote ? !hasCaret : hasCaret) return null\n\n var lineStart = pos\n while (lineStart > 0 && source[lineStart - 1] !== '\\n') lineStart--\n if (\n calculateIndent(source, lineStart, pos).spaceEquivalent >= 4 ||\n state.inline\n )\n return null\n\n var labelStart = pos + (isFootnote ? 2 : 1)\n var len = source.length\n var refEnd = findUnescapedChar(source, labelStart, len, ']')\n if (refEnd === -1) return null\n var ref = source.slice(labelStart, refEnd)\n if (ref.length > 999) return null\n\n var hasNonWhitespace = false,\n hasUnescapedBracket = false,\n labelHasNewlines = false\n for (var j = 0; j < ref.length; j++) {\n var c = ref[j]\n if (c === '\\\\' && j + 1 < ref.length) {\n j++\n continue\n }\n var cCode = charCode(c)\n if (cCode === $.CHAR_BRACKET_OPEN || cCode === $.CHAR_BRACKET_CLOSE) {\n hasUnescapedBracket = true\n } else if (cCode === $.CHAR_NEWLINE || cCode === $.CHAR_CR) {\n labelHasNewlines = true\n } else if (cCode !== $.CHAR_SPACE && cCode !== $.CHAR_TAB) {\n hasNonWhitespace = true\n }\n }\n if (!hasNonWhitespace || hasUnescapedBracket) return null\n\n var i = refEnd + 1\n if (labelHasNewlines) {\n var labelStartCode = charCode(source, labelStart)\n var refEndPrevCode = charCode(source, refEnd - 1)\n if (\n labelStartCode === $.CHAR_NEWLINE ||\n labelStartCode === $.CHAR_CR ||\n refEndPrevCode === $.CHAR_NEWLINE ||\n refEndPrevCode === $.CHAR_CR ||\n i >= len ||\n source[i] !== ':'\n )\n return null\n } else {\n if (i >= len || source[i] !== ':') {\n i = util.skipWhitespace(source, i)\n if (i < len && charCode(source, i) === $.CHAR_NEWLINE)\n i = util.skipWhitespace(source, i + 1)\n if (i >= len || source[i] !== ':') return null\n }\n }\n i++\n\n var urlNewlineCount = 0\n while (i < len) {\n var iCode = charCode(source, i)\n if (iCode === $.CHAR_NEWLINE) {\n if (++urlNewlineCount > 1) break\n i = util.skipWhitespace(source, i + 1)\n } else if (iCode === $.CHAR_SPACE || iCode === $.CHAR_TAB) {\n i++\n } else {\n break\n }\n }\n\n const contentResult = isFootnote\n ? parseFootnoteContent(source, i)\n : parseRefContent(source, i, urlNewlineCount)\n if (!contentResult) return null\n\n const normalizedRef = normalizeReferenceLabel(ref)\n const refs = state.refs || {}\n const storageKey = isFootnote ? `^${normalizedRef}` : normalizedRef\n if (!refs[storageKey]) {\n refs[storageKey] = {\n target: unescapeUrlOrTitle(contentResult.target.trim()),\n title: contentResult.title\n ? unescapeUrlOrTitle(contentResult.title)\n : undefined,\n }\n state.refs = refs\n }\n\n return {\n type: isFootnote ? RuleType.footnote : RuleType.ref,\n endPos: contentResult.endPos,\n } as (MarkdownToJSX.ReferenceNode | MarkdownToJSX.FootnoteNode) & {\n endPos: number\n }\n}\n\n// Delimiter stack entry for CommonMark spec delimiter stack algorithm\ninterface DelimiterEntry {\n nodeIndex: number // Index in result array where this delimiter text node is\n type: '*' | '_' | '~' | '='\n length: number // Number of delimiters in the run\n canOpen: boolean // Whether this delimiter can open emphasis\n canClose: boolean // Whether this delimiter can close emphasis\n active: boolean // Whether this delimiter is active\n sourcePos: number // Source position where this delimiter starts (for overlap detection)\n inAnchor: boolean // Whether this delimiter was collected inside a link (should not match with delimiters outside)\n}\n\n// Process emphasis using delimiter stack algorithm per CommonMark spec\nfunction processEmphasis(\n nodes: MarkdownToJSX.ASTNode[],\n delimiterStack: DelimiterEntry[],\n stackBottom: number | null\n): void {\n // openers_bottom for each delimiter type, indexed by numeric key: typeCode * 6 + (length % 3) * 2 + (canOpen ? 1 : 0)\n // Type codes: '*' = 0, '_' = 1, '~' = 2, '=' = 3\n var openersBottom: number[] = []\n\n var currentPosition = stackBottom === null ? 0 : stackBottom + 1\n\n while (currentPosition < delimiterStack.length) {\n var closer = delimiterStack[currentPosition]\n if (\n !closer ||\n (closer.type !== '*' &&\n closer.type !== '_' &&\n closer.type !== '~' &&\n closer.type !== '=')\n ) {\n currentPosition++\n continue\n }\n\n if (!closer.canClose || !closer.active) {\n currentPosition++\n continue\n }\n\n // Convert type to numeric code: '*' = 0, '_' = 1, '~' = 2, '=' = 3\n var typeCode =\n closer.type === '*'\n ? 0\n : closer.type === '_'\n ? 1\n : closer.type === '~'\n ? 2\n : 3\n var openersBottomKey =\n typeCode * 6 + (closer.length % 3) * 2 + (closer.canOpen ? 1 : 0)\n var openersBottomIndex =\n openersBottom[openersBottomKey] !== undefined\n ? openersBottom[openersBottomKey]\n : stackBottom === null\n ? -1\n : stackBottom\n\n var openerIndex = -1\n var closerType = closer.type\n var closerInAnchor = closer.inAnchor\n var closerCanOpen = closer.canOpen\n var closerLength = closer.length\n var closerLengthMod3 = closerLength % 3\n\n for (var i = currentPosition - 1; i > openersBottomIndex; i--) {\n var candidate = delimiterStack[i]\n if (\n !candidate ||\n !candidate.active ||\n candidate.type !== closerType ||\n !candidate.canOpen ||\n candidate.inAnchor !== closerInAnchor\n )\n continue\n var openerLength = candidate.length\n if (\n (!closerCanOpen && !candidate.canClose) ||\n closerLengthMod3 === 0 ||\n (openerLength + closerLength) % 3 !== 0\n ) {\n openerIndex = i\n break\n }\n }\n\n if (openerIndex >= 0) {\n var opener = delimiterStack[openerIndex]\n var openerLength = opener.length\n\n // Determine if emphasis or strong emphasis (both must have length >= 2 for strong)\n var isStrong = openerLength >= 2 && closerLength >= 2\n var delimitersToRemove = isStrong ? 2 : 1\n if (\n delimitersToRemove > openerLength ||\n delimitersToRemove > closerLength\n ) {\n currentPosition++\n continue\n }\n\n var openerNodeIndex = opener.nodeIndex\n var closerNodeIndex = closer.nodeIndex\n var contentStartIndex = openerNodeIndex + 1\n var contentEndIndex = closerNodeIndex\n var contentNodes = nodes.slice(contentStartIndex, contentEndIndex)\n\n // Remove content nodes from nodes array (they'll be in the emphasis node)\n if (contentNodes.length > 0) {\n var nodesRemoved = contentEndIndex - contentStartIndex\n nodes.splice(contentStartIndex, nodesRemoved)\n for (var k = 0; k < delimiterStack.length; k++) {\n if (delimiterStack[k].nodeIndex > contentStartIndex)\n delimiterStack[k].nodeIndex -= nodesRemoved\n }\n if (closerNodeIndex > contentStartIndex) closerNodeIndex -= nodesRemoved\n }\n\n var emphasisTag =\n opener.type === '~'\n ? 'del'\n : opener.type === '='\n ? 'mark'\n : isStrong\n ? 'strong'\n : 'em'\n var emphasisNode: MarkdownToJSX.FormattedTextNode = {\n type: RuleType.textFormatted,\n tag: emphasisTag,\n children: contentNodes,\n }\n\n var openerNode = nodes[openerNodeIndex] as MarkdownToJSX.TextNode\n if (!openerNode || !openerNode.text) {\n opener.active = closer.active = false\n continue\n }\n\n // Remove delimiters from opener text node\n var openerRemoved = openerNode.text.length <= delimitersToRemove\n if (openerRemoved) {\n nodes.splice(openerNodeIndex, 1)\n for (var k = 0; k < delimiterStack.length; k++) {\n if (delimiterStack[k].nodeIndex > openerNodeIndex)\n delimiterStack[k].nodeIndex--\n }\n if (closerNodeIndex > openerNodeIndex) closerNodeIndex--\n } else {\n openerNode.text = openerNode.text.slice(delimitersToRemove)\n }\n\n var closerNode = nodes[closerNodeIndex] as MarkdownToJSX.TextNode\n if (!closerNode || !closerNode.text) {\n opener.active = closer.active = false\n continue\n }\n var closerRemoved = closerNode.text.length <= delimitersToRemove\n if (closerRemoved) {\n nodes.splice(closerNodeIndex, 1)\n for (var k = 0; k < delimiterStack.length; k++) {\n if (delimiterStack[k].nodeIndex > closerNodeIndex)\n delimiterStack[k].nodeIndex--\n }\n } else {\n closerNode.text = closerNode.text.slice(delimitersToRemove)\n }\n\n // Insert emphasis node after opener (or at the position where opener was)\n var insertIndex = openerRemoved\n ? openerNodeIndex < closerNodeIndex\n ? closerNodeIndex - 1\n : openerNodeIndex\n : openerNodeIndex + 1\n if (insertIndex < 0 || insertIndex > nodes.length)\n insertIndex = insertIndex < 0 ? 0 : nodes.length\n nodes.splice(insertIndex, 0, emphasisNode)\n\n // Update node indices in delimiter stack after insertion\n for (var k = 0; k < delimiterStack.length; k++) {\n if (delimiterStack[k].nodeIndex >= insertIndex) {\n delimiterStack[k].nodeIndex++\n }\n }\n\n // Remove delimiters between opener and closer from stack\n for (var k = openerIndex + 1; k < currentPosition; k++) {\n delimiterStack[k].active = false\n }\n\n // Update opener and closer in stack\n if (openerRemoved) {\n opener.active = false\n } else {\n opener.length -= delimitersToRemove\n if (opener.length === 0) opener.active = false\n }\n\n if (closerRemoved) {\n closer.active = false\n currentPosition++\n } else {\n closer.length -= delimitersToRemove\n if (closer.length === 0) {\n closer.active = false\n currentPosition++\n }\n }\n } else {\n // No opener found\n openersBottom[openersBottomKey] = currentPosition - 1\n if (!closer.canOpen) {\n closer.active = false\n }\n currentPosition++\n }\n }\n\n // Remove inactive delimiters from stack (O(n) shift algorithm instead of O(n²) splice)\n var writeIndex = 0\n for (var i = 0; i < delimiterStack.length; i++) {\n if (delimiterStack[i].active) {\n delimiterStack[writeIndex++] = delimiterStack[i]\n }\n }\n delimiterStack.length = writeIndex\n}\n\nexport function parseMarkdown(\n input: string,\n state: MarkdownToJSX.State,\n options: ParseOptions\n): MarkdownToJSX.ASTNode[] {\n var result: MarkdownToJSX.ASTNode[] = []\n var pos = 0\n var REF_CHECK_UNSET = -3\n var cachedRefCheckPos = REF_CHECK_UNSET\n\n // If inline mode, just parse the entire input as inline content\n if (state.inline)\n return parseInlineSpan(input, 0, input.length, state, options)\n\n // Block parsing mode\n\n // Check for frontmatter at the beginning (skip if doesn't start with ---)\n if (pos === 0 && input.startsWith('---')) {\n var frontmatterResult = parseFrontmatter(input, pos)\n if (frontmatterResult) {\n result.push(frontmatterResult)\n pos = frontmatterResult.endPos\n }\n }\n\n while (pos < input.length) {\n // Skip leading newlines (but preserve whitespace for indented code blocks)\n while (pos < input.length && input[pos] === '\\n') {\n pos++\n }\n\n if (pos >= input.length) break\n cachedRefCheckPos = REF_CHECK_UNSET\n\n const char = input[pos]\n\n // Try parseBlock first (handles indentation and tries all block parsers)\n // Note: Individual parsers called by parseBlock track their own attempts\n const parseResult = parseBlock(input, pos, state, options)\n if (parseResult) {\n const t = parseResult.type\n if (t === RuleType.codeBlock) {\n var isFenced = char === '`' || char === '~'\n if (!isFenced && (char === ' ' || char === '\\t')) {\n const lineEnd = util.findLineEnd(input, pos)\n const indentInfo = calculateIndent(input, pos, lineEnd)\n isFenced =\n indentInfo.spaceEquivalent <= 3 &&\n pos + indentInfo.charCount < input.length &&\n (input[pos + indentInfo.charCount] === '`' ||\n input[pos + indentInfo.charCount] === '~')\n }\n } else if (t === RuleType.breakThematic) {} else if (t === RuleType.blockQuote) {} else if (t === RuleType.heading) {} else if (t === RuleType.orderedList || t === RuleType.unorderedList) {} else if (t === RuleType.table) {} else if (t === RuleType.htmlComment) {} else if (t === RuleType.htmlBlock) {} else if (t === RuleType.ref) {}\n\n // Special handling for HTML comments with trailing content\n if (parseResult.type === RuleType.htmlComment) {\n result.push(parseResult)\n const htmlCheckPos = pos\n pos = parseResult.endPos\n\n // Per CommonMark spec Example 177: HTML comment blocks end at --> on the same line\n // If there's content after --> on the same line, it should be treated as literal text\n const commentLineEnd = util.findLineEnd(input, htmlCheckPos)\n if (pos < commentLineEnd) {\n const textContent = input.slice(pos, commentLineEnd)\n if (textContent.trim().length > 0) {\n result.push({\n type: RuleType.text,\n text: textContent,\n } as MarkdownToJSX.TextNode)\n }\n pos = commentLineEnd\n if (pos < input.length && input[pos] === '\\n') {\n pos++\n }\n }\n continue\n }\n // Special handling for HTML self-closing closing tags\n if (\n parseResult.type === RuleType.htmlBlock ||\n parseResult.type === RuleType.htmlSelfClosing\n ) {\n const isSelfClosingClosingTag =\n parseResult.type === RuleType.htmlSelfClosing &&\n parseResult.isClosingTag === true\n if (isSelfClosingClosingTag && !state.inline && !state.inHTML) {\n // Don't match, fall through to other parsers\n } else {\n result.push(parseResult)\n pos = parseResult.endPos\n continue\n }\n } else {\n result.push(parseResult)\n pos = parseResult.endPos\n continue\n }\n }\n\n // Reference definition - check BEFORE setext heading to prevent conflicts\n // Reference definitions take precedence over setext headings (e.g., [foo]: /url\\n===)\n let refCheckPos =\n cachedRefCheckPos !== REF_CHECK_UNSET ? cachedRefCheckPos : pos\n if (cachedRefCheckPos === REF_CHECK_UNSET) {\n if (isSpaceOrTab(char)) {\n const lineEnd = util.findLineEnd(input, pos)\n const indentInfo = calculateIndent(input, pos, lineEnd)\n const checkPos = pos + indentInfo.charCount\n if (\n indentInfo.spaceEquivalent <= 3 &&\n checkPos < input.length &&\n input[checkPos] === '['\n ) {\n refCheckPos = checkPos\n } else {\n refCheckPos = -1\n }\n } else if (char === '[') {\n refCheckPos = pos\n } else {\n refCheckPos = -1\n }\n cachedRefCheckPos = refCheckPos\n }\n\n if (\n refCheckPos >= 0 &&\n refCheckPos + 1 < input.length &&\n input[refCheckPos + 1] === '^'\n ) {\n refCheckPos = -1\n }\n\n if (refCheckPos >= 0) {\n const parseResult = parseDefinition(\n input,\n refCheckPos,\n state,\n options,\n false\n )\n if (parseResult) {\n result.push(parseResult)\n pos = parseResult.endPos\n continue\n }\n // parseDefinition returned null - check if this is an invalid reference definition that should be skipped\n // Per CommonMark Examples 208 and 210: certain invalid reference definitions should be skipped entirely\n const skipResult = shouldSkipInvalidReferenceDefinition(\n input,\n refCheckPos,\n pos === 0\n )\n if (skipResult.shouldSkip) {\n pos = skipResult.newPos\n continue\n }\n }\n\n // Heading (Setext style) - check after reference definitions\n const setextResult = parseHeadingSetext(input, pos, state, options)\n if (setextResult) {\n result.push(setextResult)\n pos = setextResult.endPos\n continue\n }\n\n // Footnote definition (skip leading whitespace)\n let footnoteCheckPos = pos\n if (isSpaceOrTab(input[footnoteCheckPos])) {\n const lineEnd = util.findLineEnd(input, pos)\n const indentInfo = calculateIndent(input, pos, lineEnd)\n footnoteCheckPos = pos + indentInfo.charCount\n }\n if (\n footnoteCheckPos < input.length &&\n input[footnoteCheckPos] === '[' &&\n footnoteCheckPos + 1 < input.length &&\n input[footnoteCheckPos + 1] === '^'\n ) {\n const footnoteResult = parseDefinition(\n input,\n footnoteCheckPos,\n state,\n options,\n true\n )\n if (footnoteResult) {\n pos = footnoteResult.endPos\n continue\n }\n }\n\n const paragraphResult = parseParagraph(input, pos, state, options)\n if (paragraphResult) {\n result.push(paragraphResult)\n pos = paragraphResult.endPos\n continue\n }\n\n pos++\n }\n\n // Note: Memory snapshot \"After block parsing\" is taken in compiler function\n // after parseMarkdown returns, not here\n\n // Footnotes footer is appended during rendering phase (not in AST)\n // Footnotes are stored in refs with '^' prefix and extracted during rendering\n\n // Collect all refs from state.refs (populated during parsing) and create a reference collection node\n // Reference nodes stay in their original positions, but we prepend a collection node\n // Include footnotes (keys starting with '^') so the renderer can handle them\n const allRefs = state.refs || {}\n const collectedRefs: {\n [key: string]: { target: string; title: string | undefined }\n } = {}\n for (const key in allRefs) {\n collectedRefs[key] = allRefs[key]\n }\n\n // Prepend reference collection node if we have any refs\n if (util.hasKeys(collectedRefs)) {\n const refCollectionNode: MarkdownToJSX.ReferenceCollectionNode = {\n type: RuleType.refCollection,\n refs: collectedRefs,\n }\n return [refCollectionNode, ...result]\n }\n\n return result\n}\n\n/**\n * Collect reference definitions from markdown input and populate the refs object.\n * This function scans the markdown for reference-style link and image definitions.\n *\n * @param input - The markdown string to scan\n * @param refs - Object to populate with reference definitions\n * @param options - Parser options\n */\nexport function collectReferenceDefinitions(\n input: string,\n refs: { [key: string]: { target: string; title: string | undefined } },\n options: ParseOptions\n): void {\n var pos = 0\n var canStartRef = true\n const len = input.length\n\n while (pos < len) {\n var newlines = 0\n // Count consecutive newlines more efficiently\n while (pos < len && charCode(input, pos) === $.CHAR_NEWLINE) {\n newlines++\n pos++\n }\n if (pos >= len) break\n if (newlines > 0) canStartRef = true\n\n // Skip fenced code\n const currentCharCode = charCode(input, pos)\n if (\n currentCharCode === $.CHAR_BACKTICK ||\n currentCharCode === $.CHAR_TILDE\n ) {\n var fence = parseCodeFenced(input, pos, { inline: false }, options)\n if (fence) {\n pos = fence.endPos\n canStartRef = true\n continue\n }\n }\n\n // Try parse ref (up to 3 space indent)\n var refPos = pos\n var indent = 0\n while (refPos < len && indent < 4) {\n const code = charCode(input, refPos)\n if (code === $.CHAR_SPACE) {\n indent++\n refPos++\n } else if (code === $.CHAR_TAB) {\n indent += 4 - (indent % 4)\n refPos++\n } else {\n break\n }\n }\n\n if (\n indent < 4 &&\n refPos < len &&\n charCode(input, refPos) === $.CHAR_BRACKET_OPEN &&\n canStartRef\n ) {\n if (refPos + 1 < len && charCode(input, refPos + 1) === $.CHAR_CARET) {\n canStartRef = false\n var lineEnd = util.findLineEnd(input, pos)\n pos = lineEnd >= len ? len : skipToNextLine(input, lineEnd)\n continue\n } else {\n var result = parseDefinition(\n input,\n refPos,\n { inline: false, refs },\n options,\n false\n )\n if (result) {\n pos = result.endPos\n canStartRef = true\n continue\n }\n // parseDefinition returned null - check if colon exists (invalid ref attempt) vs paragraph content\n var lineEnd = util.findLineEnd(input, pos)\n var colonPos = input.indexOf(':', refPos + 1)\n if (colonPos === -1 || colonPos >= lineEnd) {\n var indentInfo = calculateIndent(input, pos, lineEnd)\n if (\n !isBlankLineCheck(input, pos, lineEnd) &&\n currentCharCode !== $.CHAR_HASH &&\n currentCharCode !== $.CHAR_GT &&\n currentCharCode !== $.CHAR_DASH &&\n currentCharCode !== $.CHAR_EQ &&\n indentInfo.spaceEquivalent < 4\n ) {\n canStartRef = false\n }\n }\n pos = lineEnd >= len ? len : skipToNextLine(input, lineEnd)\n continue\n }\n }\n\n // Scan blockquotes for nested refs\n if (currentCharCode === $.CHAR_GT && canStartRef) {\n var bqEnd = pos\n var bqLines = []\n while (bqEnd < len) {\n var lineEnd = util.findLineEnd(input, bqEnd)\n var quotePos = bqEnd\n while (quotePos < lineEnd) {\n const code = charCode(input, quotePos)\n if (code === $.CHAR_SPACE || code === $.CHAR_TAB) {\n quotePos++\n } else {\n break\n }\n }\n if (quotePos >= lineEnd || charCode(input, quotePos) !== $.CHAR_GT)\n break\n\n var contentStart = quotePos + 1\n if (\n contentStart < lineEnd &&\n (charCode(input, contentStart) === $.CHAR_SPACE ||\n charCode(input, contentStart) === $.CHAR_TAB)\n )\n contentStart++\n bqLines.push(input.slice(contentStart, lineEnd))\n bqEnd = skipToNextLine(input, lineEnd)\n }\n if (bqLines.length) {\n collectReferenceDefinitions(bqLines.join('\\n'), refs, options)\n pos = bqEnd\n canStartRef = true\n continue\n }\n }\n\n var lineEnd = util.findLineEnd(input, pos)\n if (lineEnd >= len) {\n pos = len\n } else {\n var isCurrentLineBlank = isBlankLineCheck(input, pos, lineEnd)\n var indentInfo = calculateIndent(input, pos, lineEnd)\n pos = skipToNextLine(input, lineEnd)\n canStartRef =\n currentCharCode === $.CHAR_HASH ||\n currentCharCode === $.CHAR_GT ||\n currentCharCode === $.CHAR_DASH ||\n currentCharCode === $.CHAR_EQ ||\n isCurrentLineBlank ||\n indentInfo.spaceEquivalent >= 4\n }\n }\n}\n\n/**\n * Given a markdown string, return an abstract syntax tree (AST) of the markdown.\n *\n * The first node in the AST is a reference collection node. This node contains all the\n * reference definitions found in the markdown. These reference definitions are used to\n * resolve reference links and images in the markdown.\n *\n * @lang zh 给定一个 Markdown 字符串,返回 Markdown 的抽象语法树 (AST)。\n *\n * AST 中的第一个节点是引用集合节点。此节点包含在 Markdown 中找到的所有引用定义。这些引用定义用于解析 Markdown 中的引用链接和图像。\n * @lang hi एक Markdown स्ट्रिंग दी गई है, Markdown का अमूर्त सिंटैक्स ट्री (AST) लौटाता है।\n *\n * AST में पहला नोड संदर्भ संग्रह नोड है। यह नोड Markdown में पाई गई सभी संदर्भ परिभाषाएं शामिल करता है। ये संदर्भ परिभाषाएं Markdown में संदर्भ लिंक्स और छवियों को पार्स करने के लिए उपयोग की जाती हैं।\n *\n * @param source - The markdown string to parse.\n * @lang zh @param source - 要解析的 Markdown 字符串。\n * @lang hi @param source - पार्स करने के लिए Markdown स्ट्रिंग।\n * @param options - The options for the parser.\n * @lang zh @param options - 解析器的选项。\n * @lang hi @param options - पार्सर के लिए विकल्प।\n * @returns The AST of the markdown.\n * @lang zh @returns Markdown 的 AST。\n * @lang hi @returns Markdown का AST।\n */\nexport function parser(\n source: string,\n options?: MarkdownToJSX.Options\n): MarkdownToJSX.ASTNode[] {\n // Default state\n const defaultState: MarkdownToJSX.State = { inline: false, refs: {} }\n const finalState = { ...defaultState }\n\n // Normalize options - convert MarkdownToJSX.Options to ParseOptions\n const finalOptions: ParseOptions = {\n ...options,\n slugify: options?.slugify\n ? (input: string) => options.slugify(input, util.slugify)\n : util.slugify,\n sanitizer: options?.sanitizer || util.sanitizer,\n tagfilter: options?.tagfilter !== false,\n }\n\n // Collect reference definitions if not in inline mode\n if (!finalState.inline) {\n collectReferenceDefinitions(source, finalState.refs || {}, finalOptions)\n }\n\n // Parse markdown\n const astNodes = parseMarkdown(source, finalState, finalOptions)\n\n return astNodes\n}\n",
|
|
9
9
|
"import * as $ from './constants'\nimport * as parse from './parse'\nimport { MarkdownToJSX, RuleType } from './types'\nimport * as util from './utils'\nconst { hasKeys } = util\n\n// Re-export parser, types, and utils for the /html entry point\nexport { parser } from './parse'\nexport { RuleType, type MarkdownToJSX } from './types'\nexport { sanitizer, slugify } from './utils'\n\n/**\n * Escape HTML entities for text content\n * Fast path: return early if no escaping needed\n */\nfunction escapeHtml(text: string): string {\n if (!text) return text\n var needsEscape = false\n var i = 0\n var len = text.length\n while (i < len) {\n var code = text.charCodeAt(i)\n if (\n code === $.CHAR_AMPERSAND ||\n code === $.CHAR_LT ||\n code === $.CHAR_GT ||\n code === $.CHAR_DOUBLE_QUOTE\n ) {\n needsEscape = true\n break\n }\n i++\n }\n if (!needsEscape) return text\n var result = ''\n i = 0\n var last = 0\n while (i < len) {\n var code = text.charCodeAt(i)\n var replacement: string | null = null\n if (code === $.CHAR_AMPERSAND) {\n replacement = '&'\n } else if (code === $.CHAR_LT) {\n replacement = '<'\n } else if (code === $.CHAR_GT) {\n replacement = '>'\n } else if (code === $.CHAR_DOUBLE_QUOTE) {\n replacement = '"'\n }\n if (replacement) {\n if (i > last) result += text.slice(last, i)\n result += replacement\n last = i + 1\n }\n i++\n }\n if (last < len) result += text.slice(last)\n return result\n}\n\n/**\n * Escape HTML for attribute values, preserving entity references\n * Only escapes bare & that are not part of valid entities\n */\nfunction escapeHtmlAttr(value: string): string {\n // Fast-path: check if escaping is needed before regex\n var needsEscape = false\n var i = 0\n var len = value.length\n while (i < len) {\n var code = value.charCodeAt(i)\n if (\n code === $.CHAR_AMPERSAND ||\n code === $.CHAR_LT ||\n code === $.CHAR_GT ||\n code === $.CHAR_DOUBLE_QUOTE\n ) {\n needsEscape = true\n break\n }\n i++\n }\n if (!needsEscape) return value\n\n return value\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/&(?!([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+);)/g, '&')\n}\n\nfunction formatAttributes(attrs: Record<string, any> = {}): string {\n // Fast-path: return empty string if no attributes\n var hasAttrs = false\n for (var key in attrs) {\n hasAttrs = true\n break\n }\n if (!hasAttrs) return ''\n\n var result = ''\n for (var key in attrs) {\n var value = attrs[key]\n if (value === undefined || value === null) continue\n result += ' '\n if (value === true) {\n result += key\n } else if (value === '') {\n result += key + '=\"\"'\n } else if (key === 'style' && typeof value === 'object' && value !== null) {\n var styleStr = ''\n var styleFirst = true\n for (var styleKey in value) {\n var styleValue = value[styleKey]\n if (styleValue != null) {\n if (styleFirst) styleFirst = false\n else styleStr += '; '\n var cssKey = ''\n for (var i = 0; i < styleKey.length; i++) {\n var code = styleKey.charCodeAt(i)\n if (code >= $.CHAR_A && code <= $.CHAR_Z) {\n cssKey += '-' + String.fromCharCode(code + $.CHAR_CASE_OFFSET)\n } else {\n cssKey += styleKey[i]\n }\n }\n styleStr += cssKey + ': ' + styleValue\n }\n }\n if (styleStr) result += 'style=\"' + escapeHtmlAttr(styleStr) + '\"'\n } else if (typeof value === 'string') {\n result += key + '=\"' + escapeHtmlAttr(value) + '\"'\n } else if (typeof value === 'number') {\n result += key + '=\"' + value + '\"'\n }\n }\n return result\n}\n\nfunction renderTag(\n defaultTag: string,\n children: string,\n overrides: HTMLOverrides,\n attrs?: Record<string, any>\n): string {\n const tag = util.getTag(defaultTag, overrides)\n const overrideProps = util.getOverrideProps(defaultTag, overrides)\n if (!attrs || !hasKeys(attrs)) {\n const attrStr = formatAttributes(overrideProps)\n return `<${tag}${attrStr}>${children}</${tag}>`\n }\n var finalAttrs = { ...overrideProps }\n for (var aKey in attrs) finalAttrs[aKey] = attrs[aKey]\n const attrStr = formatAttributes(finalAttrs)\n return `<${tag}${attrStr}>${children}</${tag}>`\n}\n\n/**\n * Override configuration for HTML tags or custom components in HTML output\n * @lang zh HTML 输出中 HTML 标签或自定义组件的覆盖配置\n * @lang hi HTML आउटपुट में HTML टैग्स या कस्टम कंपोनेंट्स के लिए ओवरराइड कॉन्फ़िगरेशन\n */\nexport type HTMLOverride =\n | {\n component?: string\n props?: Record<string, string | number | boolean>\n }\n | string\n\n/**\n * Map of HTML tags and custom components to their override configurations\n * @lang zh HTML 标签和自定义组件到其覆盖配置的映射\n * @lang hi HTML टैग्स और कस्टम कंपोनेंट्स से उनकी ओवरराइड कॉन्फ़िगरेशन का मैप\n */\nexport type HTMLOverrides = {\n [tag in MarkdownToJSX.HTMLTags]?: HTMLOverride\n} & {\n [customComponent: string]: HTMLOverride\n}\n\n/**\n * HTML compiler options\n * @lang zh HTML 编译器选项\n * @lang hi HTML कंपाइलर विकल्प\n */\nexport type HTMLOptions = Omit<\n MarkdownToJSX.Options,\n 'createElement' | 'wrapperProps' | 'overrides'\n> & {\n /** Reference definitions for link resolution */\n /** @lang zh 用于链接解析的引用定义 */\n /** @lang hi लिंक रिज़ॉल्यूशन के लिए संदर्भ परिभाषाएं */\n refs?: { [key: string]: { target: string; title: string | undefined } }\n /** Custom rendering function for AST rules */\n /** @lang zh AST 规则的自定义渲染函数 */\n /** @lang hi AST नियमों के लिए कस्टम रेंडरिंग फ़ंक्शन */\n renderRule?: (\n next: () => string,\n node: MarkdownToJSX.ASTNode,\n renderChildren: (children: MarkdownToJSX.ASTNode[]) => string,\n state: MarkdownToJSX.State\n ) => string\n /** Override configurations for HTML tags */\n /** @lang zh HTML 标签的覆盖配置 */\n /** @lang hi HTML टैग्स के लिए ओवरराइड कॉन्फ़िगरेशन */\n overrides?: HTMLOverrides\n /** Props for wrapper element */\n /** @lang zh 包装元素的属性 */\n /** @lang hi रैपर एलिमेंट के लिए props */\n wrapperProps?: Record<string, string | number | boolean>\n /** Internal flag for wrapper auto-detection */\n /** @lang zh 包装器自动检测的内部标志 */\n /** @lang hi रैपर ऑटो-डिटेक्शन के लिए आंतरिक फ़्लैग */\n wrapperWasAutoSet?: boolean\n}\n\nfunction shouldSkipNode(\n node: MarkdownToJSX.ASTNode,\n preserveFrontmatter: boolean\n): boolean {\n return (\n node.type === RuleType.footnote ||\n node.type === RuleType.ref ||\n (node.type === RuleType.frontmatter && !preserveFrontmatter)\n )\n}\n\n/**\n * Convert AST nodes to HTML string\n * @lang zh 将 AST 节点转换为 HTML 字符串\n * @lang hi AST नोड्स को HTML स्ट्रिंग में बदलें\n *\n * @param nodes - Array of AST nodes to render\n * @lang zh @param nodes - 要渲染的 AST 节点数组\n * @lang hi @param nodes - रेंडर करने के लिए AST नोड्स की सरणी\n * @param options - HTML compiler options\n * @lang zh @param options - HTML 编译器选项\n * @lang hi @param options - HTML कंपाइलर विकल्प\n * @returns HTML string\n * @lang zh @returns HTML 字符串\n * @lang hi @returns HTML स्ट्रिंग\n */\nexport function astToHTML(\n nodes: MarkdownToJSX.ASTNode[],\n options: HTMLOptions = {}\n): string {\n const sanitize = options.sanitizer || util.sanitizer\n const slug = options.slugify || util.slugify\n var refs = options.refs || {}\n var overrides = options.overrides || {}\n\n // Extract refs from reference collection node and filter non-renderable nodes\n var refsFromAST: {\n [key: string]: { target: string; title: string | undefined }\n } = {}\n var nonRefCollectionNodes: MarkdownToJSX.ASTNode[] = []\n var foundRefCollection = false\n for (var i = 0; i < nodes.length; i++) {\n var node = nodes[i]\n if (node.type === RuleType.refCollection && !foundRefCollection) {\n refsFromAST = (node as MarkdownToJSX.ReferenceCollectionNode).refs || {}\n foundRefCollection = true\n continue\n }\n if (shouldSkipNode(node, !!options.preserveFrontmatter)) continue\n nonRefCollectionNodes.push(node)\n }\n for (var key in refsFromAST) refs[key] = refsFromAST[key]\n\n var updatedOptions = { ...options, refs, overrides }\n\n /**\n * Encode special characters in URL (backslashes and backticks)\n * Preserves existing percent-encoded sequences\n */\n function encodeUrlSpecialChars(url: string): string {\n var result = ''\n var i = 0\n var len = url.length\n while (i < len) {\n // Preserve existing percent-encoded sequences\n if (\n url[i] === '%' &&\n i + 2 < len &&\n isHexChar(url.charCodeAt(i + 1)) &&\n isHexChar(url.charCodeAt(i + 2))\n ) {\n result += url[i] + url[i + 1] + url[i + 2]\n i += 3\n } else {\n var code = url.charCodeAt(i)\n if (code === $.CHAR_BACKSLASH) {\n result += '%5C'\n } else if (code === $.CHAR_BACKTICK) {\n result += '%60'\n } else {\n result += encodeURI(url[i])\n }\n i++\n }\n }\n return result\n }\n\n function isHexChar(code: number): boolean {\n return (\n (code >= $.CHAR_DIGIT_0 && code <= $.CHAR_DIGIT_9) ||\n (code >= $.CHAR_a && code <= $.CHAR_f) ||\n (code >= $.CHAR_A && code <= $.CHAR_F)\n )\n }\n\n function sanitizeAndReencodeUrl(url: string): string | null {\n var sanitized = sanitize(url, 'a', 'href')\n if (sanitized === null || sanitized === url) return sanitized\n return encodeUrlSpecialChars(sanitized)\n }\n\n function mergeAttrs(\n base: Record<string, any> | undefined,\n overrideProps: Record<string, any>\n ): Record<string, any> {\n var merged = base || {}\n if (hasKeys(overrideProps)) {\n merged = { ...merged }\n for (var key in overrideProps) merged[key] = overrideProps[key]\n }\n return merged\n }\n\n function renderChildren(children: MarkdownToJSX.ASTNode[]): string {\n return children.length ? astToHTML(children, updatedOptions) : ''\n }\n\n function renderNode(\n node: MarkdownToJSX.ASTNode,\n state: MarkdownToJSX.State = {}\n ): string {\n if (!node || typeof node !== 'object') return ''\n if (\n node.type === RuleType.ref ||\n node.type === RuleType.refCollection ||\n shouldSkipNode(node, !!options.preserveFrontmatter)\n )\n return ''\n\n switch (node.type) {\n case RuleType.blockQuote: {\n var children = node.children\n ? astToHTML(node.children, updatedOptions)\n : ''\n if (node.alert) {\n children = `<header>${escapeHtml(node.alert)}</header>` + children\n return renderTag('blockquote', children, overrides, {\n class:\n 'markdown-alert-' + slug(node.alert.toLowerCase(), util.slugify),\n })\n }\n return renderTag('blockquote', children, overrides)\n }\n\n case RuleType.breakLine: {\n return '<br />'\n }\n case RuleType.breakThematic: {\n return '<hr />'\n }\n\n case RuleType.frontmatter: {\n return '<pre>' + escapeHtml(node.text) + '</pre>'\n }\n\n case RuleType.codeBlock: {\n var codeAttrs: Record<string, any> = node.attrs || {}\n if (node.lang) {\n codeAttrs = { ...codeAttrs }\n const decodedLang = util.decodeEntityReferences(node.lang)\n const existingClass =\n (codeAttrs.class as string) || (codeAttrs.className as string) || ''\n codeAttrs.class = existingClass\n ? existingClass + ' language-' + decodedLang\n : 'language-' + decodedLang\n delete codeAttrs.className\n }\n const attrs = formatAttributes(codeAttrs)\n const text = node.text || ''\n return `<pre><code${attrs}>${escapeHtml(text)}</code></pre>`\n }\n\n case RuleType.codeInline: {\n return '<code>' + escapeHtml(node.text || '') + '</code>'\n }\n\n case RuleType.footnoteReference: {\n const href = sanitize(node.target || '', 'a', 'href') || ''\n const text = escapeHtml(node.text || '')\n return `<a href=\"${escapeHtml(href)}\"><sup>${text}</sup></a>`\n }\n\n case RuleType.gfmTask: {\n return (\n '<input' +\n (node.completed ? ' checked=\"\"' : '') +\n ' disabled=\"\" type=\"checkbox\">'\n )\n }\n\n case RuleType.heading: {\n const level = node.level || 1\n const attrs = node.id?.trim() ? { id: node.id } : undefined\n return renderTag(\n 'h' + level,\n node.children ? astToHTML(node.children, updatedOptions) : '',\n overrides,\n attrs\n )\n }\n\n case RuleType.htmlComment: {\n const htmlCommentNode = node as MarkdownToJSX.HTMLCommentNode & {\n raw?: boolean\n endsWithGreaterThan?: boolean\n }\n if (htmlCommentNode.raw) {\n return htmlCommentNode.text\n }\n if (htmlCommentNode.endsWithGreaterThan) {\n return `<!--${node.text}>`\n }\n return `<!--${node.text}-->`\n }\n\n case RuleType.htmlBlock: {\n const htmlNode = node as MarkdownToJSX.HTMLNode & {\n rawAttrs?: string\n isClosingTag?: boolean\n }\n const defaultTag = htmlNode.tag || 'div'\n const tag = util.getTag(defaultTag, overrides)\n const overrideProps = util.getOverrideProps(defaultTag, overrides)\n var attrsStr: string\n if (htmlNode.rawAttrs !== undefined) {\n attrsStr =\n htmlNode.rawAttrs\n .replace(/\\n\\s*/g, '')\n .replace(/\\r\\s*/g, '')\n .replace(/\\t\\s*/g, '') +\n (hasKeys(overrideProps)\n ? ' ' + formatAttributes(overrideProps).trim()\n : '')\n } else {\n attrsStr = formatAttributes(mergeAttrs(htmlNode.attrs, overrideProps))\n }\n if (options.tagfilter && util.shouldFilterTag(tag)) {\n return htmlNode.isClosingTag\n ? `</${tag}>`\n : `<${tag}${attrsStr}>`\n }\n if (htmlNode.rawText) {\n if (htmlNode.verbatim) {\n var textContent = options.tagfilter\n ? util.applyTagFilterToText(htmlNode.rawText)\n : htmlNode.rawText\n if (htmlNode.isClosingTag) return `</${tag}>${textContent}`\n var tagLower = tag.toLowerCase()\n var isType1Block =\n tagLower === 'pre' ||\n tagLower === 'script' ||\n tagLower === 'style' ||\n tagLower === 'textarea'\n if (isType1Block) {\n var textLen = htmlNode.rawText.length\n var textStart = 0\n while (\n textStart < textLen &&\n htmlNode.rawText.charCodeAt(textStart) === $.CHAR_SPACE\n )\n textStart++\n if (\n textStart < textLen &&\n htmlNode.rawText.charCodeAt(textStart) === $.CHAR_LT\n ) {\n var openingTagEnd = htmlNode.rawText.indexOf('>', textStart)\n if (openingTagEnd !== -1) {\n var rawOpeningTag = htmlNode.rawText.slice(\n textStart,\n openingTagEnd + 1\n )\n if (\n rawOpeningTag.charCodeAt(1) >= $.CHAR_a &&\n rawOpeningTag.charCodeAt(1) <= $.CHAR_z\n ) {\n var tagStart = 1\n var tagEnd = tagStart\n while (\n tagEnd < rawOpeningTag.length &&\n rawOpeningTag.charCodeAt(tagEnd) >= $.CHAR_a &&\n rawOpeningTag.charCodeAt(tagEnd) <= $.CHAR_z\n )\n tagEnd++\n var foundTag = rawOpeningTag\n .slice(tagStart, tagEnd)\n .toLowerCase()\n if (foundTag === tagLower) {\n var innerText = htmlNode.rawText.slice(openingTagEnd + 1)\n return (\n rawOpeningTag +\n (options.tagfilter\n ? util.applyTagFilterToText(innerText)\n : innerText)\n )\n }\n }\n }\n }\n var closingTag = '</' + tagLower + '>'\n var hasClosingTag = htmlNode.rawText.indexOf(closingTag) !== -1\n return hasClosingTag\n ? `<${tag}${attrsStr}>${textContent}`\n : `<${tag}${attrsStr}>${textContent}</${tag}>`\n }\n var trimmed = htmlNode.rawText.trim()\n if (trimmed.length > 0 && trimmed.charCodeAt(0) === $.CHAR_LT) {\n if (\n trimmed.charCodeAt(1) >= $.CHAR_a &&\n trimmed.charCodeAt(1) <= $.CHAR_z\n ) {\n var tagStart = 1\n var tagEnd = tagStart\n while (\n tagEnd < trimmed.length &&\n trimmed.charCodeAt(tagEnd) >= $.CHAR_a &&\n trimmed.charCodeAt(tagEnd) <= $.CHAR_z\n )\n tagEnd++\n var foundTag = trimmed.slice(tagStart, tagEnd).toLowerCase()\n if (\n foundTag === tagLower &&\n trimmed.indexOf('</' + tagLower + '>', tagEnd) === -1\n ) {\n return textContent\n }\n }\n }\n var trimmedStart = 0\n while (\n trimmedStart < textContent.length &&\n textContent.charCodeAt(trimmedStart) === $.CHAR_SPACE\n )\n trimmedStart++\n return `<${tag}${attrsStr}>${trimmedStart > 0 ? textContent.slice(trimmedStart) : trimmed ? textContent : ''}`\n }\n var textContent = options.tagfilter\n ? util.applyTagFilterToText(htmlNode.rawText)\n : htmlNode.rawText\n return `<${tag}${attrsStr}>${textContent}</${tag}>`\n }\n const children = htmlNode.children\n ? astToHTML(htmlNode.children, updatedOptions)\n : ''\n if (htmlNode.isClosingTag) return `</${tag}>${children}`\n return children.trim()\n ? `<${tag}${attrsStr}>${children}</${tag}>`\n : `<${tag}${attrsStr}>${children}`\n }\n\n case RuleType.htmlSelfClosing: {\n const htmlNode = node as MarkdownToJSX.HTMLSelfClosingNode & {\n rawText?: string\n isClosingTag?: boolean\n }\n const defaultTag = htmlNode.tag || 'div'\n const tag = util.getTag(defaultTag, overrides)\n if (htmlNode.rawText) {\n return options.tagfilter && util.shouldFilterTag(tag)\n ? htmlNode.rawText.replace(/^</, '<')\n : htmlNode.rawText\n }\n if (htmlNode.isClosingTag) return `</${tag}>`\n const overrideProps = util.getOverrideProps(defaultTag, overrides)\n const mergedAttrs = mergeAttrs(htmlNode.attrs, overrideProps)\n const attrsStr = formatAttributes(mergedAttrs)\n if (options.tagfilter && util.shouldFilterTag(tag)) {\n return `<${tag}${attrsStr} />`\n }\n return `<${tag}${attrsStr} />`\n }\n\n case RuleType.image: {\n const tag = util.getTag('img', overrides)\n const overrideProps = util.getOverrideProps('img', overrides)\n const src = sanitize(node.target || '', 'img', 'src') || ''\n var attrs: Record<string, any> = {\n ...overrideProps,\n alt: node.alt || '',\n }\n if (node.title) attrs.title = node.title\n return `<${tag} src=\"${escapeHtml(src)}\"${formatAttributes(attrs)} />`\n }\n\n case RuleType.link: {\n const tag = util.getTag('a', overrides)\n const overrideProps = util.getOverrideProps('a', overrides)\n var attrs: Record<string, any> = { ...overrideProps }\n if (node.target != null) {\n const href = sanitizeAndReencodeUrl(\n encodeUrlSpecialChars(util.decodeEntityReferences(node.target))\n )\n if (href != null) attrs.href = href\n }\n if (node.title) attrs.title = util.decodeEntityReferences(node.title)\n return `<${tag}${formatAttributes(attrs)}>${node.children ? astToHTML(node.children, updatedOptions) : ''}</${tag}>`\n }\n\n case RuleType.table: {\n const tableNode = node as MarkdownToJSX.TableNode\n const alignments = tableNode.align || []\n var header = ''\n var headerCells = tableNode.header || []\n for (var hi = 0; hi < headerCells.length; hi++) {\n var align = alignments[hi]\n header +=\n '<th' +\n (align ? ` align=\"${align}\"` : '') +\n '>' +\n astToHTML(headerCells[hi], updatedOptions) +\n '</th>'\n }\n var rows = ''\n var tableRows = tableNode.cells || []\n for (var ri = 0; ri < tableRows.length; ri++) {\n var row = tableRows[ri] || []\n rows += '<tr>'\n for (var ci = 0; ci < row.length; ci++) {\n var align = alignments[ci]\n rows +=\n '<td' +\n (align ? ` align=\"${align}\"` : '') +\n '>' +\n astToHTML(row[ci], updatedOptions) +\n '</td>'\n }\n rows += '</tr>'\n }\n const tag = util.getTag('table', overrides)\n const attrs = formatAttributes(\n util.getOverrideProps('table', overrides)\n )\n return `<${tag}${attrs}><thead><tr>${header}</tr></thead>${rows ? `<tbody>${rows}</tbody>` : ''}</${tag}>`\n }\n\n case RuleType.text: {\n // Inline escapeHtml for common text node case\n var text = node.text || ''\n if (!text) return text\n var needsEscape = false\n var i = 0\n var len = text.length\n while (i < len) {\n var code = text.charCodeAt(i)\n if (\n code === $.CHAR_AMPERSAND ||\n code === $.CHAR_LT ||\n code === $.CHAR_GT ||\n code === $.CHAR_DOUBLE_QUOTE\n ) {\n needsEscape = true\n break\n }\n i++\n }\n if (!needsEscape) return text\n var result = ''\n i = 0\n var last = 0\n while (i < len) {\n var code = text.charCodeAt(i)\n var replacement: string | null = null\n if (code === $.CHAR_AMPERSAND) {\n replacement = '&'\n } else if (code === $.CHAR_LT) {\n replacement = '<'\n } else if (code === $.CHAR_GT) {\n replacement = '>'\n } else if (code === $.CHAR_DOUBLE_QUOTE) {\n replacement = '"'\n }\n if (replacement) {\n if (i > last) result += text.slice(last, i)\n result += replacement\n last = i + 1\n }\n i++\n }\n if (last < len) result += text.slice(last)\n return result\n }\n\n case RuleType.textFormatted: {\n return renderTag(\n node.tag || 'strong',\n node.children ? astToHTML(node.children, updatedOptions) : '',\n overrides\n )\n }\n\n case RuleType.orderedList:\n case RuleType.unorderedList: {\n var items = ''\n var listItems = node.items || []\n for (var li = 0; li < listItems.length; li++) {\n items += '<li>' + astToHTML(listItems[li], updatedOptions) + '</li>'\n }\n const tag = node.type === RuleType.orderedList ? 'ol' : 'ul'\n const attrs =\n node.type === RuleType.orderedList &&\n node.start != null &&\n node.start !== 1\n ? { start: node.start }\n : undefined\n return renderTag(tag, items, overrides, attrs)\n }\n\n case RuleType.paragraph: {\n var paragraphOpts = { ...updatedOptions, refs: {}, wrapper: null }\n if (options.forceInline) {\n return node.children ? astToHTML(node.children, paragraphOpts) : ''\n }\n var children = node.children\n ? astToHTML(node.children, paragraphOpts)\n : ''\n // Per CommonMark: collapse trailing spaces before newlines (soft line breaks)\n // Don't collapse spaces inside HTML attribute values\n var hasSpaceNewline = false\n for (var checki = 0; checki < children.length - 1; checki++) {\n if (\n children.charCodeAt(checki) === $.CHAR_SPACE &&\n children.charCodeAt(checki + 1) === $.CHAR_NEWLINE\n ) {\n hasSpaceNewline = true\n break\n }\n }\n if (hasSpaceNewline) {\n var result = ''\n var i = 0\n var len = children.length\n var inTag = false\n var quoteCount = 0\n while (i < len) {\n var code = children.charCodeAt(i)\n if (code === $.CHAR_LT) {\n inTag = true\n quoteCount = 0\n } else if (code === $.CHAR_GT) {\n inTag = false\n quoteCount = 0\n } else if (inTag && code === $.CHAR_DOUBLE_QUOTE) {\n quoteCount++\n }\n if (\n code === $.CHAR_SPACE &&\n i + 1 < len &&\n children.charCodeAt(i + 1) === $.CHAR_NEWLINE\n ) {\n if (inTag && quoteCount % 2 === 1) {\n result += ' \\n'\n } else {\n result += '\\n'\n }\n i += 2\n } else {\n result += children[i]\n i++\n }\n }\n children = result\n }\n\n const attrsStr = formatAttributes(util.getOverrideProps('p', overrides))\n const tag = util.getTag('p', overrides)\n\n const paragraphNode = node as MarkdownToJSX.ParagraphNode & {\n removedClosingTags?: MarkdownToJSX.ASTNode[]\n }\n var closingTags = ''\n if (paragraphNode.removedClosingTags?.length) {\n for (\n var cti = 0;\n cti < paragraphNode.removedClosingTags.length;\n cti++\n ) {\n closingTags += renderNode(\n paragraphNode.removedClosingTags[cti],\n state\n )\n }\n }\n return `<${tag}${attrsStr}>${children}</${tag}>${closingTags}`\n }\n\n default:\n return ''\n }\n }\n\n function renderNodeWithRule(\n node: MarkdownToJSX.ASTNode,\n state: MarkdownToJSX.State = {}\n ): string {\n if (!node || typeof node !== 'object') return ''\n\n // renderRule must be checked FIRST, before any filtering or rendering logic\n // This gives users full control to render even normally-skipped nodes\n if (options.renderRule) {\n return options.renderRule(\n () => {\n // Default behavior: skip ref, refCollection, and other filtered nodes\n if (\n node.type === RuleType.ref ||\n node.type === RuleType.refCollection ||\n shouldSkipNode(node, !!options.preserveFrontmatter)\n )\n return ''\n return renderNode(node, state)\n },\n node,\n renderChildren,\n state\n )\n }\n\n // Default filtering: skip ref, refCollection, and other filtered nodes\n if (\n node.type === RuleType.ref ||\n node.type === RuleType.refCollection ||\n shouldSkipNode(node, !!options.preserveFrontmatter)\n )\n return ''\n\n return renderNode(node, state)\n }\n\n var content = ''\n if (Array.isArray(nodes)) {\n for (var ci = 0; ci < nonRefCollectionNodes.length; ci++) {\n content += renderNodeWithRule(nonRefCollectionNodes[ci], {\n key: ci,\n refs,\n })\n }\n } else {\n content = renderNodeWithRule(nodes, { refs })\n }\n\n // Extract and render footnotes\n var footnoteFooter = ''\n for (var key in refs) {\n if (key.charCodeAt(0) === $.CHAR_CARET) {\n if (!footnoteFooter) footnoteFooter = '<footer>'\n const id = key.slice(1)\n const parsed = parse.parseMarkdown(\n refs[key].target,\n { inline: true, refs },\n {\n ...updatedOptions,\n overrides: updatedOptions.overrides as MarkdownToJSX.Overrides,\n sanitizer: sanitize,\n slugify: (i: string) => slug(i, util.slugify),\n tagfilter: updatedOptions.tagfilter !== false,\n }\n )\n var filtered: MarkdownToJSX.ASTNode[] = []\n for (var pi = 0; pi < parsed.length; pi++) {\n if (parsed[pi].type !== RuleType.refCollection)\n filtered.push(parsed[pi])\n }\n const footnoteContent = astToHTML(filtered, {\n ...updatedOptions,\n refs: {},\n forceInline: true,\n wrapper: null,\n })\n footnoteFooter += `<div id=\"${escapeHtmlAttr(slug(id, util.slugify))}\">${escapeHtml(id)}: ${footnoteContent}</div>`\n }\n }\n if (footnoteFooter) footnoteFooter += '</footer>'\n\n // Handle wrapper options\n if (options.wrapper === null) {\n return content + footnoteFooter\n }\n\n // Determine if content should be wrapped (only when explicitly requested)\n const hasMultipleChildren = nonRefCollectionNodes.length > 1\n const hasExplicitWrapper = options.wrapper != null\n const wrapperWasExplicit =\n hasExplicitWrapper && typeof options.wrapper === 'string'\n const shouldWrap =\n options.forceWrapper ||\n (options.forceInline && hasExplicitWrapper) ||\n (hasMultipleChildren && hasExplicitWrapper)\n\n if (!shouldWrap) {\n return content + footnoteFooter\n }\n\n // Extract paragraph content when forceInline or forceWrapper with explicit wrapper\n var contentToWrap = content\n if (\n options.forceInline ||\n (options.forceWrapper && wrapperWasExplicit && !options.wrapperWasAutoSet)\n ) {\n if (\n !hasMultipleChildren &&\n nonRefCollectionNodes.length === 1 &&\n nonRefCollectionNodes[0].type === RuleType.paragraph\n ) {\n const paragraphNode =\n nonRefCollectionNodes[0] as MarkdownToJSX.ParagraphNode\n if (paragraphNode.children) {\n contentToWrap = astToHTML(paragraphNode.children, {\n ...updatedOptions,\n refs: {},\n forceInline: true,\n wrapper: null,\n })\n }\n }\n }\n\n // Determine wrapper tag\n const wrapperTag =\n typeof options.wrapper === 'string'\n ? options.wrapper\n : options.forceInline\n ? 'span'\n : 'div'\n\n var wrapperAttrs = ''\n if (options.wrapperProps) {\n var sanitizedProps: Record<string, string> = {}\n for (var wpKey in options.wrapperProps) {\n var wpValue = options.wrapperProps[wpKey]\n if (wpValue != null) {\n var sanitized = sanitize(String(wpValue), wrapperTag, wpKey)\n if (sanitized !== null) sanitizedProps[wpKey] = sanitized\n }\n }\n wrapperAttrs = formatAttributes(sanitizedProps)\n }\n\n return `<${wrapperTag}${wrapperAttrs}>${contentToWrap + footnoteFooter}</${wrapperTag}>`\n}\n\n/**\n * Compiler function that parses markdown and renders to HTML string\n * Convenience function that combines parser() and html()\n * @lang zh 解析 Markdown 并渲染为 HTML 字符串的编译器函数\n * 结合 parser() 和 html() 的便捷函数\n * @lang hi Markdown को पार्स करने और HTML स्ट्रिंग में रेंडर करने वाला कंपाइलर फ़ंक्शन\n * parser() और html() को जोड़ने वाला सुविधाजनक फ़ंक्शन\n *\n * @param markdown - Markdown string to compile\n * @lang zh @param markdown - 要编译的 Markdown 字符串\n * @lang hi @param markdown - कंपाइल करने के लिए Markdown स्ट्रिंग\n * @param options - HTML compiler options\n * @lang zh @param options - HTML 编译器选项\n * @lang hi @param options - HTML कंपाइलर विकल्प\n * @returns HTML string\n * @lang zh @returns HTML 字符串\n * @lang hi @returns HTML स्ट्रिंग\n */\nexport function compiler(markdown: string, options?: HTMLOptions): string {\n const inline = options?.forceInline || false\n const parseOptions: parse.ParseOptions = {\n ...options,\n overrides: options?.overrides as MarkdownToJSX.Overrides,\n sanitizer: options?.sanitizer,\n slugify: options?.slugify\n ? (i: string) => options.slugify!(i, util.slugify)\n : util.slugify,\n tagfilter: options?.tagfilter !== false,\n }\n const ast = parse.parser(markdown, { ...parseOptions, forceInline: inline })\n const htmlOptions: HTMLOptions = {\n ...options,\n forceInline: inline,\n } as HTMLOptions\n var wrapperWasAutoSet = false\n if (options?.wrapper === undefined) {\n var nonRefCount = 0\n for (var ni = 0; ni < ast.length; ni++) {\n var n = ast[ni]\n if (\n n.type !== RuleType.refCollection &&\n n.type !== RuleType.footnote &&\n n.type !== RuleType.ref &&\n (n.type !== RuleType.frontmatter || !options?.preserveFrontmatter)\n ) {\n nonRefCount++\n }\n }\n if (nonRefCount > 1 || options?.forceWrapper) {\n htmlOptions.wrapper = 'div'\n wrapperWasAutoSet = true\n } else if (inline && nonRefCount > 0) {\n htmlOptions.wrapper = 'span'\n wrapperWasAutoSet = true\n }\n }\n htmlOptions.wrapperWasAutoSet = wrapperWasAutoSet\n return astToHTML(ast, htmlOptions)\n}\n"
|
|
10
10
|
],
|
|
11
|
-
"mappings": "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",
|
|
12
|
-
"debugId": "
|
|
11
|
+
"mappings": "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",
|
|
12
|
+
"debugId": "10B43136D48846A264756E2164756E21",
|
|
13
13
|
"names": []
|
|
14
14
|
}
|