@notectl/core 2.3.1 → 2.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/THIRD-PARTY-NOTICES.md +129 -0
- package/dist/chunks/{AlignmentPlugin--xAFlRqE.mjs → AlignmentPlugin-C9Rr_R-g.mjs} +2 -2
- package/dist/chunks/{AlignmentPlugin--xAFlRqE.mjs.map → AlignmentPlugin-C9Rr_R-g.mjs.map} +1 -1
- package/dist/chunks/{AttributedMarkCommands-bagbH8Qt.mjs → AttributedMarkCommands-BCvmqeFZ.mjs} +2 -2
- package/dist/chunks/{AttributedMarkCommands-bagbH8Qt.mjs.map → AttributedMarkCommands-BCvmqeFZ.mjs.map} +1 -1
- package/dist/chunks/{BidiIsolationPlugin-DBXyXpgm.mjs → BidiIsolationPlugin-Cw2KMk-H.mjs} +2 -2
- package/dist/chunks/{BidiIsolationPlugin-DBXyXpgm.mjs.map → BidiIsolationPlugin-Cw2KMk-H.mjs.map} +1 -1
- package/dist/chunks/{BlockInsertion-CJusvrDL.mjs → BlockInsertion-CYH2gRkY.mjs} +2 -2
- package/dist/chunks/{BlockInsertion-CJusvrDL.mjs.map → BlockInsertion-CYH2gRkY.mjs.map} +1 -1
- package/dist/chunks/{BlockquotePlugin-Bz2glHwX.mjs → BlockquotePlugin-0bZSbkyo.mjs} +2 -2
- package/dist/chunks/{BlockquotePlugin-Bz2glHwX.mjs.map → BlockquotePlugin-0bZSbkyo.mjs.map} +1 -1
- package/dist/chunks/CaretNavigationPlugin-BPZ9b6XR.mjs +2 -0
- package/dist/chunks/CaretNavigationPlugin-BPZ9b6XR.mjs.map +1 -0
- package/dist/chunks/CodeBlockPlugin-BCJ3faXx.mjs +2 -0
- package/dist/chunks/{CodeBlockPlugin-C1hrdbSZ.mjs.map → CodeBlockPlugin-BCJ3faXx.mjs.map} +1 -1
- package/dist/chunks/{ColorGrid-C9RQoEWF.mjs → ColorGrid-DQEkJ-0y.mjs} +2 -2
- package/dist/chunks/{ColorGrid-C9RQoEWF.mjs.map → ColorGrid-DQEkJ-0y.mjs.map} +1 -1
- package/dist/chunks/ColorPickerPopup-CyF26zIU.mjs +2 -0
- package/dist/chunks/{ColorPickerPopup-DiA68Pzz.mjs.map → ColorPickerPopup-CyF26zIU.mjs.map} +1 -1
- package/dist/chunks/Commands-D5ND50PQ.mjs +2 -0
- package/dist/chunks/{Commands-1dFFldi7.mjs.map → Commands-D5ND50PQ.mjs.map} +1 -1
- package/dist/chunks/{Decoration-BpoEOANl.mjs → Decoration-BOP1TAUd.mjs} +2 -2
- package/dist/chunks/{Decoration-BpoEOANl.mjs.map → Decoration-BOP1TAUd.mjs.map} +1 -1
- package/dist/chunks/{FontPlugin-By-TGrQo.mjs → FontPlugin-D041tiLe.mjs} +2 -2
- package/dist/chunks/{FontPlugin-By-TGrQo.mjs.map → FontPlugin-D041tiLe.mjs.map} +1 -1
- package/dist/chunks/{FontSizePlugin-Dln-tYXV.mjs → FontSizePlugin-8CAvj1RD.mjs} +2 -2
- package/dist/chunks/{FontSizePlugin-Dln-tYXV.mjs.map → FontSizePlugin-8CAvj1RD.mjs.map} +1 -1
- package/dist/chunks/{FormulaPlugin-By1befrR.mjs → FormulaPlugin-DJ39BtqV.mjs} +2 -2
- package/dist/chunks/FormulaPlugin-DJ39BtqV.mjs.map +1 -0
- package/dist/chunks/GapCursorNavigation-DCWOmopl.mjs +2 -0
- package/dist/chunks/{GapCursorNavigation-BuXngVu-.mjs.map → GapCursorNavigation-DCWOmopl.mjs.map} +1 -1
- package/dist/chunks/GapCursorPlugin-2iR6506y.mjs +2 -0
- package/dist/chunks/{GapCursorPlugin-DAxVzXRs.mjs.map → GapCursorPlugin-2iR6506y.mjs.map} +1 -1
- package/dist/chunks/{HardBreakPlugin-DlbSlrdq.mjs → HardBreakPlugin-vniSvTgq.mjs} +2 -2
- package/dist/chunks/{HardBreakPlugin-DlbSlrdq.mjs.map → HardBreakPlugin-vniSvTgq.mjs.map} +1 -1
- package/dist/chunks/{HeadingPlugin-uMAjPOk5.mjs → HeadingPlugin-DUKsLuMd.mjs} +2 -2
- package/dist/chunks/{HeadingPlugin-uMAjPOk5.mjs.map → HeadingPlugin-DUKsLuMd.mjs.map} +1 -1
- package/dist/chunks/{HighlightPlugin-Bj7FPkIQ.mjs → HighlightPlugin-DRTAE1N5.mjs} +2 -2
- package/dist/chunks/{HighlightPlugin-Bj7FPkIQ.mjs.map → HighlightPlugin-DRTAE1N5.mjs.map} +1 -1
- package/dist/chunks/HorizontalRulePlugin-B9OvwrKB.mjs +2 -0
- package/dist/chunks/{HorizontalRulePlugin-DUVmTQpX.mjs.map → HorizontalRulePlugin-B9OvwrKB.mjs.map} +1 -1
- package/dist/chunks/{ImagePlugin-FToCOjd5.mjs → ImagePlugin-CwxTRr6d.mjs} +2 -2
- package/dist/chunks/{ImagePlugin-FToCOjd5.mjs.map → ImagePlugin-CwxTRr6d.mjs.map} +1 -1
- package/dist/chunks/{InlineCodePlugin-pISIoGQE.mjs → InlineCodePlugin-uxgMUX_E.mjs} +2 -2
- package/dist/chunks/{InlineCodePlugin-pISIoGQE.mjs.map → InlineCodePlugin-uxgMUX_E.mjs.map} +1 -1
- package/dist/chunks/{LinkPlugin-Ct5Z180S.mjs → LinkPlugin-CvWHbSkb.mjs} +2 -2
- package/dist/chunks/{LinkPlugin-Ct5Z180S.mjs.map → LinkPlugin-CvWHbSkb.mjs.map} +1 -1
- package/dist/chunks/{ListPlugin-DAY5ezNs.mjs → ListPlugin-BchSFWVn.mjs} +2 -2
- package/dist/chunks/{ListPlugin-DAY5ezNs.mjs.map → ListPlugin-BchSFWVn.mjs.map} +1 -1
- package/dist/chunks/{MarkdownHTMLRegistry-CKEx7LkR.mjs → MarkdownHTMLRegistry-Q7l0d6Ma.mjs} +2 -2
- package/dist/chunks/{MarkdownHTMLRegistry-CKEx7LkR.mjs.map → MarkdownHTMLRegistry-Q7l0d6Ma.mjs.map} +1 -1
- package/dist/chunks/{MarkdownParser-CWt3M6jR.mjs → MarkdownParser-Dp62mfUq.mjs} +2 -2
- package/dist/chunks/{MarkdownParser-CWt3M6jR.mjs.map → MarkdownParser-Dp62mfUq.mjs.map} +1 -1
- package/dist/chunks/{MarkdownSerializer-J-i28out.mjs → MarkdownSerializer-DBELFAeo.mjs} +2 -2
- package/dist/chunks/{MarkdownSerializer-J-i28out.mjs.map → MarkdownSerializer-DBELFAeo.mjs.map} +1 -1
- package/dist/chunks/MathFont-BS8IwYh2.mjs +2 -0
- package/dist/chunks/MathFont-BS8IwYh2.mjs.map +1 -0
- package/dist/chunks/NodeSelectionCommands-WH5snxr_.mjs +2 -0
- package/dist/chunks/{NodeSelectionCommands-1PjwUDTJ.mjs.map → NodeSelectionCommands-WH5snxr_.mjs.map} +1 -1
- package/dist/chunks/PluginHelpers-KDuTlmXm.mjs +2 -0
- package/dist/chunks/{PluginHelpers-Dx_0hfDe.mjs.map → PluginHelpers-KDuTlmXm.mjs.map} +1 -1
- package/dist/chunks/{PopupManager-CT-fMZJn.mjs → PopupManager-Cj86uDEB.mjs} +2 -2
- package/dist/chunks/{PopupManager-CT-fMZJn.mjs.map → PopupManager-Cj86uDEB.mjs.map} +1 -1
- package/dist/chunks/PrintPlugin-D2javl_d.mjs +2 -0
- package/dist/chunks/{PrintPlugin-7zz9mhhU.mjs.map → PrintPlugin-D2javl_d.mjs.map} +1 -1
- package/dist/chunks/SimpleMark-gTQaSJcO.mjs +2 -0
- package/dist/chunks/{SimpleMark-7CQcA4RK.mjs.map → SimpleMark-gTQaSJcO.mjs.map} +1 -1
- package/dist/chunks/SmartPastePlugin-BvJQ-fOz.mjs +2 -0
- package/dist/chunks/SmartPastePlugin-BvJQ-fOz.mjs.map +1 -0
- package/dist/chunks/StarterFonts-BDQPg-cu.mjs +2 -0
- package/dist/chunks/StarterFonts-BDQPg-cu.mjs.map +1 -0
- package/dist/chunks/{StrikethroughPlugin-C2oWvGc3.mjs → StrikethroughPlugin-BdrG1TTY.mjs} +2 -2
- package/dist/chunks/{StrikethroughPlugin-C2oWvGc3.mjs.map → StrikethroughPlugin-BdrG1TTY.mjs.map} +1 -1
- package/dist/chunks/{SuperSubPlugin-D1xaKrSu.mjs → SuperSubPlugin-DTZB0Y3D.mjs} +2 -2
- package/dist/chunks/{SuperSubPlugin-D1xaKrSu.mjs.map → SuperSubPlugin-DTZB0Y3D.mjs.map} +1 -1
- package/dist/chunks/{TablePlugin-PJe3zwr-.mjs → TablePlugin-CPvg9YZS.mjs} +2 -2
- package/dist/chunks/{TablePlugin-PJe3zwr-.mjs.map → TablePlugin-CPvg9YZS.mjs.map} +1 -1
- package/dist/chunks/{TextColorPlugin-CTd9tfeG.mjs → TextColorPlugin-Ckg3KWvb.mjs} +2 -2
- package/dist/chunks/{TextColorPlugin-CTd9tfeG.mjs.map → TextColorPlugin-Ckg3KWvb.mjs.map} +1 -1
- package/dist/chunks/{TextDirectionAutoPlugin-CPnKVVuI.mjs → TextDirectionAutoPlugin-DRGbgTlx.mjs} +2 -2
- package/dist/chunks/{TextDirectionAutoPlugin-CPnKVVuI.mjs.map → TextDirectionAutoPlugin-DRGbgTlx.mjs.map} +1 -1
- package/dist/chunks/TextDirectionPlugin-BCeYyJHo.mjs +2 -0
- package/dist/chunks/{TextDirectionPlugin-Bns_03vL.mjs.map → TextDirectionPlugin-BCeYyJHo.mjs.map} +1 -1
- package/dist/chunks/TextDirectionService-OFOU6r_s.mjs +2 -0
- package/dist/chunks/{TextDirectionService-BcX07mw2.mjs.map → TextDirectionService-OFOU6r_s.mjs.map} +1 -1
- package/dist/chunks/TextFormattingPlugin-BhRxSC8q.mjs +2 -0
- package/dist/chunks/{TextFormattingPlugin-DBVlePqj.mjs.map → TextFormattingPlugin-BhRxSC8q.mjs.map} +1 -1
- package/dist/chunks/ThemeEngine-BUVo_zaT.mjs +3 -0
- package/dist/chunks/ThemeEngine-BUVo_zaT.mjs.map +1 -0
- package/dist/chunks/ToolbarPlugin-dmTj1jIz.mjs +2 -0
- package/dist/chunks/{ToolbarPlugin-DtfGTO_V.mjs.map → ToolbarPlugin-dmTj1jIz.mjs.map} +1 -1
- package/dist/chunks/{VideoPlugin-BrR8g6Rz.mjs → VideoPlugin-BugkI7-m.mjs} +2 -2
- package/dist/chunks/{VideoPlugin-BrR8g6Rz.mjs.map → VideoPlugin-BugkI7-m.mjs.map} +1 -1
- package/dist/chunks/XmlSupport-DIXH5on9.mjs +2 -0
- package/dist/chunks/XmlSupport-DIXH5on9.mjs.map +1 -0
- package/dist/chunks/full-JM0-SwWy.mjs +2 -0
- package/dist/chunks/{full-DSWM4cKQ.mjs.map → full-JM0-SwWy.mjs.map} +1 -1
- package/dist/chunks/minimal-DSlR2A27.mjs +2 -0
- package/dist/chunks/{minimal-CFkkPXef.mjs.map → minimal-DSlR2A27.mjs.map} +1 -1
- package/dist/chunks/register-BjsdJ3Aq.mjs +2 -0
- package/dist/chunks/register-BjsdJ3Aq.mjs.map +1 -0
- package/dist/chunks/src-5GKFQ2mQ.mjs +2 -0
- package/dist/chunks/src-5GKFQ2mQ.mjs.map +1 -0
- package/dist/chunks/xml-BsV44TrJ.mjs +2 -0
- package/dist/chunks/xml-BsV44TrJ.mjs.map +1 -0
- package/dist/editor/NotectlEditor.d.ts.map +1 -1
- package/dist/fonts/math.d.ts +3 -0
- package/dist/fonts/math.d.ts.map +1 -0
- package/dist/fonts/math.mjs +1 -0
- package/dist/fonts/starter.d.ts +3 -0
- package/dist/fonts/starter.d.ts.map +1 -0
- package/dist/fonts/starter.mjs +1 -0
- package/dist/fonts.d.ts +4 -4
- package/dist/fonts.mjs +1 -1
- package/dist/full.d.ts +1 -1
- package/dist/full.mjs +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/markdown.mjs +1 -1
- package/dist/notectl-core.mjs +1 -1
- package/dist/notectl-core.umd.js +1 -1
- package/dist/notectl-core.umd.js.map +1 -1
- package/dist/plugins/alignment.mjs +1 -1
- package/dist/plugins/bidi-isolation.mjs +1 -1
- package/dist/plugins/blockquote.mjs +1 -1
- package/dist/plugins/caret-navigation.mjs +1 -1
- package/dist/plugins/code-block/CodeBlockHighlighting.d.ts.map +1 -1
- package/dist/plugins/code-block.mjs +1 -1
- package/dist/plugins/font-size.mjs +1 -1
- package/dist/plugins/font.mjs +1 -1
- package/dist/plugins/formula/FormulaTypes.d.ts +1 -1
- package/dist/plugins/formula.mjs +1 -1
- package/dist/plugins/gap-cursor.mjs +1 -1
- package/dist/plugins/hard-break.mjs +1 -1
- package/dist/plugins/heading.mjs +1 -1
- package/dist/plugins/highlight.mjs +1 -1
- package/dist/plugins/horizontal-rule.mjs +1 -1
- package/dist/plugins/image.mjs +1 -1
- package/dist/plugins/inline-code.mjs +1 -1
- package/dist/plugins/language.mjs +1 -1
- package/dist/plugins/link.mjs +1 -1
- package/dist/plugins/list.mjs +1 -1
- package/dist/plugins/print.mjs +1 -1
- package/dist/plugins/shared.mjs +1 -1
- package/dist/plugins/smart-paste/SmartPastePlugin.d.ts.map +1 -1
- package/dist/plugins/smart-paste.mjs +1 -1
- package/dist/plugins/strikethrough.mjs +1 -1
- package/dist/plugins/super-sub.mjs +1 -1
- package/dist/plugins/table.mjs +1 -1
- package/dist/plugins/text-color.mjs +1 -1
- package/dist/plugins/text-direction-auto.mjs +1 -1
- package/dist/plugins/text-direction.mjs +1 -1
- package/dist/plugins/text-formatting.mjs +1 -1
- package/dist/plugins/toolbar.mjs +1 -1
- package/dist/plugins/video.mjs +1 -1
- package/dist/presets/full.d.ts +1 -1
- package/dist/presets/full.mjs +1 -1
- package/dist/presets/minimal.d.ts +1 -1
- package/dist/presets/minimal.mjs +1 -1
- package/dist/presets.d.ts +1 -1
- package/dist/presets.mjs +1 -1
- package/dist/register.d.ts +3 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.mjs +1 -0
- package/package.json +24 -223
- package/dist/chunks/CaretNavigationPlugin-CNsT0eb4.mjs +0 -2
- package/dist/chunks/CaretNavigationPlugin-CNsT0eb4.mjs.map +0 -1
- package/dist/chunks/CodeBlockPlugin-C1hrdbSZ.mjs +0 -2
- package/dist/chunks/ColorPickerPopup-DiA68Pzz.mjs +0 -2
- package/dist/chunks/Commands-1dFFldi7.mjs +0 -2
- package/dist/chunks/FormulaPlugin-By1befrR.mjs.map +0 -1
- package/dist/chunks/GapCursorNavigation-BuXngVu-.mjs +0 -2
- package/dist/chunks/GapCursorPlugin-DAxVzXRs.mjs +0 -2
- package/dist/chunks/HorizontalRulePlugin-DUVmTQpX.mjs +0 -2
- package/dist/chunks/NodeSelectionCommands-1PjwUDTJ.mjs +0 -2
- package/dist/chunks/PluginHelpers-Dx_0hfDe.mjs +0 -2
- package/dist/chunks/PrintPlugin-7zz9mhhU.mjs +0 -2
- package/dist/chunks/PrintTypes-CxU69qu3.mjs +0 -3
- package/dist/chunks/PrintTypes-CxU69qu3.mjs.map +0 -1
- package/dist/chunks/SimpleMark-7CQcA4RK.mjs +0 -2
- package/dist/chunks/SmartPastePlugin-CYa_nD9v.mjs +0 -2
- package/dist/chunks/SmartPastePlugin-CYa_nD9v.mjs.map +0 -1
- package/dist/chunks/TextDirectionPlugin-Bns_03vL.mjs +0 -2
- package/dist/chunks/TextDirectionService-BcX07mw2.mjs +0 -2
- package/dist/chunks/TextFormattingPlugin-DBVlePqj.mjs +0 -2
- package/dist/chunks/ToolbarPlugin-DtfGTO_V.mjs +0 -2
- package/dist/chunks/XmlDetector-D7TQpw-e.mjs +0 -2
- package/dist/chunks/XmlDetector-D7TQpw-e.mjs.map +0 -1
- package/dist/chunks/XmlSupport-BYiRwlkK.mjs +0 -2
- package/dist/chunks/XmlSupport-BYiRwlkK.mjs.map +0 -1
- package/dist/chunks/fonts-DQC6Uj4r.mjs +0 -2
- package/dist/chunks/fonts-DQC6Uj4r.mjs.map +0 -1
- package/dist/chunks/full-DSWM4cKQ.mjs +0 -2
- package/dist/chunks/minimal-CFkkPXef.mjs +0 -2
- package/dist/chunks/src-DiAOfuOT.mjs +0 -2
- package/dist/chunks/src-DiAOfuOT.mjs.map +0 -1
package/dist/chunks/{MarkdownHTMLRegistry-CKEx7LkR.mjs.map → MarkdownHTMLRegistry-Q7l0d6Ma.mjs.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarkdownHTMLRegistry-CKEx7LkR.mjs","names":[],"sources":["../../src/serialization/markdown/GfmTableParser.ts","../../src/serialization/markdown/MarkdownEntities.ts","../../src/serialization/markdown/BlockTokenizer.ts","../../src/serialization/markdown/MarkdownHTMLRegistry.ts"],"sourcesContent":["/**\n * GFM table detection and row parsing.\n *\n * A table is a header row, a delimiter row (`| --- | :--: |`), and zero or more\n * body rows. Column alignment is derived from the colons in the delimiter row.\n * Cells hold raw inline text, parsed later by the inline tokenizer.\n */\n\n/** Column alignment derived from the delimiter row. */\nexport type ColumnAlign = 'start' | 'center' | 'end' | null;\n\n/** A parsed GFM table (cells are raw inline strings). */\nexport interface TableData {\n\treadonly aligns: readonly ColumnAlign[];\n\treadonly header: readonly string[];\n\treadonly rows: readonly (readonly string[])[];\n\treadonly linesConsumed: number;\n}\n\nconst DELIMITER_ROW = /^\\s*\\|?\\s*:?-+:?\\s*(\\|\\s*:?-+:?\\s*)*\\|?\\s*$/;\n\n/** Splits a table row into trimmed cells, honoring escaped `\\|` and outer pipes. */\nfunction splitRow(line: string): string[] {\n\tlet s: string = line.trim();\n\tif (s.startsWith('|')) s = s.slice(1);\n\tif (s.endsWith('|') && !s.endsWith('\\\\|')) s = s.slice(0, -1);\n\n\tconst cells: string[] = [];\n\tlet current = '';\n\tfor (let i = 0; i < s.length; i++) {\n\t\tconst ch: string = s[i] ?? '';\n\t\tif (ch === '\\\\' && s[i + 1] === '|') {\n\t\t\tcurrent += '|';\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (ch === '|') {\n\t\t\tcells.push(current.trim());\n\t\t\tcurrent = '';\n\t\t\tcontinue;\n\t\t}\n\t\tcurrent += ch;\n\t}\n\tcells.push(current.trim());\n\treturn cells;\n}\n\n/** Reads the alignment of a single delimiter cell (`:--`, `--:`, `:-:`, `--`). */\nfunction cellAlign(cell: string): ColumnAlign {\n\tconst trimmed: string = cell.trim();\n\tconst left: boolean = trimmed.startsWith(':');\n\tconst right: boolean = trimmed.endsWith(':');\n\tif (left && right) return 'center';\n\tif (right) return 'end';\n\tif (left) return 'start';\n\treturn null;\n}\n\n/**\n * Attempts to parse a GFM table beginning at `start`. Returns the table data or\n * null when the two leading lines are not a header + delimiter pair. The body\n * extends until a blank line or the start of another block (`interrupts`); a\n * plain paragraph-like line inside that range is a lazy single-cell row, per\n * the GFM spec (\"the table is broken at the first empty line or beginning of\n * another block-level structural element\").\n */\nexport function matchTable(\n\tlines: readonly string[],\n\tstart: number,\n\tinterrupts?: (line: string) => boolean,\n): TableData | null {\n\tconst headerLine: string = lines[start] ?? '';\n\tconst delimLine: string = lines[start + 1] ?? '';\n\tif (!headerLine.includes('|')) return null;\n\tif (!DELIMITER_ROW.test(delimLine)) return null;\n\n\tconst header: string[] = splitRow(headerLine);\n\tconst aligns: ColumnAlign[] = splitRow(delimLine).map(cellAlign);\n\tif (aligns.length !== header.length) return null;\n\n\tconst rows: string[][] = [];\n\tlet i: number = start + 2;\n\twhile (i < lines.length) {\n\t\tconst line: string = lines[i] ?? '';\n\t\tif (line.trim() === '') break;\n\t\tif (!line.includes('|') && (!interrupts || interrupts(line))) break;\n\t\trows.push(splitRow(line));\n\t\ti++;\n\t}\n\n\treturn { aligns, header, rows, linesConsumed: i - start };\n}\n","/**\n * HTML entity and backslash-escape decoding shared by the Markdown parser.\n *\n * CommonMark recognizes entity and numeric character references (and backslash\n * escapes) not only in inline text but also inside link destinations, link\n * titles, link reference definitions, and code-fence info strings. The small\n * built-in table covers the common names; uncommon names are decoded through\n * the environment's HTML parser when a DOM is available (browser, happy-dom),\n * because embedding the full HTML5 table (~2200 names) would bloat the chunk.\n * Without a DOM (pure Node) unknown entities stay literal, which never loses\n * content.\n */\n\n/** Characters a backslash may escape (CommonMark ASCII punctuation). */\nexport const ESCAPABLE = /[!-/:-@[-`{-~]/;\n\n/** Sticky matcher so callers scan at an index without slicing (linear-time, D1). */\nconst ENTITY_AT = /&(#[xX][0-9a-fA-F]{1,6}|#[0-9]{1,7}|[a-zA-Z][a-zA-Z0-9]{1,31});/y;\n\nconst NAMED_ENTITIES: Readonly<Record<string, string>> = {\n\tamp: '&',\n\tlt: '<',\n\tgt: '>',\n\tquot: '\"',\n\tapos: \"'\",\n\tnbsp: ' ',\n\tcopy: '©',\n\treg: '®',\n\thellip: '…',\n\tmdash: '—',\n\tndash: '–',\n};\n\n/**\n * Decodes a single HTML entity body (without `&`/`;`), or returns it verbatim.\n * Per CommonMark, U+0000 and invalid code points decode to U+FFFD; decoded\n * line separators become plain spaces so a text node never carries a raw\n * newline (block boundaries are structural in the editor model).\n */\nexport function decodeEntity(body: string): string {\n\tif (body[0] === '#') {\n\t\tconst isHex: boolean = body[1] === 'x' || body[1] === 'X';\n\t\tconst code: number = Number.parseInt(body.slice(isHex ? 2 : 1), isHex ? 16 : 10);\n\t\tif (!Number.isFinite(code) || code < 0 || code > 0x10ffff) return `&${body};`;\n\t\tif (code === 0) return '�';\n\t\ttry {\n\t\t\tconst decoded: string = String.fromCodePoint(code);\n\t\t\treturn decoded === '\\n' || decoded === '\\r' ? ' ' : decoded;\n\t\t} catch {\n\t\t\treturn '�';\n\t\t}\n\t}\n\treturn NAMED_ENTITIES[body] ?? decodeNamedEntityViaDom(body) ?? `&${body};`;\n}\n\n/** Matches an entity reference at `pos` in `text`, or null. */\nexport function matchEntityAt(text: string, pos: number): RegExpExecArray | null {\n\tENTITY_AT.lastIndex = pos;\n\treturn ENTITY_AT.exec(text);\n}\n\nconst domEntityCache = new Map<string, string | null>();\n\nfunction decodeNamedEntityViaDom(body: string): string | null {\n\tif (typeof document === 'undefined') return null;\n\tconst cached: string | null | undefined = domEntityCache.get(body);\n\tif (cached !== undefined) return cached;\n\t// `body` is regex-restricted to alphanumerics, so this cannot inject markup.\n\tconst holder: HTMLElement = document.createElement('div');\n\tholder.innerHTML = `&${body};`;\n\tconst text: string = holder.textContent ?? '';\n\tconst decoded: string | null = text !== '' && text !== `&${body};` ? text : null;\n\tdomEntityCache.set(body, decoded);\n\treturn decoded;\n}\n\n/**\n * Decodes backslash escapes and entity references in a single left-to-right\n * pass (an escaped `&` therefore never starts an entity). Used for the string\n * contexts CommonMark decodes outside inline text: link destinations, titles,\n * reference definitions, and fence info strings.\n */\nexport function decodeEscapesAndEntities(text: string): string {\n\tlet out = '';\n\tlet i = 0;\n\twhile (i < text.length) {\n\t\tconst ch: string = text[i] ?? '';\n\t\tif (ch === '\\\\' && ESCAPABLE.test(text[i + 1] ?? '')) {\n\t\t\tout += text[i + 1];\n\t\t\ti += 2;\n\t\t\tcontinue;\n\t\t}\n\t\tif (ch === '&') {\n\t\t\tconst match: RegExpExecArray | null = matchEntityAt(text, i);\n\t\t\tif (match?.[1]) {\n\t\t\t\tout += decodeEntity(match[1]);\n\t\t\t\ti += match[0].length;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tout += ch;\n\t\ti++;\n\t}\n\treturn out;\n}\n\n/** Decodes only entity references (escapes were already consumed by the caller). */\nexport function decodeEntitiesOnly(text: string): string {\n\tlet out = '';\n\tlet i = 0;\n\twhile (i < text.length) {\n\t\tconst ch: string = text[i] ?? '';\n\t\tif (ch === '&') {\n\t\t\tconst match: RegExpExecArray | null = matchEntityAt(text, i);\n\t\t\tif (match?.[1]) {\n\t\t\t\tout += decodeEntity(match[1]);\n\t\t\t\ti += match[0].length;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tout += ch;\n\t\ti++;\n\t}\n\treturn out;\n}\n","/**\n * Block-level Markdown tokenizer.\n *\n * A line scanner that turns Markdown source into a flat (recursive for\n * blockquotes) list of block tokens. The grammar is centralized here, by\n * necessity: CommonMark block structure is global and context-sensitive and\n * cannot be decomposed into per-spec rules (D4). `MarkdownParser` maps these\n * tokens to schema node types by name.\n *\n * List items follow CommonMark content-column semantics (#194): each item owns\n * a content column derived from its marker; subsequent lines indented at least\n * that far are the item's own content region, dedented and tokenized\n * recursively. A region that yields a single paragraph keeps the item a leaf;\n * anything else makes the item a container with block children. Nested list\n * items are hoisted out of the region into flat siblings (the editor's\n * flat-with-indent sibling model, indent = nesting level). Markers indented\n * four or more columns are not markers (indented code / lazy text, per spec).\n * Blockquotes support lazy paragraph continuation, and so do list items.\n */\n\nimport type { MarkdownSyntaxExtension } from '../../model/MarkdownSyntaxRegistry.js';\nimport { type ColumnAlign, type TableData, matchTable } from './GfmTableParser.js';\nimport { decodeEscapesAndEntities } from './MarkdownEntities.js';\n\n/** A parsed block-level token. Inline text is left raw for the inline parser. */\nexport type BlockToken =\n\t| { readonly type: 'heading'; readonly level: number; readonly text: string }\n\t| { readonly type: 'paragraph'; readonly text: string }\n\t| { readonly type: 'code_block'; readonly language: string; readonly code: string }\n\t| { readonly type: 'hr' }\n\t| { readonly type: 'blockquote'; readonly children: readonly BlockToken[] }\n\t| {\n\t\t\treadonly type: 'list_item';\n\t\t\treadonly listType: 'bullet' | 'ordered' | 'checklist';\n\t\t\treadonly indent: number;\n\t\t\treadonly checked: boolean;\n\t\t\t/** Inline text of a leaf item; empty when `children` is present. */\n\t\t\treadonly text: string;\n\t\t\t/** Block children of a multi-block (container) item, absent for leaves. */\n\t\t\treadonly children?: readonly BlockToken[];\n\t }\n\t| { readonly type: 'html'; readonly html: string }\n\t| {\n\t\t\treadonly type: 'table';\n\t\t\treadonly aligns: readonly ColumnAlign[];\n\t\t\treadonly header: readonly string[];\n\t\t\treadonly rows: readonly (readonly string[])[];\n\t }\n\t| {\n\t\t\treadonly type: 'extension_block';\n\t\t\treadonly nodeType: string;\n\t\t\treadonly attrs: Record<string, string | number | boolean>;\n\t };\n\n/** Block-level HTML tags that begin an HTML block; inline tags fall through to paragraphs. */\nconst BLOCK_HTML_TAGS: ReadonlySet<string> = new Set([\n\t'address',\n\t'article',\n\t'aside',\n\t'blockquote',\n\t'details',\n\t'div',\n\t'dl',\n\t'dd',\n\t'dt',\n\t'figure',\n\t'figcaption',\n\t'footer',\n\t'form',\n\t'h1',\n\t'h2',\n\t'h3',\n\t'h4',\n\t'h5',\n\t'h6',\n\t'header',\n\t'hr',\n\t'iframe',\n\t'main',\n\t'nav',\n\t'ol',\n\t'p',\n\t'pre',\n\t'section',\n\t'table',\n\t'tbody',\n\t'td',\n\t'tfoot',\n\t'th',\n\t'thead',\n\t'tr',\n\t'ul',\n\t'video',\n]);\n\n// Exported so the parser's link-reference pre-pass can reuse the exact grammar\n// when deciding block boundaries (single source of truth for the syntax).\nexport const ATX_HEADING = /^ {0,3}(#{1,6})(?:[ \\t]+(.*?))?(?:[ \\t]+#+)?[ \\t]*$/;\nexport const FENCE_OPEN = /^ {0,3}(`{3,}|~{3,})[ \\t]*(.*)$/;\nexport const THEMATIC_BREAK = /^ {0,3}([-*_])[ \\t]*(?:\\1[ \\t]*){2,}$/;\nconst BLOCKQUOTE = /^ {0,3}>[ ]?/;\nconst BULLET_ITEM = /^([ \\t]*)([-*+])(?:([ \\t]+)(.*))?$/;\nconst ORDERED_ITEM = /^([ \\t]*)(\\d{1,9})([.)])(?:([ \\t]+)(.*))?$/;\nconst TASK_PREFIX = /^\\[([ xX])\\][ \\t]+(.*)$/;\n// Exported alongside the other grammar patterns so the serializer's line-start\n// escaping re-parses paragraph lines with the exact same rules (single source of\n// truth: a line the tokenizer would read as a setext underline gets escaped).\nexport const SETEXT_H1 = /^ {0,3}=+[ \\t]*$/;\nexport const SETEXT_H2 = /^ {0,3}-+[ \\t]*$/;\nconst HTML_BLOCK_START = /^ {0,3}<(\\/?)([a-zA-Z][a-zA-Z0-9-]*)|^ {0,3}<!--/;\n\n/** Leading-whitespace columns that open an indented code block (CommonMark). */\nconst INDENTED_CODE_COLUMNS = 4;\n\n/** Maximum leading columns of a list marker; deeper markers are code/lazy text. */\nconst MAX_MARKER_INDENT_COLUMNS = 3;\n\n/**\n * Maximum container nesting (blockquotes, list-item regions) before the\n * construct is treated as literal text. Each level recurses\n * (`tokenizeLines` → container consumer → `tokenizeLines`), so an adversarial\n * paste of thousands of `>`/`-` prefixes would overflow the stack. The cap\n * keeps recursion bounded; deeper content degrades to a paragraph (no data\n * loss, the marker characters are preserved). Real documents never nest this\n * deep.\n */\nconst MAX_CONTAINER_DEPTH = 32;\n\nfunction isBlank(line: string): boolean {\n\treturn line.trim() === '';\n}\n\n/**\n * Matches a fence opener. A backtick fence whose info string contains a\n * backtick is not a fence per CommonMark (it reads as an inline code span).\n */\nexport function matchFenceOpen(line: string): RegExpMatchArray | null {\n\tconst match: RegExpMatchArray | null = line.match(FENCE_OPEN);\n\tif (!match) return null;\n\tif ((match[1] ?? '')[0] === '`' && (match[2] ?? '').includes('`')) return null;\n\treturn match;\n}\n\n/** Tokenizes a full Markdown source string into block tokens. */\nexport function tokenizeBlocks(\n\tsource: string,\n\tgfm = true,\n\textensions: readonly MarkdownSyntaxExtension[] = [],\n): BlockToken[] {\n\t// A single trailing newline closes the last line; it is not an extra line\n\t// (otherwise an unclosed fence at EOF would gain a phantom blank line).\n\tconst normalized: string = source.replace(/\\r\\n?/g, '\\n').replace(/\\n$/, '');\n\treturn tokenizeLines(normalized.split('\\n'), gfm, extensions);\n}\n\nfunction tokenizeLines(\n\tlines: readonly string[],\n\tgfm: boolean,\n\textensions: readonly MarkdownSyntaxExtension[],\n\tdepth = 0,\n): BlockToken[] {\n\tconst tokens: BlockToken[] = [];\n\tlet i = 0;\n\n\twhile (i < lines.length) {\n\t\tconst line: string = lines[i] ?? '';\n\n\t\tif (isBlank(line)) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst extension: number = tryExtensionBlock(extensions, lines, i, tokens);\n\t\tif (extension > 0) {\n\t\t\ti += extension;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (gfm) {\n\t\t\tconst table: TableData | null = matchTable(lines, i, interruptsParagraph);\n\t\t\tif (table) {\n\t\t\t\ttokens.push({\n\t\t\t\t\ttype: 'table',\n\t\t\t\t\taligns: table.aligns,\n\t\t\t\t\theader: table.header,\n\t\t\t\t\trows: table.rows,\n\t\t\t\t});\n\t\t\t\ti += table.linesConsumed;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tconst fence: RegExpMatchArray | null = matchFenceOpen(line);\n\t\tif (fence) {\n\t\t\ti = consumeFencedCode(lines, i, fence, tokens);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst atx: RegExpMatchArray | null = line.match(ATX_HEADING);\n\t\tif (atx) {\n\t\t\tconst rawText: string = (atx[2] ?? '').trim();\n\t\t\t// Content that is only `#`s is a closing sequence, not text (`### ###`).\n\t\t\tconst text: string = /^#+$/.test(rawText) ? '' : rawText;\n\t\t\ttokens.push({ type: 'heading', level: (atx[1] ?? '#').length, text });\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (THEMATIC_BREAK.test(line)) {\n\t\t\ttokens.push({ type: 'hr' });\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (BLOCKQUOTE.test(line)) {\n\t\t\t// Depth guard: past the cap, stop recursing and keep the `>` lines as\n\t\t\t// literal paragraph text rather than overflowing the stack.\n\t\t\tif (depth >= MAX_CONTAINER_DEPTH) {\n\t\t\t\ti = consumeParagraph(lines, i, tokens);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\ti = consumeBlockquote(lines, i, tokens, gfm, extensions, depth);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst marker: ListMarker | null = depth < MAX_CONTAINER_DEPTH ? matchListMarker(line) : null;\n\t\tif (marker) {\n\t\t\ti = consumeListItem(lines, i, marker, tokens, gfm, extensions, depth);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (canStartIndentedCode(line)) {\n\t\t\ti = consumeIndentedCode(lines, i, tokens);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (isHtmlBlockStart(line)) {\n\t\t\ti = consumeHtmlBlock(lines, i, tokens);\n\t\t\tcontinue;\n\t\t}\n\n\t\ti = consumeParagraph(lines, i, tokens);\n\t}\n\n\treturn tokens;\n}\n\n/** Consumes a fenced code block; returns the next line index. */\nfunction consumeFencedCode(\n\tlines: readonly string[],\n\tstart: number,\n\tfence: RegExpMatchArray,\n\ttokens: BlockToken[],\n): number {\n\tconst fenceStr: string = fence[1] ?? '```';\n\tconst fenceChar: string = fenceStr[0] ?? '`';\n\tconst language: string = decodeEscapesAndEntities((fence[2] ?? '').trim().split(/\\s+/)[0] ?? '');\n\tconst closeRe = new RegExp(`^ {0,3}${`\\\\${fenceChar}`}{${fenceStr.length},}[ \\\\t]*$`);\n\t// An indented opening fence strips up to that indentation from each body line.\n\tconst openLine: string = lines[start] ?? '';\n\tconst openIndent: number = openLine.length - openLine.trimStart().length;\n\n\tconst body: string[] = [];\n\tlet i: number = start + 1;\n\twhile (i < lines.length) {\n\t\tconst line: string = lines[i] ?? '';\n\t\tif (closeRe.test(line)) {\n\t\t\ti++;\n\t\t\tbreak;\n\t\t}\n\t\tbody.push(stripLeadingSpaces(line, openIndent));\n\t\ti++;\n\t}\n\ttokens.push({ type: 'code_block', language, code: body.join('\\n') });\n\treturn i;\n}\n\n/** Removes up to `max` leading spaces from a line. */\nfunction stripLeadingSpaces(line: string, max: number): string {\n\tlet i = 0;\n\twhile (i < max && line[i] === ' ') i++;\n\treturn line.slice(i);\n}\n\n/**\n * Whether a line opens an indented code block (#195): at least four columns of\n * leading whitespace (tab-aware). Indented content that belongs to an open\n * list item never reaches this check — it is consumed into the item's content\n * region first (#194).\n */\nfunction canStartIndentedCode(line: string): boolean {\n\treturn indentColumns(line) >= INDENTED_CODE_COLUMNS;\n}\n\n/** Columns of leading whitespace, with tabs advancing to 4-column tab stops. */\nfunction indentColumns(line: string): number {\n\tlet col = 0;\n\tfor (const ch of line) {\n\t\tif (ch === ' ') col++;\n\t\telse if (ch === '\\t') col += 4 - (col % 4);\n\t\telse break;\n\t}\n\treturn col;\n}\n\n/**\n * Strips `columns` columns of leading whitespace (tab-aware). The remaining\n * leading whitespace is re-emitted as spaces measured in absolute columns:\n * tab stops depend on the column a tab starts in, so dedented lines must not\n * carry raw tabs whose width would be recomputed in the wrong context.\n */\nfunction stripIndent(line: string, columns: number): string {\n\tlet col = 0;\n\tlet i = 0;\n\twhile (i < line.length) {\n\t\tconst ch: string = line[i] ?? '';\n\t\tif (ch === ' ') col++;\n\t\telse if (ch === '\\t') col += 4 - (col % 4);\n\t\telse break;\n\t\ti++;\n\t}\n\treturn ' '.repeat(Math.max(0, col - columns)) + line.slice(i);\n}\n\n/**\n * Strips `columns` columns of leading whitespace from a code line, preserving\n * literal tabs beyond the strip boundary. Indented-code content is literal, so\n * tabs are significant (Makefiles, Go) and must survive verbatim — unlike\n * {@link stripIndent}, which normalizes re-tokenized structural whitespace to\n * spaces. Only a tab straddling the strip boundary contributes spaces (the part\n * of its width past `columns`); tabs fully past the boundary are kept as-is.\n */\nfunction stripCodeIndent(line: string, columns: number): string {\n\tlet col = 0;\n\tlet i = 0;\n\twhile (i < line.length && col < columns) {\n\t\tconst ch: string = line[i] ?? '';\n\t\tif (ch === ' ') {\n\t\t\tcol++;\n\t\t\ti++;\n\t\t} else if (ch === '\\t') {\n\t\t\tconst next: number = col + 4 - (col % 4);\n\t\t\tif (next > columns) {\n\t\t\t\t// Straddling tab: emit only its overflow past the boundary as spaces\n\t\t\t\t// and keep the remainder of the line (including later tabs) verbatim.\n\t\t\t\treturn ' '.repeat(next - columns) + line.slice(i + 1);\n\t\t\t}\n\t\t\tcol = next;\n\t\t\ti++;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn line.slice(i);\n}\n\n/**\n * Consumes an indented code block: all subsequent lines indented by at least\n * four columns, keeping interior blank lines but not trailing ones (they\n * separate the block from what follows). Returns the next line index.\n */\nfunction consumeIndentedCode(\n\tlines: readonly string[],\n\tstart: number,\n\ttokens: BlockToken[],\n): number {\n\tconst body: string[] = [];\n\tconst pendingBlanks: string[] = [];\n\tlet i: number = start;\n\twhile (i < lines.length) {\n\t\tconst line: string = lines[i] ?? '';\n\t\tif (isBlank(line)) {\n\t\t\t// Interior blank lines keep their content beyond the stripped columns.\n\t\t\tpendingBlanks.push(stripCodeIndent(line, INDENTED_CODE_COLUMNS));\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (indentColumns(line) < INDENTED_CODE_COLUMNS) break;\n\t\twhile (pendingBlanks.length > 0) body.push(pendingBlanks.shift() ?? '');\n\t\tbody.push(stripCodeIndent(line, INDENTED_CODE_COLUMNS));\n\t\ti++;\n\t}\n\ttokens.push({ type: 'code_block', language: '', code: body.join('\\n') });\n\treturn i - pendingBlanks.length;\n}\n\n/** Tries each extension's `matchBlock`; pushes a token and returns lines consumed (0 = no match). */\nfunction tryExtensionBlock(\n\textensions: readonly MarkdownSyntaxExtension[],\n\tlines: readonly string[],\n\tlineIndex: number,\n\ttokens: BlockToken[],\n): number {\n\tfor (const ext of extensions) {\n\t\tconst match = ext.matchBlock?.(lines, lineIndex);\n\t\tif (match && match.linesConsumed > 0) {\n\t\t\ttokens.push({ type: 'extension_block', nodeType: match.type, attrs: match.attrs });\n\t\t\treturn match.linesConsumed;\n\t\t}\n\t}\n\treturn 0;\n}\n\n/**\n * Consumes consecutive `>`-prefixed lines (plus lazy paragraph continuation\n * lines, per CommonMark) and recurses into their content. A plain line\n * continues the quote only while the innermost open block is a paragraph.\n */\nfunction consumeBlockquote(\n\tlines: readonly string[],\n\tstart: number,\n\ttokens: BlockToken[],\n\tgfm: boolean,\n\textensions: readonly MarkdownSyntaxExtension[],\n\tdepth: number,\n): number {\n\tconst inner: string[] = [];\n\tlet i: number = start;\n\tlet lazyOk = false;\n\twhile (i < lines.length) {\n\t\tconst line: string = lines[i] ?? '';\n\t\tif (BLOCKQUOTE.test(line)) {\n\t\t\tconst stripped: string = line.replace(BLOCKQUOTE, '');\n\t\t\tinner.push(stripped);\n\t\t\tlazyOk = continuesAsParagraph(stripped);\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (\n\t\t\tlazyOk &&\n\t\t\t!isBlank(line) &&\n\t\t\t!interruptsParagraph(line) &&\n\t\t\t!(gfm && matchTable(lines, i, interruptsParagraph))\n\t\t) {\n\t\t\tinner.push(line);\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\tbreak;\n\t}\n\ttokens.push({ type: 'blockquote', children: tokenizeLines(inner, gfm, extensions, depth + 1) });\n\treturn i;\n}\n\n/**\n * Whether a stripped container line leaves a paragraph open at its innermost\n * level: quote prefixes and list markers are peeled off (`> 1. > text` opens a\n * paragraph two containers deep, which a lazy line may continue).\n */\nfunction continuesAsParagraph(stripped: string): boolean {\n\tlet content: string = stripped;\n\tfor (;;) {\n\t\tif (BLOCKQUOTE.test(content)) {\n\t\t\tcontent = content.replace(BLOCKQUOTE, '');\n\t\t\tcontinue;\n\t\t}\n\t\tconst marker: ListMarker | null = matchListMarker(content);\n\t\tif (marker && marker.firstText !== '') {\n\t\t\tcontent = marker.firstText;\n\t\t\tcontinue;\n\t\t}\n\t\tbreak;\n\t}\n\tif (content.trim() === '' || interruptsParagraph(content)) return false;\n\t// An indented-code line is not a paragraph, so nothing can lazily continue it.\n\treturn indentColumns(content) < INDENTED_CODE_COLUMNS;\n}\n\n/** Geometry and metadata of a single list-marker line. */\ninterface ListMarker {\n\treadonly listType: 'bullet' | 'ordered' | 'checklist';\n\treadonly checked: boolean;\n\t/** Column where the item's content begins; region lines must reach it. */\n\treadonly contentColumn: number;\n\t/** The marker line's own content (task prefix stripped), '' for empty items. */\n\treadonly firstText: string;\n\t/** The ordered start number (1 for bullets). */\n\treadonly startNumber: number;\n}\n\n/** Columns spanned by a whitespace run starting at an absolute column. */\nfunction columnsFrom(start: number, whitespace: string): number {\n\tlet col: number = start;\n\tfor (const ch of whitespace) {\n\t\tif (ch === ' ') col++;\n\t\telse if (ch === '\\t') col += 4 - (col % 4);\n\t\telse break;\n\t}\n\treturn col - start;\n}\n\n/**\n * Parses a list-marker line into its content-column geometry, or null when the\n * line is not a valid marker: markers indented four or more columns are\n * indented code or lazy text, never list items (CommonMark).\n */\nfunction matchListMarker(line: string): ListMarker | null {\n\tconst bullet: RegExpMatchArray | null = line.match(BULLET_ITEM);\n\tconst ordered: RegExpMatchArray | null = bullet ? null : line.match(ORDERED_ITEM);\n\tconst match: RegExpMatchArray | null = bullet ?? ordered;\n\tif (!match) return null;\n\n\tconst leadingColumns: number = indentColumns(match[1] ?? '');\n\tif (leadingColumns > MAX_MARKER_INDENT_COLUMNS) return null;\n\n\tconst markerText: string = (bullet ? match[2] : `${match[2]}${match[3]}`) ?? '-';\n\tconst markerEnd: number = leadingColumns + markerText.length;\n\tconst spacing: string = (bullet ? match[3] : match[4]) ?? '';\n\tconst spacingColumns: number = columnsFrom(markerEnd, spacing);\n\tconst rawContent: string = (bullet ? match[4] : match[5]) ?? '';\n\tconst startNumber: number = ordered ? Number.parseInt(match[2] ?? '1', 10) : 1;\n\n\tlet contentColumn: number;\n\tlet firstText: string;\n\tif (rawContent.trim() === '') {\n\t\tcontentColumn = markerEnd + 1;\n\t\tfirstText = '';\n\t} else if (spacingColumns >= 5) {\n\t\t// Content five or more columns past the marker starts as indented code;\n\t\t// the content column sits one past the marker (CommonMark).\n\t\tcontentColumn = markerEnd + 1;\n\t\tfirstText = ' '.repeat(spacingColumns - 1) + rawContent;\n\t} else {\n\t\tcontentColumn = markerEnd + spacingColumns;\n\t\tfirstText = rawContent;\n\t}\n\n\tconst task: RegExpMatchArray | null = firstText.match(TASK_PREFIX);\n\tif (task) {\n\t\treturn {\n\t\t\tlistType: 'checklist',\n\t\t\tchecked: (task[1] ?? ' ').toLowerCase() === 'x',\n\t\t\tcontentColumn,\n\t\t\tfirstText: task[2] ?? '',\n\t\t\tstartNumber,\n\t\t};\n\t}\n\treturn {\n\t\tlistType: ordered ? 'ordered' : 'bullet',\n\t\tchecked: false,\n\t\tcontentColumn,\n\t\tfirstText,\n\t\tstartNumber,\n\t};\n}\n\n/**\n * Consumes one list item: the marker line plus its content region — every\n * following line indented to the content column (dedented), interior blank\n * lines, and lazy paragraph continuation lines. The collected content is\n * tokenized recursively; nested list items are hoisted into flat siblings.\n * Returns the next line index.\n */\nfunction consumeListItem(\n\tlines: readonly string[],\n\tstart: number,\n\tmarker: ListMarker,\n\ttokens: BlockToken[],\n\tgfm: boolean,\n\textensions: readonly MarkdownSyntaxExtension[],\n\tdepth: number,\n): number {\n\tconst region: string[] = [];\n\tconst tracker: (line: string, paragraphOpen: boolean) => boolean = createParagraphTracker();\n\tlet firstText: string = marker.firstText;\n\tlet paragraphOpen: boolean = firstText === '' ? false : tracker(firstText, false);\n\tlet pendingBlanks = 0;\n\tlet i: number = start + 1;\n\n\twhile (i < lines.length) {\n\t\tconst line: string = lines[i] ?? '';\n\n\t\tif (isBlank(line)) {\n\t\t\t// An item may begin with at most one blank line: a marker with no\n\t\t\t// content followed by a blank line stays an empty item (CommonMark).\n\t\t\tif (firstText === '' && region.length === 0) break;\n\t\t\tpendingBlanks++;\n\t\t\tparagraphOpen = false;\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (indentColumns(line) >= marker.contentColumn) {\n\t\t\twhile (pendingBlanks > 0) {\n\t\t\t\tregion.push('');\n\t\t\t\tpendingBlanks--;\n\t\t\t}\n\t\t\tconst dedented: string = stripIndent(line, marker.contentColumn);\n\t\t\tregion.push(dedented);\n\t\t\tparagraphOpen = tracker(dedented, paragraphOpen);\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Under-indented: only a lazy paragraph continuation keeps the item open.\n\t\t// Any valid marker line is a sibling item, never lazy text (the\n\t\t// ordered-must-start-at-1 interrupt rule applies to paragraphs only).\n\t\tif (matchListMarker(line)) break;\n\t\tif (!paragraphOpen) break;\n\t\tif (interruptsParagraph(line)) break;\n\t\tif (gfm && matchTable(lines, i, interruptsParagraph)) break;\n\t\t// A lazy line belongs textually to the open paragraph: fold it into the\n\t\t// previous logical line so it can never re-parse as a block start in the\n\t\t// item's sub-document (`- d\\n - e` keeps \"- e\" as paragraph text).\n\t\tconst lazy: string = line.trimStart();\n\t\tconst lastRegionLine: string | undefined = region[region.length - 1];\n\t\tif (lastRegionLine !== undefined) {\n\t\t\tregion[region.length - 1] = `${lastRegionLine}\\n${lazy}`;\n\t\t} else {\n\t\t\tfirstText = firstText === '' ? lazy : `${firstText}\\n${lazy}`;\n\t\t}\n\t\tparagraphOpen = tracker(lazy, paragraphOpen);\n\t\ti++;\n\t}\n\n\tappendListItemTokens(marker, firstText, region, tokens, gfm, extensions, depth);\n\treturn i;\n}\n\n/**\n * Tracks whether the innermost open block of an item's content region is a\n * paragraph — the precondition for lazy continuation. Fenced code suspends\n * laziness until the fence closes; block starters close the paragraph. The\n * caller passes whether a paragraph is currently open, because an indented line\n * cannot start an indented code block while a paragraph is open (CommonMark): it\n * continues that paragraph instead, and only opens a code block from a closed\n * state.\n */\nfunction createParagraphTracker(): (line: string, paragraphOpen: boolean) => boolean {\n\tlet closeRe: RegExp | null = null;\n\treturn (line: string, paragraphOpen: boolean): boolean => {\n\t\tif (closeRe) {\n\t\t\tif (closeRe.test(line)) closeRe = null;\n\t\t\treturn false;\n\t\t}\n\t\tconst fence: RegExpMatchArray | null = matchFenceOpen(line);\n\t\tif (fence) {\n\t\t\tconst fenceStr: string = fence[1] ?? '```';\n\t\t\tconst fenceChar: string = fenceStr[0] ?? '`';\n\t\t\tcloseRe = new RegExp(`^ {0,3}${`\\\\${fenceChar}`}{${fenceStr.length},}[ \\\\t]*$`);\n\t\t\treturn false;\n\t\t}\n\t\tif (isBlank(line)) return false;\n\t\tif (BLOCKQUOTE.test(line) || matchListMarker(line)) return continuesAsParagraph(line);\n\t\t// Indented code cannot interrupt an open paragraph: an indented line keeps\n\t\t// the paragraph open, and only opens a code block when none is open.\n\t\tif (indentColumns(line) >= INDENTED_CODE_COLUMNS) return paragraphOpen;\n\t\treturn !interruptsParagraph(line);\n\t};\n}\n\n/**\n * Builds the item token(s) from the marker line and its dedented content\n * region: the content is tokenized recursively; a single-paragraph result\n * keeps the item a leaf, anything else becomes a container with block\n * children. Nested list items are hoisted out into flat siblings one indent\n * deeper (the editor's flat-with-indent sibling model).\n */\nfunction appendListItemTokens(\n\tmarker: ListMarker,\n\tfirstText: string,\n\tregion: readonly string[],\n\ttokens: BlockToken[],\n\tgfm: boolean,\n\textensions: readonly MarkdownSyntaxExtension[],\n\tdepth: number,\n): void {\n\tconst subLines: string[] = firstText === '' ? [...region] : [firstText, ...region];\n\tconst subTokens: BlockToken[] =\n\t\tsubLines.length === 0 ? [] : tokenizeLines(subLines, gfm, extensions, depth + 1);\n\n\tconst lifted: BlockToken[] = [];\n\tconst own: BlockToken[] = [];\n\tfor (const token of subTokens) {\n\t\tif (token.type === 'list_item') {\n\t\t\tlifted.push({ ...token, indent: token.indent + 1 });\n\t\t} else {\n\t\t\town.push(token);\n\t\t}\n\t}\n\n\tconst first: BlockToken | undefined = own[0];\n\tif (own.length === 1 && first?.type === 'paragraph') {\n\t\ttokens.push(makeListItemToken(marker, first.text));\n\t} else if (own.length === 0) {\n\t\ttokens.push(makeListItemToken(marker, ''));\n\t} else {\n\t\ttokens.push(makeListItemToken(marker, '', own));\n\t}\n\ttokens.push(...lifted);\n}\n\n/** Builds a `list_item` token at indent 0 of the current tokenization level. */\nfunction makeListItemToken(\n\tmarker: ListMarker,\n\ttext: string,\n\tchildren?: readonly BlockToken[],\n): BlockToken {\n\tconst base = {\n\t\ttype: 'list_item' as const,\n\t\tlistType: marker.listType,\n\t\tindent: 0,\n\t\tchecked: marker.checked,\n\t\ttext,\n\t};\n\treturn children ? { ...base, children } : base;\n}\n\n/**\n * Whether a list-item line may interrupt an open paragraph: CommonMark forbids\n * empty items and ordered items not starting at 1 from doing so (`14.` in prose\n * must not begin a list).\n */\nfunction listItemInterrupts(line: string): boolean {\n\tconst marker: ListMarker | null = matchListMarker(line);\n\tif (!marker) return false;\n\tif (marker.firstText.trim() === '') return false;\n\tif (marker.listType === 'ordered') return marker.startNumber === 1;\n\treturn true;\n}\n\n/** Whether a line begins a block-level HTML element (inline tags fall through). */\nfunction isHtmlBlockStart(line: string): boolean {\n\tconst match: RegExpMatchArray | null = line.match(HTML_BLOCK_START);\n\tif (!match) return false;\n\tif (line.trimStart().startsWith('<!--')) return true;\n\tconst tag: string = (match[2] ?? '').toLowerCase();\n\treturn BLOCK_HTML_TAGS.has(tag);\n}\n\n/** Consumes an HTML block up to the next blank line. */\nfunction consumeHtmlBlock(lines: readonly string[], start: number, tokens: BlockToken[]): number {\n\tconst html: string[] = [];\n\tlet i: number = start;\n\twhile (i < lines.length) {\n\t\tconst line: string = lines[i] ?? '';\n\t\tif (isBlank(line)) break;\n\t\thtml.push(line);\n\t\ti++;\n\t}\n\ttokens.push({ type: 'html', html: html.join('\\n') });\n\treturn i;\n}\n\n/** Whether a line would interrupt an open paragraph (begins another block). */\nfunction interruptsParagraph(line: string): boolean {\n\tif (isBlank(line)) return true;\n\tif (ATX_HEADING.test(line)) return true;\n\tif (matchFenceOpen(line)) return true;\n\tif (THEMATIC_BREAK.test(line)) return true;\n\tif (BLOCKQUOTE.test(line)) return true;\n\tif (listItemInterrupts(line)) return true;\n\tif (isHtmlBlockStart(line)) return true;\n\treturn false;\n}\n\n/** Consumes a paragraph (with lazy continuation) or a setext heading. */\nfunction consumeParagraph(lines: readonly string[], start: number, tokens: BlockToken[]): number {\n\tconst collected: string[] = [lines[start] ?? ''];\n\tlet i: number = start + 1;\n\n\twhile (i < lines.length) {\n\t\tconst line: string = lines[i] ?? '';\n\n\t\t// A setext underline turns the collected paragraph into a heading.\n\t\tif (SETEXT_H1.test(line)) {\n\t\t\ttokens.push({ type: 'heading', level: 1, text: joinParagraph(collected) });\n\t\t\treturn i + 1;\n\t\t}\n\t\t// A `-` underline outranks a thematic break when a paragraph sits above it.\n\t\tif (SETEXT_H2.test(line)) {\n\t\t\ttokens.push({ type: 'heading', level: 2, text: joinParagraph(collected) });\n\t\t\treturn i + 1;\n\t\t}\n\n\t\tif (interruptsParagraph(line)) break;\n\t\tcollected.push(line);\n\t\ti++;\n\t}\n\n\ttokens.push({ type: 'paragraph', text: joinParagraphText(collected) });\n\treturn i;\n}\n\n/**\n * Joins collected paragraph lines for inline parsing. Leading indentation is\n * insignificant and stripped, but trailing spaces on interior lines are kept:\n * two or more of them encode a hard break, which the inline parser consumes\n * (#193). The final line's trailing whitespace carries no meaning and is\n * dropped.\n */\nfunction joinParagraphText(lines: readonly string[]): string {\n\treturn lines\n\t\t.map((line, index) => (index === lines.length - 1 ? line.trim() : line.trimStart()))\n\t\t.join('\\n');\n}\n\n/** Joins multi-line paragraph text into a single-line heading string. */\nfunction joinParagraph(lines: readonly string[]): string {\n\treturn lines\n\t\t.map((l) => l.trim())\n\t\t.join(' ')\n\t\t.trim();\n}\n","/**\n * Minimal HTML-only schema for Markdown's raw-HTML seam.\n *\n * Registry-free Markdown calls still need the portable structures owned by the\n * codec when a block must become raw HTML (for example to retain an `htmlId`).\n * An explicitly supplied registry is returned unchanged and remains the sole\n * authority. No plugin or view module is imported here.\n */\n\nimport { escapeAttr, sanitizeHref } from '../../model/HTMLUtils.js';\nimport type { HTMLExportContext } from '../../model/NodeSpec.js';\nimport { SchemaRegistry } from '../../model/SchemaRegistry.js';\nimport {\n\tTABLE_COLUMN_WIDTH_DATA_ATTRIBUTE,\n\tTABLE_ROW_MIN_HEIGHT_DATA_ATTRIBUTE,\n\tnormalizeTableColumnWidthsPx,\n\tserializeTableDimensionAttrs,\n} from '../TableDimensions.js';\n\nlet baselineRegistry: SchemaRegistry | undefined;\n\n/** Resolves the schema at an HTML boundary without supplementing an explicit schema. */\nexport function resolveMarkdownHTMLRegistry(registry?: SchemaRegistry): SchemaRegistry {\n\tif (registry) return registry;\n\tbaselineRegistry ??= createBaselineRegistry();\n\treturn baselineRegistry;\n}\n\nfunction htmlOnlyDOM(): HTMLElement {\n\tthrow new Error('The Markdown HTML registry cannot render editor DOM.');\n}\n\nfunction createBaselineRegistry(): SchemaRegistry {\n\tconst registry = new SchemaRegistry();\n\tregisterBlocks(registry);\n\tregisterMarks(registry);\n\tregisterInlineNodes(registry);\n\treturn registry;\n}\n\nfunction registerBlocks(registry: SchemaRegistry): void {\n\tregistry.registerNodeSpec({\n\t\ttype: 'paragraph',\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTML: (_node, content) => `<p>${content || '<br>'}</p>`,\n\t\tparseHTML: [{ tag: 'p' }, { tag: 'div', priority: 10 }],\n\t\tsanitize: { tags: ['p'] },\n\t});\n\n\tregistry.registerNodeSpec({\n\t\ttype: 'heading',\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTML(node, content) {\n\t\t\tconst raw: unknown = node.attrs?.level;\n\t\t\tconst level: number =\n\t\t\t\ttypeof raw === 'number' && Number.isFinite(raw)\n\t\t\t\t\t? Math.max(1, Math.min(6, Math.floor(raw)))\n\t\t\t\t\t: 1;\n\t\t\treturn `<h${level}>${content || '<br>'}</h${level}>`;\n\t\t},\n\t\tparseHTML: [1, 2, 3, 4, 5, 6].map((level) => ({\n\t\t\ttag: `h${level}`,\n\t\t\tgetAttrs: () => ({ level }),\n\t\t})),\n\t\tsanitize: { tags: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] },\n\t});\n\n\tregistry.registerNodeSpec({\n\t\ttype: 'list_item',\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTML(node, content) {\n\t\t\tif (node.attrs?.listType !== 'checklist') return `<li>${content || '<br>'}</li>`;\n\t\t\tconst checked: boolean = node.attrs.checked === true;\n\t\t\treturn (\n\t\t\t\t`<li role=\"checkbox\" aria-checked=\"${String(checked)}\">` +\n\t\t\t\t`<input type=\"checkbox\" disabled${checked ? ' checked' : ''}>` +\n\t\t\t\t`${content || '<br>'}</li>`\n\t\t\t);\n\t\t},\n\t\tparseHTML: [{ tag: 'li' }],\n\t\tsanitize: {\n\t\t\ttags: ['ul', 'ol', 'li', 'input'],\n\t\t\tattrs: ['type', 'disabled', 'checked', 'role', 'aria-checked'],\n\t\t},\n\t});\n\n\tregistry.registerNodeSpec({\n\t\ttype: 'blockquote',\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTML: (_node, content) => `<blockquote>${content || '<br>'}</blockquote>`,\n\t\tparseHTML: [{ tag: 'blockquote' }],\n\t\tsanitize: { tags: ['blockquote'] },\n\t});\n\n\tregistry.registerNodeSpec({\n\t\ttype: 'code_block',\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTML(node, content) {\n\t\t\tconst language: string = String(node.attrs?.language ?? '');\n\t\t\tconst languageClass: string = language ? ` class=\"language-${escapeAttr(language)}\"` : '';\n\t\t\treturn `<pre><code${languageClass}>${content}</code></pre>`;\n\t\t},\n\t\tparseHTML: [\n\t\t\t{\n\t\t\t\ttag: 'pre',\n\t\t\t\tgetAttrs(el) {\n\t\t\t\t\tconst code: HTMLElement | null = el.querySelector('code');\n\t\t\t\t\tconst language: string = code?.className.match(/(?:^|\\s)language-(\\S+)/)?.[1] ?? '';\n\t\t\t\t\treturn { language };\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\tsanitize: { tags: ['pre', 'code'], attrs: ['class'] },\n\t});\n\n\tregistry.registerNodeSpec({\n\t\ttype: 'horizontal_rule',\n\t\tisVoid: true,\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTML: () => '<hr>',\n\t\tparseHTML: [{ tag: 'hr' }],\n\t\tsanitize: { tags: ['hr'] },\n\t});\n\n\tregistry.registerNodeSpec({\n\t\ttype: 'image',\n\t\tisVoid: true,\n\t\tattrs: {\n\t\t\tsrc: { default: '' },\n\t\t\talt: { default: '' },\n\t\t\ttitle: { default: '' },\n\t\t\talign: { default: 'center' },\n\t\t},\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTML(node) {\n\t\t\tconst src: string = escapeAttr(String(node.attrs?.src ?? ''));\n\t\t\tconst alt: string = escapeAttr(String(node.attrs?.alt ?? ''));\n\t\t\tconst title: string = String(node.attrs?.title ?? '');\n\t\t\tconst titleAttr: string = title ? ` title=\"${escapeAttr(title)}\"` : '';\n\t\t\tconst dimension = (name: string, value: unknown): string =>\n\t\t\t\ttypeof value === 'number' && Number.isFinite(value) && value > 0\n\t\t\t\t\t? ` ${name}=\"${String(value)}\"`\n\t\t\t\t\t: '';\n\t\t\treturn (\n\t\t\t\t`<figure><img src=\"${src}\" alt=\"${alt}\"${titleAttr}` +\n\t\t\t\t`${dimension('width', node.attrs?.width)}${dimension('height', node.attrs?.height)}></figure>`\n\t\t\t);\n\t\t},\n\t\tparseHTML: [\n\t\t\t{\n\t\t\t\ttag: 'figure',\n\t\t\t\tgetAttrs(el) {\n\t\t\t\t\tconst image: HTMLImageElement | null = el.querySelector('img');\n\t\t\t\t\treturn image ? imageAttrs(image) : false;\n\t\t\t\t},\n\t\t\t},\n\t\t\t{ tag: 'img', getAttrs: (el) => imageAttrs(el as HTMLImageElement) },\n\t\t],\n\t\tsanitize: {\n\t\t\ttags: ['figure', 'img'],\n\t\t\tattrs: ['src', 'alt', 'title', 'width', 'height'],\n\t\t},\n\t});\n\n\tregistry.registerNodeSpec({\n\t\ttype: 'table',\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTML(node, content, ctx?: HTMLExportContext) {\n\t\t\tconst widths: readonly (number | null)[] | undefined = normalizeTableColumnWidthsPx(\n\t\t\t\tnode.attrs?.columnWidthsPx,\n\t\t\t);\n\t\t\tconst colgroup: string = widths\n\t\t\t\t? `<colgroup>${widths\n\t\t\t\t\t\t.map((width: number | null): string => {\n\t\t\t\t\t\t\tconst attrs: string = serializeTableDimensionAttrs(\n\t\t\t\t\t\t\t\tTABLE_COLUMN_WIDTH_DATA_ATTRIBUTE,\n\t\t\t\t\t\t\t\t'width',\n\t\t\t\t\t\t\t\twidth,\n\t\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn `<col${attrs}>`;\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.join('')}</colgroup>`\n\t\t\t\t: '';\n\t\t\tconst tableAttrs: string = widths ? tableDimensionStyle(widths, ctx) : '';\n\t\t\treturn `<table${tableAttrs}>${colgroup}<tbody>${content}</tbody></table>`;\n\t\t},\n\t\tsanitize: {\n\t\t\ttags: ['table', 'colgroup', 'col', 'thead', 'tbody', 'tfoot'],\n\t\t\tattrs: ['span', 'width', TABLE_COLUMN_WIDTH_DATA_ATTRIBUTE],\n\t\t},\n\t});\n\n\tregistry.registerNodeSpec({\n\t\ttype: 'table_row',\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTML(node, content, ctx?: HTMLExportContext) {\n\t\t\tconst attrs: string = serializeTableDimensionAttrs(\n\t\t\t\tTABLE_ROW_MIN_HEIGHT_DATA_ATTRIBUTE,\n\t\t\t\t'height',\n\t\t\t\tnode.attrs?.minHeightPx,\n\t\t\t\tctx,\n\t\t\t);\n\t\t\treturn `<tr${attrs}>${content}</tr>`;\n\t\t},\n\t\tsanitize: {\n\t\t\ttags: ['tr'],\n\t\t\tattrs: ['height', TABLE_ROW_MIN_HEIGHT_DATA_ATTRIBUTE],\n\t\t},\n\t});\n\n\tregistry.registerNodeSpec({\n\t\ttype: 'table_cell',\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTML(node, content) {\n\t\t\tconst span = (name: string, value: unknown): string =>\n\t\t\t\ttypeof value === 'number' && Number.isInteger(value) && value > 1\n\t\t\t\t\t? ` ${name}=\"${String(value)}\"`\n\t\t\t\t\t: '';\n\t\t\treturn `<td${span('colspan', node.attrs?.colspan)}${span(\n\t\t\t\t'rowspan',\n\t\t\t\tnode.attrs?.rowspan,\n\t\t\t)}>${content}</td>`;\n\t\t},\n\t\tsanitize: { tags: ['td', 'th'], attrs: ['colspan', 'rowspan'] },\n\t});\n}\n\nfunction tableDimensionStyle(widths: readonly (number | null)[], ctx?: HTMLExportContext): string {\n\tconst minimumWidthPx: number = widths.reduce<number>(\n\t\t(total: number, width: number | null): number => total + (width ?? 60),\n\t\t0,\n\t);\n\tconst allExplicit: boolean = widths.every(\n\t\t(width: number | null): width is number => width !== null,\n\t);\n\tconst declarations: string = allExplicit\n\t\t? `width: ${String(minimumWidthPx)}px; min-width: ${String(minimumWidthPx)}px; table-layout: fixed`\n\t\t: `width: 100%; min-width: ${String(minimumWidthPx)}px; table-layout: fixed`;\n\treturn ctx?.styleAttr(declarations) ?? ` style=\"${declarations}\"`;\n}\n\nfunction imageAttrs(image: HTMLImageElement): Record<string, string | number | boolean> {\n\tconst attrs: Record<string, string | number | boolean> = {\n\t\t...inlineImageAttrs(image),\n\t\talign: 'center',\n\t};\n\tfor (const name of ['width', 'height'] as const) {\n\t\tconst value: number = Number.parseFloat(image.getAttribute(name) ?? '');\n\t\tif (Number.isFinite(value) && value > 0) attrs[name] = value;\n\t}\n\treturn attrs;\n}\n\nfunction inlineImageAttrs(image: HTMLImageElement): Record<string, string> {\n\tconst attrs: Record<string, string> = {\n\t\tsrc: image.getAttribute('src') ?? '',\n\t\talt: image.getAttribute('alt') ?? '',\n\t};\n\tconst title: string | null = image.getAttribute('title');\n\tif (title) attrs.title = title;\n\treturn attrs;\n}\n\nfunction registerMarks(registry: SchemaRegistry): void {\n\tconst tagMarks: readonly {\n\t\treadonly type: string;\n\t\treadonly rank: number;\n\t\treadonly tag: string;\n\t\treadonly parseTags: readonly string[];\n\t}[] = [\n\t\t{ type: 'bold', rank: 0, tag: 'strong', parseTags: ['strong', 'b'] },\n\t\t{ type: 'italic', rank: 1, tag: 'em', parseTags: ['em', 'i'] },\n\t\t{ type: 'underline', rank: 2, tag: 'u', parseTags: ['u'] },\n\t\t{ type: 'code', rank: 3, tag: 'code', parseTags: ['code'] },\n\t\t{ type: 'strikethrough', rank: 4, tag: 's', parseTags: ['s', 'strike', 'del'] },\n\t];\n\n\tfor (const mark of tagMarks) {\n\t\tregistry.registerMarkSpec({\n\t\t\ttype: mark.type,\n\t\t\trank: mark.rank,\n\t\t\ttoDOM: htmlOnlyDOM,\n\t\t\ttoHTMLString: (_value, content) => `<${mark.tag}>${content}</${mark.tag}>`,\n\t\t\tparseHTML: mark.parseTags.map((tag) => ({\n\t\t\t\ttag,\n\t\t\t\tgetAttrs:\n\t\t\t\t\ttag === 'code' ? (el) => (el.parentElement?.tagName === 'PRE' ? false : {}) : undefined,\n\t\t\t})),\n\t\t\tsanitize: { tags: mark.parseTags },\n\t\t});\n\t}\n\n\tregistry.registerMarkSpec({\n\t\ttype: 'link',\n\t\trank: 10,\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTMLString(mark, content) {\n\t\t\tconst href: string = escapeAttr(sanitizeHref(String(mark.attrs?.href ?? '')));\n\t\t\tconst title: string = String(mark.attrs?.title ?? '');\n\t\t\tconst titleAttr: string = title ? ` title=\"${escapeAttr(title)}\"` : '';\n\t\t\treturn `<a href=\"${href}\"${titleAttr}>${content}</a>`;\n\t\t},\n\t\tparseHTML: [\n\t\t\t{\n\t\t\t\ttag: 'a',\n\t\t\t\tgetAttrs(el) {\n\t\t\t\t\tconst href: string = sanitizeHref(el.getAttribute('href') ?? '');\n\t\t\t\t\tconst title: string | null = el.getAttribute('title');\n\t\t\t\t\treturn title ? { href, title } : { href };\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\tsanitize: { tags: ['a'], attrs: ['href', 'title'] },\n\t});\n}\n\nfunction registerInlineNodes(registry: SchemaRegistry): void {\n\tregistry.registerInlineNodeSpec({\n\t\ttype: 'hard_break',\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTMLString: () => '<br>',\n\t\tparseHTML: [{ tag: 'br' }],\n\t\tsanitize: { tags: ['br'] },\n\t});\n\n\tregistry.registerInlineNodeSpec({\n\t\ttype: 'image_inline',\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTMLString(node) {\n\t\t\tconst src: string = escapeAttr(String(node.attrs.src ?? ''));\n\t\t\tconst alt: string = escapeAttr(String(node.attrs.alt ?? ''));\n\t\t\tconst title: string = String(node.attrs.title ?? '');\n\t\t\tconst titleAttr: string = title ? ` title=\"${escapeAttr(title)}\"` : '';\n\t\t\treturn `<img src=\"${src}\" alt=\"${alt}\"${titleAttr}>`;\n\t\t},\n\t\tparseHTML: [{ tag: 'img', getAttrs: (el) => inlineImageAttrs(el as HTMLImageElement) }],\n\t\tsanitize: { tags: ['img'], attrs: ['src', 'alt', 'title'] },\n\t});\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MarkdownHTMLRegistry-Q7l0d6Ma.mjs","names":[],"sources":["../../src/serialization/markdown/GfmTableParser.ts","../../src/serialization/markdown/MarkdownEntities.ts","../../src/serialization/markdown/BlockTokenizer.ts","../../src/serialization/markdown/MarkdownHTMLRegistry.ts"],"sourcesContent":["/**\n * GFM table detection and row parsing.\n *\n * A table is a header row, a delimiter row (`| --- | :--: |`), and zero or more\n * body rows. Column alignment is derived from the colons in the delimiter row.\n * Cells hold raw inline text, parsed later by the inline tokenizer.\n */\n\n/** Column alignment derived from the delimiter row. */\nexport type ColumnAlign = 'start' | 'center' | 'end' | null;\n\n/** A parsed GFM table (cells are raw inline strings). */\nexport interface TableData {\n\treadonly aligns: readonly ColumnAlign[];\n\treadonly header: readonly string[];\n\treadonly rows: readonly (readonly string[])[];\n\treadonly linesConsumed: number;\n}\n\nconst DELIMITER_ROW = /^\\s*\\|?\\s*:?-+:?\\s*(\\|\\s*:?-+:?\\s*)*\\|?\\s*$/;\n\n/** Splits a table row into trimmed cells, honoring escaped `\\|` and outer pipes. */\nfunction splitRow(line: string): string[] {\n\tlet s: string = line.trim();\n\tif (s.startsWith('|')) s = s.slice(1);\n\tif (s.endsWith('|') && !s.endsWith('\\\\|')) s = s.slice(0, -1);\n\n\tconst cells: string[] = [];\n\tlet current = '';\n\tfor (let i = 0; i < s.length; i++) {\n\t\tconst ch: string = s[i] ?? '';\n\t\tif (ch === '\\\\' && s[i + 1] === '|') {\n\t\t\tcurrent += '|';\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (ch === '|') {\n\t\t\tcells.push(current.trim());\n\t\t\tcurrent = '';\n\t\t\tcontinue;\n\t\t}\n\t\tcurrent += ch;\n\t}\n\tcells.push(current.trim());\n\treturn cells;\n}\n\n/** Reads the alignment of a single delimiter cell (`:--`, `--:`, `:-:`, `--`). */\nfunction cellAlign(cell: string): ColumnAlign {\n\tconst trimmed: string = cell.trim();\n\tconst left: boolean = trimmed.startsWith(':');\n\tconst right: boolean = trimmed.endsWith(':');\n\tif (left && right) return 'center';\n\tif (right) return 'end';\n\tif (left) return 'start';\n\treturn null;\n}\n\n/**\n * Attempts to parse a GFM table beginning at `start`. Returns the table data or\n * null when the two leading lines are not a header + delimiter pair. The body\n * extends until a blank line or the start of another block (`interrupts`); a\n * plain paragraph-like line inside that range is a lazy single-cell row, per\n * the GFM spec (\"the table is broken at the first empty line or beginning of\n * another block-level structural element\").\n */\nexport function matchTable(\n\tlines: readonly string[],\n\tstart: number,\n\tinterrupts?: (line: string) => boolean,\n): TableData | null {\n\tconst headerLine: string = lines[start] ?? '';\n\tconst delimLine: string = lines[start + 1] ?? '';\n\tif (!headerLine.includes('|')) return null;\n\tif (!DELIMITER_ROW.test(delimLine)) return null;\n\n\tconst header: string[] = splitRow(headerLine);\n\tconst aligns: ColumnAlign[] = splitRow(delimLine).map(cellAlign);\n\tif (aligns.length !== header.length) return null;\n\n\tconst rows: string[][] = [];\n\tlet i: number = start + 2;\n\twhile (i < lines.length) {\n\t\tconst line: string = lines[i] ?? '';\n\t\tif (line.trim() === '') break;\n\t\tif (!line.includes('|') && (!interrupts || interrupts(line))) break;\n\t\trows.push(splitRow(line));\n\t\ti++;\n\t}\n\n\treturn { aligns, header, rows, linesConsumed: i - start };\n}\n","/**\n * HTML entity and backslash-escape decoding shared by the Markdown parser.\n *\n * CommonMark recognizes entity and numeric character references (and backslash\n * escapes) not only in inline text but also inside link destinations, link\n * titles, link reference definitions, and code-fence info strings. The small\n * built-in table covers the common names; uncommon names are decoded through\n * the environment's HTML parser when a DOM is available (browser, happy-dom),\n * because embedding the full HTML5 table (~2200 names) would bloat the chunk.\n * Without a DOM (pure Node) unknown entities stay literal, which never loses\n * content.\n */\n\n/** Characters a backslash may escape (CommonMark ASCII punctuation). */\nexport const ESCAPABLE = /[!-/:-@[-`{-~]/;\n\n/** Sticky matcher so callers scan at an index without slicing (linear-time, D1). */\nconst ENTITY_AT = /&(#[xX][0-9a-fA-F]{1,6}|#[0-9]{1,7}|[a-zA-Z][a-zA-Z0-9]{1,31});/y;\n\nconst NAMED_ENTITIES: Readonly<Record<string, string>> = {\n\tamp: '&',\n\tlt: '<',\n\tgt: '>',\n\tquot: '\"',\n\tapos: \"'\",\n\tnbsp: ' ',\n\tcopy: '©',\n\treg: '®',\n\thellip: '…',\n\tmdash: '—',\n\tndash: '–',\n};\n\n/**\n * Decodes a single HTML entity body (without `&`/`;`), or returns it verbatim.\n * Per CommonMark, U+0000 and invalid code points decode to U+FFFD; decoded\n * line separators become plain spaces so a text node never carries a raw\n * newline (block boundaries are structural in the editor model).\n */\nexport function decodeEntity(body: string): string {\n\tif (body[0] === '#') {\n\t\tconst isHex: boolean = body[1] === 'x' || body[1] === 'X';\n\t\tconst code: number = Number.parseInt(body.slice(isHex ? 2 : 1), isHex ? 16 : 10);\n\t\tif (!Number.isFinite(code) || code < 0 || code > 0x10ffff) return `&${body};`;\n\t\tif (code === 0) return '�';\n\t\ttry {\n\t\t\tconst decoded: string = String.fromCodePoint(code);\n\t\t\treturn decoded === '\\n' || decoded === '\\r' ? ' ' : decoded;\n\t\t} catch {\n\t\t\treturn '�';\n\t\t}\n\t}\n\treturn NAMED_ENTITIES[body] ?? decodeNamedEntityViaDom(body) ?? `&${body};`;\n}\n\n/** Matches an entity reference at `pos` in `text`, or null. */\nexport function matchEntityAt(text: string, pos: number): RegExpExecArray | null {\n\tENTITY_AT.lastIndex = pos;\n\treturn ENTITY_AT.exec(text);\n}\n\nconst domEntityCache = new Map<string, string | null>();\n\nfunction decodeNamedEntityViaDom(body: string): string | null {\n\tif (typeof document === 'undefined') return null;\n\tconst cached: string | null | undefined = domEntityCache.get(body);\n\tif (cached !== undefined) return cached;\n\t// `body` is regex-restricted to alphanumerics, so this cannot inject markup.\n\tconst holder: HTMLElement = document.createElement('div');\n\tholder.innerHTML = `&${body};`;\n\tconst text: string = holder.textContent ?? '';\n\tconst decoded: string | null = text !== '' && text !== `&${body};` ? text : null;\n\tdomEntityCache.set(body, decoded);\n\treturn decoded;\n}\n\n/**\n * Decodes backslash escapes and entity references in a single left-to-right\n * pass (an escaped `&` therefore never starts an entity). Used for the string\n * contexts CommonMark decodes outside inline text: link destinations, titles,\n * reference definitions, and fence info strings.\n */\nexport function decodeEscapesAndEntities(text: string): string {\n\tlet out = '';\n\tlet i = 0;\n\twhile (i < text.length) {\n\t\tconst ch: string = text[i] ?? '';\n\t\tif (ch === '\\\\' && ESCAPABLE.test(text[i + 1] ?? '')) {\n\t\t\tout += text[i + 1];\n\t\t\ti += 2;\n\t\t\tcontinue;\n\t\t}\n\t\tif (ch === '&') {\n\t\t\tconst match: RegExpExecArray | null = matchEntityAt(text, i);\n\t\t\tif (match?.[1]) {\n\t\t\t\tout += decodeEntity(match[1]);\n\t\t\t\ti += match[0].length;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tout += ch;\n\t\ti++;\n\t}\n\treturn out;\n}\n\n/** Decodes only entity references (escapes were already consumed by the caller). */\nexport function decodeEntitiesOnly(text: string): string {\n\tlet out = '';\n\tlet i = 0;\n\twhile (i < text.length) {\n\t\tconst ch: string = text[i] ?? '';\n\t\tif (ch === '&') {\n\t\t\tconst match: RegExpExecArray | null = matchEntityAt(text, i);\n\t\t\tif (match?.[1]) {\n\t\t\t\tout += decodeEntity(match[1]);\n\t\t\t\ti += match[0].length;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tout += ch;\n\t\ti++;\n\t}\n\treturn out;\n}\n","/**\n * Block-level Markdown tokenizer.\n *\n * A line scanner that turns Markdown source into a flat (recursive for\n * blockquotes) list of block tokens. The grammar is centralized here, by\n * necessity: CommonMark block structure is global and context-sensitive and\n * cannot be decomposed into per-spec rules (D4). `MarkdownParser` maps these\n * tokens to schema node types by name.\n *\n * List items follow CommonMark content-column semantics (#194): each item owns\n * a content column derived from its marker; subsequent lines indented at least\n * that far are the item's own content region, dedented and tokenized\n * recursively. A region that yields a single paragraph keeps the item a leaf;\n * anything else makes the item a container with block children. Nested list\n * items are hoisted out of the region into flat siblings (the editor's\n * flat-with-indent sibling model, indent = nesting level). Markers indented\n * four or more columns are not markers (indented code / lazy text, per spec).\n * Blockquotes support lazy paragraph continuation, and so do list items.\n */\n\nimport type { MarkdownSyntaxExtension } from '../../model/MarkdownSyntaxRegistry.js';\nimport { type ColumnAlign, type TableData, matchTable } from './GfmTableParser.js';\nimport { decodeEscapesAndEntities } from './MarkdownEntities.js';\n\n/** A parsed block-level token. Inline text is left raw for the inline parser. */\nexport type BlockToken =\n\t| { readonly type: 'heading'; readonly level: number; readonly text: string }\n\t| { readonly type: 'paragraph'; readonly text: string }\n\t| { readonly type: 'code_block'; readonly language: string; readonly code: string }\n\t| { readonly type: 'hr' }\n\t| { readonly type: 'blockquote'; readonly children: readonly BlockToken[] }\n\t| {\n\t\t\treadonly type: 'list_item';\n\t\t\treadonly listType: 'bullet' | 'ordered' | 'checklist';\n\t\t\treadonly indent: number;\n\t\t\treadonly checked: boolean;\n\t\t\t/** Inline text of a leaf item; empty when `children` is present. */\n\t\t\treadonly text: string;\n\t\t\t/** Block children of a multi-block (container) item, absent for leaves. */\n\t\t\treadonly children?: readonly BlockToken[];\n\t }\n\t| { readonly type: 'html'; readonly html: string }\n\t| {\n\t\t\treadonly type: 'table';\n\t\t\treadonly aligns: readonly ColumnAlign[];\n\t\t\treadonly header: readonly string[];\n\t\t\treadonly rows: readonly (readonly string[])[];\n\t }\n\t| {\n\t\t\treadonly type: 'extension_block';\n\t\t\treadonly nodeType: string;\n\t\t\treadonly attrs: Record<string, string | number | boolean>;\n\t };\n\n/** Block-level HTML tags that begin an HTML block; inline tags fall through to paragraphs. */\nconst BLOCK_HTML_TAGS: ReadonlySet<string> = new Set([\n\t'address',\n\t'article',\n\t'aside',\n\t'blockquote',\n\t'details',\n\t'div',\n\t'dl',\n\t'dd',\n\t'dt',\n\t'figure',\n\t'figcaption',\n\t'footer',\n\t'form',\n\t'h1',\n\t'h2',\n\t'h3',\n\t'h4',\n\t'h5',\n\t'h6',\n\t'header',\n\t'hr',\n\t'iframe',\n\t'main',\n\t'nav',\n\t'ol',\n\t'p',\n\t'pre',\n\t'section',\n\t'table',\n\t'tbody',\n\t'td',\n\t'tfoot',\n\t'th',\n\t'thead',\n\t'tr',\n\t'ul',\n\t'video',\n]);\n\n// Exported so the parser's link-reference pre-pass can reuse the exact grammar\n// when deciding block boundaries (single source of truth for the syntax).\nexport const ATX_HEADING = /^ {0,3}(#{1,6})(?:[ \\t]+(.*?))?(?:[ \\t]+#+)?[ \\t]*$/;\nexport const FENCE_OPEN = /^ {0,3}(`{3,}|~{3,})[ \\t]*(.*)$/;\nexport const THEMATIC_BREAK = /^ {0,3}([-*_])[ \\t]*(?:\\1[ \\t]*){2,}$/;\nconst BLOCKQUOTE = /^ {0,3}>[ ]?/;\nconst BULLET_ITEM = /^([ \\t]*)([-*+])(?:([ \\t]+)(.*))?$/;\nconst ORDERED_ITEM = /^([ \\t]*)(\\d{1,9})([.)])(?:([ \\t]+)(.*))?$/;\nconst TASK_PREFIX = /^\\[([ xX])\\][ \\t]+(.*)$/;\n// Exported alongside the other grammar patterns so the serializer's line-start\n// escaping re-parses paragraph lines with the exact same rules (single source of\n// truth: a line the tokenizer would read as a setext underline gets escaped).\nexport const SETEXT_H1 = /^ {0,3}=+[ \\t]*$/;\nexport const SETEXT_H2 = /^ {0,3}-+[ \\t]*$/;\nconst HTML_BLOCK_START = /^ {0,3}<(\\/?)([a-zA-Z][a-zA-Z0-9-]*)|^ {0,3}<!--/;\n\n/** Leading-whitespace columns that open an indented code block (CommonMark). */\nconst INDENTED_CODE_COLUMNS = 4;\n\n/** Maximum leading columns of a list marker; deeper markers are code/lazy text. */\nconst MAX_MARKER_INDENT_COLUMNS = 3;\n\n/**\n * Maximum container nesting (blockquotes, list-item regions) before the\n * construct is treated as literal text. Each level recurses\n * (`tokenizeLines` → container consumer → `tokenizeLines`), so an adversarial\n * paste of thousands of `>`/`-` prefixes would overflow the stack. The cap\n * keeps recursion bounded; deeper content degrades to a paragraph (no data\n * loss, the marker characters are preserved). Real documents never nest this\n * deep.\n */\nconst MAX_CONTAINER_DEPTH = 32;\n\nfunction isBlank(line: string): boolean {\n\treturn line.trim() === '';\n}\n\n/**\n * Matches a fence opener. A backtick fence whose info string contains a\n * backtick is not a fence per CommonMark (it reads as an inline code span).\n */\nexport function matchFenceOpen(line: string): RegExpMatchArray | null {\n\tconst match: RegExpMatchArray | null = line.match(FENCE_OPEN);\n\tif (!match) return null;\n\tif ((match[1] ?? '')[0] === '`' && (match[2] ?? '').includes('`')) return null;\n\treturn match;\n}\n\n/** Tokenizes a full Markdown source string into block tokens. */\nexport function tokenizeBlocks(\n\tsource: string,\n\tgfm = true,\n\textensions: readonly MarkdownSyntaxExtension[] = [],\n): BlockToken[] {\n\t// A single trailing newline closes the last line; it is not an extra line\n\t// (otherwise an unclosed fence at EOF would gain a phantom blank line).\n\tconst normalized: string = source.replace(/\\r\\n?/g, '\\n').replace(/\\n$/, '');\n\treturn tokenizeLines(normalized.split('\\n'), gfm, extensions);\n}\n\nfunction tokenizeLines(\n\tlines: readonly string[],\n\tgfm: boolean,\n\textensions: readonly MarkdownSyntaxExtension[],\n\tdepth = 0,\n): BlockToken[] {\n\tconst tokens: BlockToken[] = [];\n\tlet i = 0;\n\n\twhile (i < lines.length) {\n\t\tconst line: string = lines[i] ?? '';\n\n\t\tif (isBlank(line)) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst extension: number = tryExtensionBlock(extensions, lines, i, tokens);\n\t\tif (extension > 0) {\n\t\t\ti += extension;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (gfm) {\n\t\t\tconst table: TableData | null = matchTable(lines, i, interruptsParagraph);\n\t\t\tif (table) {\n\t\t\t\ttokens.push({\n\t\t\t\t\ttype: 'table',\n\t\t\t\t\taligns: table.aligns,\n\t\t\t\t\theader: table.header,\n\t\t\t\t\trows: table.rows,\n\t\t\t\t});\n\t\t\t\ti += table.linesConsumed;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tconst fence: RegExpMatchArray | null = matchFenceOpen(line);\n\t\tif (fence) {\n\t\t\ti = consumeFencedCode(lines, i, fence, tokens);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst atx: RegExpMatchArray | null = line.match(ATX_HEADING);\n\t\tif (atx) {\n\t\t\tconst rawText: string = (atx[2] ?? '').trim();\n\t\t\t// Content that is only `#`s is a closing sequence, not text (`### ###`).\n\t\t\tconst text: string = /^#+$/.test(rawText) ? '' : rawText;\n\t\t\ttokens.push({ type: 'heading', level: (atx[1] ?? '#').length, text });\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (THEMATIC_BREAK.test(line)) {\n\t\t\ttokens.push({ type: 'hr' });\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (BLOCKQUOTE.test(line)) {\n\t\t\t// Depth guard: past the cap, stop recursing and keep the `>` lines as\n\t\t\t// literal paragraph text rather than overflowing the stack.\n\t\t\tif (depth >= MAX_CONTAINER_DEPTH) {\n\t\t\t\ti = consumeParagraph(lines, i, tokens);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\ti = consumeBlockquote(lines, i, tokens, gfm, extensions, depth);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst marker: ListMarker | null = depth < MAX_CONTAINER_DEPTH ? matchListMarker(line) : null;\n\t\tif (marker) {\n\t\t\ti = consumeListItem(lines, i, marker, tokens, gfm, extensions, depth);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (canStartIndentedCode(line)) {\n\t\t\ti = consumeIndentedCode(lines, i, tokens);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (isHtmlBlockStart(line)) {\n\t\t\ti = consumeHtmlBlock(lines, i, tokens);\n\t\t\tcontinue;\n\t\t}\n\n\t\ti = consumeParagraph(lines, i, tokens);\n\t}\n\n\treturn tokens;\n}\n\n/** Consumes a fenced code block; returns the next line index. */\nfunction consumeFencedCode(\n\tlines: readonly string[],\n\tstart: number,\n\tfence: RegExpMatchArray,\n\ttokens: BlockToken[],\n): number {\n\tconst fenceStr: string = fence[1] ?? '```';\n\tconst fenceChar: string = fenceStr[0] ?? '`';\n\tconst language: string = decodeEscapesAndEntities((fence[2] ?? '').trim().split(/\\s+/)[0] ?? '');\n\tconst closeRe = new RegExp(`^ {0,3}${`\\\\${fenceChar}`}{${fenceStr.length},}[ \\\\t]*$`);\n\t// An indented opening fence strips up to that indentation from each body line.\n\tconst openLine: string = lines[start] ?? '';\n\tconst openIndent: number = openLine.length - openLine.trimStart().length;\n\n\tconst body: string[] = [];\n\tlet i: number = start + 1;\n\twhile (i < lines.length) {\n\t\tconst line: string = lines[i] ?? '';\n\t\tif (closeRe.test(line)) {\n\t\t\ti++;\n\t\t\tbreak;\n\t\t}\n\t\tbody.push(stripLeadingSpaces(line, openIndent));\n\t\ti++;\n\t}\n\ttokens.push({ type: 'code_block', language, code: body.join('\\n') });\n\treturn i;\n}\n\n/** Removes up to `max` leading spaces from a line. */\nfunction stripLeadingSpaces(line: string, max: number): string {\n\tlet i = 0;\n\twhile (i < max && line[i] === ' ') i++;\n\treturn line.slice(i);\n}\n\n/**\n * Whether a line opens an indented code block (#195): at least four columns of\n * leading whitespace (tab-aware). Indented content that belongs to an open\n * list item never reaches this check — it is consumed into the item's content\n * region first (#194).\n */\nfunction canStartIndentedCode(line: string): boolean {\n\treturn indentColumns(line) >= INDENTED_CODE_COLUMNS;\n}\n\n/** Columns of leading whitespace, with tabs advancing to 4-column tab stops. */\nfunction indentColumns(line: string): number {\n\tlet col = 0;\n\tfor (const ch of line) {\n\t\tif (ch === ' ') col++;\n\t\telse if (ch === '\\t') col += 4 - (col % 4);\n\t\telse break;\n\t}\n\treturn col;\n}\n\n/**\n * Strips `columns` columns of leading whitespace (tab-aware). The remaining\n * leading whitespace is re-emitted as spaces measured in absolute columns:\n * tab stops depend on the column a tab starts in, so dedented lines must not\n * carry raw tabs whose width would be recomputed in the wrong context.\n */\nfunction stripIndent(line: string, columns: number): string {\n\tlet col = 0;\n\tlet i = 0;\n\twhile (i < line.length) {\n\t\tconst ch: string = line[i] ?? '';\n\t\tif (ch === ' ') col++;\n\t\telse if (ch === '\\t') col += 4 - (col % 4);\n\t\telse break;\n\t\ti++;\n\t}\n\treturn ' '.repeat(Math.max(0, col - columns)) + line.slice(i);\n}\n\n/**\n * Strips `columns` columns of leading whitespace from a code line, preserving\n * literal tabs beyond the strip boundary. Indented-code content is literal, so\n * tabs are significant (Makefiles, Go) and must survive verbatim — unlike\n * {@link stripIndent}, which normalizes re-tokenized structural whitespace to\n * spaces. Only a tab straddling the strip boundary contributes spaces (the part\n * of its width past `columns`); tabs fully past the boundary are kept as-is.\n */\nfunction stripCodeIndent(line: string, columns: number): string {\n\tlet col = 0;\n\tlet i = 0;\n\twhile (i < line.length && col < columns) {\n\t\tconst ch: string = line[i] ?? '';\n\t\tif (ch === ' ') {\n\t\t\tcol++;\n\t\t\ti++;\n\t\t} else if (ch === '\\t') {\n\t\t\tconst next: number = col + 4 - (col % 4);\n\t\t\tif (next > columns) {\n\t\t\t\t// Straddling tab: emit only its overflow past the boundary as spaces\n\t\t\t\t// and keep the remainder of the line (including later tabs) verbatim.\n\t\t\t\treturn ' '.repeat(next - columns) + line.slice(i + 1);\n\t\t\t}\n\t\t\tcol = next;\n\t\t\ti++;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn line.slice(i);\n}\n\n/**\n * Consumes an indented code block: all subsequent lines indented by at least\n * four columns, keeping interior blank lines but not trailing ones (they\n * separate the block from what follows). Returns the next line index.\n */\nfunction consumeIndentedCode(\n\tlines: readonly string[],\n\tstart: number,\n\ttokens: BlockToken[],\n): number {\n\tconst body: string[] = [];\n\tconst pendingBlanks: string[] = [];\n\tlet i: number = start;\n\twhile (i < lines.length) {\n\t\tconst line: string = lines[i] ?? '';\n\t\tif (isBlank(line)) {\n\t\t\t// Interior blank lines keep their content beyond the stripped columns.\n\t\t\tpendingBlanks.push(stripCodeIndent(line, INDENTED_CODE_COLUMNS));\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (indentColumns(line) < INDENTED_CODE_COLUMNS) break;\n\t\twhile (pendingBlanks.length > 0) body.push(pendingBlanks.shift() ?? '');\n\t\tbody.push(stripCodeIndent(line, INDENTED_CODE_COLUMNS));\n\t\ti++;\n\t}\n\ttokens.push({ type: 'code_block', language: '', code: body.join('\\n') });\n\treturn i - pendingBlanks.length;\n}\n\n/** Tries each extension's `matchBlock`; pushes a token and returns lines consumed (0 = no match). */\nfunction tryExtensionBlock(\n\textensions: readonly MarkdownSyntaxExtension[],\n\tlines: readonly string[],\n\tlineIndex: number,\n\ttokens: BlockToken[],\n): number {\n\tfor (const ext of extensions) {\n\t\tconst match = ext.matchBlock?.(lines, lineIndex);\n\t\tif (match && match.linesConsumed > 0) {\n\t\t\ttokens.push({ type: 'extension_block', nodeType: match.type, attrs: match.attrs });\n\t\t\treturn match.linesConsumed;\n\t\t}\n\t}\n\treturn 0;\n}\n\n/**\n * Consumes consecutive `>`-prefixed lines (plus lazy paragraph continuation\n * lines, per CommonMark) and recurses into their content. A plain line\n * continues the quote only while the innermost open block is a paragraph.\n */\nfunction consumeBlockquote(\n\tlines: readonly string[],\n\tstart: number,\n\ttokens: BlockToken[],\n\tgfm: boolean,\n\textensions: readonly MarkdownSyntaxExtension[],\n\tdepth: number,\n): number {\n\tconst inner: string[] = [];\n\tlet i: number = start;\n\tlet lazyOk = false;\n\twhile (i < lines.length) {\n\t\tconst line: string = lines[i] ?? '';\n\t\tif (BLOCKQUOTE.test(line)) {\n\t\t\tconst stripped: string = line.replace(BLOCKQUOTE, '');\n\t\t\tinner.push(stripped);\n\t\t\tlazyOk = continuesAsParagraph(stripped);\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (\n\t\t\tlazyOk &&\n\t\t\t!isBlank(line) &&\n\t\t\t!interruptsParagraph(line) &&\n\t\t\t!(gfm && matchTable(lines, i, interruptsParagraph))\n\t\t) {\n\t\t\tinner.push(line);\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\tbreak;\n\t}\n\ttokens.push({ type: 'blockquote', children: tokenizeLines(inner, gfm, extensions, depth + 1) });\n\treturn i;\n}\n\n/**\n * Whether a stripped container line leaves a paragraph open at its innermost\n * level: quote prefixes and list markers are peeled off (`> 1. > text` opens a\n * paragraph two containers deep, which a lazy line may continue).\n */\nfunction continuesAsParagraph(stripped: string): boolean {\n\tlet content: string = stripped;\n\tfor (;;) {\n\t\tif (BLOCKQUOTE.test(content)) {\n\t\t\tcontent = content.replace(BLOCKQUOTE, '');\n\t\t\tcontinue;\n\t\t}\n\t\tconst marker: ListMarker | null = matchListMarker(content);\n\t\tif (marker && marker.firstText !== '') {\n\t\t\tcontent = marker.firstText;\n\t\t\tcontinue;\n\t\t}\n\t\tbreak;\n\t}\n\tif (content.trim() === '' || interruptsParagraph(content)) return false;\n\t// An indented-code line is not a paragraph, so nothing can lazily continue it.\n\treturn indentColumns(content) < INDENTED_CODE_COLUMNS;\n}\n\n/** Geometry and metadata of a single list-marker line. */\ninterface ListMarker {\n\treadonly listType: 'bullet' | 'ordered' | 'checklist';\n\treadonly checked: boolean;\n\t/** Column where the item's content begins; region lines must reach it. */\n\treadonly contentColumn: number;\n\t/** The marker line's own content (task prefix stripped), '' for empty items. */\n\treadonly firstText: string;\n\t/** The ordered start number (1 for bullets). */\n\treadonly startNumber: number;\n}\n\n/** Columns spanned by a whitespace run starting at an absolute column. */\nfunction columnsFrom(start: number, whitespace: string): number {\n\tlet col: number = start;\n\tfor (const ch of whitespace) {\n\t\tif (ch === ' ') col++;\n\t\telse if (ch === '\\t') col += 4 - (col % 4);\n\t\telse break;\n\t}\n\treturn col - start;\n}\n\n/**\n * Parses a list-marker line into its content-column geometry, or null when the\n * line is not a valid marker: markers indented four or more columns are\n * indented code or lazy text, never list items (CommonMark).\n */\nfunction matchListMarker(line: string): ListMarker | null {\n\tconst bullet: RegExpMatchArray | null = line.match(BULLET_ITEM);\n\tconst ordered: RegExpMatchArray | null = bullet ? null : line.match(ORDERED_ITEM);\n\tconst match: RegExpMatchArray | null = bullet ?? ordered;\n\tif (!match) return null;\n\n\tconst leadingColumns: number = indentColumns(match[1] ?? '');\n\tif (leadingColumns > MAX_MARKER_INDENT_COLUMNS) return null;\n\n\tconst markerText: string = (bullet ? match[2] : `${match[2]}${match[3]}`) ?? '-';\n\tconst markerEnd: number = leadingColumns + markerText.length;\n\tconst spacing: string = (bullet ? match[3] : match[4]) ?? '';\n\tconst spacingColumns: number = columnsFrom(markerEnd, spacing);\n\tconst rawContent: string = (bullet ? match[4] : match[5]) ?? '';\n\tconst startNumber: number = ordered ? Number.parseInt(match[2] ?? '1', 10) : 1;\n\n\tlet contentColumn: number;\n\tlet firstText: string;\n\tif (rawContent.trim() === '') {\n\t\tcontentColumn = markerEnd + 1;\n\t\tfirstText = '';\n\t} else if (spacingColumns >= 5) {\n\t\t// Content five or more columns past the marker starts as indented code;\n\t\t// the content column sits one past the marker (CommonMark).\n\t\tcontentColumn = markerEnd + 1;\n\t\tfirstText = ' '.repeat(spacingColumns - 1) + rawContent;\n\t} else {\n\t\tcontentColumn = markerEnd + spacingColumns;\n\t\tfirstText = rawContent;\n\t}\n\n\tconst task: RegExpMatchArray | null = firstText.match(TASK_PREFIX);\n\tif (task) {\n\t\treturn {\n\t\t\tlistType: 'checklist',\n\t\t\tchecked: (task[1] ?? ' ').toLowerCase() === 'x',\n\t\t\tcontentColumn,\n\t\t\tfirstText: task[2] ?? '',\n\t\t\tstartNumber,\n\t\t};\n\t}\n\treturn {\n\t\tlistType: ordered ? 'ordered' : 'bullet',\n\t\tchecked: false,\n\t\tcontentColumn,\n\t\tfirstText,\n\t\tstartNumber,\n\t};\n}\n\n/**\n * Consumes one list item: the marker line plus its content region — every\n * following line indented to the content column (dedented), interior blank\n * lines, and lazy paragraph continuation lines. The collected content is\n * tokenized recursively; nested list items are hoisted into flat siblings.\n * Returns the next line index.\n */\nfunction consumeListItem(\n\tlines: readonly string[],\n\tstart: number,\n\tmarker: ListMarker,\n\ttokens: BlockToken[],\n\tgfm: boolean,\n\textensions: readonly MarkdownSyntaxExtension[],\n\tdepth: number,\n): number {\n\tconst region: string[] = [];\n\tconst tracker: (line: string, paragraphOpen: boolean) => boolean = createParagraphTracker();\n\tlet firstText: string = marker.firstText;\n\tlet paragraphOpen: boolean = firstText === '' ? false : tracker(firstText, false);\n\tlet pendingBlanks = 0;\n\tlet i: number = start + 1;\n\n\twhile (i < lines.length) {\n\t\tconst line: string = lines[i] ?? '';\n\n\t\tif (isBlank(line)) {\n\t\t\t// An item may begin with at most one blank line: a marker with no\n\t\t\t// content followed by a blank line stays an empty item (CommonMark).\n\t\t\tif (firstText === '' && region.length === 0) break;\n\t\t\tpendingBlanks++;\n\t\t\tparagraphOpen = false;\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (indentColumns(line) >= marker.contentColumn) {\n\t\t\twhile (pendingBlanks > 0) {\n\t\t\t\tregion.push('');\n\t\t\t\tpendingBlanks--;\n\t\t\t}\n\t\t\tconst dedented: string = stripIndent(line, marker.contentColumn);\n\t\t\tregion.push(dedented);\n\t\t\tparagraphOpen = tracker(dedented, paragraphOpen);\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Under-indented: only a lazy paragraph continuation keeps the item open.\n\t\t// Any valid marker line is a sibling item, never lazy text (the\n\t\t// ordered-must-start-at-1 interrupt rule applies to paragraphs only).\n\t\tif (matchListMarker(line)) break;\n\t\tif (!paragraphOpen) break;\n\t\tif (interruptsParagraph(line)) break;\n\t\tif (gfm && matchTable(lines, i, interruptsParagraph)) break;\n\t\t// A lazy line belongs textually to the open paragraph: fold it into the\n\t\t// previous logical line so it can never re-parse as a block start in the\n\t\t// item's sub-document (`- d\\n - e` keeps \"- e\" as paragraph text).\n\t\tconst lazy: string = line.trimStart();\n\t\tconst lastRegionLine: string | undefined = region[region.length - 1];\n\t\tif (lastRegionLine !== undefined) {\n\t\t\tregion[region.length - 1] = `${lastRegionLine}\\n${lazy}`;\n\t\t} else {\n\t\t\tfirstText = firstText === '' ? lazy : `${firstText}\\n${lazy}`;\n\t\t}\n\t\tparagraphOpen = tracker(lazy, paragraphOpen);\n\t\ti++;\n\t}\n\n\tappendListItemTokens(marker, firstText, region, tokens, gfm, extensions, depth);\n\treturn i;\n}\n\n/**\n * Tracks whether the innermost open block of an item's content region is a\n * paragraph — the precondition for lazy continuation. Fenced code suspends\n * laziness until the fence closes; block starters close the paragraph. The\n * caller passes whether a paragraph is currently open, because an indented line\n * cannot start an indented code block while a paragraph is open (CommonMark): it\n * continues that paragraph instead, and only opens a code block from a closed\n * state.\n */\nfunction createParagraphTracker(): (line: string, paragraphOpen: boolean) => boolean {\n\tlet closeRe: RegExp | null = null;\n\treturn (line: string, paragraphOpen: boolean): boolean => {\n\t\tif (closeRe) {\n\t\t\tif (closeRe.test(line)) closeRe = null;\n\t\t\treturn false;\n\t\t}\n\t\tconst fence: RegExpMatchArray | null = matchFenceOpen(line);\n\t\tif (fence) {\n\t\t\tconst fenceStr: string = fence[1] ?? '```';\n\t\t\tconst fenceChar: string = fenceStr[0] ?? '`';\n\t\t\tcloseRe = new RegExp(`^ {0,3}${`\\\\${fenceChar}`}{${fenceStr.length},}[ \\\\t]*$`);\n\t\t\treturn false;\n\t\t}\n\t\tif (isBlank(line)) return false;\n\t\tif (BLOCKQUOTE.test(line) || matchListMarker(line)) return continuesAsParagraph(line);\n\t\t// Indented code cannot interrupt an open paragraph: an indented line keeps\n\t\t// the paragraph open, and only opens a code block when none is open.\n\t\tif (indentColumns(line) >= INDENTED_CODE_COLUMNS) return paragraphOpen;\n\t\treturn !interruptsParagraph(line);\n\t};\n}\n\n/**\n * Builds the item token(s) from the marker line and its dedented content\n * region: the content is tokenized recursively; a single-paragraph result\n * keeps the item a leaf, anything else becomes a container with block\n * children. Nested list items are hoisted out into flat siblings one indent\n * deeper (the editor's flat-with-indent sibling model).\n */\nfunction appendListItemTokens(\n\tmarker: ListMarker,\n\tfirstText: string,\n\tregion: readonly string[],\n\ttokens: BlockToken[],\n\tgfm: boolean,\n\textensions: readonly MarkdownSyntaxExtension[],\n\tdepth: number,\n): void {\n\tconst subLines: string[] = firstText === '' ? [...region] : [firstText, ...region];\n\tconst subTokens: BlockToken[] =\n\t\tsubLines.length === 0 ? [] : tokenizeLines(subLines, gfm, extensions, depth + 1);\n\n\tconst lifted: BlockToken[] = [];\n\tconst own: BlockToken[] = [];\n\tfor (const token of subTokens) {\n\t\tif (token.type === 'list_item') {\n\t\t\tlifted.push({ ...token, indent: token.indent + 1 });\n\t\t} else {\n\t\t\town.push(token);\n\t\t}\n\t}\n\n\tconst first: BlockToken | undefined = own[0];\n\tif (own.length === 1 && first?.type === 'paragraph') {\n\t\ttokens.push(makeListItemToken(marker, first.text));\n\t} else if (own.length === 0) {\n\t\ttokens.push(makeListItemToken(marker, ''));\n\t} else {\n\t\ttokens.push(makeListItemToken(marker, '', own));\n\t}\n\ttokens.push(...lifted);\n}\n\n/** Builds a `list_item` token at indent 0 of the current tokenization level. */\nfunction makeListItemToken(\n\tmarker: ListMarker,\n\ttext: string,\n\tchildren?: readonly BlockToken[],\n): BlockToken {\n\tconst base = {\n\t\ttype: 'list_item' as const,\n\t\tlistType: marker.listType,\n\t\tindent: 0,\n\t\tchecked: marker.checked,\n\t\ttext,\n\t};\n\treturn children ? { ...base, children } : base;\n}\n\n/**\n * Whether a list-item line may interrupt an open paragraph: CommonMark forbids\n * empty items and ordered items not starting at 1 from doing so (`14.` in prose\n * must not begin a list).\n */\nfunction listItemInterrupts(line: string): boolean {\n\tconst marker: ListMarker | null = matchListMarker(line);\n\tif (!marker) return false;\n\tif (marker.firstText.trim() === '') return false;\n\tif (marker.listType === 'ordered') return marker.startNumber === 1;\n\treturn true;\n}\n\n/** Whether a line begins a block-level HTML element (inline tags fall through). */\nfunction isHtmlBlockStart(line: string): boolean {\n\tconst match: RegExpMatchArray | null = line.match(HTML_BLOCK_START);\n\tif (!match) return false;\n\tif (line.trimStart().startsWith('<!--')) return true;\n\tconst tag: string = (match[2] ?? '').toLowerCase();\n\treturn BLOCK_HTML_TAGS.has(tag);\n}\n\n/** Consumes an HTML block up to the next blank line. */\nfunction consumeHtmlBlock(lines: readonly string[], start: number, tokens: BlockToken[]): number {\n\tconst html: string[] = [];\n\tlet i: number = start;\n\twhile (i < lines.length) {\n\t\tconst line: string = lines[i] ?? '';\n\t\tif (isBlank(line)) break;\n\t\thtml.push(line);\n\t\ti++;\n\t}\n\ttokens.push({ type: 'html', html: html.join('\\n') });\n\treturn i;\n}\n\n/** Whether a line would interrupt an open paragraph (begins another block). */\nfunction interruptsParagraph(line: string): boolean {\n\tif (isBlank(line)) return true;\n\tif (ATX_HEADING.test(line)) return true;\n\tif (matchFenceOpen(line)) return true;\n\tif (THEMATIC_BREAK.test(line)) return true;\n\tif (BLOCKQUOTE.test(line)) return true;\n\tif (listItemInterrupts(line)) return true;\n\tif (isHtmlBlockStart(line)) return true;\n\treturn false;\n}\n\n/** Consumes a paragraph (with lazy continuation) or a setext heading. */\nfunction consumeParagraph(lines: readonly string[], start: number, tokens: BlockToken[]): number {\n\tconst collected: string[] = [lines[start] ?? ''];\n\tlet i: number = start + 1;\n\n\twhile (i < lines.length) {\n\t\tconst line: string = lines[i] ?? '';\n\n\t\t// A setext underline turns the collected paragraph into a heading.\n\t\tif (SETEXT_H1.test(line)) {\n\t\t\ttokens.push({ type: 'heading', level: 1, text: joinParagraph(collected) });\n\t\t\treturn i + 1;\n\t\t}\n\t\t// A `-` underline outranks a thematic break when a paragraph sits above it.\n\t\tif (SETEXT_H2.test(line)) {\n\t\t\ttokens.push({ type: 'heading', level: 2, text: joinParagraph(collected) });\n\t\t\treturn i + 1;\n\t\t}\n\n\t\tif (interruptsParagraph(line)) break;\n\t\tcollected.push(line);\n\t\ti++;\n\t}\n\n\ttokens.push({ type: 'paragraph', text: joinParagraphText(collected) });\n\treturn i;\n}\n\n/**\n * Joins collected paragraph lines for inline parsing. Leading indentation is\n * insignificant and stripped, but trailing spaces on interior lines are kept:\n * two or more of them encode a hard break, which the inline parser consumes\n * (#193). The final line's trailing whitespace carries no meaning and is\n * dropped.\n */\nfunction joinParagraphText(lines: readonly string[]): string {\n\treturn lines\n\t\t.map((line, index) => (index === lines.length - 1 ? line.trim() : line.trimStart()))\n\t\t.join('\\n');\n}\n\n/** Joins multi-line paragraph text into a single-line heading string. */\nfunction joinParagraph(lines: readonly string[]): string {\n\treturn lines\n\t\t.map((l) => l.trim())\n\t\t.join(' ')\n\t\t.trim();\n}\n","/**\n * Minimal HTML-only schema for Markdown's raw-HTML seam.\n *\n * Registry-free Markdown calls still need the portable structures owned by the\n * codec when a block must become raw HTML (for example to retain an `htmlId`).\n * An explicitly supplied registry is returned unchanged and remains the sole\n * authority. No plugin or view module is imported here.\n */\n\nimport { escapeAttr, sanitizeHref } from '../../model/HTMLUtils.js';\nimport type { HTMLExportContext } from '../../model/NodeSpec.js';\nimport { SchemaRegistry } from '../../model/SchemaRegistry.js';\nimport {\n\tTABLE_COLUMN_WIDTH_DATA_ATTRIBUTE,\n\tTABLE_ROW_MIN_HEIGHT_DATA_ATTRIBUTE,\n\tnormalizeTableColumnWidthsPx,\n\tserializeTableDimensionAttrs,\n} from '../TableDimensions.js';\n\nlet baselineRegistry: SchemaRegistry | undefined;\n\n/** Resolves the schema at an HTML boundary without supplementing an explicit schema. */\nexport function resolveMarkdownHTMLRegistry(registry?: SchemaRegistry): SchemaRegistry {\n\tif (registry) return registry;\n\tbaselineRegistry ??= createBaselineRegistry();\n\treturn baselineRegistry;\n}\n\nfunction htmlOnlyDOM(): HTMLElement {\n\tthrow new Error('The Markdown HTML registry cannot render editor DOM.');\n}\n\nfunction createBaselineRegistry(): SchemaRegistry {\n\tconst registry = new SchemaRegistry();\n\tregisterBlocks(registry);\n\tregisterMarks(registry);\n\tregisterInlineNodes(registry);\n\treturn registry;\n}\n\nfunction registerBlocks(registry: SchemaRegistry): void {\n\tregistry.registerNodeSpec({\n\t\ttype: 'paragraph',\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTML: (_node, content) => `<p>${content || '<br>'}</p>`,\n\t\tparseHTML: [{ tag: 'p' }, { tag: 'div', priority: 10 }],\n\t\tsanitize: { tags: ['p'] },\n\t});\n\n\tregistry.registerNodeSpec({\n\t\ttype: 'heading',\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTML(node, content) {\n\t\t\tconst raw: unknown = node.attrs?.level;\n\t\t\tconst level: number =\n\t\t\t\ttypeof raw === 'number' && Number.isFinite(raw)\n\t\t\t\t\t? Math.max(1, Math.min(6, Math.floor(raw)))\n\t\t\t\t\t: 1;\n\t\t\treturn `<h${level}>${content || '<br>'}</h${level}>`;\n\t\t},\n\t\tparseHTML: [1, 2, 3, 4, 5, 6].map((level) => ({\n\t\t\ttag: `h${level}`,\n\t\t\tgetAttrs: () => ({ level }),\n\t\t})),\n\t\tsanitize: { tags: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] },\n\t});\n\n\tregistry.registerNodeSpec({\n\t\ttype: 'list_item',\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTML(node, content) {\n\t\t\tif (node.attrs?.listType !== 'checklist') return `<li>${content || '<br>'}</li>`;\n\t\t\tconst checked: boolean = node.attrs.checked === true;\n\t\t\treturn (\n\t\t\t\t`<li role=\"checkbox\" aria-checked=\"${String(checked)}\">` +\n\t\t\t\t`<input type=\"checkbox\" disabled${checked ? ' checked' : ''}>` +\n\t\t\t\t`${content || '<br>'}</li>`\n\t\t\t);\n\t\t},\n\t\tparseHTML: [{ tag: 'li' }],\n\t\tsanitize: {\n\t\t\ttags: ['ul', 'ol', 'li', 'input'],\n\t\t\tattrs: ['type', 'disabled', 'checked', 'role', 'aria-checked'],\n\t\t},\n\t});\n\n\tregistry.registerNodeSpec({\n\t\ttype: 'blockquote',\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTML: (_node, content) => `<blockquote>${content || '<br>'}</blockquote>`,\n\t\tparseHTML: [{ tag: 'blockquote' }],\n\t\tsanitize: { tags: ['blockquote'] },\n\t});\n\n\tregistry.registerNodeSpec({\n\t\ttype: 'code_block',\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTML(node, content) {\n\t\t\tconst language: string = String(node.attrs?.language ?? '');\n\t\t\tconst languageClass: string = language ? ` class=\"language-${escapeAttr(language)}\"` : '';\n\t\t\treturn `<pre><code${languageClass}>${content}</code></pre>`;\n\t\t},\n\t\tparseHTML: [\n\t\t\t{\n\t\t\t\ttag: 'pre',\n\t\t\t\tgetAttrs(el) {\n\t\t\t\t\tconst code: HTMLElement | null = el.querySelector('code');\n\t\t\t\t\tconst language: string = code?.className.match(/(?:^|\\s)language-(\\S+)/)?.[1] ?? '';\n\t\t\t\t\treturn { language };\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\tsanitize: { tags: ['pre', 'code'], attrs: ['class'] },\n\t});\n\n\tregistry.registerNodeSpec({\n\t\ttype: 'horizontal_rule',\n\t\tisVoid: true,\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTML: () => '<hr>',\n\t\tparseHTML: [{ tag: 'hr' }],\n\t\tsanitize: { tags: ['hr'] },\n\t});\n\n\tregistry.registerNodeSpec({\n\t\ttype: 'image',\n\t\tisVoid: true,\n\t\tattrs: {\n\t\t\tsrc: { default: '' },\n\t\t\talt: { default: '' },\n\t\t\ttitle: { default: '' },\n\t\t\talign: { default: 'center' },\n\t\t},\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTML(node) {\n\t\t\tconst src: string = escapeAttr(String(node.attrs?.src ?? ''));\n\t\t\tconst alt: string = escapeAttr(String(node.attrs?.alt ?? ''));\n\t\t\tconst title: string = String(node.attrs?.title ?? '');\n\t\t\tconst titleAttr: string = title ? ` title=\"${escapeAttr(title)}\"` : '';\n\t\t\tconst dimension = (name: string, value: unknown): string =>\n\t\t\t\ttypeof value === 'number' && Number.isFinite(value) && value > 0\n\t\t\t\t\t? ` ${name}=\"${String(value)}\"`\n\t\t\t\t\t: '';\n\t\t\treturn (\n\t\t\t\t`<figure><img src=\"${src}\" alt=\"${alt}\"${titleAttr}` +\n\t\t\t\t`${dimension('width', node.attrs?.width)}${dimension('height', node.attrs?.height)}></figure>`\n\t\t\t);\n\t\t},\n\t\tparseHTML: [\n\t\t\t{\n\t\t\t\ttag: 'figure',\n\t\t\t\tgetAttrs(el) {\n\t\t\t\t\tconst image: HTMLImageElement | null = el.querySelector('img');\n\t\t\t\t\treturn image ? imageAttrs(image) : false;\n\t\t\t\t},\n\t\t\t},\n\t\t\t{ tag: 'img', getAttrs: (el) => imageAttrs(el as HTMLImageElement) },\n\t\t],\n\t\tsanitize: {\n\t\t\ttags: ['figure', 'img'],\n\t\t\tattrs: ['src', 'alt', 'title', 'width', 'height'],\n\t\t},\n\t});\n\n\tregistry.registerNodeSpec({\n\t\ttype: 'table',\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTML(node, content, ctx?: HTMLExportContext) {\n\t\t\tconst widths: readonly (number | null)[] | undefined = normalizeTableColumnWidthsPx(\n\t\t\t\tnode.attrs?.columnWidthsPx,\n\t\t\t);\n\t\t\tconst colgroup: string = widths\n\t\t\t\t? `<colgroup>${widths\n\t\t\t\t\t\t.map((width: number | null): string => {\n\t\t\t\t\t\t\tconst attrs: string = serializeTableDimensionAttrs(\n\t\t\t\t\t\t\t\tTABLE_COLUMN_WIDTH_DATA_ATTRIBUTE,\n\t\t\t\t\t\t\t\t'width',\n\t\t\t\t\t\t\t\twidth,\n\t\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn `<col${attrs}>`;\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.join('')}</colgroup>`\n\t\t\t\t: '';\n\t\t\tconst tableAttrs: string = widths ? tableDimensionStyle(widths, ctx) : '';\n\t\t\treturn `<table${tableAttrs}>${colgroup}<tbody>${content}</tbody></table>`;\n\t\t},\n\t\tsanitize: {\n\t\t\ttags: ['table', 'colgroup', 'col', 'thead', 'tbody', 'tfoot'],\n\t\t\tattrs: ['span', 'width', TABLE_COLUMN_WIDTH_DATA_ATTRIBUTE],\n\t\t},\n\t});\n\n\tregistry.registerNodeSpec({\n\t\ttype: 'table_row',\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTML(node, content, ctx?: HTMLExportContext) {\n\t\t\tconst attrs: string = serializeTableDimensionAttrs(\n\t\t\t\tTABLE_ROW_MIN_HEIGHT_DATA_ATTRIBUTE,\n\t\t\t\t'height',\n\t\t\t\tnode.attrs?.minHeightPx,\n\t\t\t\tctx,\n\t\t\t);\n\t\t\treturn `<tr${attrs}>${content}</tr>`;\n\t\t},\n\t\tsanitize: {\n\t\t\ttags: ['tr'],\n\t\t\tattrs: ['height', TABLE_ROW_MIN_HEIGHT_DATA_ATTRIBUTE],\n\t\t},\n\t});\n\n\tregistry.registerNodeSpec({\n\t\ttype: 'table_cell',\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTML(node, content) {\n\t\t\tconst span = (name: string, value: unknown): string =>\n\t\t\t\ttypeof value === 'number' && Number.isInteger(value) && value > 1\n\t\t\t\t\t? ` ${name}=\"${String(value)}\"`\n\t\t\t\t\t: '';\n\t\t\treturn `<td${span('colspan', node.attrs?.colspan)}${span(\n\t\t\t\t'rowspan',\n\t\t\t\tnode.attrs?.rowspan,\n\t\t\t)}>${content}</td>`;\n\t\t},\n\t\tsanitize: { tags: ['td', 'th'], attrs: ['colspan', 'rowspan'] },\n\t});\n}\n\nfunction tableDimensionStyle(widths: readonly (number | null)[], ctx?: HTMLExportContext): string {\n\tconst minimumWidthPx: number = widths.reduce<number>(\n\t\t(total: number, width: number | null): number => total + (width ?? 60),\n\t\t0,\n\t);\n\tconst allExplicit: boolean = widths.every(\n\t\t(width: number | null): width is number => width !== null,\n\t);\n\tconst declarations: string = allExplicit\n\t\t? `width: ${String(minimumWidthPx)}px; min-width: ${String(minimumWidthPx)}px; table-layout: fixed`\n\t\t: `width: 100%; min-width: ${String(minimumWidthPx)}px; table-layout: fixed`;\n\treturn ctx?.styleAttr(declarations) ?? ` style=\"${declarations}\"`;\n}\n\nfunction imageAttrs(image: HTMLImageElement): Record<string, string | number | boolean> {\n\tconst attrs: Record<string, string | number | boolean> = {\n\t\t...inlineImageAttrs(image),\n\t\talign: 'center',\n\t};\n\tfor (const name of ['width', 'height'] as const) {\n\t\tconst value: number = Number.parseFloat(image.getAttribute(name) ?? '');\n\t\tif (Number.isFinite(value) && value > 0) attrs[name] = value;\n\t}\n\treturn attrs;\n}\n\nfunction inlineImageAttrs(image: HTMLImageElement): Record<string, string> {\n\tconst attrs: Record<string, string> = {\n\t\tsrc: image.getAttribute('src') ?? '',\n\t\talt: image.getAttribute('alt') ?? '',\n\t};\n\tconst title: string | null = image.getAttribute('title');\n\tif (title) attrs.title = title;\n\treturn attrs;\n}\n\nfunction registerMarks(registry: SchemaRegistry): void {\n\tconst tagMarks: readonly {\n\t\treadonly type: string;\n\t\treadonly rank: number;\n\t\treadonly tag: string;\n\t\treadonly parseTags: readonly string[];\n\t}[] = [\n\t\t{ type: 'bold', rank: 0, tag: 'strong', parseTags: ['strong', 'b'] },\n\t\t{ type: 'italic', rank: 1, tag: 'em', parseTags: ['em', 'i'] },\n\t\t{ type: 'underline', rank: 2, tag: 'u', parseTags: ['u'] },\n\t\t{ type: 'code', rank: 3, tag: 'code', parseTags: ['code'] },\n\t\t{ type: 'strikethrough', rank: 4, tag: 's', parseTags: ['s', 'strike', 'del'] },\n\t];\n\n\tfor (const mark of tagMarks) {\n\t\tregistry.registerMarkSpec({\n\t\t\ttype: mark.type,\n\t\t\trank: mark.rank,\n\t\t\ttoDOM: htmlOnlyDOM,\n\t\t\ttoHTMLString: (_value, content) => `<${mark.tag}>${content}</${mark.tag}>`,\n\t\t\tparseHTML: mark.parseTags.map((tag) => ({\n\t\t\t\ttag,\n\t\t\t\tgetAttrs:\n\t\t\t\t\ttag === 'code' ? (el) => (el.parentElement?.tagName === 'PRE' ? false : {}) : undefined,\n\t\t\t})),\n\t\t\tsanitize: { tags: mark.parseTags },\n\t\t});\n\t}\n\n\tregistry.registerMarkSpec({\n\t\ttype: 'link',\n\t\trank: 10,\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTMLString(mark, content) {\n\t\t\tconst href: string = escapeAttr(sanitizeHref(String(mark.attrs?.href ?? '')));\n\t\t\tconst title: string = String(mark.attrs?.title ?? '');\n\t\t\tconst titleAttr: string = title ? ` title=\"${escapeAttr(title)}\"` : '';\n\t\t\treturn `<a href=\"${href}\"${titleAttr}>${content}</a>`;\n\t\t},\n\t\tparseHTML: [\n\t\t\t{\n\t\t\t\ttag: 'a',\n\t\t\t\tgetAttrs(el) {\n\t\t\t\t\tconst href: string = sanitizeHref(el.getAttribute('href') ?? '');\n\t\t\t\t\tconst title: string | null = el.getAttribute('title');\n\t\t\t\t\treturn title ? { href, title } : { href };\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t\tsanitize: { tags: ['a'], attrs: ['href', 'title'] },\n\t});\n}\n\nfunction registerInlineNodes(registry: SchemaRegistry): void {\n\tregistry.registerInlineNodeSpec({\n\t\ttype: 'hard_break',\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTMLString: () => '<br>',\n\t\tparseHTML: [{ tag: 'br' }],\n\t\tsanitize: { tags: ['br'] },\n\t});\n\n\tregistry.registerInlineNodeSpec({\n\t\ttype: 'image_inline',\n\t\ttoDOM: htmlOnlyDOM,\n\t\ttoHTMLString(node) {\n\t\t\tconst src: string = escapeAttr(String(node.attrs.src ?? ''));\n\t\t\tconst alt: string = escapeAttr(String(node.attrs.alt ?? ''));\n\t\t\tconst title: string = String(node.attrs.title ?? '');\n\t\t\tconst titleAttr: string = title ? ` title=\"${escapeAttr(title)}\"` : '';\n\t\t\treturn `<img src=\"${src}\" alt=\"${alt}\"${titleAttr}>`;\n\t\t},\n\t\tparseHTML: [{ tag: 'img', getAttrs: (el) => inlineImageAttrs(el as HTMLImageElement) }],\n\t\tsanitize: { tags: ['img'], attrs: ['src', 'alt', 'title'] },\n\t});\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t}from"./rolldown-runtime-H_PjY6_i.mjs";import{T as e,l as s,o as n,s as i,u as r}from"./Document-827l3P80.mjs";import{a as o,i as l,r as h}from"./TypeBrands-Ch9856Gb.mjs";import{n as c}from"./ContentModel-NpAj7vGW.mjs";import{t as a}from"./DocumentParser-D2tr3ZKn.mjs";import{c as u,d as p,f,l as m,n as d,o as x,s as g,t as k,u as v}from"./MarkdownHTMLRegistry-CKEx7LkR.mjs";function y(t,e=""){return{type:t,literal:e,children:[],href:"",title:"",alt:"",inlineType:"",attrs:{},prev:null,next:null}}function b(t,e){e.prev=t,e.next=t.next,t.next&&(t.next.prev=e),t.next=e}function _(t){t.prev&&(t.prev.next=t.next),t.next&&(t.next.prev=t.prev),t.prev=null,t.next=null}var w=/[\s*_~(]/,S=/^[a-zA-Z0-9_-]+$/,A=/[a-zA-Z0-9.+_-]+@[a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)+/y,D=/[a-zA-Z0-9.+_-]/,T=/[a-zA-Z0-9_-]/;function W(t,e){const s=t[e]??"";return("h"===s||"w"===s||"m"===s||"x"===s||"f"===s)&&!(e>0&&!w.test(t[e-1]??""))&&(t.startsWith("http://",e)||t.startsWith("https://",e)||t.startsWith("ftp://",e)||t.startsWith("www.",e)||t.startsWith("mailto:",e)||t.startsWith("xmpp:",e))}function z(t,e){let s=e;for(;s<t.length;){const e=t[s]??"";if("<"===e||/\s/.test(e))break;s++}return function(t){let e=0,s=0;for(const i of t)"("===i?e++:")"===i&&s++;let n=t.length;for(;n>0;){const i=t[n-1]??"";if("?!.,:*_~".includes(i))n--;else{if(!(")"===i&&s>e)){if(";"===i){let e=n-2;for(;e>0&&/[a-zA-Z0-9]/.test(t[e]??"");)e--;if("&"===t[e]&&e<n-2){n=e;continue}}break}n--,s--}}return t.slice(0,n)}(t.slice(e,s))}function O(t){const e=t.search(/[/?#:]/);return-1===e?t:t.slice(0,e)}function Z(t){const e=t.split(".");return!(e.length<2||!e.every(t=>S.test(t))||e.slice(-2).some(t=>t.includes("_")))}function $(t){return!t.endsWith("-")&&!t.endsWith("_")}function E(t){!function(t){let e=0;for(const s of t){const n=e>0?t[e-1]:void 0;n&&"text"===n.type&&"text"===s.type?n.literal+=s.literal:(t[e]=s,e++)}t.length=e}(t);for(let e=0;e<t.length;e++){const s=t[e];if(s&&!C(s.type)){if("text"===s.type){const n=I(s.literal);n&&(t.splice(e,1,...n),e+=n.length-1);continue}s.children.length>0&&E(s.children)}}}function C(t){return"link"===t||"image"===t||"code"===t||"html_inline"===t||"inline_node"===t}function I(t){const e=[];let s=0,n=t.indexOf("@");for(;-1!==n;){let i=n;for(;i>s&&D.test(t[i-1]??"");)i--;let r=n+1;for(;r<t.length&&(T.test(t[r]??"")||"."===t[r]);)r++;for(;r>n+1&&"."===t[r-1];)r--;const o=t.slice(i,r);if(i<n&&B(o,r-n-1)){i>s&&e.push(y("text",t.slice(s,i)));const l=y("link");l.href=`mailto:${o}`,l.children=[y("text",o)],e.push(l),s=r,n=t.indexOf("@",r);continue}n=t.indexOf("@",n+1)}return 0===e.length?null:(s<t.length&&e.push(y("text",t.slice(s))),e)}function B(t,e){if(e<=0)return!1;const s=t.slice(t.indexOf("@")+1).split(".");return!(s.length<2)&&!s.some(t=>""===t)&&$(t)}var M=/^ {0,3}\[((?:\\.|[^\\[\]])+)\]:(.*)$/,L=/^( {0,3}(?:> ?)+)(.*)$/,N=/^[ \t]*(?:"((?:\\.|[^"\\])*)"|'((?:\\.|[^'\\])*)'|\(((?:\\.|[^()\\])*)\))[ \t]*$/,j=/^ {0,3}(`{3,}|~{3,})[ \t]*$/;function R(t){return t.trim().replace(/[ \t\n]+/g," ").toLowerCase().toUpperCase().toLowerCase()}function G(t,e,s,n,i){const r=t[e]??"",o=r.match(M);if(!o){if(""===s){const t=r.match(L);if(t?.[1]&&M.test(t[2]??"")&&G([t[2]??""],0,t[1],n,[])>0)return i.push(t[1].trimEnd()),1}return 0}const l=o[1]??"";let h=(o[2]??"").trim(),c=1;if(""===h&&""===s){const s=t[e+c]??"";if(""===s.trim())return 0;h=s.trim(),c++}if(""===h)return 0;const a=function(t){if("<"===t[0]){let e=1;for(;e<t.length;){const s=t[e]??"";if("\\"!==s){if(">"===s)return{href:p(t.slice(1,e)),end:e+1};if("<"===s)return null;e++}else e+=2}return null}let e=0,s=0;for(;s<t.length;){const n=t[s]??"";if(" "===n||"\t"===n)break;if("\\"!==n){if("("===n&&e++,")"===n){if(0===e)break;e--}s++}else s+=2}return 0===s?null:{href:p(t.slice(0,s)),end:s}}(h);if(!a)return 0;const u=h.slice(a.end).trim();let f;if(""!==u){const t=u.match(N);if(!t)return 0;f=H(t)}else if(""===s){const s=(t[e+c]??"").match(N);s&&(f=H(s),c++)}const m=R(l);return""===m||n.has(m)||n.set(m,void 0!==f?{href:a.href,title:f}:{href:a.href}),c}function H(t){return p(t[1]??t[2]??t[3]??"")}var q=8192,F=/[\p{P}\p{S}]/u,K=/[!-/:-@[-`{-~]/,P=/[!-/:-@[-`{-~]/,J=new Set(["u","sup","sub","span","mark","b","i","em","strong","code","s","del","small","abbr","kbd","a"]);function U(t){return""===t||/\s/.test(t)}function Q(t){return""!==t&&(t.charCodeAt(0)<128?K.test(t):F.test(t))}var V=class{pos=0;text;len;ctx;delimiters=null;brackets=null;tail=null;constructor(t,e){this.text=t,this.len=t.length,this.ctx=e}parse(){const t=y("text");for(this.tail=t;this.pos<this.len;){const t=this.parseToken();t&&this.appendNode(t)}return this.processEmphasis(null),function(t){const e=[];let s=t.next;for(;s;)e.push(s),s=s.next;return e}(t)}appendNode(t){this.tail&&b(this.tail,t),this.tail=t}parseToken(){const t=this.text[this.pos]??"";switch(t){case"\n":return this.parseNewline();case"\\":return this.parseBackslash();case"`":return this.parseBackticks();case"*":case"_":case"~":case"=":case"^":return this.parseDelimiterRun(t);case"[":return this.parseOpenBracket(!1);case"!":return"["===this.text[this.pos+1]?this.parseOpenBracket(!0):(this.pos++,y("text","!"));case"]":return this.parseCloseBracket();case"<":return this.parseLessThan();case"&":return this.parseEntity();default:{const t=this.parseGfmAutolink();if(t)return t;return this.parseExtension()||this.parseString()}}}parseString(){const t=this.pos;for(this.pos++;this.pos<this.len;){const t=this.text[this.pos]??"";if("\n\\`*_~=^[]!<&".includes(t))break;if(this.matchesGfmAutolinkStart())break;if(this.matchesExtensionStart())break;this.pos++}return y("text",this.text.slice(t,this.pos))}parseGfmAutolink(){if(!this.ctx.opts.gfm||this.brackets)return null;const t=(e=this.text,s=this.pos,W(e,s)?e.startsWith("http://",s)||e.startsWith("https://",s)||e.startsWith("ftp://",s)?function(t,e){const s=z(t,e),n=t.startsWith("https://",e)?8:t.startsWith("http://",e)?7:6;return Z(O(s.slice(n)))?{href:s,display:s,length:s.length}:null}(e,s):e.startsWith("www.",s)?function(t,e){const s=z(t,e);return Z(O(s))?{href:`http://${s}`,display:s,length:s.length}:null}(e,s):function(t,e){const s=t.startsWith("mailto:",e)?7:5;A.lastIndex=e+s;const n=A.exec(t)?.[0];if(!n||!$(n))return null;const i=t.slice(e,e+s+n.length);return{href:i,display:i,length:i.length}}(e,s):null);var e,s;if(!t)return null;this.pos+=t.length;const n=y("link");return n.href=t.href,n.children=[y("text",t.display)],n}matchesGfmAutolinkStart(){return!(!this.ctx.opts.gfm||this.brackets)&&W(this.text,this.pos)}parseExtension(){for(const t of this.ctx.opts.syntaxExtensions){const e=t.matchInline?.(this.text,this.pos);if(e){this.pos+=e.length;const t=y("inline_node");return t.inlineType=e.type,t.attrs=e.attrs,t}}return null}matchesExtensionStart(){for(const t of this.ctx.opts.syntaxExtensions)if(t.matchInline?.(this.text,this.pos))return!0;return!1}parseNewline(){for(this.pos++;" "===this.text[this.pos];)this.pos++;const t=this.tail;if(t&&"text"===t.type&&t.literal.endsWith(" ")){const e=t.literal.endsWith(" ");return t.literal=t.literal.replace(/[ \t]+$/,""),y(e?"hardbreak":"softbreak")}return y("softbreak")}parseBackslash(){this.pos++;const t=this.text[this.pos]??"";if("\n"===t){for(this.pos++;" "===this.text[this.pos];)this.pos++;return y("hardbreak")}return P.test(t)?(this.pos++,y("text",t)):y("text","\\")}parseBackticks(){const t=this.pos;let e=0;for(;"`"===this.text[this.pos];)e++,this.pos++;const s="`".repeat(e),n=this.pos;let i=n;for(;i<this.len;){const t=this.text.indexOf(s,i);if(-1===t)break;if("`"!==this.text[t-1]&&"`"!==this.text[t+e]){let s=this.text.slice(n,t).replace(/\n/g," ");return s.length>2&&s.startsWith(" ")&&s.endsWith(" ")&&""!==s.trim()&&(s=s.slice(1,-1)),this.pos=t+e,y("code",s)}i=t+1}return this.pos=n,y("text",this.text.slice(t,n))}parseDelimiterRun(t){const{numdelims:e,canOpen:s,canClose:n}=this.scanDelims(t),i=y("text",t.repeat(e)),r={cc:t,numdelims:e,origdelims:e,node:i,canOpen:s,canClose:n,prev:this.delimiters,next:null};return this.delimiters&&(this.delimiters.next=r),this.delimiters=r,i}scanDelims(t){const e=this.pos;for(;this.text[this.pos]===t;)this.pos++;const s=this.pos-e,n=0===e?"":this.text[e-1]??"",i=this.text[this.pos]??"",r=U(n),o=U(i),l=Q(n),h=Q(i),c=!o&&(!h||r||l),a=!r&&(!l||o||h);let u,p;return"_"===t?(u=c&&(!a||l),p=a&&(!c||h)):(u=c,p=a),{numdelims:s,canOpen:u,canClose:p}}parseOpenBracket(t){const e=t?"![":"[";this.pos+=e.length;const s=y("text",e);return this.brackets={node:s,prev:this.brackets,prevDelim:this.delimiters,index:this.pos,image:t,active:!0},s}parseCloseBracket(){this.pos++;const t=this.brackets;if(!t||!t.active)return t&&(this.brackets=t.prev),y("text","]");const e=this.parseLinkTarget(t);if(!e)return this.brackets=t.prev,y("text","]");const s=y(t.image?"image":"link");s.href=e.href,s.title=e.title,this.processEmphasis(t.prevDelim);let n=t.node.next;for(;n;){const t=n.next;_(n),s.children.push(n),n=t}if(t.image&&(s.alt=tt(s.children),s.children=[]),b(t.node,s),_(t.node),this.tail=s,!t.image){let e=t.prev;for(;e;)e.image||(e.active=!1),e=e.prev}return this.brackets=t.prev,null}parseLinkTarget(t){if("("===this.text[this.pos]){const t=this.parseInlineDestination();if(t)return t}let e=this.text.slice(t.index,this.pos-1),s=!1,n=this.pos;if("["===this.text[this.pos]){const t=this.text.indexOf("]",this.pos+1);if(-1!==t){const i=this.text.slice(this.pos+1,t);""!==i.trim()&&(e=i,s=!0),n=t+1}}if(!s&&e.includes("["))return null;const i=this.ctx.linkRefs.get(R(e));return i?(this.pos=n,{href:i.href,title:i.title??""}):null}parseInlineDestination(){let t=this.pos+1;for(;" "===this.text[t]||"\n"===this.text[t];)t++;let e="";if("<"===this.text[t]){let s=t+1;const n=Math.min(this.len,t+1+q);for(;s<n;){const t=this.text[s]??"";if("\\"===t&&P.test(this.text[s+1]??""))s+=2;else{if(">"===t||"<"===t||"\n"===t)break;s++}}if(">"!==this.text[s])return null;e=p(this.text.slice(t+1,s)),t=s+1}else{let s=0;const n=Math.min(this.len,t+q);for(;t<n;){const n=this.text[t]??"";if("\\"===n&&P.test(this.text[t+1]??""))e+=this.text[t+1],t+=2;else{if("("===n)s++;else if(")"===n){if(0===s)break;s--}else if(" "===n||"\t"===n||"\n"===n||"["===n||"]"===n)break;e+=n,t++}}if(t>=n&&")"!==this.text[t])return null;e=m(e)}for(;" "===this.text[t]||"\n"===this.text[t];)t++;let s="";const n=this.text[t]??"";if('"'===n||"'"===n||"("===n){const e=this.parseLinkTitle(t);if(!e)return null;s=e.title,t=e.next}for(;" "===this.text[t]||"\n"===this.text[t];)t++;return")"!==this.text[t]?null:(this.pos=t+1,{href:e,title:s})}parseLinkTitle(t){const e=this.text[t]??"",s="("===e?")":e;let n="",i=t+1;const r=Math.min(this.len,t+1+q);for(;i<r;){const t=this.text[i]??"";if("\\"===t&&P.test(this.text[i+1]??""))n+=this.text[i+1],i+=2;else{if(t===s)return{title:m(n),next:i+1};n+=t,i++}}return null}parseEntity(){const t=f(this.text,this.pos);return t?.[1]?(this.pos+=t[0].length,y("text",v(t[1]))):(this.pos++,y("text","&"))}parseLessThan(){const t=this.parseAutolink();if(t)return t;return this.parseInlineHtml()||(this.pos++,y("text","<"))}parseAutolink(){const t=this.text.slice(this.pos),e=t.match(/^<([a-zA-Z][a-zA-Z0-9+.-]{1,31}:[^<>\s]*)>/);if(e?.[1]){this.pos+=e[0].length;const t=y("link");return t.href=e[1],t.children=[y("text",e[1])],t}const s=t.match(/^<([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)>/);if(s?.[1]){this.pos+=s[0].length;const t=y("link");return t.href=`mailto:${s[1]}`,t.children=[y("text",s[1])],t}return null}parseInlineHtml(){const t=this.text.slice(this.pos),e=t.match(/^<([a-zA-Z][a-zA-Z0-9-]*)(?:\s[^<>]*)?>/);if(!e?.[1]){const e=t.match(/^<!--[\s\S]*?-->/);return e?(this.pos+=e[0].length,y("html_inline",Y(e[0]))):null}const s=e[1].toLowerCase();if(J.has(s)){const t=`</${s}>`,n=this.text.toLowerCase().indexOf(t,this.pos+e[0].length);if(-1!==n){const e=n+t.length,s=this.text.slice(this.pos,e);return this.pos=e,y("html_inline",Y(s))}}return this.pos+=e[0].length,y("html_inline",Y(e[0]))}processEmphasis(t){const e=/* @__PURE__ */new Map,s=s=>{const n=X(s);return e.has(n)?e.get(n)??null:t};let n=t?t.next:this.firstDelimiter();for(;n;){if(!n.canClose){n=n.next;continue}const i=n.cc;let r=n.prev,o=!1;const l=s(n);for(;r&&r!==t&&r!==l;){if(r.cc===i&&r.canOpen&&this.emphMatches(r,n)){o=!0;break}r=r.prev}if(!o){e.set(X(n),n.prev),n.canOpen||this.removeDelimiter(n),n=n.next;continue}const h=r,c=this.wrapCount(i,h,n);if(0!==c){if(this.wrapEmphasis(i,h,n,c),h.numdelims-=c,n.numdelims-=c,h.node.literal=h.node.literal.slice(c),n.node.literal=n.node.literal.slice(c),this.removeDelimitersBetween(h,n),0===h.numdelims&&this.removeDelimiter(h),0===n.numdelims){const t=n.next;this.removeDelimiter(n),n=t}}else n=n.next}for(;this.delimiters&&this.delimiters!==t;)this.removeDelimiter(this.delimiters)}firstDelimiter(){let t=this.delimiters;for(;t?.prev;)t=t.prev;return t}emphMatches(t,e){return"*"!==t.cc&&"_"!==t.cc||!((e.canOpen||t.canClose)&&e.origdelims%3!=0&&(t.origdelims+e.origdelims)%3==0)}wrapCount(t,e,s){const n=e.numdelims>=2&&s.numdelims>=2;return"*"===t||"_"===t?n?2:1:"~"===t?this.ctx.opts.gfm&&n?2:this.ctx.opts.extendedInlineSyntax?1:0:"="===t?this.ctx.opts.extendedInlineSyntax&&n?2:0:"^"===t&&this.ctx.opts.extendedInlineSyntax?1:0}wrapKind(t,e){return"*"===t||"_"===t?2===e?"strong":"emph":"~"===t?2===e?"strike":"sub":"="===t?"highlight":"sup"}wrapEmphasis(t,e,s,n){const i=y(this.wrapKind(t,n));let r=e.node.next;for(;r&&r!==s.node;){const t=r.next;_(r),i.children.push(r),r=t}b(e.node,i)}removeDelimitersBetween(t,e){let s=e.prev;for(;s&&s!==t;){const t=s.prev;this.removeDelimiter(s),s=t}}removeDelimiter(t){t.prev&&(t.prev.next=t.next),t.next&&(t.next.prev=t.prev),t.next||(this.delimiters=t.prev)}};function X(t){return`${t.cc}${t.canOpen?1:0}${t.origdelims%3}`}function Y(t){return t.replace(/\n[ \t]*/g," ")}function tt(t){let e="";for(const s of t)"text"===s.type||"code"===s.type?e+=s.literal:"softbreak"===s.type||"hardbreak"===s.type?e+=" ":s.children.length?e+=tt(s.children):s.alt&&(e+=s.alt);return e}var et={emph:"italic",strong:"bold",strike:"strikethrough",highlight:"highlight",sup:"superscript",sub:"subscript"};function st(t,e,s,n){for(const i of t)nt(i,e,s,n)}function nt(t,e,n,i){switch(t.type){case"text":return void(t.literal&&i.push(r(t.literal,[...e])));case"softbreak":return void i.push(r(" ",[...e]));case"hardbreak":return void i.push(s(h("hard_break"),{}));case"code":return void i.push(r(t.literal,it(e,n,"code")));case"link":{const s={href:t.href};return t.title&&(s.title=t.title),void st(t.children,it(e,n,"link",s),n,i)}case"image":return void function(t,e,n,i){if(!n.registry||void 0!==n.registry.getInlineNodeSpec("image_inline")){const n={src:t.href,alt:t.alt};return t.title&&(n.title=t.title),void i.push(s(h("image_inline"),n,[...e]))}t.alt&&i.push(r(t.alt,[...e]))}(t,e,n,i);case"inline_node":return void i.push(s(h(t.inlineType),t.attrs,[...e]));case"html_inline":return void function(t,e,n,i){if((!n.registry||void 0!==n.registry.getInlineNodeSpec("hard_break"))&&/^<br\s*\/?>$/i.test(t.trim()))return void i.push(s(h("hard_break"),{},[...e]));const o=a(`<p>${t}</p>`,k(n.registry)).children[0];if(!o)return;let l=!1;for(const h of o.children)"text"in h&&""!==h.text?(i.push(r(h.text,rt(e,h.marks))),l=!0):"inlineType"in h&&(i.push(s(h.inlineType,h.attrs,rt(e,h.marks))),l=!0);l||n.registry||i.push(r(t,[...e]))}(t.literal,e,n,i);default:{const s=et[t.type];st(t.children,s?it(e,n,s):e,n,i)}}}function it(t,e,s,n){if(!function(t,e){return!t.registry||void 0!==t.registry.getMarkSpec(e)}(e,s))return[...t];const i=n?{type:l(s),attrs:n}:{type:l(s)};return[...t,i]}function rt(t,e){const s=[...t];for(const n of e)s.some(t=>t.type===n.type)||s.push(n);return s}function ot(t,e){if(t.length!==e.length)return!1;const s=t=>`${t.type}:${JSON.stringify(t.attrs??{})}`,n=new Set(e.map(s));return t.every(t=>n.has(s(t)))}function lt(t,e){const s=new V(t,e).parse();e.opts.gfm&&E(s);const n=[];st(s,[],e,n);const i=function(t){const e=[];for(const s of t){const t=e[e.length-1];"text"in s&&t&&"text"in t&&ot(t.marks,s.marks)?e[e.length-1]={type:"text",text:t.text+s.text,marks:t.marks}:e.push(s)}return e}(n);return i.length>0?i:[r("")]}function ht(t){const e=t?.flavor??"gfm";return{flavor:e,gfm:"gfm"===e,extendedInlineSyntax:t?.extendedInlineSyntax??!1,htmlFallback:!1!==t?.htmlFallback,syntaxExtensions:t?.syntaxExtensions??[]}}var ct=/* @__PURE__ */t({parseMarkdownToDocument:()=>at});function at(t,e,s){const{source:n,linkRefs:r}=function(t){const e=/* @__PURE__ */new Map,s=t.split("\n"),n=[];let i=null,r=!1,o=0;for(;o<s.length;){const t=s[o]??"";if(i){n.push(t);const e=t.match(j)?.[1];e&&e[0]===i.char&&e.length>=i.len&&(i=null),r=!1,o++;continue}const l=g(t);if(l?.[1]){i={char:l[1][0]??"`",len:l[1].length},n.push(t),r=!1,o++;continue}const h=r?0:G(s,o,"",e,n);h>0?o+=h:(n.push(t),r=""!==t.trim()&&!d.test(t)&&!x.test(t),o++)}return{source:n.join("\n"),linkRefs:e}}(t.replace(/\r\n?/g,"\n")),o={registry:e,opts:ht(s),linkRefs:r},l=ut(u(n,o.opts.gfm,o.opts.syntaxExtensions),o);if(0===l.length)return i();const h=i(l);return e?c(h,e):h}function ut(t,e){const s=[];for(const n of t)pt(n,s,e);return s}function pt(t,s,i){switch(t.type){case"heading":return void s.push(ft("heading",lt(t.text,i),i,{level:t.level}));case"paragraph":{const l=lt(t.text,i),h=function(t,s){if(1!==t.length)return null;const i=t[0];if(!i||!e(i)||"image_inline"!==i.inlineType)return null;if(i.marks.length>0)return null;if(s.registry&&!s.registry.getNodeSpec("image"))return null;const l={src:String(i.attrs.src??""),alt:String(i.attrs.alt??""),align:"center"};return i.attrs.title&&(l.title=String(i.attrs.title)),n(o("image"),[r("")],void 0,l)}(l,i);return void s.push(h??ft("paragraph",l,i))}case"table":return void s.push(function(t,e,s,i){if(i.registry&&!i.registry.getNodeSpec("table"))return ft("paragraph",lt([e,...s].map(t=>t.join(" | ")).join("\n"),i),i);const r=e=>{const s=e.map((e,s)=>{const r=t[s]??null,l=n(o("paragraph"),lt(e,i),void 0,r?{align:r}:void 0);return n(o("table_cell"),[l])});return n(o("table_row"),s)},l=e.length,h=[r(e),...s.map(t=>r((t=>{if(t.length===l)return t;const e=t.slice(0,l);for(;e.length<l;)e.push("");return e})(t)))];return n(o("table"),h)}(t.aligns,t.header,t.rows,i));case"extension_block":return void s.push(ft(t.nodeType,[r("")],i,t.attrs));case"code_block":return void s.push(ft("code_block",[r(t.code)],i,{language:t.language}));case"hr":return void s.push(ft("horizontal_rule",[r("")],i));case"list_item":{const e={listType:t.listType,indent:t.indent,checked:t.checked};if(t.children&&t.children.length>0){const r=ut(t.children,i);return i.registry&&!i.registry.getNodeSpec("list_item")?void s.push(...r):void s.push(n(o("list_item"),r,void 0,e))}return void s.push(ft("list_item",lt(t.text,i),i,e))}case"blockquote":{const e=ut(t.children,i);return 0===e.length&&e.push(n(o("paragraph"),[r("")])),void s.push(function(t,e,s){const i=mt(t,s);return i!==o(t)?e[0]??n(o("paragraph"),[r("")]):n(i,e)}("blockquote",e,i))}case"html":if(function(t){let e=t.trim();for(;e.startsWith("\x3c!--");){const t=e.indexOf("--\x3e");if(-1===t)return!1;e=e.slice(t+3).trim()}return""===e}(t.html))return;for(const e of a(t.html,k(i.registry)).children)s.push(e);return}}function ft(t,e,s,i){const l=mt(t,s);return n(l,e.length>0?e:[r("")],void 0,i&&l===o(t)?i:void 0)}function mt(t,e){return e.registry&&!e.registry.getNodeSpec(t)?o("paragraph"):o(t)}export{at as n,ct as t};
|
|
2
|
-
//# sourceMappingURL=MarkdownParser-
|
|
1
|
+
import{t}from"./rolldown-runtime-H_PjY6_i.mjs";import{T as e,l as s,o as n,s as i,u as r}from"./Document-827l3P80.mjs";import{a as o,i as l,r as h}from"./TypeBrands-Ch9856Gb.mjs";import{n as c}from"./ContentModel-NpAj7vGW.mjs";import{t as a}from"./DocumentParser-D2tr3ZKn.mjs";import{c as u,d as p,f,l as m,n as d,o as x,s as g,t as k,u as v}from"./MarkdownHTMLRegistry-Q7l0d6Ma.mjs";function y(t,e=""){return{type:t,literal:e,children:[],href:"",title:"",alt:"",inlineType:"",attrs:{},prev:null,next:null}}function b(t,e){e.prev=t,e.next=t.next,t.next&&(t.next.prev=e),t.next=e}function _(t){t.prev&&(t.prev.next=t.next),t.next&&(t.next.prev=t.prev),t.prev=null,t.next=null}var w=/[\s*_~(]/,S=/^[a-zA-Z0-9_-]+$/,A=/[a-zA-Z0-9.+_-]+@[a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)+/y,D=/[a-zA-Z0-9.+_-]/,T=/[a-zA-Z0-9_-]/;function W(t,e){const s=t[e]??"";return("h"===s||"w"===s||"m"===s||"x"===s||"f"===s)&&!(e>0&&!w.test(t[e-1]??""))&&(t.startsWith("http://",e)||t.startsWith("https://",e)||t.startsWith("ftp://",e)||t.startsWith("www.",e)||t.startsWith("mailto:",e)||t.startsWith("xmpp:",e))}function z(t,e){let s=e;for(;s<t.length;){const e=t[s]??"";if("<"===e||/\s/.test(e))break;s++}return function(t){let e=0,s=0;for(const i of t)"("===i?e++:")"===i&&s++;let n=t.length;for(;n>0;){const i=t[n-1]??"";if("?!.,:*_~".includes(i))n--;else{if(!(")"===i&&s>e)){if(";"===i){let e=n-2;for(;e>0&&/[a-zA-Z0-9]/.test(t[e]??"");)e--;if("&"===t[e]&&e<n-2){n=e;continue}}break}n--,s--}}return t.slice(0,n)}(t.slice(e,s))}function O(t){const e=t.search(/[/?#:]/);return-1===e?t:t.slice(0,e)}function Z(t){const e=t.split(".");return!(e.length<2||!e.every(t=>S.test(t))||e.slice(-2).some(t=>t.includes("_")))}function $(t){return!t.endsWith("-")&&!t.endsWith("_")}function E(t){!function(t){let e=0;for(const s of t){const n=e>0?t[e-1]:void 0;n&&"text"===n.type&&"text"===s.type?n.literal+=s.literal:(t[e]=s,e++)}t.length=e}(t);for(let e=0;e<t.length;e++){const s=t[e];if(s&&!C(s.type)){if("text"===s.type){const n=I(s.literal);n&&(t.splice(e,1,...n),e+=n.length-1);continue}s.children.length>0&&E(s.children)}}}function C(t){return"link"===t||"image"===t||"code"===t||"html_inline"===t||"inline_node"===t}function I(t){const e=[];let s=0,n=t.indexOf("@");for(;-1!==n;){let i=n;for(;i>s&&D.test(t[i-1]??"");)i--;let r=n+1;for(;r<t.length&&(T.test(t[r]??"")||"."===t[r]);)r++;for(;r>n+1&&"."===t[r-1];)r--;const o=t.slice(i,r);if(i<n&&B(o,r-n-1)){i>s&&e.push(y("text",t.slice(s,i)));const l=y("link");l.href=`mailto:${o}`,l.children=[y("text",o)],e.push(l),s=r,n=t.indexOf("@",r);continue}n=t.indexOf("@",n+1)}return 0===e.length?null:(s<t.length&&e.push(y("text",t.slice(s))),e)}function B(t,e){if(e<=0)return!1;const s=t.slice(t.indexOf("@")+1).split(".");return!(s.length<2)&&!s.some(t=>""===t)&&$(t)}var M=/^ {0,3}\[((?:\\.|[^\\[\]])+)\]:(.*)$/,L=/^( {0,3}(?:> ?)+)(.*)$/,N=/^[ \t]*(?:"((?:\\.|[^"\\])*)"|'((?:\\.|[^'\\])*)'|\(((?:\\.|[^()\\])*)\))[ \t]*$/,j=/^ {0,3}(`{3,}|~{3,})[ \t]*$/;function R(t){return t.trim().replace(/[ \t\n]+/g," ").toLowerCase().toUpperCase().toLowerCase()}function G(t,e,s,n,i){const r=t[e]??"",o=r.match(M);if(!o){if(""===s){const t=r.match(L);if(t?.[1]&&M.test(t[2]??"")&&G([t[2]??""],0,t[1],n,[])>0)return i.push(t[1].trimEnd()),1}return 0}const l=o[1]??"";let h=(o[2]??"").trim(),c=1;if(""===h&&""===s){const s=t[e+c]??"";if(""===s.trim())return 0;h=s.trim(),c++}if(""===h)return 0;const a=function(t){if("<"===t[0]){let e=1;for(;e<t.length;){const s=t[e]??"";if("\\"!==s){if(">"===s)return{href:p(t.slice(1,e)),end:e+1};if("<"===s)return null;e++}else e+=2}return null}let e=0,s=0;for(;s<t.length;){const n=t[s]??"";if(" "===n||"\t"===n)break;if("\\"!==n){if("("===n&&e++,")"===n){if(0===e)break;e--}s++}else s+=2}return 0===s?null:{href:p(t.slice(0,s)),end:s}}(h);if(!a)return 0;const u=h.slice(a.end).trim();let f;if(""!==u){const t=u.match(N);if(!t)return 0;f=H(t)}else if(""===s){const s=(t[e+c]??"").match(N);s&&(f=H(s),c++)}const m=R(l);return""===m||n.has(m)||n.set(m,void 0!==f?{href:a.href,title:f}:{href:a.href}),c}function H(t){return p(t[1]??t[2]??t[3]??"")}var q=8192,F=/[\p{P}\p{S}]/u,K=/[!-/:-@[-`{-~]/,P=/[!-/:-@[-`{-~]/,J=new Set(["u","sup","sub","span","mark","b","i","em","strong","code","s","del","small","abbr","kbd","a"]);function U(t){return""===t||/\s/.test(t)}function Q(t){return""!==t&&(t.charCodeAt(0)<128?K.test(t):F.test(t))}var V=class{pos=0;text;len;ctx;delimiters=null;brackets=null;tail=null;constructor(t,e){this.text=t,this.len=t.length,this.ctx=e}parse(){const t=y("text");for(this.tail=t;this.pos<this.len;){const t=this.parseToken();t&&this.appendNode(t)}return this.processEmphasis(null),function(t){const e=[];let s=t.next;for(;s;)e.push(s),s=s.next;return e}(t)}appendNode(t){this.tail&&b(this.tail,t),this.tail=t}parseToken(){const t=this.text[this.pos]??"";switch(t){case"\n":return this.parseNewline();case"\\":return this.parseBackslash();case"`":return this.parseBackticks();case"*":case"_":case"~":case"=":case"^":return this.parseDelimiterRun(t);case"[":return this.parseOpenBracket(!1);case"!":return"["===this.text[this.pos+1]?this.parseOpenBracket(!0):(this.pos++,y("text","!"));case"]":return this.parseCloseBracket();case"<":return this.parseLessThan();case"&":return this.parseEntity();default:{const t=this.parseGfmAutolink();if(t)return t;return this.parseExtension()||this.parseString()}}}parseString(){const t=this.pos;for(this.pos++;this.pos<this.len;){const t=this.text[this.pos]??"";if("\n\\`*_~=^[]!<&".includes(t))break;if(this.matchesGfmAutolinkStart())break;if(this.matchesExtensionStart())break;this.pos++}return y("text",this.text.slice(t,this.pos))}parseGfmAutolink(){if(!this.ctx.opts.gfm||this.brackets)return null;const t=(e=this.text,s=this.pos,W(e,s)?e.startsWith("http://",s)||e.startsWith("https://",s)||e.startsWith("ftp://",s)?function(t,e){const s=z(t,e),n=t.startsWith("https://",e)?8:t.startsWith("http://",e)?7:6;return Z(O(s.slice(n)))?{href:s,display:s,length:s.length}:null}(e,s):e.startsWith("www.",s)?function(t,e){const s=z(t,e);return Z(O(s))?{href:`http://${s}`,display:s,length:s.length}:null}(e,s):function(t,e){const s=t.startsWith("mailto:",e)?7:5;A.lastIndex=e+s;const n=A.exec(t)?.[0];if(!n||!$(n))return null;const i=t.slice(e,e+s+n.length);return{href:i,display:i,length:i.length}}(e,s):null);var e,s;if(!t)return null;this.pos+=t.length;const n=y("link");return n.href=t.href,n.children=[y("text",t.display)],n}matchesGfmAutolinkStart(){return!(!this.ctx.opts.gfm||this.brackets)&&W(this.text,this.pos)}parseExtension(){for(const t of this.ctx.opts.syntaxExtensions){const e=t.matchInline?.(this.text,this.pos);if(e){this.pos+=e.length;const t=y("inline_node");return t.inlineType=e.type,t.attrs=e.attrs,t}}return null}matchesExtensionStart(){for(const t of this.ctx.opts.syntaxExtensions)if(t.matchInline?.(this.text,this.pos))return!0;return!1}parseNewline(){for(this.pos++;" "===this.text[this.pos];)this.pos++;const t=this.tail;if(t&&"text"===t.type&&t.literal.endsWith(" ")){const e=t.literal.endsWith(" ");return t.literal=t.literal.replace(/[ \t]+$/,""),y(e?"hardbreak":"softbreak")}return y("softbreak")}parseBackslash(){this.pos++;const t=this.text[this.pos]??"";if("\n"===t){for(this.pos++;" "===this.text[this.pos];)this.pos++;return y("hardbreak")}return P.test(t)?(this.pos++,y("text",t)):y("text","\\")}parseBackticks(){const t=this.pos;let e=0;for(;"`"===this.text[this.pos];)e++,this.pos++;const s="`".repeat(e),n=this.pos;let i=n;for(;i<this.len;){const t=this.text.indexOf(s,i);if(-1===t)break;if("`"!==this.text[t-1]&&"`"!==this.text[t+e]){let s=this.text.slice(n,t).replace(/\n/g," ");return s.length>2&&s.startsWith(" ")&&s.endsWith(" ")&&""!==s.trim()&&(s=s.slice(1,-1)),this.pos=t+e,y("code",s)}i=t+1}return this.pos=n,y("text",this.text.slice(t,n))}parseDelimiterRun(t){const{numdelims:e,canOpen:s,canClose:n}=this.scanDelims(t),i=y("text",t.repeat(e)),r={cc:t,numdelims:e,origdelims:e,node:i,canOpen:s,canClose:n,prev:this.delimiters,next:null};return this.delimiters&&(this.delimiters.next=r),this.delimiters=r,i}scanDelims(t){const e=this.pos;for(;this.text[this.pos]===t;)this.pos++;const s=this.pos-e,n=0===e?"":this.text[e-1]??"",i=this.text[this.pos]??"",r=U(n),o=U(i),l=Q(n),h=Q(i),c=!o&&(!h||r||l),a=!r&&(!l||o||h);let u,p;return"_"===t?(u=c&&(!a||l),p=a&&(!c||h)):(u=c,p=a),{numdelims:s,canOpen:u,canClose:p}}parseOpenBracket(t){const e=t?"![":"[";this.pos+=e.length;const s=y("text",e);return this.brackets={node:s,prev:this.brackets,prevDelim:this.delimiters,index:this.pos,image:t,active:!0},s}parseCloseBracket(){this.pos++;const t=this.brackets;if(!t||!t.active)return t&&(this.brackets=t.prev),y("text","]");const e=this.parseLinkTarget(t);if(!e)return this.brackets=t.prev,y("text","]");const s=y(t.image?"image":"link");s.href=e.href,s.title=e.title,this.processEmphasis(t.prevDelim);let n=t.node.next;for(;n;){const t=n.next;_(n),s.children.push(n),n=t}if(t.image&&(s.alt=tt(s.children),s.children=[]),b(t.node,s),_(t.node),this.tail=s,!t.image){let e=t.prev;for(;e;)e.image||(e.active=!1),e=e.prev}return this.brackets=t.prev,null}parseLinkTarget(t){if("("===this.text[this.pos]){const t=this.parseInlineDestination();if(t)return t}let e=this.text.slice(t.index,this.pos-1),s=!1,n=this.pos;if("["===this.text[this.pos]){const t=this.text.indexOf("]",this.pos+1);if(-1!==t){const i=this.text.slice(this.pos+1,t);""!==i.trim()&&(e=i,s=!0),n=t+1}}if(!s&&e.includes("["))return null;const i=this.ctx.linkRefs.get(R(e));return i?(this.pos=n,{href:i.href,title:i.title??""}):null}parseInlineDestination(){let t=this.pos+1;for(;" "===this.text[t]||"\n"===this.text[t];)t++;let e="";if("<"===this.text[t]){let s=t+1;const n=Math.min(this.len,t+1+q);for(;s<n;){const t=this.text[s]??"";if("\\"===t&&P.test(this.text[s+1]??""))s+=2;else{if(">"===t||"<"===t||"\n"===t)break;s++}}if(">"!==this.text[s])return null;e=p(this.text.slice(t+1,s)),t=s+1}else{let s=0;const n=Math.min(this.len,t+q);for(;t<n;){const n=this.text[t]??"";if("\\"===n&&P.test(this.text[t+1]??""))e+=this.text[t+1],t+=2;else{if("("===n)s++;else if(")"===n){if(0===s)break;s--}else if(" "===n||"\t"===n||"\n"===n||"["===n||"]"===n)break;e+=n,t++}}if(t>=n&&")"!==this.text[t])return null;e=m(e)}for(;" "===this.text[t]||"\n"===this.text[t];)t++;let s="";const n=this.text[t]??"";if('"'===n||"'"===n||"("===n){const e=this.parseLinkTitle(t);if(!e)return null;s=e.title,t=e.next}for(;" "===this.text[t]||"\n"===this.text[t];)t++;return")"!==this.text[t]?null:(this.pos=t+1,{href:e,title:s})}parseLinkTitle(t){const e=this.text[t]??"",s="("===e?")":e;let n="",i=t+1;const r=Math.min(this.len,t+1+q);for(;i<r;){const t=this.text[i]??"";if("\\"===t&&P.test(this.text[i+1]??""))n+=this.text[i+1],i+=2;else{if(t===s)return{title:m(n),next:i+1};n+=t,i++}}return null}parseEntity(){const t=f(this.text,this.pos);return t?.[1]?(this.pos+=t[0].length,y("text",v(t[1]))):(this.pos++,y("text","&"))}parseLessThan(){const t=this.parseAutolink();if(t)return t;return this.parseInlineHtml()||(this.pos++,y("text","<"))}parseAutolink(){const t=this.text.slice(this.pos),e=t.match(/^<([a-zA-Z][a-zA-Z0-9+.-]{1,31}:[^<>\s]*)>/);if(e?.[1]){this.pos+=e[0].length;const t=y("link");return t.href=e[1],t.children=[y("text",e[1])],t}const s=t.match(/^<([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)>/);if(s?.[1]){this.pos+=s[0].length;const t=y("link");return t.href=`mailto:${s[1]}`,t.children=[y("text",s[1])],t}return null}parseInlineHtml(){const t=this.text.slice(this.pos),e=t.match(/^<([a-zA-Z][a-zA-Z0-9-]*)(?:\s[^<>]*)?>/);if(!e?.[1]){const e=t.match(/^<!--[\s\S]*?-->/);return e?(this.pos+=e[0].length,y("html_inline",Y(e[0]))):null}const s=e[1].toLowerCase();if(J.has(s)){const t=`</${s}>`,n=this.text.toLowerCase().indexOf(t,this.pos+e[0].length);if(-1!==n){const e=n+t.length,s=this.text.slice(this.pos,e);return this.pos=e,y("html_inline",Y(s))}}return this.pos+=e[0].length,y("html_inline",Y(e[0]))}processEmphasis(t){const e=/* @__PURE__ */new Map,s=s=>{const n=X(s);return e.has(n)?e.get(n)??null:t};let n=t?t.next:this.firstDelimiter();for(;n;){if(!n.canClose){n=n.next;continue}const i=n.cc;let r=n.prev,o=!1;const l=s(n);for(;r&&r!==t&&r!==l;){if(r.cc===i&&r.canOpen&&this.emphMatches(r,n)){o=!0;break}r=r.prev}if(!o){e.set(X(n),n.prev),n.canOpen||this.removeDelimiter(n),n=n.next;continue}const h=r,c=this.wrapCount(i,h,n);if(0!==c){if(this.wrapEmphasis(i,h,n,c),h.numdelims-=c,n.numdelims-=c,h.node.literal=h.node.literal.slice(c),n.node.literal=n.node.literal.slice(c),this.removeDelimitersBetween(h,n),0===h.numdelims&&this.removeDelimiter(h),0===n.numdelims){const t=n.next;this.removeDelimiter(n),n=t}}else n=n.next}for(;this.delimiters&&this.delimiters!==t;)this.removeDelimiter(this.delimiters)}firstDelimiter(){let t=this.delimiters;for(;t?.prev;)t=t.prev;return t}emphMatches(t,e){return"*"!==t.cc&&"_"!==t.cc||!((e.canOpen||t.canClose)&&e.origdelims%3!=0&&(t.origdelims+e.origdelims)%3==0)}wrapCount(t,e,s){const n=e.numdelims>=2&&s.numdelims>=2;return"*"===t||"_"===t?n?2:1:"~"===t?this.ctx.opts.gfm&&n?2:this.ctx.opts.extendedInlineSyntax?1:0:"="===t?this.ctx.opts.extendedInlineSyntax&&n?2:0:"^"===t&&this.ctx.opts.extendedInlineSyntax?1:0}wrapKind(t,e){return"*"===t||"_"===t?2===e?"strong":"emph":"~"===t?2===e?"strike":"sub":"="===t?"highlight":"sup"}wrapEmphasis(t,e,s,n){const i=y(this.wrapKind(t,n));let r=e.node.next;for(;r&&r!==s.node;){const t=r.next;_(r),i.children.push(r),r=t}b(e.node,i)}removeDelimitersBetween(t,e){let s=e.prev;for(;s&&s!==t;){const t=s.prev;this.removeDelimiter(s),s=t}}removeDelimiter(t){t.prev&&(t.prev.next=t.next),t.next&&(t.next.prev=t.prev),t.next||(this.delimiters=t.prev)}};function X(t){return`${t.cc}${t.canOpen?1:0}${t.origdelims%3}`}function Y(t){return t.replace(/\n[ \t]*/g," ")}function tt(t){let e="";for(const s of t)"text"===s.type||"code"===s.type?e+=s.literal:"softbreak"===s.type||"hardbreak"===s.type?e+=" ":s.children.length?e+=tt(s.children):s.alt&&(e+=s.alt);return e}var et={emph:"italic",strong:"bold",strike:"strikethrough",highlight:"highlight",sup:"superscript",sub:"subscript"};function st(t,e,s,n){for(const i of t)nt(i,e,s,n)}function nt(t,e,n,i){switch(t.type){case"text":return void(t.literal&&i.push(r(t.literal,[...e])));case"softbreak":return void i.push(r(" ",[...e]));case"hardbreak":return void i.push(s(h("hard_break"),{}));case"code":return void i.push(r(t.literal,it(e,n,"code")));case"link":{const s={href:t.href};return t.title&&(s.title=t.title),void st(t.children,it(e,n,"link",s),n,i)}case"image":return void function(t,e,n,i){if(!n.registry||void 0!==n.registry.getInlineNodeSpec("image_inline")){const n={src:t.href,alt:t.alt};return t.title&&(n.title=t.title),void i.push(s(h("image_inline"),n,[...e]))}t.alt&&i.push(r(t.alt,[...e]))}(t,e,n,i);case"inline_node":return void i.push(s(h(t.inlineType),t.attrs,[...e]));case"html_inline":return void function(t,e,n,i){if((!n.registry||void 0!==n.registry.getInlineNodeSpec("hard_break"))&&/^<br\s*\/?>$/i.test(t.trim()))return void i.push(s(h("hard_break"),{},[...e]));const o=a(`<p>${t}</p>`,k(n.registry)).children[0];if(!o)return;let l=!1;for(const h of o.children)"text"in h&&""!==h.text?(i.push(r(h.text,rt(e,h.marks))),l=!0):"inlineType"in h&&(i.push(s(h.inlineType,h.attrs,rt(e,h.marks))),l=!0);l||n.registry||i.push(r(t,[...e]))}(t.literal,e,n,i);default:{const s=et[t.type];st(t.children,s?it(e,n,s):e,n,i)}}}function it(t,e,s,n){if(!function(t,e){return!t.registry||void 0!==t.registry.getMarkSpec(e)}(e,s))return[...t];const i=n?{type:l(s),attrs:n}:{type:l(s)};return[...t,i]}function rt(t,e){const s=[...t];for(const n of e)s.some(t=>t.type===n.type)||s.push(n);return s}function ot(t,e){if(t.length!==e.length)return!1;const s=t=>`${t.type}:${JSON.stringify(t.attrs??{})}`,n=new Set(e.map(s));return t.every(t=>n.has(s(t)))}function lt(t,e){const s=new V(t,e).parse();e.opts.gfm&&E(s);const n=[];st(s,[],e,n);const i=function(t){const e=[];for(const s of t){const t=e[e.length-1];"text"in s&&t&&"text"in t&&ot(t.marks,s.marks)?e[e.length-1]={type:"text",text:t.text+s.text,marks:t.marks}:e.push(s)}return e}(n);return i.length>0?i:[r("")]}function ht(t){const e=t?.flavor??"gfm";return{flavor:e,gfm:"gfm"===e,extendedInlineSyntax:t?.extendedInlineSyntax??!1,htmlFallback:!1!==t?.htmlFallback,syntaxExtensions:t?.syntaxExtensions??[]}}var ct=/* @__PURE__ */t({parseMarkdownToDocument:()=>at});function at(t,e,s){const{source:n,linkRefs:r}=function(t){const e=/* @__PURE__ */new Map,s=t.split("\n"),n=[];let i=null,r=!1,o=0;for(;o<s.length;){const t=s[o]??"";if(i){n.push(t);const e=t.match(j)?.[1];e&&e[0]===i.char&&e.length>=i.len&&(i=null),r=!1,o++;continue}const l=g(t);if(l?.[1]){i={char:l[1][0]??"`",len:l[1].length},n.push(t),r=!1,o++;continue}const h=r?0:G(s,o,"",e,n);h>0?o+=h:(n.push(t),r=""!==t.trim()&&!d.test(t)&&!x.test(t),o++)}return{source:n.join("\n"),linkRefs:e}}(t.replace(/\r\n?/g,"\n")),o={registry:e,opts:ht(s),linkRefs:r},l=ut(u(n,o.opts.gfm,o.opts.syntaxExtensions),o);if(0===l.length)return i();const h=i(l);return e?c(h,e):h}function ut(t,e){const s=[];for(const n of t)pt(n,s,e);return s}function pt(t,s,i){switch(t.type){case"heading":return void s.push(ft("heading",lt(t.text,i),i,{level:t.level}));case"paragraph":{const l=lt(t.text,i),h=function(t,s){if(1!==t.length)return null;const i=t[0];if(!i||!e(i)||"image_inline"!==i.inlineType)return null;if(i.marks.length>0)return null;if(s.registry&&!s.registry.getNodeSpec("image"))return null;const l={src:String(i.attrs.src??""),alt:String(i.attrs.alt??""),align:"center"};return i.attrs.title&&(l.title=String(i.attrs.title)),n(o("image"),[r("")],void 0,l)}(l,i);return void s.push(h??ft("paragraph",l,i))}case"table":return void s.push(function(t,e,s,i){if(i.registry&&!i.registry.getNodeSpec("table"))return ft("paragraph",lt([e,...s].map(t=>t.join(" | ")).join("\n"),i),i);const r=e=>{const s=e.map((e,s)=>{const r=t[s]??null,l=n(o("paragraph"),lt(e,i),void 0,r?{align:r}:void 0);return n(o("table_cell"),[l])});return n(o("table_row"),s)},l=e.length,h=[r(e),...s.map(t=>r((t=>{if(t.length===l)return t;const e=t.slice(0,l);for(;e.length<l;)e.push("");return e})(t)))];return n(o("table"),h)}(t.aligns,t.header,t.rows,i));case"extension_block":return void s.push(ft(t.nodeType,[r("")],i,t.attrs));case"code_block":return void s.push(ft("code_block",[r(t.code)],i,{language:t.language}));case"hr":return void s.push(ft("horizontal_rule",[r("")],i));case"list_item":{const e={listType:t.listType,indent:t.indent,checked:t.checked};if(t.children&&t.children.length>0){const r=ut(t.children,i);return i.registry&&!i.registry.getNodeSpec("list_item")?void s.push(...r):void s.push(n(o("list_item"),r,void 0,e))}return void s.push(ft("list_item",lt(t.text,i),i,e))}case"blockquote":{const e=ut(t.children,i);return 0===e.length&&e.push(n(o("paragraph"),[r("")])),void s.push(function(t,e,s){const i=mt(t,s);return i!==o(t)?e[0]??n(o("paragraph"),[r("")]):n(i,e)}("blockquote",e,i))}case"html":if(function(t){let e=t.trim();for(;e.startsWith("\x3c!--");){const t=e.indexOf("--\x3e");if(-1===t)return!1;e=e.slice(t+3).trim()}return""===e}(t.html))return;for(const e of a(t.html,k(i.registry)).children)s.push(e);return}}function ft(t,e,s,i){const l=mt(t,s);return n(l,e.length>0?e:[r("")],void 0,i&&l===o(t)?i:void 0)}function mt(t,e){return e.registry&&!e.registry.getNodeSpec(t)?o("paragraph"):o(t)}export{at as n,ct as t};
|
|
2
|
+
//# sourceMappingURL=MarkdownParser-Dp62mfUq.mjs.map
|