@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.
Files changed (197) hide show
  1. package/README.md +1 -1
  2. package/THIRD-PARTY-NOTICES.md +129 -0
  3. package/dist/chunks/{AlignmentPlugin--xAFlRqE.mjs → AlignmentPlugin-C9Rr_R-g.mjs} +2 -2
  4. package/dist/chunks/{AlignmentPlugin--xAFlRqE.mjs.map → AlignmentPlugin-C9Rr_R-g.mjs.map} +1 -1
  5. package/dist/chunks/{AttributedMarkCommands-bagbH8Qt.mjs → AttributedMarkCommands-BCvmqeFZ.mjs} +2 -2
  6. package/dist/chunks/{AttributedMarkCommands-bagbH8Qt.mjs.map → AttributedMarkCommands-BCvmqeFZ.mjs.map} +1 -1
  7. package/dist/chunks/{BidiIsolationPlugin-DBXyXpgm.mjs → BidiIsolationPlugin-Cw2KMk-H.mjs} +2 -2
  8. package/dist/chunks/{BidiIsolationPlugin-DBXyXpgm.mjs.map → BidiIsolationPlugin-Cw2KMk-H.mjs.map} +1 -1
  9. package/dist/chunks/{BlockInsertion-CJusvrDL.mjs → BlockInsertion-CYH2gRkY.mjs} +2 -2
  10. package/dist/chunks/{BlockInsertion-CJusvrDL.mjs.map → BlockInsertion-CYH2gRkY.mjs.map} +1 -1
  11. package/dist/chunks/{BlockquotePlugin-Bz2glHwX.mjs → BlockquotePlugin-0bZSbkyo.mjs} +2 -2
  12. package/dist/chunks/{BlockquotePlugin-Bz2glHwX.mjs.map → BlockquotePlugin-0bZSbkyo.mjs.map} +1 -1
  13. package/dist/chunks/CaretNavigationPlugin-BPZ9b6XR.mjs +2 -0
  14. package/dist/chunks/CaretNavigationPlugin-BPZ9b6XR.mjs.map +1 -0
  15. package/dist/chunks/CodeBlockPlugin-BCJ3faXx.mjs +2 -0
  16. package/dist/chunks/{CodeBlockPlugin-C1hrdbSZ.mjs.map → CodeBlockPlugin-BCJ3faXx.mjs.map} +1 -1
  17. package/dist/chunks/{ColorGrid-C9RQoEWF.mjs → ColorGrid-DQEkJ-0y.mjs} +2 -2
  18. package/dist/chunks/{ColorGrid-C9RQoEWF.mjs.map → ColorGrid-DQEkJ-0y.mjs.map} +1 -1
  19. package/dist/chunks/ColorPickerPopup-CyF26zIU.mjs +2 -0
  20. package/dist/chunks/{ColorPickerPopup-DiA68Pzz.mjs.map → ColorPickerPopup-CyF26zIU.mjs.map} +1 -1
  21. package/dist/chunks/Commands-D5ND50PQ.mjs +2 -0
  22. package/dist/chunks/{Commands-1dFFldi7.mjs.map → Commands-D5ND50PQ.mjs.map} +1 -1
  23. package/dist/chunks/{Decoration-BpoEOANl.mjs → Decoration-BOP1TAUd.mjs} +2 -2
  24. package/dist/chunks/{Decoration-BpoEOANl.mjs.map → Decoration-BOP1TAUd.mjs.map} +1 -1
  25. package/dist/chunks/{FontPlugin-By-TGrQo.mjs → FontPlugin-D041tiLe.mjs} +2 -2
  26. package/dist/chunks/{FontPlugin-By-TGrQo.mjs.map → FontPlugin-D041tiLe.mjs.map} +1 -1
  27. package/dist/chunks/{FontSizePlugin-Dln-tYXV.mjs → FontSizePlugin-8CAvj1RD.mjs} +2 -2
  28. package/dist/chunks/{FontSizePlugin-Dln-tYXV.mjs.map → FontSizePlugin-8CAvj1RD.mjs.map} +1 -1
  29. package/dist/chunks/{FormulaPlugin-By1befrR.mjs → FormulaPlugin-DJ39BtqV.mjs} +2 -2
  30. package/dist/chunks/FormulaPlugin-DJ39BtqV.mjs.map +1 -0
  31. package/dist/chunks/GapCursorNavigation-DCWOmopl.mjs +2 -0
  32. package/dist/chunks/{GapCursorNavigation-BuXngVu-.mjs.map → GapCursorNavigation-DCWOmopl.mjs.map} +1 -1
  33. package/dist/chunks/GapCursorPlugin-2iR6506y.mjs +2 -0
  34. package/dist/chunks/{GapCursorPlugin-DAxVzXRs.mjs.map → GapCursorPlugin-2iR6506y.mjs.map} +1 -1
  35. package/dist/chunks/{HardBreakPlugin-DlbSlrdq.mjs → HardBreakPlugin-vniSvTgq.mjs} +2 -2
  36. package/dist/chunks/{HardBreakPlugin-DlbSlrdq.mjs.map → HardBreakPlugin-vniSvTgq.mjs.map} +1 -1
  37. package/dist/chunks/{HeadingPlugin-uMAjPOk5.mjs → HeadingPlugin-DUKsLuMd.mjs} +2 -2
  38. package/dist/chunks/{HeadingPlugin-uMAjPOk5.mjs.map → HeadingPlugin-DUKsLuMd.mjs.map} +1 -1
  39. package/dist/chunks/{HighlightPlugin-Bj7FPkIQ.mjs → HighlightPlugin-DRTAE1N5.mjs} +2 -2
  40. package/dist/chunks/{HighlightPlugin-Bj7FPkIQ.mjs.map → HighlightPlugin-DRTAE1N5.mjs.map} +1 -1
  41. package/dist/chunks/HorizontalRulePlugin-B9OvwrKB.mjs +2 -0
  42. package/dist/chunks/{HorizontalRulePlugin-DUVmTQpX.mjs.map → HorizontalRulePlugin-B9OvwrKB.mjs.map} +1 -1
  43. package/dist/chunks/{ImagePlugin-FToCOjd5.mjs → ImagePlugin-CwxTRr6d.mjs} +2 -2
  44. package/dist/chunks/{ImagePlugin-FToCOjd5.mjs.map → ImagePlugin-CwxTRr6d.mjs.map} +1 -1
  45. package/dist/chunks/{InlineCodePlugin-pISIoGQE.mjs → InlineCodePlugin-uxgMUX_E.mjs} +2 -2
  46. package/dist/chunks/{InlineCodePlugin-pISIoGQE.mjs.map → InlineCodePlugin-uxgMUX_E.mjs.map} +1 -1
  47. package/dist/chunks/{LinkPlugin-Ct5Z180S.mjs → LinkPlugin-CvWHbSkb.mjs} +2 -2
  48. package/dist/chunks/{LinkPlugin-Ct5Z180S.mjs.map → LinkPlugin-CvWHbSkb.mjs.map} +1 -1
  49. package/dist/chunks/{ListPlugin-DAY5ezNs.mjs → ListPlugin-BchSFWVn.mjs} +2 -2
  50. package/dist/chunks/{ListPlugin-DAY5ezNs.mjs.map → ListPlugin-BchSFWVn.mjs.map} +1 -1
  51. package/dist/chunks/{MarkdownHTMLRegistry-CKEx7LkR.mjs → MarkdownHTMLRegistry-Q7l0d6Ma.mjs} +2 -2
  52. package/dist/chunks/{MarkdownHTMLRegistry-CKEx7LkR.mjs.map → MarkdownHTMLRegistry-Q7l0d6Ma.mjs.map} +1 -1
  53. package/dist/chunks/{MarkdownParser-CWt3M6jR.mjs → MarkdownParser-Dp62mfUq.mjs} +2 -2
  54. package/dist/chunks/{MarkdownParser-CWt3M6jR.mjs.map → MarkdownParser-Dp62mfUq.mjs.map} +1 -1
  55. package/dist/chunks/{MarkdownSerializer-J-i28out.mjs → MarkdownSerializer-DBELFAeo.mjs} +2 -2
  56. package/dist/chunks/{MarkdownSerializer-J-i28out.mjs.map → MarkdownSerializer-DBELFAeo.mjs.map} +1 -1
  57. package/dist/chunks/MathFont-BS8IwYh2.mjs +2 -0
  58. package/dist/chunks/MathFont-BS8IwYh2.mjs.map +1 -0
  59. package/dist/chunks/NodeSelectionCommands-WH5snxr_.mjs +2 -0
  60. package/dist/chunks/{NodeSelectionCommands-1PjwUDTJ.mjs.map → NodeSelectionCommands-WH5snxr_.mjs.map} +1 -1
  61. package/dist/chunks/PluginHelpers-KDuTlmXm.mjs +2 -0
  62. package/dist/chunks/{PluginHelpers-Dx_0hfDe.mjs.map → PluginHelpers-KDuTlmXm.mjs.map} +1 -1
  63. package/dist/chunks/{PopupManager-CT-fMZJn.mjs → PopupManager-Cj86uDEB.mjs} +2 -2
  64. package/dist/chunks/{PopupManager-CT-fMZJn.mjs.map → PopupManager-Cj86uDEB.mjs.map} +1 -1
  65. package/dist/chunks/PrintPlugin-D2javl_d.mjs +2 -0
  66. package/dist/chunks/{PrintPlugin-7zz9mhhU.mjs.map → PrintPlugin-D2javl_d.mjs.map} +1 -1
  67. package/dist/chunks/SimpleMark-gTQaSJcO.mjs +2 -0
  68. package/dist/chunks/{SimpleMark-7CQcA4RK.mjs.map → SimpleMark-gTQaSJcO.mjs.map} +1 -1
  69. package/dist/chunks/SmartPastePlugin-BvJQ-fOz.mjs +2 -0
  70. package/dist/chunks/SmartPastePlugin-BvJQ-fOz.mjs.map +1 -0
  71. package/dist/chunks/StarterFonts-BDQPg-cu.mjs +2 -0
  72. package/dist/chunks/StarterFonts-BDQPg-cu.mjs.map +1 -0
  73. package/dist/chunks/{StrikethroughPlugin-C2oWvGc3.mjs → StrikethroughPlugin-BdrG1TTY.mjs} +2 -2
  74. package/dist/chunks/{StrikethroughPlugin-C2oWvGc3.mjs.map → StrikethroughPlugin-BdrG1TTY.mjs.map} +1 -1
  75. package/dist/chunks/{SuperSubPlugin-D1xaKrSu.mjs → SuperSubPlugin-DTZB0Y3D.mjs} +2 -2
  76. package/dist/chunks/{SuperSubPlugin-D1xaKrSu.mjs.map → SuperSubPlugin-DTZB0Y3D.mjs.map} +1 -1
  77. package/dist/chunks/{TablePlugin-PJe3zwr-.mjs → TablePlugin-CPvg9YZS.mjs} +2 -2
  78. package/dist/chunks/{TablePlugin-PJe3zwr-.mjs.map → TablePlugin-CPvg9YZS.mjs.map} +1 -1
  79. package/dist/chunks/{TextColorPlugin-CTd9tfeG.mjs → TextColorPlugin-Ckg3KWvb.mjs} +2 -2
  80. package/dist/chunks/{TextColorPlugin-CTd9tfeG.mjs.map → TextColorPlugin-Ckg3KWvb.mjs.map} +1 -1
  81. package/dist/chunks/{TextDirectionAutoPlugin-CPnKVVuI.mjs → TextDirectionAutoPlugin-DRGbgTlx.mjs} +2 -2
  82. package/dist/chunks/{TextDirectionAutoPlugin-CPnKVVuI.mjs.map → TextDirectionAutoPlugin-DRGbgTlx.mjs.map} +1 -1
  83. package/dist/chunks/TextDirectionPlugin-BCeYyJHo.mjs +2 -0
  84. package/dist/chunks/{TextDirectionPlugin-Bns_03vL.mjs.map → TextDirectionPlugin-BCeYyJHo.mjs.map} +1 -1
  85. package/dist/chunks/TextDirectionService-OFOU6r_s.mjs +2 -0
  86. package/dist/chunks/{TextDirectionService-BcX07mw2.mjs.map → TextDirectionService-OFOU6r_s.mjs.map} +1 -1
  87. package/dist/chunks/TextFormattingPlugin-BhRxSC8q.mjs +2 -0
  88. package/dist/chunks/{TextFormattingPlugin-DBVlePqj.mjs.map → TextFormattingPlugin-BhRxSC8q.mjs.map} +1 -1
  89. package/dist/chunks/ThemeEngine-BUVo_zaT.mjs +3 -0
  90. package/dist/chunks/ThemeEngine-BUVo_zaT.mjs.map +1 -0
  91. package/dist/chunks/ToolbarPlugin-dmTj1jIz.mjs +2 -0
  92. package/dist/chunks/{ToolbarPlugin-DtfGTO_V.mjs.map → ToolbarPlugin-dmTj1jIz.mjs.map} +1 -1
  93. package/dist/chunks/{VideoPlugin-BrR8g6Rz.mjs → VideoPlugin-BugkI7-m.mjs} +2 -2
  94. package/dist/chunks/{VideoPlugin-BrR8g6Rz.mjs.map → VideoPlugin-BugkI7-m.mjs.map} +1 -1
  95. package/dist/chunks/XmlSupport-DIXH5on9.mjs +2 -0
  96. package/dist/chunks/XmlSupport-DIXH5on9.mjs.map +1 -0
  97. package/dist/chunks/full-JM0-SwWy.mjs +2 -0
  98. package/dist/chunks/{full-DSWM4cKQ.mjs.map → full-JM0-SwWy.mjs.map} +1 -1
  99. package/dist/chunks/minimal-DSlR2A27.mjs +2 -0
  100. package/dist/chunks/{minimal-CFkkPXef.mjs.map → minimal-DSlR2A27.mjs.map} +1 -1
  101. package/dist/chunks/register-BjsdJ3Aq.mjs +2 -0
  102. package/dist/chunks/register-BjsdJ3Aq.mjs.map +1 -0
  103. package/dist/chunks/src-5GKFQ2mQ.mjs +2 -0
  104. package/dist/chunks/src-5GKFQ2mQ.mjs.map +1 -0
  105. package/dist/chunks/xml-BsV44TrJ.mjs +2 -0
  106. package/dist/chunks/xml-BsV44TrJ.mjs.map +1 -0
  107. package/dist/editor/NotectlEditor.d.ts.map +1 -1
  108. package/dist/fonts/math.d.ts +3 -0
  109. package/dist/fonts/math.d.ts.map +1 -0
  110. package/dist/fonts/math.mjs +1 -0
  111. package/dist/fonts/starter.d.ts +3 -0
  112. package/dist/fonts/starter.d.ts.map +1 -0
  113. package/dist/fonts/starter.mjs +1 -0
  114. package/dist/fonts.d.ts +4 -4
  115. package/dist/fonts.mjs +1 -1
  116. package/dist/full.d.ts +1 -1
  117. package/dist/full.mjs +1 -1
  118. package/dist/index.d.ts +2 -1
  119. package/dist/index.d.ts.map +1 -1
  120. package/dist/markdown.mjs +1 -1
  121. package/dist/notectl-core.mjs +1 -1
  122. package/dist/notectl-core.umd.js +1 -1
  123. package/dist/notectl-core.umd.js.map +1 -1
  124. package/dist/plugins/alignment.mjs +1 -1
  125. package/dist/plugins/bidi-isolation.mjs +1 -1
  126. package/dist/plugins/blockquote.mjs +1 -1
  127. package/dist/plugins/caret-navigation.mjs +1 -1
  128. package/dist/plugins/code-block/CodeBlockHighlighting.d.ts.map +1 -1
  129. package/dist/plugins/code-block.mjs +1 -1
  130. package/dist/plugins/font-size.mjs +1 -1
  131. package/dist/plugins/font.mjs +1 -1
  132. package/dist/plugins/formula/FormulaTypes.d.ts +1 -1
  133. package/dist/plugins/formula.mjs +1 -1
  134. package/dist/plugins/gap-cursor.mjs +1 -1
  135. package/dist/plugins/hard-break.mjs +1 -1
  136. package/dist/plugins/heading.mjs +1 -1
  137. package/dist/plugins/highlight.mjs +1 -1
  138. package/dist/plugins/horizontal-rule.mjs +1 -1
  139. package/dist/plugins/image.mjs +1 -1
  140. package/dist/plugins/inline-code.mjs +1 -1
  141. package/dist/plugins/language.mjs +1 -1
  142. package/dist/plugins/link.mjs +1 -1
  143. package/dist/plugins/list.mjs +1 -1
  144. package/dist/plugins/print.mjs +1 -1
  145. package/dist/plugins/shared.mjs +1 -1
  146. package/dist/plugins/smart-paste/SmartPastePlugin.d.ts.map +1 -1
  147. package/dist/plugins/smart-paste.mjs +1 -1
  148. package/dist/plugins/strikethrough.mjs +1 -1
  149. package/dist/plugins/super-sub.mjs +1 -1
  150. package/dist/plugins/table.mjs +1 -1
  151. package/dist/plugins/text-color.mjs +1 -1
  152. package/dist/plugins/text-direction-auto.mjs +1 -1
  153. package/dist/plugins/text-direction.mjs +1 -1
  154. package/dist/plugins/text-formatting.mjs +1 -1
  155. package/dist/plugins/toolbar.mjs +1 -1
  156. package/dist/plugins/video.mjs +1 -1
  157. package/dist/presets/full.d.ts +1 -1
  158. package/dist/presets/full.mjs +1 -1
  159. package/dist/presets/minimal.d.ts +1 -1
  160. package/dist/presets/minimal.mjs +1 -1
  161. package/dist/presets.d.ts +1 -1
  162. package/dist/presets.mjs +1 -1
  163. package/dist/register.d.ts +3 -0
  164. package/dist/register.d.ts.map +1 -0
  165. package/dist/register.mjs +1 -0
  166. package/package.json +24 -223
  167. package/dist/chunks/CaretNavigationPlugin-CNsT0eb4.mjs +0 -2
  168. package/dist/chunks/CaretNavigationPlugin-CNsT0eb4.mjs.map +0 -1
  169. package/dist/chunks/CodeBlockPlugin-C1hrdbSZ.mjs +0 -2
  170. package/dist/chunks/ColorPickerPopup-DiA68Pzz.mjs +0 -2
  171. package/dist/chunks/Commands-1dFFldi7.mjs +0 -2
  172. package/dist/chunks/FormulaPlugin-By1befrR.mjs.map +0 -1
  173. package/dist/chunks/GapCursorNavigation-BuXngVu-.mjs +0 -2
  174. package/dist/chunks/GapCursorPlugin-DAxVzXRs.mjs +0 -2
  175. package/dist/chunks/HorizontalRulePlugin-DUVmTQpX.mjs +0 -2
  176. package/dist/chunks/NodeSelectionCommands-1PjwUDTJ.mjs +0 -2
  177. package/dist/chunks/PluginHelpers-Dx_0hfDe.mjs +0 -2
  178. package/dist/chunks/PrintPlugin-7zz9mhhU.mjs +0 -2
  179. package/dist/chunks/PrintTypes-CxU69qu3.mjs +0 -3
  180. package/dist/chunks/PrintTypes-CxU69qu3.mjs.map +0 -1
  181. package/dist/chunks/SimpleMark-7CQcA4RK.mjs +0 -2
  182. package/dist/chunks/SmartPastePlugin-CYa_nD9v.mjs +0 -2
  183. package/dist/chunks/SmartPastePlugin-CYa_nD9v.mjs.map +0 -1
  184. package/dist/chunks/TextDirectionPlugin-Bns_03vL.mjs +0 -2
  185. package/dist/chunks/TextDirectionService-BcX07mw2.mjs +0 -2
  186. package/dist/chunks/TextFormattingPlugin-DBVlePqj.mjs +0 -2
  187. package/dist/chunks/ToolbarPlugin-DtfGTO_V.mjs +0 -2
  188. package/dist/chunks/XmlDetector-D7TQpw-e.mjs +0 -2
  189. package/dist/chunks/XmlDetector-D7TQpw-e.mjs.map +0 -1
  190. package/dist/chunks/XmlSupport-BYiRwlkK.mjs +0 -2
  191. package/dist/chunks/XmlSupport-BYiRwlkK.mjs.map +0 -1
  192. package/dist/chunks/fonts-DQC6Uj4r.mjs +0 -2
  193. package/dist/chunks/fonts-DQC6Uj4r.mjs.map +0 -1
  194. package/dist/chunks/full-DSWM4cKQ.mjs +0 -2
  195. package/dist/chunks/minimal-CFkkPXef.mjs +0 -2
  196. package/dist/chunks/src-DiAOfuOT.mjs +0 -2
  197. package/dist/chunks/src-DiAOfuOT.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"MarkdownSerializer-J-i28out.mjs","names":[],"sources":["../../src/serialization/markdown/MarkdownContext.ts","../../src/serialization/markdown/MarkdownEscape.ts","../../src/serialization/markdown/InlineSerializers.ts","../../src/serialization/markdown/BlockSerializers.ts","../../src/serialization/MarkdownSerializer.ts"],"sourcesContent":["/**\n * Resolved serialization options and the context threaded through the Markdown\n * serializer. Kept separate from the serializer modules so block/inline\n * serializers can share the type without a circular import.\n */\n\nimport type { MarkdownExportContext } from '../../model/NodeSpec.js';\nimport type { SchemaRegistry } from '../../model/SchemaRegistry.js';\nimport type { MarkdownSerializeOptions } from '../MarkdownTypes.js';\n\n/** Fully-resolved serialization options (no `undefined`). */\nexport interface ResolvedSerializeOptions {\n\treadonly flavor: 'commonmark' | 'gfm';\n\treadonly gfm: boolean;\n\treadonly htmlFallback: boolean;\n\treadonly headingStyle: 'atx' | 'setext';\n\treadonly bullet: string;\n\treadonly emphasis: string;\n\treadonly codeFence: string;\n\treadonly listIndent: number;\n}\n\n/** Internal context shared by all serialization helpers. */\nexport interface SerContext {\n\treadonly registry?: SchemaRegistry;\n\treadonly opts: ResolvedSerializeOptions;\n\t/** Precomputed mark rank map (built once per pass) for HTML-fallback marks. */\n\treadonly markOrder?: Map<string, number>;\n\t/**\n\t * True while serializing the block children of a list item (#194): thematic\n\t * breaks emit `***` there, because `---` on an indented continuation line\n\t * would re-parse as a setext underline or a bullet marker.\n\t */\n\treadonly inListItem?: boolean;\n}\n\n/** Resolves user-facing options into a complete settings object with defaults. */\nexport function resolveSerializeOptions(\n\toptions?: MarkdownSerializeOptions,\n): ResolvedSerializeOptions {\n\tconst flavor: 'commonmark' | 'gfm' = options?.flavor ?? 'gfm';\n\treturn {\n\t\tflavor,\n\t\tgfm: flavor === 'gfm',\n\t\thtmlFallback: options?.htmlFallback !== false,\n\t\theadingStyle: options?.headingStyle ?? 'atx',\n\t\tbullet: options?.bullet ?? '-',\n\t\temphasis: options?.emphasis ?? '*',\n\t\tcodeFence: options?.codeFence ?? '```',\n\t\tlistIndent: options?.listIndent ?? 2,\n\t};\n}\n\n/** Builds the public {@link MarkdownExportContext} passed to per-spec hooks. */\nexport function exportContext(opts: ResolvedSerializeOptions): MarkdownExportContext {\n\treturn { flavor: opts.flavor, htmlFallback: opts.htmlFallback };\n}\n","/**\n * CommonMark escaping rules for Markdown serialization.\n *\n * Escaping is contextual: inline text backslash-escapes characters that would\n * otherwise start emphasis/code/links, while the start of a line additionally\n * escapes block markers (`#`, `>`, `-`, …) so prose never accidentally becomes\n * a heading or list on re-parse. Output stays minimal: we do not escape every\n * punctuation character, only those that are actually ambiguous in context.\n */\n\nimport { FENCE_OPEN, SETEXT_H1, SETEXT_H2, THEMATIC_BREAK } from './BlockTokenizer.js';\n\n/** Inline specials that always need escaping in text content. */\nconst ALWAYS_ESCAPE = new Set(['\\\\', '`', '*', '[', ']', '<', '>']);\n\n/** Whether the character at `i` sits between two word characters (intra-word). */\nfunction isIntraWord(text: string, i: number): boolean {\n\tconst prev: string | undefined = text[i - 1];\n\tconst next: string | undefined = text[i + 1];\n\tif (prev === undefined || next === undefined) return false;\n\treturn /\\w/.test(prev) && /\\w/.test(next);\n}\n\n/**\n * Escapes inline text so it round-trips as literal content. `~` is escaped only\n * for GFM (where `~~` is strikethrough); `_` is escaped only when it is not\n * intra-word, matching CommonMark's emphasis rules (so `a_b_c` stays literal).\n */\nexport function escapeInline(text: string, gfm: boolean): string {\n\tlet out = '';\n\tfor (let i = 0; i < text.length; i++) {\n\t\tconst ch: string = text[i] ?? '';\n\t\tif (ALWAYS_ESCAPE.has(ch)) {\n\t\t\tout += `\\\\${ch}`;\n\t\t\tcontinue;\n\t\t}\n\t\tif (ch === '_' && !isIntraWord(text, i)) {\n\t\t\tout += '\\\\_';\n\t\t\tcontinue;\n\t\t}\n\t\tif (ch === '~' && gfm) {\n\t\t\tout += '\\\\~';\n\t\t\tcontinue;\n\t\t}\n\t\tif (ch === '&') {\n\t\t\tout += '&amp;';\n\t\t\tcontinue;\n\t\t}\n\t\tout += ch;\n\t}\n\treturn out;\n}\n\n/** Pattern matching a leading block marker that must be escaped in paragraph text. */\nconst LINE_START_MARKER = /^(\\s*)([#>])/;\n/** Pattern matching a leading list bullet (`- `, `* `, `+ `). */\nconst LINE_START_BULLET = /^(\\s*)([-*+])(\\s)/;\n/** Pattern matching a leading ordered marker (`1.` / `1)`). */\nconst LINE_START_ORDERED = /^(\\s*)(\\d{1,9})([.)])(\\s)/;\n\n/**\n * Whether a whole line would re-parse as a block construct that spans the entire\n * line: a thematic break, a setext underline, or an opening code fence. These\n * carry no trailing content marker (unlike `#`/`-`/`1.`), so they slip past the\n * leading-marker rules above. Backtick fences and `*`/`_`/`~` breaks are already\n * neutralized by inline escaping (they arrive backslash-prefixed); what reaches\n * here is `-`/`=` runs and, under CommonMark, `~~~` fences.\n */\nfunction reparsesAsBlockLine(line: string): boolean {\n\treturn (\n\t\tTHEMATIC_BREAK.test(line) ||\n\t\tSETEXT_H1.test(line) ||\n\t\tSETEXT_H2.test(line) ||\n\t\tFENCE_OPEN.test(line)\n\t);\n}\n\n/**\n * Escapes leading block markers at the start of a paragraph line so the text\n * does not re-parse as a heading, blockquote, list, thematic break, setext\n * underline, or code fence.\n */\nexport function escapeLineStart(line: string): string {\n\tif (LINE_START_MARKER.test(line)) {\n\t\treturn line.replace(LINE_START_MARKER, (_m, ws: string, marker: string) => `${ws}\\\\${marker}`);\n\t}\n\tif (LINE_START_BULLET.test(line)) {\n\t\treturn line.replace(\n\t\t\tLINE_START_BULLET,\n\t\t\t(_m, ws: string, marker: string, sp: string) => `${ws}\\\\${marker}${sp}`,\n\t\t);\n\t}\n\tif (LINE_START_ORDERED.test(line)) {\n\t\treturn line.replace(\n\t\t\tLINE_START_ORDERED,\n\t\t\t(_m, ws: string, num: string, marker: string, sp: string) => `${ws}${num}\\\\${marker}${sp}`,\n\t\t);\n\t}\n\tif (reparsesAsBlockLine(line)) {\n\t\t// Backslash the first non-space character: that breaks the run so the line\n\t\t// stays a paragraph, and `\\-` / `\\=` / `\\~` decode back to the literal char.\n\t\treturn line.replace(/\\S/, (ch) => `\\\\${ch}`);\n\t}\n\treturn line;\n}\n\n/** Escapes the destination of a link/image so spaces and parens stay intact. */\nexport function escapeLinkDestination(url: string): string {\n\tif (/[\\s()]/.test(url)) {\n\t\treturn `<${url.replace(/([<>])/g, '\\\\$1')}>`;\n\t}\n\treturn url;\n}\n\n/** Escapes a link/image title for the `\"...\"` form. */\nexport function escapeLinkTitle(title: string): string {\n\treturn title.replace(/([\"\\\\])/g, '\\\\$1');\n}\n\n/**\n * Picks a backtick fence long enough to wrap `content` as an inline code span.\n * CommonMark requires a fence longer than any backtick run inside the content.\n */\nexport function codeSpanFence(content: string): string {\n\tlet longest = 0;\n\tlet current = 0;\n\tfor (const ch of content) {\n\t\tif (ch === '`') {\n\t\t\tcurrent++;\n\t\t\tlongest = Math.max(longest, current);\n\t\t} else {\n\t\t\tcurrent = 0;\n\t\t}\n\t}\n\treturn '`'.repeat(longest + 1);\n}\n\n/** Wraps `content` in a correctly sized inline code span, padding when needed. */\nexport function wrapCodeSpan(content: string): string {\n\tconst fence: string = codeSpanFence(content);\n\t// Pad with a space when content starts/ends with a backtick or is all spaces,\n\t// per CommonMark's code-span stripping rule.\n\tconst needsPad: boolean =\n\t\tcontent.startsWith('`') ||\n\t\tcontent.endsWith('`') ||\n\t\t(content.length > 0 && content.trim().length === 0);\n\tconst inner: string = needsPad ? ` ${content} ` : content;\n\treturn `${fence}${inner}${fence}`;\n}\n","/**\n * Inline Markdown serialization: marks (emphasis nesting), code spans, links and\n * inline nodes. Marks with no portable Markdown form (underline, highlight, …)\n * fall back to raw inline HTML via the existing `MarkSerializer` (D3).\n *\n * Emphasis delimiters are emitted with a ProseMirror-markdown-style\n * reconciliation: shared \"mixable\" marks keep their open position across\n * adjacent text runs, so the serializer never produces ambiguous adjacent\n * delimiters (e.g. `**a*****b***`) that would mis-parse on round-trip.\n */\n\nimport type { InlineNode, Mark, TextNode } from '../../model/Document.js';\nimport { createTextNode, isInlineNode, markSetsEqual } from '../../model/Document.js';\nimport type { HTMLExportContext } from '../../model/NodeSpec.js';\nimport { serializeMarksToHTML } from '../MarkSerializer.js';\nimport { type SerContext, exportContext } from './MarkdownContext.js';\nimport {\n\tescapeInline,\n\tescapeLinkDestination,\n\tescapeLinkTitle,\n\twrapCodeSpan,\n} from './MarkdownEscape.js';\nimport { resolveMarkdownHTMLRegistry } from './MarkdownHTMLRegistry.js';\n\n/** Inline HTML export context (inline-style mode) for HTML-fallback marks. */\nconst INLINE_HTML_CTX: HTMLExportContext = {\n\tstyleAttr: (declarations: string) => (declarations ? ` style=\"${declarations}\"` : ''),\n};\n\n/** Whether a mark is serialized as a Markdown delimiter (vs. HTML fallback / code). */\nfunction isStackMark(mark: Mark, gfm: boolean): boolean {\n\tconst t: string = mark.type;\n\tif (t === 'link' || t === 'bold' || t === 'italic') return true;\n\tif (t === 'strikethrough' && gfm) return true;\n\treturn false;\n}\n\n/** Returns the open/close delimiter pair for a stack mark. */\nfunction delimiters(mark: Mark, ctx: SerContext): { open: string; close: string } {\n\tconst emphasis: string = ctx.opts.emphasis;\n\tswitch (mark.type) {\n\t\tcase 'bold':\n\t\t\treturn { open: emphasis.repeat(2), close: emphasis.repeat(2) };\n\t\tcase 'italic':\n\t\t\treturn { open: emphasis, close: emphasis };\n\t\tcase 'strikethrough':\n\t\t\treturn { open: '~~', close: '~~' };\n\t\tdefault: {\n\t\t\t// link\n\t\t\tconst href: string = String(mark.attrs?.href ?? '');\n\t\t\tconst title: string = String(mark.attrs?.title ?? '');\n\t\t\tconst dest: string = escapeLinkDestination(href);\n\t\t\tconst titlePart: string = title ? ` \"${escapeLinkTitle(title)}\"` : '';\n\t\t\treturn { open: '[', close: `](${dest}${titlePart})` };\n\t\t}\n\t}\n}\n\n/** Mixable marks may be reordered to keep shared marks open; link may not. */\nfunction isMixable(mark: Mark): boolean {\n\treturn mark.type !== 'link';\n}\n\n/** Structural equality for stack marks (type + attrs). */\nfunction marksEqual(a: Mark, b: Mark): boolean {\n\tif (a.type !== b.type) return false;\n\treturn JSON.stringify(a.attrs ?? {}) === JSON.stringify(b.attrs ?? {});\n}\n\n/** Collects the stack (delimiter) marks of a text or inline node, link outermost. */\nfunction stackMarksOf(node: TextNode | InlineNode, gfm: boolean): Mark[] {\n\tconst link: Mark[] = [];\n\tconst emphasis: Mark[] = [];\n\tfor (const mark of node.marks) {\n\t\tif (!isStackMark(mark, gfm)) continue;\n\t\tif (mark.type === 'link') link.push(mark);\n\t\telse emphasis.push(mark);\n\t}\n\treturn [...link, ...emphasis];\n}\n\n/**\n * Reorders a node's stack marks so that mixable marks already open (in `active`)\n * keep their position, minimizing close/reopen churn. Link stays outermost.\n */\nfunction reorderToActive(marks: readonly Mark[], active: readonly Mark[]): Mark[] {\n\tconst result: Mark[] = [];\n\tconst remaining: Mark[] = [...marks];\n\n\t// Non-mixable (link) first, preserving its position.\n\tfor (let i = remaining.length - 1; i >= 0; i--) {\n\t\tconst mark = remaining[i];\n\t\tif (mark && !isMixable(mark)) {\n\t\t\tresult.push(mark);\n\t\t\tremaining.splice(i, 1);\n\t\t}\n\t}\n\n\t// Then mixable marks already active, in active order.\n\tfor (const a of active) {\n\t\tif (!isMixable(a)) continue;\n\t\tconst idx: number = remaining.findIndex((m) => marksEqual(m, a));\n\t\tif (idx !== -1) {\n\t\t\tconst found = remaining[idx];\n\t\t\tif (found) result.push(found);\n\t\t\tremaining.splice(idx, 1);\n\t\t}\n\t}\n\n\t// Finally any new mixable marks.\n\tfor (const m of remaining) result.push(m);\n\treturn result;\n}\n\n/** Renders the literal content of a text node (code span, HTML-fallback, or escaped text). */\nfunction renderTextContent(node: TextNode, ctx: SerContext): string {\n\tif (node.text === '') return '';\n\n\tconst hasCode: boolean = node.marks.some((m) => m.type === 'code');\n\tif (hasCode) return wrapCodeSpan(node.text);\n\n\tconst gfm: boolean = ctx.opts.gfm;\n\tconst fallbackMarks: Mark[] = node.marks.filter((m) => !isStackMark(m, gfm) && m.type !== 'code');\n\n\tif (fallbackMarks.length > 0 && ctx.opts.htmlFallback) {\n\t\treturn serializeMarksToHTML(\n\t\t\tnode.text,\n\t\t\tfallbackMarks,\n\t\t\tresolveMarkdownHTMLRegistry(ctx.registry),\n\t\t\tctx.markOrder,\n\t\t\tINLINE_HTML_CTX,\n\t\t);\n\t}\n\t// htmlFallback off: keep text, drop styling.\n\treturn escapeInline(node.text, gfm);\n}\n\n/** Serializes a single inline node (hard break, inline image, math, plugin extensions). */\nfunction serializeInlineNode(node: InlineNode, ctx: SerContext): string {\n\tif (node.inlineType === 'hard_break') return '\\\\\\n';\n\tif (node.inlineType === 'image_inline') return serializeInlineImage(node, ctx);\n\n\tconst spec = ctx.registry?.getInlineNodeSpec(node.inlineType);\n\tconst md: string | null | undefined = spec?.toMarkdown?.(node, exportContext(ctx.opts));\n\tif (md != null) return md;\n\n\tif (ctx.opts.htmlFallback && spec?.toHTMLString) return spec.toHTMLString(node);\n\treturn '';\n}\n\n/** Serializes an inline image node to `![alt](src \"title\")` (engine-owned standard construct). */\nfunction serializeInlineImage(node: InlineNode, ctx: SerContext): string {\n\tconst src: string = String(node.attrs.src ?? '');\n\tconst alt: string = String(node.attrs.alt ?? '');\n\tconst title: string = String(node.attrs.title ?? '');\n\tconst titlePart: string = title ? ` \"${escapeLinkTitle(title)}\"` : '';\n\treturn `![${escapeInline(alt, ctx.opts.gfm)}](${escapeLinkDestination(src)}${titlePart})`;\n}\n\n/** Merges adjacent text nodes with identical mark sets; inline nodes are boundaries. */\nfunction mergeAdjacent(children: readonly (TextNode | InlineNode)[]): (TextNode | InlineNode)[] {\n\tconst result: (TextNode | InlineNode)[] = [];\n\tfor (const child of children) {\n\t\tconst prev = result[result.length - 1];\n\t\tif (\n\t\t\t!isInlineNode(child) &&\n\t\t\tprev &&\n\t\t\t!isInlineNode(prev) &&\n\t\t\tmarkSetsEqual(prev.marks, child.marks)\n\t\t) {\n\t\t\tresult[result.length - 1] = { type: 'text', text: prev.text + child.text, marks: prev.marks };\n\t\t} else {\n\t\t\tresult.push(child);\n\t\t}\n\t}\n\treturn result;\n}\n\n/** A flanking-sensitive emphasis mark (bold/italic/strike) whose delimiters must hug non-whitespace. */\nfunction isFlankingMark(mark: Mark, gfm: boolean): boolean {\n\treturn isStackMark(mark, gfm) && mark.type !== 'link';\n}\n\n/** Whether a sibling carries a mark equal to `mark` (false for inline nodes / no sibling). */\nfunction siblingHasMark(node: TextNode | InlineNode | undefined, mark: Mark): boolean {\n\tif (!node || isInlineNode(node)) return false;\n\treturn node.marks.some((m) => marksEqual(m, mark));\n}\n\n/** Length of the leading run of ASCII/Unicode whitespace in `text`. */\nfunction leadingWhitespace(text: string): number {\n\tlet i = 0;\n\twhile (i < text.length && /\\s/.test(text[i] as string)) i++;\n\treturn i;\n}\n\n/** Length of the trailing run of whitespace in `text`. */\nfunction trailingWhitespace(text: string): number {\n\tlet i: number = text.length;\n\twhile (i > 0 && /\\s/.test(text[i - 1] as string)) i--;\n\treturn text.length - i;\n}\n\n/** Returns `marks` with every mark in `strip` removed. */\nfunction withoutMarks(marks: readonly Mark[], strip: readonly Mark[]): Mark[] {\n\tif (strip.length === 0) return [...marks];\n\treturn marks.filter((m) => !strip.some((s) => marksEqual(s, m)));\n}\n\n/** Splits one text node's edge whitespace out of its flanking emphasis marks. */\nfunction expelNodeWhitespace(\n\tnode: TextNode,\n\tprev: TextNode | InlineNode | undefined,\n\tnext: TextNode | InlineNode | undefined,\n\tgfm: boolean,\n\tout: (TextNode | InlineNode)[],\n): void {\n\tconst flanking: Mark[] = node.marks.filter((m) => isFlankingMark(m, gfm));\n\tif (flanking.length === 0) {\n\t\tout.push(node);\n\t\treturn;\n\t}\n\n\tconst text: string = node.text;\n\tconst leadLen: number = leadingWhitespace(text);\n\n\t// All whitespace: a flanking mark survives only when interior on BOTH sides\n\t// (a same-mark neighbor before and after); otherwise it is expelled.\n\tif (leadLen === text.length) {\n\t\tconst strip: Mark[] = flanking.filter(\n\t\t\t(m) => !(siblingHasMark(prev, m) && siblingHasMark(next, m)),\n\t\t);\n\t\tout.push(createTextNode(text, withoutMarks(node.marks, strip)));\n\t\treturn;\n\t}\n\n\tconst trailLen: number = trailingWhitespace(text);\n\tconst lead: string = text.slice(0, leadLen);\n\tconst core: string = text.slice(leadLen, text.length - trailLen);\n\tconst trail: string = text.slice(text.length - trailLen);\n\n\tif (lead) {\n\t\tconst strip: Mark[] = flanking.filter((m) => !siblingHasMark(prev, m));\n\t\tout.push(createTextNode(lead, withoutMarks(node.marks, strip)));\n\t}\n\tout.push(createTextNode(core, node.marks));\n\tif (trail) {\n\t\tconst strip: Mark[] = flanking.filter((m) => !siblingHasMark(next, m));\n\t\tout.push(createTextNode(trail, withoutMarks(node.marks, strip)));\n\t}\n}\n\n/**\n * Expels whitespace from the edges of flanking-sensitive emphasis spans\n * (bold/italic/strikethrough). A `**` delimiter that hugs whitespace\n * (`**end **`) is not flanking, so CommonMark — and this engine's own parser —\n * read it literally, breaking the round-trip. Whitespace at a mark's span\n * boundary is moved outside the mark; whitespace interior to a span is kept.\n */\nfunction expelEdgeWhitespace(\n\tchildren: readonly (TextNode | InlineNode)[],\n\tgfm: boolean,\n): (TextNode | InlineNode)[] {\n\tconst out: (TextNode | InlineNode)[] = [];\n\tfor (let i = 0; i < children.length; i++) {\n\t\tconst child = children[i];\n\t\tif (!child) continue;\n\t\tif (isInlineNode(child)) {\n\t\t\tout.push(child);\n\t\t\tcontinue;\n\t\t}\n\t\texpelNodeWhitespace(child, children[i - 1], children[i + 1], gfm, out);\n\t}\n\treturn mergeAdjacent(out);\n}\n\n/** Serializes inline children of a leaf block to a Markdown string. */\nexport function serializeInlineContent(\n\tchildren: readonly (TextNode | InlineNode)[],\n\tctx: SerContext,\n): string {\n\tconst gfm: boolean = ctx.opts.gfm;\n\tconst merged: (TextNode | InlineNode)[] = expelEdgeWhitespace(mergeAdjacent(children), gfm);\n\tlet out = '';\n\tlet active: Mark[] = [];\n\n\tconst closeFrom = (keep: number): void => {\n\t\tfor (let i = active.length - 1; i >= keep; i--) {\n\t\t\tconst mark = active[i];\n\t\t\tif (mark) out += delimiters(mark, ctx).close;\n\t\t}\n\t\tactive = active.slice(0, keep);\n\t};\n\n\tfor (const child of merged) {\n\t\t// Inline nodes carry stack marks too (e.g. a `link` on an inline image), so\n\t\t// they flow through the same open/close reconciliation as text. The only\n\t\t// difference is the literal content emitted between the delimiters.\n\t\tconst target: Mark[] = reorderToActive(stackMarksOf(child, gfm), active);\n\n\t\tlet keep = 0;\n\t\twhile (\n\t\t\tkeep < active.length &&\n\t\t\tkeep < target.length &&\n\t\t\tmarksEqual(active[keep] as Mark, target[keep] as Mark)\n\t\t) {\n\t\t\tkeep++;\n\t\t}\n\t\tcloseFrom(keep);\n\t\tfor (let i = keep; i < target.length; i++) {\n\t\t\tconst mark = target[i];\n\t\t\tif (!mark) continue;\n\t\t\tout += delimiters(mark, ctx).open;\n\t\t\tactive.push(mark);\n\t\t}\n\n\t\tout += isInlineNode(child) ? serializeInlineNode(child, ctx) : renderTextContent(child, ctx);\n\t}\n\n\tcloseFrom(0);\n\treturn out;\n}\n","/**\n * Block-level Markdown serialization.\n *\n * Leaf/self-contained blocks (paragraph, heading, code_block, horizontal_rule,\n * image) have built-in emitters keyed by type name — the same centralized,\n * by-type-name mapping the importer uses, and the shape `prosemirror-markdown`\n * uses. Container/structural blocks (blockquote, list, table) are engine-owned\n * because their children need per-line prefixing/indentation that cannot be\n * composed from a wrapper (D12): each container serializes its own children and\n * applies its prefix to those known lines (never a post-hoc regex on assembled\n * output). Unknown/superset blocks defer to the per-spec `toMarkdown` hook, then\n * to a raw-HTML fallback via `toHTML` (D3, D4).\n */\n\nimport { isNodeOfType } from '../../model/AttrRegistry.js';\nimport type { BlockNode } from '../../model/Document.js';\nimport {\n\tgetBlockChildren,\n\tgetBlockText,\n\tgetInlineChildren,\n\tisLeafBlock,\n} from '../../model/Document.js';\nimport { normalizeHTMLId } from '../../model/HTMLUtils.js';\nimport { serializeDocumentToHTML } from '../DocumentSerializer.js';\nimport {\n\thasExplicitTableColumnWidth,\n\tnormalizeSerializedTableDimensionPx,\n} from '../TableDimensions.js';\nimport { serializeInlineContent } from './InlineSerializers.js';\nimport { type SerContext, exportContext } from './MarkdownContext.js';\nimport {\n\tescapeInline,\n\tescapeLineStart,\n\tescapeLinkDestination,\n\tescapeLinkTitle,\n} from './MarkdownEscape.js';\nimport { resolveMarkdownHTMLRegistry } from './MarkdownHTMLRegistry.js';\n\n/** Serializes a sequence of blocks, grouping consecutive list items, joined by blank lines. */\nexport function serializeBlocks(blocks: readonly BlockNode[], ctx: SerContext): string {\n\tconst parts: string[] = [];\n\tlet i = 0;\n\twhile (i < blocks.length) {\n\t\tconst block: BlockNode | undefined = blocks[i];\n\t\tif (!block) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (isNodeOfType(block, 'list_item')) {\n\t\t\tconst items: BlockNode[] = [];\n\t\t\twhile (i < blocks.length) {\n\t\t\t\tconst item: BlockNode | undefined = blocks[i];\n\t\t\t\tif (!item || !isNodeOfType(item, 'list_item')) break;\n\t\t\t\titems.push(item);\n\t\t\t\ti++;\n\t\t\t}\n\t\t\tparts.push(\n\t\t\t\tctx.opts.htmlFallback && items.some(hasHTMLIdInTree)\n\t\t\t\t\t? serializeHTMLFallback(items, ctx)\n\t\t\t\t\t: serializeListGroup(items, ctx),\n\t\t\t);\n\t\t} else {\n\t\t\tparts.push(serializeBlock(block, ctx));\n\t\t\ti++;\n\t\t}\n\t}\n\treturn parts.filter((p) => p.length > 0).join('\\n\\n');\n}\n\n/** Serializes a single (non-list-item) block. */\nexport function serializeBlock(block: BlockNode, ctx: SerContext): string {\n\tif (ctx.opts.htmlFallback && hasHTMLIdInTree(block)) {\n\t\treturn serializeHTMLFallback([block], ctx);\n\t}\n\tconst type: string = block.type;\n\n\tif (type === 'paragraph') return serializeParagraph(block, ctx);\n\tif (type === 'heading') return serializeHeading(block, ctx);\n\tif (type === 'code_block') return serializeCodeBlock(block, ctx);\n\tif (type === 'horizontal_rule') return ctx.inListItem ? '***' : '---';\n\tif (type === 'image') return serializeImage(block, ctx);\n\tif (type === 'blockquote') return serializeBlockquote(block, ctx);\n\tif (type === 'table') return serializeTable(block, ctx);\n\tif (type === 'title') return serializeTitleLike(block, ctx, 1);\n\tif (type === 'subtitle') return serializeTitleLike(block, ctx, 2);\n\n\treturn serializeUnknownBlock(block, ctx);\n}\n\n/** Whether a block subtree carries HTML-only identity that Markdown cannot express. */\nfunction hasHTMLIdInTree(block: BlockNode): boolean {\n\tif (normalizeHTMLId(block.htmlId)) return true;\n\treturn getBlockChildren(block).some(hasHTMLIdInTree);\n}\n\n/** Emits a complete block run as raw HTML without leaking internal block IDs. */\nfunction serializeHTMLFallback(blocks: readonly BlockNode[], ctx: SerContext): string {\n\treturn serializeDocumentToHTML({ children: blocks }, resolveMarkdownHTMLRegistry(ctx.registry), {\n\t\tincludeBlockIds: false,\n\t});\n}\n\n/** Paragraph: inline content with leading block markers escaped per line. */\nfunction serializeParagraph(block: BlockNode, ctx: SerContext): string {\n\tconst content: string = serializeInlineContent(getInlineChildren(block), ctx);\n\tif (content.trim() === '') return '';\n\treturn content.split('\\n').map(escapeLineStart).join('\\n');\n}\n\n/** Heading: ATX (`## h`) by default, setext for levels 1-2 when requested. */\nfunction serializeHeading(block: BlockNode, ctx: SerContext): string {\n\tconst level: number = clampLevel((block.attrs?.level as number | undefined) ?? 1);\n\tconst content: string = serializeInlineContent(getInlineChildren(block), ctx).replace(/\\n/g, ' ');\n\n\tif (ctx.opts.headingStyle === 'setext' && level <= 2 && content !== '') {\n\t\tconst underline: string = level === 1 ? '=' : '-';\n\t\treturn `${content}\\n${underline.repeat(Math.max(3, content.length))}`;\n\t}\n\tconst hashes: string = '#'.repeat(level);\n\treturn content ? `${hashes} ${content}` : hashes;\n}\n\nfunction clampLevel(level: number): number {\n\tif (level < 1) return 1;\n\tif (level > 6) return 6;\n\treturn Math.floor(level);\n}\n\n/** Fenced code block; the fence is grown to exceed any fence run inside the code. */\nfunction serializeCodeBlock(block: BlockNode, ctx: SerContext): string {\n\tconst lang: string = String(block.attrs?.language ?? '');\n\tconst code: string = getBlockText(block);\n\tconst fenceChar: string = ctx.opts.codeFence[0] ?? '`';\n\tconst fence: string = fenceChar.repeat(Math.max(3, longestRun(code, fenceChar) + 1));\n\treturn `${fence}${lang}\\n${code}\\n${fence}`;\n}\n\n/** Length of the longest consecutive run of `ch` in `text`. */\nfunction longestRun(text: string, ch: string): number {\n\tlet longest = 0;\n\tlet current = 0;\n\tfor (const c of text) {\n\t\tif (c === ch) {\n\t\t\tcurrent++;\n\t\t\tlongest = Math.max(longest, current);\n\t\t} else {\n\t\t\tcurrent = 0;\n\t\t}\n\t}\n\treturn longest;\n}\n\n/** Standalone image on its own line; styling-bearing images use HTML fallback (D3). */\nfunction serializeImage(block: BlockNode, ctx: SerContext): string {\n\tconst src: string = String(block.attrs?.src ?? '');\n\tconst alt: string = String(block.attrs?.alt ?? '');\n\tconst title: string = String(block.attrs?.title ?? '');\n\tconst width = block.attrs?.width as number | undefined;\n\tconst height = block.attrs?.height as number | undefined;\n\tconst align = block.attrs?.align as string | undefined;\n\tconst hasStyling: boolean =\n\t\twidth !== undefined || height !== undefined || (align !== undefined && align !== 'center');\n\n\tif (hasStyling && ctx.opts.htmlFallback) {\n\t\tconst html: string | undefined = ctx.registry?.getNodeSpec('image')?.toHTML?.(block, '');\n\t\tif (html) return html;\n\t}\n\n\tconst titlePart: string = title ? ` \"${escapeLinkTitle(title)}\"` : '';\n\treturn `![${escapeInline(alt, ctx.opts.gfm)}](${escapeLinkDestination(src)}${titlePart})`;\n}\n\n/** Blockquote container: serialize children, then prefix every line with `> `. */\nfunction serializeBlockquote(block: BlockNode, ctx: SerContext): string {\n\tconst inner: string = serializeBlocks(getBlockChildren(block), ctx);\n\treturn inner\n\t\t.split('\\n')\n\t\t.map((line) => (line === '' ? '>' : `> ${line}`))\n\t\t.join('\\n');\n}\n\n/** title/subtitle: HTML fallback (`<h1 class>`) by default; degrade to `#`/`##` otherwise (D5). */\nfunction serializeTitleLike(block: BlockNode, ctx: SerContext, level: number): string {\n\tif (ctx.opts.htmlFallback) {\n\t\tconst content: string = serializeInlineContent(getInlineChildren(block), ctx);\n\t\tconst html: string | undefined = ctx.registry\n\t\t\t?.getNodeSpec(block.type)\n\t\t\t?.toHTML?.(block, content);\n\t\tif (html) return html;\n\t}\n\tconst content: string = serializeInlineContent(getInlineChildren(block), ctx).replace(/\\n/g, ' ');\n\tconst hashes: string = '#'.repeat(level);\n\treturn content ? `${hashes} ${content}` : hashes;\n}\n\n/** Unknown / superset block: per-spec `toMarkdown` hook, then raw-HTML fallback, then degrade. */\nfunction serializeUnknownBlock(block: BlockNode, ctx: SerContext): string {\n\tconst spec = ctx.registry?.getNodeSpec(block.type);\n\tconst content: string = isLeafBlock(block)\n\t\t? serializeInlineContent(getInlineChildren(block), ctx)\n\t\t: serializeBlocks(getBlockChildren(block), ctx);\n\n\tconst md: string | null | undefined = spec?.toMarkdown?.(block, content, exportContext(ctx.opts));\n\tif (md != null) return md;\n\n\tif (ctx.opts.htmlFallback && spec?.toHTML) return spec.toHTML(block, content);\n\n\t// htmlFallback off: keep textual content, drop the unrepresentable wrapper.\n\treturn content;\n}\n\n/**\n * Serializes a run of consecutive list items into Markdown list lines.\n *\n * Indent maps to CommonMark content columns (#194): each level's items are\n * padded to the content column of the last item one level up, so the parser\n * reads them back as nested (a `1. ` parent needs three columns, `- ` two).\n * Container items emit their block children indented to their own content\n * column, separated by the blank lines `serializeBlocks` produces.\n *\n * A nesting level is valid only when the level above it has a preceding item to\n * anchor the content column. An item whose stored indent skips a level (an\n * orphan, e.g. a first item the user tabbed in) is clamped to one deeper than\n * the previous item's effective level. This keeps every marker at a content\n * column an actual parent established, so the emitted pad never lands at four or\n * more columns — which the parser would read as indented code, merging the item\n * into its predecessor or dropping its marker (grammar disagreement). The stored\n * indent is preserved in the model; only its Markdown rendering normalizes.\n */\nfunction serializeListGroup(items: readonly BlockNode[], ctx: SerContext): string {\n\tconst lines: string[] = [];\n\tconst counters: number[] = [];\n\tconst contentColumns: number[] = [];\n\tlet previousIndent = -1;\n\n\tfor (const item of items) {\n\t\tconst listType: string = String(item.attrs?.listType ?? 'bullet');\n\t\tconst storedIndent: number = Math.max(0, (item.attrs?.indent as number | undefined) ?? 0);\n\t\t// Clamp to at most one level deeper than the previous item so a parent\n\t\t// content column always exists (no orphan levels, no >=4-column pad).\n\t\tconst indent: number = Math.min(storedIndent, previousIndent + 1);\n\t\tpreviousIndent = indent;\n\t\tconst padWidth: number = indent === 0 ? 0 : (contentColumns[indent - 1] ?? 0);\n\t\tconst pad: string = ' '.repeat(padWidth);\n\n\t\t// Reset deeper counters/columns when we step back out.\n\t\tcounters.length = indent + 1;\n\t\tcontentColumns.length = indent + 1;\n\n\t\tlet marker: string;\n\t\tif (listType === 'ordered') {\n\t\t\tcounters[indent] = (counters[indent] ?? 0) + 1;\n\t\t\tmarker = `${counters[indent]}.`;\n\t\t} else if (listType === 'checklist') {\n\t\t\tconst checked: boolean = item.attrs?.checked === true;\n\t\t\tmarker = `${ctx.opts.bullet} [${checked ? 'x' : ' '}]`;\n\t\t} else {\n\t\t\tmarker = ctx.opts.bullet;\n\t\t}\n\n\t\t// The task marker belongs to the first content line, not the geometry:\n\t\t// continuation lines of `- [x] foo` align to the bullet's content column.\n\t\tconst markerWidth: number =\n\t\t\tlistType === 'checklist' ? ctx.opts.bullet.length + 1 : marker.length + 1;\n\t\tcontentColumns[indent] = padWidth + markerWidth;\n\n\t\tif (isLeafBlock(item)) {\n\t\t\t// The item content is now block-tokenized on re-import, so a leaf whose\n\t\t\t// text begins with a block marker (`# `, `- `, `> `, `1. `) must be\n\t\t\t// line-start escaped or it reimports as a heading/nested-item child.\n\t\t\tconst content: string = escapeLineStart(\n\t\t\t\tserializeInlineContent(getInlineChildren(item), ctx).replace(/\\n/g, ' '),\n\t\t\t);\n\t\t\tlines.push(content ? `${pad}${marker} ${content}` : `${pad}${marker}`);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Container item (#194): serialize the block children, put the first line\n\t\t// on the marker line, and indent the rest to the item's content column.\n\t\tconst inner: string = serializeBlocks(getBlockChildren(item), { ...ctx, inListItem: true });\n\t\tif (inner === '') {\n\t\t\tlines.push(`${pad}${marker}`);\n\t\t\tcontinue;\n\t\t}\n\t\tconst contentPad: string = ' '.repeat(contentColumns[indent] ?? padWidth + markerWidth);\n\t\tconst innerLines: string[] = inner.split('\\n');\n\t\tlines.push(`${pad}${marker} ${innerLines[0] ?? ''}`);\n\t\tfor (let li = 1; li < innerLines.length; li++) {\n\t\t\tconst innerLine: string = innerLines[li] ?? '';\n\t\t\tlines.push(innerLine === '' ? '' : `${contentPad}${innerLine}`);\n\t\t}\n\t}\n\n\treturn lines.join('\\n');\n}\n\n/** GFM table; tables with colspan/rowspan fall back to raw HTML (D3, no GFM equivalent). */\nfunction serializeTable(block: BlockNode, ctx: SerContext): string {\n\tconst rows: readonly BlockNode[] = getBlockChildren(block);\n\tif (rows.length === 0) return '';\n\n\t// CommonMark has no table syntax. Keep the semantic hierarchy through the\n\t// same raw-HTML seam used for spans and HTML IDs.\n\tif (!ctx.opts.gfm && ctx.opts.htmlFallback) {\n\t\treturn serializeHTMLFallback([block], ctx);\n\t}\n\n\t// GFM has no syntax for either logical column widths or row minimum\n\t// heights. Preserve them through the existing semantic HTML seam when it\n\t// is available. With `htmlFallback: false`, the documented behavior is a\n\t// plain pipe table whose dimensions reset to automatic on re-import.\n\tif (ctx.opts.htmlFallback && (hasSpannedCells(rows) || hasExplicitTableDimensions(block, rows))) {\n\t\treturn serializeHTMLFallback([block], ctx);\n\t}\n\n\tconst matrix: string[][] = rows.map((row) =>\n\t\tgetBlockChildren(row).map((cell) => serializeCell(cell, ctx)),\n\t);\n\tconst columns: number = matrix.reduce((max, row) => Math.max(max, row.length), 0);\n\tif (columns === 0) return '';\n\n\tconst renderRow = (cells: string[]): string => {\n\t\tconst padded: string[] = [...cells];\n\t\twhile (padded.length < columns) padded.push('');\n\t\treturn `| ${padded.join(' | ')} |`;\n\t};\n\n\tconst headerRow: BlockNode | undefined = rows[0];\n\tconst delimiters: string[] = Array.from({ length: columns }, (_v, col) =>\n\t\talignMarker(columnAlign(headerRow, col)),\n\t);\n\n\tconst out: string[] = [];\n\tout.push(renderRow(matrix[0] ?? []));\n\tout.push(`| ${delimiters.join(' | ')} |`);\n\tfor (let i = 1; i < matrix.length; i++) {\n\t\tout.push(renderRow(matrix[i] ?? []));\n\t}\n\treturn out.join('\\n');\n}\n\n/** Reads the column alignment from a header cell's paragraph `align` attribute. */\nfunction columnAlign(headerRow: BlockNode | undefined, col: number): string | undefined {\n\tif (!headerRow) return undefined;\n\tconst cell: BlockNode | undefined = getBlockChildren(headerRow)[col];\n\tif (!cell) return undefined;\n\tconst paragraph: BlockNode | undefined = getBlockChildren(cell)[0];\n\treturn paragraph?.attrs?.align as string | undefined;\n}\n\n/** Maps a logical alignment to its GFM delimiter marker. */\nfunction alignMarker(align: string | undefined): string {\n\tif (align === 'start') return ':---';\n\tif (align === 'center') return ':---:';\n\tif (align === 'end') return '---:';\n\treturn '---';\n}\n\n/** Whether any cell in the rows carries a colspan/rowspan > 1. */\nfunction hasSpannedCells(rows: readonly BlockNode[]): boolean {\n\tfor (const row of rows) {\n\t\tfor (const cell of getBlockChildren(row)) {\n\t\t\tconst colspan = cell.attrs?.colspan as number | undefined;\n\t\t\tconst rowspan = cell.attrs?.rowspan as number | undefined;\n\t\t\tif ((colspan ?? 1) > 1 || (rowspan ?? 1) > 1) return true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/** Whether the table carries any safe dimension that GFM cannot represent. */\nfunction hasExplicitTableDimensions(table: BlockNode, rows: readonly BlockNode[]): boolean {\n\tif (hasExplicitTableColumnWidth(table.attrs?.columnWidthsPx)) return true;\n\treturn rows.some(\n\t\t(row: BlockNode): boolean =>\n\t\t\tnormalizeSerializedTableDimensionPx(row.attrs?.minHeightPx) !== undefined,\n\t);\n}\n\n/** Serializes a table cell to single-line inline Markdown, escaping pipes. */\nfunction serializeCell(cell: BlockNode, ctx: SerContext): string {\n\tconst blocks: readonly BlockNode[] = getBlockChildren(cell);\n\tconst inline: string = blocks\n\t\t.map((b) => serializeInlineContent(getInlineChildren(b), ctx))\n\t\t.join(' ')\n\t\t.replace(/\\n/g, ' ');\n\treturn inline.replace(/\\|/g, '\\\\|').trim();\n}\n","/**\n * MarkdownSerializer: converts an immutable Document into a Markdown string.\n *\n * Mirrors `DocumentSerializer.ts` (HTML) but is reached **only** via dynamic\n * `import()` from the async web-component method and the paste branch, so the\n * bundler genuinely code-splits the engine out of the core chunk (D13). Pure\n * functions — operate on Document/SchemaRegistry, no class state.\n */\n\nimport type { Document } from '../model/Document.js';\nimport type { SchemaRegistry } from '../model/SchemaRegistry.js';\nimport { buildMarkOrder } from './MarkSerializer.js';\nimport type { MarkdownSerializeOptions } from './MarkdownTypes.js';\nimport { serializeBlocks } from './markdown/BlockSerializers.js';\nimport { type SerContext, resolveSerializeOptions } from './markdown/MarkdownContext.js';\n\n/**\n * Serializes a document to a Markdown string.\n *\n * Standard CommonMark/GFM constructs are emitted by the engine's built-in\n * by-type mappings; unrepresentable nodes/marks emit raw HTML (valid Markdown)\n * when `htmlFallback` is on (default), or degrade gracefully when off (D3).\n */\nexport function serializeDocumentToMarkdown(\n\tdoc: Document,\n\tregistry?: SchemaRegistry,\n\toptions?: MarkdownSerializeOptions,\n): string {\n\tconst ctx: SerContext = {\n\t\tregistry,\n\t\topts: resolveSerializeOptions(options),\n\t\tmarkOrder: registry ? buildMarkOrder(registry) : undefined,\n\t};\n\tconst body: string = serializeBlocks(doc.children, ctx);\n\treturn finalizeDocument(body);\n}\n\n/**\n * Closes the assembled document with a single trailing newline, dropping any\n * leading/trailing blank lines. It intentionally does NOT touch the interior:\n * each block serializer is responsible for emitting clean lines, and\n * `serializeBlocks` already joins blocks with exactly one blank line. Trimming\n * only the document boundaries is provably code-safe, since a document never\n * begins or ends inside a code body (blocks open and close on their own\n * delimiters), so significant blank lines and trailing spaces inside a\n * `code_block` survive verbatim at any nesting depth.\n */\nfunction finalizeDocument(markdown: string): string {\n\tconst trimmed: string = markdown.trim();\n\treturn trimmed.length > 0 ? `${trimmed}\\n` : '';\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"MarkdownSerializer-DBELFAeo.mjs","names":[],"sources":["../../src/serialization/markdown/MarkdownContext.ts","../../src/serialization/markdown/MarkdownEscape.ts","../../src/serialization/markdown/InlineSerializers.ts","../../src/serialization/markdown/BlockSerializers.ts","../../src/serialization/MarkdownSerializer.ts"],"sourcesContent":["/**\n * Resolved serialization options and the context threaded through the Markdown\n * serializer. Kept separate from the serializer modules so block/inline\n * serializers can share the type without a circular import.\n */\n\nimport type { MarkdownExportContext } from '../../model/NodeSpec.js';\nimport type { SchemaRegistry } from '../../model/SchemaRegistry.js';\nimport type { MarkdownSerializeOptions } from '../MarkdownTypes.js';\n\n/** Fully-resolved serialization options (no `undefined`). */\nexport interface ResolvedSerializeOptions {\n\treadonly flavor: 'commonmark' | 'gfm';\n\treadonly gfm: boolean;\n\treadonly htmlFallback: boolean;\n\treadonly headingStyle: 'atx' | 'setext';\n\treadonly bullet: string;\n\treadonly emphasis: string;\n\treadonly codeFence: string;\n\treadonly listIndent: number;\n}\n\n/** Internal context shared by all serialization helpers. */\nexport interface SerContext {\n\treadonly registry?: SchemaRegistry;\n\treadonly opts: ResolvedSerializeOptions;\n\t/** Precomputed mark rank map (built once per pass) for HTML-fallback marks. */\n\treadonly markOrder?: Map<string, number>;\n\t/**\n\t * True while serializing the block children of a list item (#194): thematic\n\t * breaks emit `***` there, because `---` on an indented continuation line\n\t * would re-parse as a setext underline or a bullet marker.\n\t */\n\treadonly inListItem?: boolean;\n}\n\n/** Resolves user-facing options into a complete settings object with defaults. */\nexport function resolveSerializeOptions(\n\toptions?: MarkdownSerializeOptions,\n): ResolvedSerializeOptions {\n\tconst flavor: 'commonmark' | 'gfm' = options?.flavor ?? 'gfm';\n\treturn {\n\t\tflavor,\n\t\tgfm: flavor === 'gfm',\n\t\thtmlFallback: options?.htmlFallback !== false,\n\t\theadingStyle: options?.headingStyle ?? 'atx',\n\t\tbullet: options?.bullet ?? '-',\n\t\temphasis: options?.emphasis ?? '*',\n\t\tcodeFence: options?.codeFence ?? '```',\n\t\tlistIndent: options?.listIndent ?? 2,\n\t};\n}\n\n/** Builds the public {@link MarkdownExportContext} passed to per-spec hooks. */\nexport function exportContext(opts: ResolvedSerializeOptions): MarkdownExportContext {\n\treturn { flavor: opts.flavor, htmlFallback: opts.htmlFallback };\n}\n","/**\n * CommonMark escaping rules for Markdown serialization.\n *\n * Escaping is contextual: inline text backslash-escapes characters that would\n * otherwise start emphasis/code/links, while the start of a line additionally\n * escapes block markers (`#`, `>`, `-`, …) so prose never accidentally becomes\n * a heading or list on re-parse. Output stays minimal: we do not escape every\n * punctuation character, only those that are actually ambiguous in context.\n */\n\nimport { FENCE_OPEN, SETEXT_H1, SETEXT_H2, THEMATIC_BREAK } from './BlockTokenizer.js';\n\n/** Inline specials that always need escaping in text content. */\nconst ALWAYS_ESCAPE = new Set(['\\\\', '`', '*', '[', ']', '<', '>']);\n\n/** Whether the character at `i` sits between two word characters (intra-word). */\nfunction isIntraWord(text: string, i: number): boolean {\n\tconst prev: string | undefined = text[i - 1];\n\tconst next: string | undefined = text[i + 1];\n\tif (prev === undefined || next === undefined) return false;\n\treturn /\\w/.test(prev) && /\\w/.test(next);\n}\n\n/**\n * Escapes inline text so it round-trips as literal content. `~` is escaped only\n * for GFM (where `~~` is strikethrough); `_` is escaped only when it is not\n * intra-word, matching CommonMark's emphasis rules (so `a_b_c` stays literal).\n */\nexport function escapeInline(text: string, gfm: boolean): string {\n\tlet out = '';\n\tfor (let i = 0; i < text.length; i++) {\n\t\tconst ch: string = text[i] ?? '';\n\t\tif (ALWAYS_ESCAPE.has(ch)) {\n\t\t\tout += `\\\\${ch}`;\n\t\t\tcontinue;\n\t\t}\n\t\tif (ch === '_' && !isIntraWord(text, i)) {\n\t\t\tout += '\\\\_';\n\t\t\tcontinue;\n\t\t}\n\t\tif (ch === '~' && gfm) {\n\t\t\tout += '\\\\~';\n\t\t\tcontinue;\n\t\t}\n\t\tif (ch === '&') {\n\t\t\tout += '&amp;';\n\t\t\tcontinue;\n\t\t}\n\t\tout += ch;\n\t}\n\treturn out;\n}\n\n/** Pattern matching a leading block marker that must be escaped in paragraph text. */\nconst LINE_START_MARKER = /^(\\s*)([#>])/;\n/** Pattern matching a leading list bullet (`- `, `* `, `+ `). */\nconst LINE_START_BULLET = /^(\\s*)([-*+])(\\s)/;\n/** Pattern matching a leading ordered marker (`1.` / `1)`). */\nconst LINE_START_ORDERED = /^(\\s*)(\\d{1,9})([.)])(\\s)/;\n\n/**\n * Whether a whole line would re-parse as a block construct that spans the entire\n * line: a thematic break, a setext underline, or an opening code fence. These\n * carry no trailing content marker (unlike `#`/`-`/`1.`), so they slip past the\n * leading-marker rules above. Backtick fences and `*`/`_`/`~` breaks are already\n * neutralized by inline escaping (they arrive backslash-prefixed); what reaches\n * here is `-`/`=` runs and, under CommonMark, `~~~` fences.\n */\nfunction reparsesAsBlockLine(line: string): boolean {\n\treturn (\n\t\tTHEMATIC_BREAK.test(line) ||\n\t\tSETEXT_H1.test(line) ||\n\t\tSETEXT_H2.test(line) ||\n\t\tFENCE_OPEN.test(line)\n\t);\n}\n\n/**\n * Escapes leading block markers at the start of a paragraph line so the text\n * does not re-parse as a heading, blockquote, list, thematic break, setext\n * underline, or code fence.\n */\nexport function escapeLineStart(line: string): string {\n\tif (LINE_START_MARKER.test(line)) {\n\t\treturn line.replace(LINE_START_MARKER, (_m, ws: string, marker: string) => `${ws}\\\\${marker}`);\n\t}\n\tif (LINE_START_BULLET.test(line)) {\n\t\treturn line.replace(\n\t\t\tLINE_START_BULLET,\n\t\t\t(_m, ws: string, marker: string, sp: string) => `${ws}\\\\${marker}${sp}`,\n\t\t);\n\t}\n\tif (LINE_START_ORDERED.test(line)) {\n\t\treturn line.replace(\n\t\t\tLINE_START_ORDERED,\n\t\t\t(_m, ws: string, num: string, marker: string, sp: string) => `${ws}${num}\\\\${marker}${sp}`,\n\t\t);\n\t}\n\tif (reparsesAsBlockLine(line)) {\n\t\t// Backslash the first non-space character: that breaks the run so the line\n\t\t// stays a paragraph, and `\\-` / `\\=` / `\\~` decode back to the literal char.\n\t\treturn line.replace(/\\S/, (ch) => `\\\\${ch}`);\n\t}\n\treturn line;\n}\n\n/** Escapes the destination of a link/image so spaces and parens stay intact. */\nexport function escapeLinkDestination(url: string): string {\n\tif (/[\\s()]/.test(url)) {\n\t\treturn `<${url.replace(/([<>])/g, '\\\\$1')}>`;\n\t}\n\treturn url;\n}\n\n/** Escapes a link/image title for the `\"...\"` form. */\nexport function escapeLinkTitle(title: string): string {\n\treturn title.replace(/([\"\\\\])/g, '\\\\$1');\n}\n\n/**\n * Picks a backtick fence long enough to wrap `content` as an inline code span.\n * CommonMark requires a fence longer than any backtick run inside the content.\n */\nexport function codeSpanFence(content: string): string {\n\tlet longest = 0;\n\tlet current = 0;\n\tfor (const ch of content) {\n\t\tif (ch === '`') {\n\t\t\tcurrent++;\n\t\t\tlongest = Math.max(longest, current);\n\t\t} else {\n\t\t\tcurrent = 0;\n\t\t}\n\t}\n\treturn '`'.repeat(longest + 1);\n}\n\n/** Wraps `content` in a correctly sized inline code span, padding when needed. */\nexport function wrapCodeSpan(content: string): string {\n\tconst fence: string = codeSpanFence(content);\n\t// Pad with a space when content starts/ends with a backtick or is all spaces,\n\t// per CommonMark's code-span stripping rule.\n\tconst needsPad: boolean =\n\t\tcontent.startsWith('`') ||\n\t\tcontent.endsWith('`') ||\n\t\t(content.length > 0 && content.trim().length === 0);\n\tconst inner: string = needsPad ? ` ${content} ` : content;\n\treturn `${fence}${inner}${fence}`;\n}\n","/**\n * Inline Markdown serialization: marks (emphasis nesting), code spans, links and\n * inline nodes. Marks with no portable Markdown form (underline, highlight, …)\n * fall back to raw inline HTML via the existing `MarkSerializer` (D3).\n *\n * Emphasis delimiters are emitted with a ProseMirror-markdown-style\n * reconciliation: shared \"mixable\" marks keep their open position across\n * adjacent text runs, so the serializer never produces ambiguous adjacent\n * delimiters (e.g. `**a*****b***`) that would mis-parse on round-trip.\n */\n\nimport type { InlineNode, Mark, TextNode } from '../../model/Document.js';\nimport { createTextNode, isInlineNode, markSetsEqual } from '../../model/Document.js';\nimport type { HTMLExportContext } from '../../model/NodeSpec.js';\nimport { serializeMarksToHTML } from '../MarkSerializer.js';\nimport { type SerContext, exportContext } from './MarkdownContext.js';\nimport {\n\tescapeInline,\n\tescapeLinkDestination,\n\tescapeLinkTitle,\n\twrapCodeSpan,\n} from './MarkdownEscape.js';\nimport { resolveMarkdownHTMLRegistry } from './MarkdownHTMLRegistry.js';\n\n/** Inline HTML export context (inline-style mode) for HTML-fallback marks. */\nconst INLINE_HTML_CTX: HTMLExportContext = {\n\tstyleAttr: (declarations: string) => (declarations ? ` style=\"${declarations}\"` : ''),\n};\n\n/** Whether a mark is serialized as a Markdown delimiter (vs. HTML fallback / code). */\nfunction isStackMark(mark: Mark, gfm: boolean): boolean {\n\tconst t: string = mark.type;\n\tif (t === 'link' || t === 'bold' || t === 'italic') return true;\n\tif (t === 'strikethrough' && gfm) return true;\n\treturn false;\n}\n\n/** Returns the open/close delimiter pair for a stack mark. */\nfunction delimiters(mark: Mark, ctx: SerContext): { open: string; close: string } {\n\tconst emphasis: string = ctx.opts.emphasis;\n\tswitch (mark.type) {\n\t\tcase 'bold':\n\t\t\treturn { open: emphasis.repeat(2), close: emphasis.repeat(2) };\n\t\tcase 'italic':\n\t\t\treturn { open: emphasis, close: emphasis };\n\t\tcase 'strikethrough':\n\t\t\treturn { open: '~~', close: '~~' };\n\t\tdefault: {\n\t\t\t// link\n\t\t\tconst href: string = String(mark.attrs?.href ?? '');\n\t\t\tconst title: string = String(mark.attrs?.title ?? '');\n\t\t\tconst dest: string = escapeLinkDestination(href);\n\t\t\tconst titlePart: string = title ? ` \"${escapeLinkTitle(title)}\"` : '';\n\t\t\treturn { open: '[', close: `](${dest}${titlePart})` };\n\t\t}\n\t}\n}\n\n/** Mixable marks may be reordered to keep shared marks open; link may not. */\nfunction isMixable(mark: Mark): boolean {\n\treturn mark.type !== 'link';\n}\n\n/** Structural equality for stack marks (type + attrs). */\nfunction marksEqual(a: Mark, b: Mark): boolean {\n\tif (a.type !== b.type) return false;\n\treturn JSON.stringify(a.attrs ?? {}) === JSON.stringify(b.attrs ?? {});\n}\n\n/** Collects the stack (delimiter) marks of a text or inline node, link outermost. */\nfunction stackMarksOf(node: TextNode | InlineNode, gfm: boolean): Mark[] {\n\tconst link: Mark[] = [];\n\tconst emphasis: Mark[] = [];\n\tfor (const mark of node.marks) {\n\t\tif (!isStackMark(mark, gfm)) continue;\n\t\tif (mark.type === 'link') link.push(mark);\n\t\telse emphasis.push(mark);\n\t}\n\treturn [...link, ...emphasis];\n}\n\n/**\n * Reorders a node's stack marks so that mixable marks already open (in `active`)\n * keep their position, minimizing close/reopen churn. Link stays outermost.\n */\nfunction reorderToActive(marks: readonly Mark[], active: readonly Mark[]): Mark[] {\n\tconst result: Mark[] = [];\n\tconst remaining: Mark[] = [...marks];\n\n\t// Non-mixable (link) first, preserving its position.\n\tfor (let i = remaining.length - 1; i >= 0; i--) {\n\t\tconst mark = remaining[i];\n\t\tif (mark && !isMixable(mark)) {\n\t\t\tresult.push(mark);\n\t\t\tremaining.splice(i, 1);\n\t\t}\n\t}\n\n\t// Then mixable marks already active, in active order.\n\tfor (const a of active) {\n\t\tif (!isMixable(a)) continue;\n\t\tconst idx: number = remaining.findIndex((m) => marksEqual(m, a));\n\t\tif (idx !== -1) {\n\t\t\tconst found = remaining[idx];\n\t\t\tif (found) result.push(found);\n\t\t\tremaining.splice(idx, 1);\n\t\t}\n\t}\n\n\t// Finally any new mixable marks.\n\tfor (const m of remaining) result.push(m);\n\treturn result;\n}\n\n/** Renders the literal content of a text node (code span, HTML-fallback, or escaped text). */\nfunction renderTextContent(node: TextNode, ctx: SerContext): string {\n\tif (node.text === '') return '';\n\n\tconst hasCode: boolean = node.marks.some((m) => m.type === 'code');\n\tif (hasCode) return wrapCodeSpan(node.text);\n\n\tconst gfm: boolean = ctx.opts.gfm;\n\tconst fallbackMarks: Mark[] = node.marks.filter((m) => !isStackMark(m, gfm) && m.type !== 'code');\n\n\tif (fallbackMarks.length > 0 && ctx.opts.htmlFallback) {\n\t\treturn serializeMarksToHTML(\n\t\t\tnode.text,\n\t\t\tfallbackMarks,\n\t\t\tresolveMarkdownHTMLRegistry(ctx.registry),\n\t\t\tctx.markOrder,\n\t\t\tINLINE_HTML_CTX,\n\t\t);\n\t}\n\t// htmlFallback off: keep text, drop styling.\n\treturn escapeInline(node.text, gfm);\n}\n\n/** Serializes a single inline node (hard break, inline image, math, plugin extensions). */\nfunction serializeInlineNode(node: InlineNode, ctx: SerContext): string {\n\tif (node.inlineType === 'hard_break') return '\\\\\\n';\n\tif (node.inlineType === 'image_inline') return serializeInlineImage(node, ctx);\n\n\tconst spec = ctx.registry?.getInlineNodeSpec(node.inlineType);\n\tconst md: string | null | undefined = spec?.toMarkdown?.(node, exportContext(ctx.opts));\n\tif (md != null) return md;\n\n\tif (ctx.opts.htmlFallback && spec?.toHTMLString) return spec.toHTMLString(node);\n\treturn '';\n}\n\n/** Serializes an inline image node to `![alt](src \"title\")` (engine-owned standard construct). */\nfunction serializeInlineImage(node: InlineNode, ctx: SerContext): string {\n\tconst src: string = String(node.attrs.src ?? '');\n\tconst alt: string = String(node.attrs.alt ?? '');\n\tconst title: string = String(node.attrs.title ?? '');\n\tconst titlePart: string = title ? ` \"${escapeLinkTitle(title)}\"` : '';\n\treturn `![${escapeInline(alt, ctx.opts.gfm)}](${escapeLinkDestination(src)}${titlePart})`;\n}\n\n/** Merges adjacent text nodes with identical mark sets; inline nodes are boundaries. */\nfunction mergeAdjacent(children: readonly (TextNode | InlineNode)[]): (TextNode | InlineNode)[] {\n\tconst result: (TextNode | InlineNode)[] = [];\n\tfor (const child of children) {\n\t\tconst prev = result[result.length - 1];\n\t\tif (\n\t\t\t!isInlineNode(child) &&\n\t\t\tprev &&\n\t\t\t!isInlineNode(prev) &&\n\t\t\tmarkSetsEqual(prev.marks, child.marks)\n\t\t) {\n\t\t\tresult[result.length - 1] = { type: 'text', text: prev.text + child.text, marks: prev.marks };\n\t\t} else {\n\t\t\tresult.push(child);\n\t\t}\n\t}\n\treturn result;\n}\n\n/** A flanking-sensitive emphasis mark (bold/italic/strike) whose delimiters must hug non-whitespace. */\nfunction isFlankingMark(mark: Mark, gfm: boolean): boolean {\n\treturn isStackMark(mark, gfm) && mark.type !== 'link';\n}\n\n/** Whether a sibling carries a mark equal to `mark` (false for inline nodes / no sibling). */\nfunction siblingHasMark(node: TextNode | InlineNode | undefined, mark: Mark): boolean {\n\tif (!node || isInlineNode(node)) return false;\n\treturn node.marks.some((m) => marksEqual(m, mark));\n}\n\n/** Length of the leading run of ASCII/Unicode whitespace in `text`. */\nfunction leadingWhitespace(text: string): number {\n\tlet i = 0;\n\twhile (i < text.length && /\\s/.test(text[i] as string)) i++;\n\treturn i;\n}\n\n/** Length of the trailing run of whitespace in `text`. */\nfunction trailingWhitespace(text: string): number {\n\tlet i: number = text.length;\n\twhile (i > 0 && /\\s/.test(text[i - 1] as string)) i--;\n\treturn text.length - i;\n}\n\n/** Returns `marks` with every mark in `strip` removed. */\nfunction withoutMarks(marks: readonly Mark[], strip: readonly Mark[]): Mark[] {\n\tif (strip.length === 0) return [...marks];\n\treturn marks.filter((m) => !strip.some((s) => marksEqual(s, m)));\n}\n\n/** Splits one text node's edge whitespace out of its flanking emphasis marks. */\nfunction expelNodeWhitespace(\n\tnode: TextNode,\n\tprev: TextNode | InlineNode | undefined,\n\tnext: TextNode | InlineNode | undefined,\n\tgfm: boolean,\n\tout: (TextNode | InlineNode)[],\n): void {\n\tconst flanking: Mark[] = node.marks.filter((m) => isFlankingMark(m, gfm));\n\tif (flanking.length === 0) {\n\t\tout.push(node);\n\t\treturn;\n\t}\n\n\tconst text: string = node.text;\n\tconst leadLen: number = leadingWhitespace(text);\n\n\t// All whitespace: a flanking mark survives only when interior on BOTH sides\n\t// (a same-mark neighbor before and after); otherwise it is expelled.\n\tif (leadLen === text.length) {\n\t\tconst strip: Mark[] = flanking.filter(\n\t\t\t(m) => !(siblingHasMark(prev, m) && siblingHasMark(next, m)),\n\t\t);\n\t\tout.push(createTextNode(text, withoutMarks(node.marks, strip)));\n\t\treturn;\n\t}\n\n\tconst trailLen: number = trailingWhitespace(text);\n\tconst lead: string = text.slice(0, leadLen);\n\tconst core: string = text.slice(leadLen, text.length - trailLen);\n\tconst trail: string = text.slice(text.length - trailLen);\n\n\tif (lead) {\n\t\tconst strip: Mark[] = flanking.filter((m) => !siblingHasMark(prev, m));\n\t\tout.push(createTextNode(lead, withoutMarks(node.marks, strip)));\n\t}\n\tout.push(createTextNode(core, node.marks));\n\tif (trail) {\n\t\tconst strip: Mark[] = flanking.filter((m) => !siblingHasMark(next, m));\n\t\tout.push(createTextNode(trail, withoutMarks(node.marks, strip)));\n\t}\n}\n\n/**\n * Expels whitespace from the edges of flanking-sensitive emphasis spans\n * (bold/italic/strikethrough). A `**` delimiter that hugs whitespace\n * (`**end **`) is not flanking, so CommonMark — and this engine's own parser —\n * read it literally, breaking the round-trip. Whitespace at a mark's span\n * boundary is moved outside the mark; whitespace interior to a span is kept.\n */\nfunction expelEdgeWhitespace(\n\tchildren: readonly (TextNode | InlineNode)[],\n\tgfm: boolean,\n): (TextNode | InlineNode)[] {\n\tconst out: (TextNode | InlineNode)[] = [];\n\tfor (let i = 0; i < children.length; i++) {\n\t\tconst child = children[i];\n\t\tif (!child) continue;\n\t\tif (isInlineNode(child)) {\n\t\t\tout.push(child);\n\t\t\tcontinue;\n\t\t}\n\t\texpelNodeWhitespace(child, children[i - 1], children[i + 1], gfm, out);\n\t}\n\treturn mergeAdjacent(out);\n}\n\n/** Serializes inline children of a leaf block to a Markdown string. */\nexport function serializeInlineContent(\n\tchildren: readonly (TextNode | InlineNode)[],\n\tctx: SerContext,\n): string {\n\tconst gfm: boolean = ctx.opts.gfm;\n\tconst merged: (TextNode | InlineNode)[] = expelEdgeWhitespace(mergeAdjacent(children), gfm);\n\tlet out = '';\n\tlet active: Mark[] = [];\n\n\tconst closeFrom = (keep: number): void => {\n\t\tfor (let i = active.length - 1; i >= keep; i--) {\n\t\t\tconst mark = active[i];\n\t\t\tif (mark) out += delimiters(mark, ctx).close;\n\t\t}\n\t\tactive = active.slice(0, keep);\n\t};\n\n\tfor (const child of merged) {\n\t\t// Inline nodes carry stack marks too (e.g. a `link` on an inline image), so\n\t\t// they flow through the same open/close reconciliation as text. The only\n\t\t// difference is the literal content emitted between the delimiters.\n\t\tconst target: Mark[] = reorderToActive(stackMarksOf(child, gfm), active);\n\n\t\tlet keep = 0;\n\t\twhile (\n\t\t\tkeep < active.length &&\n\t\t\tkeep < target.length &&\n\t\t\tmarksEqual(active[keep] as Mark, target[keep] as Mark)\n\t\t) {\n\t\t\tkeep++;\n\t\t}\n\t\tcloseFrom(keep);\n\t\tfor (let i = keep; i < target.length; i++) {\n\t\t\tconst mark = target[i];\n\t\t\tif (!mark) continue;\n\t\t\tout += delimiters(mark, ctx).open;\n\t\t\tactive.push(mark);\n\t\t}\n\n\t\tout += isInlineNode(child) ? serializeInlineNode(child, ctx) : renderTextContent(child, ctx);\n\t}\n\n\tcloseFrom(0);\n\treturn out;\n}\n","/**\n * Block-level Markdown serialization.\n *\n * Leaf/self-contained blocks (paragraph, heading, code_block, horizontal_rule,\n * image) have built-in emitters keyed by type name — the same centralized,\n * by-type-name mapping the importer uses, and the shape `prosemirror-markdown`\n * uses. Container/structural blocks (blockquote, list, table) are engine-owned\n * because their children need per-line prefixing/indentation that cannot be\n * composed from a wrapper (D12): each container serializes its own children and\n * applies its prefix to those known lines (never a post-hoc regex on assembled\n * output). Unknown/superset blocks defer to the per-spec `toMarkdown` hook, then\n * to a raw-HTML fallback via `toHTML` (D3, D4).\n */\n\nimport { isNodeOfType } from '../../model/AttrRegistry.js';\nimport type { BlockNode } from '../../model/Document.js';\nimport {\n\tgetBlockChildren,\n\tgetBlockText,\n\tgetInlineChildren,\n\tisLeafBlock,\n} from '../../model/Document.js';\nimport { normalizeHTMLId } from '../../model/HTMLUtils.js';\nimport { serializeDocumentToHTML } from '../DocumentSerializer.js';\nimport {\n\thasExplicitTableColumnWidth,\n\tnormalizeSerializedTableDimensionPx,\n} from '../TableDimensions.js';\nimport { serializeInlineContent } from './InlineSerializers.js';\nimport { type SerContext, exportContext } from './MarkdownContext.js';\nimport {\n\tescapeInline,\n\tescapeLineStart,\n\tescapeLinkDestination,\n\tescapeLinkTitle,\n} from './MarkdownEscape.js';\nimport { resolveMarkdownHTMLRegistry } from './MarkdownHTMLRegistry.js';\n\n/** Serializes a sequence of blocks, grouping consecutive list items, joined by blank lines. */\nexport function serializeBlocks(blocks: readonly BlockNode[], ctx: SerContext): string {\n\tconst parts: string[] = [];\n\tlet i = 0;\n\twhile (i < blocks.length) {\n\t\tconst block: BlockNode | undefined = blocks[i];\n\t\tif (!block) {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (isNodeOfType(block, 'list_item')) {\n\t\t\tconst items: BlockNode[] = [];\n\t\t\twhile (i < blocks.length) {\n\t\t\t\tconst item: BlockNode | undefined = blocks[i];\n\t\t\t\tif (!item || !isNodeOfType(item, 'list_item')) break;\n\t\t\t\titems.push(item);\n\t\t\t\ti++;\n\t\t\t}\n\t\t\tparts.push(\n\t\t\t\tctx.opts.htmlFallback && items.some(hasHTMLIdInTree)\n\t\t\t\t\t? serializeHTMLFallback(items, ctx)\n\t\t\t\t\t: serializeListGroup(items, ctx),\n\t\t\t);\n\t\t} else {\n\t\t\tparts.push(serializeBlock(block, ctx));\n\t\t\ti++;\n\t\t}\n\t}\n\treturn parts.filter((p) => p.length > 0).join('\\n\\n');\n}\n\n/** Serializes a single (non-list-item) block. */\nexport function serializeBlock(block: BlockNode, ctx: SerContext): string {\n\tif (ctx.opts.htmlFallback && hasHTMLIdInTree(block)) {\n\t\treturn serializeHTMLFallback([block], ctx);\n\t}\n\tconst type: string = block.type;\n\n\tif (type === 'paragraph') return serializeParagraph(block, ctx);\n\tif (type === 'heading') return serializeHeading(block, ctx);\n\tif (type === 'code_block') return serializeCodeBlock(block, ctx);\n\tif (type === 'horizontal_rule') return ctx.inListItem ? '***' : '---';\n\tif (type === 'image') return serializeImage(block, ctx);\n\tif (type === 'blockquote') return serializeBlockquote(block, ctx);\n\tif (type === 'table') return serializeTable(block, ctx);\n\tif (type === 'title') return serializeTitleLike(block, ctx, 1);\n\tif (type === 'subtitle') return serializeTitleLike(block, ctx, 2);\n\n\treturn serializeUnknownBlock(block, ctx);\n}\n\n/** Whether a block subtree carries HTML-only identity that Markdown cannot express. */\nfunction hasHTMLIdInTree(block: BlockNode): boolean {\n\tif (normalizeHTMLId(block.htmlId)) return true;\n\treturn getBlockChildren(block).some(hasHTMLIdInTree);\n}\n\n/** Emits a complete block run as raw HTML without leaking internal block IDs. */\nfunction serializeHTMLFallback(blocks: readonly BlockNode[], ctx: SerContext): string {\n\treturn serializeDocumentToHTML({ children: blocks }, resolveMarkdownHTMLRegistry(ctx.registry), {\n\t\tincludeBlockIds: false,\n\t});\n}\n\n/** Paragraph: inline content with leading block markers escaped per line. */\nfunction serializeParagraph(block: BlockNode, ctx: SerContext): string {\n\tconst content: string = serializeInlineContent(getInlineChildren(block), ctx);\n\tif (content.trim() === '') return '';\n\treturn content.split('\\n').map(escapeLineStart).join('\\n');\n}\n\n/** Heading: ATX (`## h`) by default, setext for levels 1-2 when requested. */\nfunction serializeHeading(block: BlockNode, ctx: SerContext): string {\n\tconst level: number = clampLevel((block.attrs?.level as number | undefined) ?? 1);\n\tconst content: string = serializeInlineContent(getInlineChildren(block), ctx).replace(/\\n/g, ' ');\n\n\tif (ctx.opts.headingStyle === 'setext' && level <= 2 && content !== '') {\n\t\tconst underline: string = level === 1 ? '=' : '-';\n\t\treturn `${content}\\n${underline.repeat(Math.max(3, content.length))}`;\n\t}\n\tconst hashes: string = '#'.repeat(level);\n\treturn content ? `${hashes} ${content}` : hashes;\n}\n\nfunction clampLevel(level: number): number {\n\tif (level < 1) return 1;\n\tif (level > 6) return 6;\n\treturn Math.floor(level);\n}\n\n/** Fenced code block; the fence is grown to exceed any fence run inside the code. */\nfunction serializeCodeBlock(block: BlockNode, ctx: SerContext): string {\n\tconst lang: string = String(block.attrs?.language ?? '');\n\tconst code: string = getBlockText(block);\n\tconst fenceChar: string = ctx.opts.codeFence[0] ?? '`';\n\tconst fence: string = fenceChar.repeat(Math.max(3, longestRun(code, fenceChar) + 1));\n\treturn `${fence}${lang}\\n${code}\\n${fence}`;\n}\n\n/** Length of the longest consecutive run of `ch` in `text`. */\nfunction longestRun(text: string, ch: string): number {\n\tlet longest = 0;\n\tlet current = 0;\n\tfor (const c of text) {\n\t\tif (c === ch) {\n\t\t\tcurrent++;\n\t\t\tlongest = Math.max(longest, current);\n\t\t} else {\n\t\t\tcurrent = 0;\n\t\t}\n\t}\n\treturn longest;\n}\n\n/** Standalone image on its own line; styling-bearing images use HTML fallback (D3). */\nfunction serializeImage(block: BlockNode, ctx: SerContext): string {\n\tconst src: string = String(block.attrs?.src ?? '');\n\tconst alt: string = String(block.attrs?.alt ?? '');\n\tconst title: string = String(block.attrs?.title ?? '');\n\tconst width = block.attrs?.width as number | undefined;\n\tconst height = block.attrs?.height as number | undefined;\n\tconst align = block.attrs?.align as string | undefined;\n\tconst hasStyling: boolean =\n\t\twidth !== undefined || height !== undefined || (align !== undefined && align !== 'center');\n\n\tif (hasStyling && ctx.opts.htmlFallback) {\n\t\tconst html: string | undefined = ctx.registry?.getNodeSpec('image')?.toHTML?.(block, '');\n\t\tif (html) return html;\n\t}\n\n\tconst titlePart: string = title ? ` \"${escapeLinkTitle(title)}\"` : '';\n\treturn `![${escapeInline(alt, ctx.opts.gfm)}](${escapeLinkDestination(src)}${titlePart})`;\n}\n\n/** Blockquote container: serialize children, then prefix every line with `> `. */\nfunction serializeBlockquote(block: BlockNode, ctx: SerContext): string {\n\tconst inner: string = serializeBlocks(getBlockChildren(block), ctx);\n\treturn inner\n\t\t.split('\\n')\n\t\t.map((line) => (line === '' ? '>' : `> ${line}`))\n\t\t.join('\\n');\n}\n\n/** title/subtitle: HTML fallback (`<h1 class>`) by default; degrade to `#`/`##` otherwise (D5). */\nfunction serializeTitleLike(block: BlockNode, ctx: SerContext, level: number): string {\n\tif (ctx.opts.htmlFallback) {\n\t\tconst content: string = serializeInlineContent(getInlineChildren(block), ctx);\n\t\tconst html: string | undefined = ctx.registry\n\t\t\t?.getNodeSpec(block.type)\n\t\t\t?.toHTML?.(block, content);\n\t\tif (html) return html;\n\t}\n\tconst content: string = serializeInlineContent(getInlineChildren(block), ctx).replace(/\\n/g, ' ');\n\tconst hashes: string = '#'.repeat(level);\n\treturn content ? `${hashes} ${content}` : hashes;\n}\n\n/** Unknown / superset block: per-spec `toMarkdown` hook, then raw-HTML fallback, then degrade. */\nfunction serializeUnknownBlock(block: BlockNode, ctx: SerContext): string {\n\tconst spec = ctx.registry?.getNodeSpec(block.type);\n\tconst content: string = isLeafBlock(block)\n\t\t? serializeInlineContent(getInlineChildren(block), ctx)\n\t\t: serializeBlocks(getBlockChildren(block), ctx);\n\n\tconst md: string | null | undefined = spec?.toMarkdown?.(block, content, exportContext(ctx.opts));\n\tif (md != null) return md;\n\n\tif (ctx.opts.htmlFallback && spec?.toHTML) return spec.toHTML(block, content);\n\n\t// htmlFallback off: keep textual content, drop the unrepresentable wrapper.\n\treturn content;\n}\n\n/**\n * Serializes a run of consecutive list items into Markdown list lines.\n *\n * Indent maps to CommonMark content columns (#194): each level's items are\n * padded to the content column of the last item one level up, so the parser\n * reads them back as nested (a `1. ` parent needs three columns, `- ` two).\n * Container items emit their block children indented to their own content\n * column, separated by the blank lines `serializeBlocks` produces.\n *\n * A nesting level is valid only when the level above it has a preceding item to\n * anchor the content column. An item whose stored indent skips a level (an\n * orphan, e.g. a first item the user tabbed in) is clamped to one deeper than\n * the previous item's effective level. This keeps every marker at a content\n * column an actual parent established, so the emitted pad never lands at four or\n * more columns — which the parser would read as indented code, merging the item\n * into its predecessor or dropping its marker (grammar disagreement). The stored\n * indent is preserved in the model; only its Markdown rendering normalizes.\n */\nfunction serializeListGroup(items: readonly BlockNode[], ctx: SerContext): string {\n\tconst lines: string[] = [];\n\tconst counters: number[] = [];\n\tconst contentColumns: number[] = [];\n\tlet previousIndent = -1;\n\n\tfor (const item of items) {\n\t\tconst listType: string = String(item.attrs?.listType ?? 'bullet');\n\t\tconst storedIndent: number = Math.max(0, (item.attrs?.indent as number | undefined) ?? 0);\n\t\t// Clamp to at most one level deeper than the previous item so a parent\n\t\t// content column always exists (no orphan levels, no >=4-column pad).\n\t\tconst indent: number = Math.min(storedIndent, previousIndent + 1);\n\t\tpreviousIndent = indent;\n\t\tconst padWidth: number = indent === 0 ? 0 : (contentColumns[indent - 1] ?? 0);\n\t\tconst pad: string = ' '.repeat(padWidth);\n\n\t\t// Reset deeper counters/columns when we step back out.\n\t\tcounters.length = indent + 1;\n\t\tcontentColumns.length = indent + 1;\n\n\t\tlet marker: string;\n\t\tif (listType === 'ordered') {\n\t\t\tcounters[indent] = (counters[indent] ?? 0) + 1;\n\t\t\tmarker = `${counters[indent]}.`;\n\t\t} else if (listType === 'checklist') {\n\t\t\tconst checked: boolean = item.attrs?.checked === true;\n\t\t\tmarker = `${ctx.opts.bullet} [${checked ? 'x' : ' '}]`;\n\t\t} else {\n\t\t\tmarker = ctx.opts.bullet;\n\t\t}\n\n\t\t// The task marker belongs to the first content line, not the geometry:\n\t\t// continuation lines of `- [x] foo` align to the bullet's content column.\n\t\tconst markerWidth: number =\n\t\t\tlistType === 'checklist' ? ctx.opts.bullet.length + 1 : marker.length + 1;\n\t\tcontentColumns[indent] = padWidth + markerWidth;\n\n\t\tif (isLeafBlock(item)) {\n\t\t\t// The item content is now block-tokenized on re-import, so a leaf whose\n\t\t\t// text begins with a block marker (`# `, `- `, `> `, `1. `) must be\n\t\t\t// line-start escaped or it reimports as a heading/nested-item child.\n\t\t\tconst content: string = escapeLineStart(\n\t\t\t\tserializeInlineContent(getInlineChildren(item), ctx).replace(/\\n/g, ' '),\n\t\t\t);\n\t\t\tlines.push(content ? `${pad}${marker} ${content}` : `${pad}${marker}`);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Container item (#194): serialize the block children, put the first line\n\t\t// on the marker line, and indent the rest to the item's content column.\n\t\tconst inner: string = serializeBlocks(getBlockChildren(item), { ...ctx, inListItem: true });\n\t\tif (inner === '') {\n\t\t\tlines.push(`${pad}${marker}`);\n\t\t\tcontinue;\n\t\t}\n\t\tconst contentPad: string = ' '.repeat(contentColumns[indent] ?? padWidth + markerWidth);\n\t\tconst innerLines: string[] = inner.split('\\n');\n\t\tlines.push(`${pad}${marker} ${innerLines[0] ?? ''}`);\n\t\tfor (let li = 1; li < innerLines.length; li++) {\n\t\t\tconst innerLine: string = innerLines[li] ?? '';\n\t\t\tlines.push(innerLine === '' ? '' : `${contentPad}${innerLine}`);\n\t\t}\n\t}\n\n\treturn lines.join('\\n');\n}\n\n/** GFM table; tables with colspan/rowspan fall back to raw HTML (D3, no GFM equivalent). */\nfunction serializeTable(block: BlockNode, ctx: SerContext): string {\n\tconst rows: readonly BlockNode[] = getBlockChildren(block);\n\tif (rows.length === 0) return '';\n\n\t// CommonMark has no table syntax. Keep the semantic hierarchy through the\n\t// same raw-HTML seam used for spans and HTML IDs.\n\tif (!ctx.opts.gfm && ctx.opts.htmlFallback) {\n\t\treturn serializeHTMLFallback([block], ctx);\n\t}\n\n\t// GFM has no syntax for either logical column widths or row minimum\n\t// heights. Preserve them through the existing semantic HTML seam when it\n\t// is available. With `htmlFallback: false`, the documented behavior is a\n\t// plain pipe table whose dimensions reset to automatic on re-import.\n\tif (ctx.opts.htmlFallback && (hasSpannedCells(rows) || hasExplicitTableDimensions(block, rows))) {\n\t\treturn serializeHTMLFallback([block], ctx);\n\t}\n\n\tconst matrix: string[][] = rows.map((row) =>\n\t\tgetBlockChildren(row).map((cell) => serializeCell(cell, ctx)),\n\t);\n\tconst columns: number = matrix.reduce((max, row) => Math.max(max, row.length), 0);\n\tif (columns === 0) return '';\n\n\tconst renderRow = (cells: string[]): string => {\n\t\tconst padded: string[] = [...cells];\n\t\twhile (padded.length < columns) padded.push('');\n\t\treturn `| ${padded.join(' | ')} |`;\n\t};\n\n\tconst headerRow: BlockNode | undefined = rows[0];\n\tconst delimiters: string[] = Array.from({ length: columns }, (_v, col) =>\n\t\talignMarker(columnAlign(headerRow, col)),\n\t);\n\n\tconst out: string[] = [];\n\tout.push(renderRow(matrix[0] ?? []));\n\tout.push(`| ${delimiters.join(' | ')} |`);\n\tfor (let i = 1; i < matrix.length; i++) {\n\t\tout.push(renderRow(matrix[i] ?? []));\n\t}\n\treturn out.join('\\n');\n}\n\n/** Reads the column alignment from a header cell's paragraph `align` attribute. */\nfunction columnAlign(headerRow: BlockNode | undefined, col: number): string | undefined {\n\tif (!headerRow) return undefined;\n\tconst cell: BlockNode | undefined = getBlockChildren(headerRow)[col];\n\tif (!cell) return undefined;\n\tconst paragraph: BlockNode | undefined = getBlockChildren(cell)[0];\n\treturn paragraph?.attrs?.align as string | undefined;\n}\n\n/** Maps a logical alignment to its GFM delimiter marker. */\nfunction alignMarker(align: string | undefined): string {\n\tif (align === 'start') return ':---';\n\tif (align === 'center') return ':---:';\n\tif (align === 'end') return '---:';\n\treturn '---';\n}\n\n/** Whether any cell in the rows carries a colspan/rowspan > 1. */\nfunction hasSpannedCells(rows: readonly BlockNode[]): boolean {\n\tfor (const row of rows) {\n\t\tfor (const cell of getBlockChildren(row)) {\n\t\t\tconst colspan = cell.attrs?.colspan as number | undefined;\n\t\t\tconst rowspan = cell.attrs?.rowspan as number | undefined;\n\t\t\tif ((colspan ?? 1) > 1 || (rowspan ?? 1) > 1) return true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/** Whether the table carries any safe dimension that GFM cannot represent. */\nfunction hasExplicitTableDimensions(table: BlockNode, rows: readonly BlockNode[]): boolean {\n\tif (hasExplicitTableColumnWidth(table.attrs?.columnWidthsPx)) return true;\n\treturn rows.some(\n\t\t(row: BlockNode): boolean =>\n\t\t\tnormalizeSerializedTableDimensionPx(row.attrs?.minHeightPx) !== undefined,\n\t);\n}\n\n/** Serializes a table cell to single-line inline Markdown, escaping pipes. */\nfunction serializeCell(cell: BlockNode, ctx: SerContext): string {\n\tconst blocks: readonly BlockNode[] = getBlockChildren(cell);\n\tconst inline: string = blocks\n\t\t.map((b) => serializeInlineContent(getInlineChildren(b), ctx))\n\t\t.join(' ')\n\t\t.replace(/\\n/g, ' ');\n\treturn inline.replace(/\\|/g, '\\\\|').trim();\n}\n","/**\n * MarkdownSerializer: converts an immutable Document into a Markdown string.\n *\n * Mirrors `DocumentSerializer.ts` (HTML) but is reached **only** via dynamic\n * `import()` from the async web-component method and the paste branch, so the\n * bundler genuinely code-splits the engine out of the core chunk (D13). Pure\n * functions — operate on Document/SchemaRegistry, no class state.\n */\n\nimport type { Document } from '../model/Document.js';\nimport type { SchemaRegistry } from '../model/SchemaRegistry.js';\nimport { buildMarkOrder } from './MarkSerializer.js';\nimport type { MarkdownSerializeOptions } from './MarkdownTypes.js';\nimport { serializeBlocks } from './markdown/BlockSerializers.js';\nimport { type SerContext, resolveSerializeOptions } from './markdown/MarkdownContext.js';\n\n/**\n * Serializes a document to a Markdown string.\n *\n * Standard CommonMark/GFM constructs are emitted by the engine's built-in\n * by-type mappings; unrepresentable nodes/marks emit raw HTML (valid Markdown)\n * when `htmlFallback` is on (default), or degrade gracefully when off (D3).\n */\nexport function serializeDocumentToMarkdown(\n\tdoc: Document,\n\tregistry?: SchemaRegistry,\n\toptions?: MarkdownSerializeOptions,\n): string {\n\tconst ctx: SerContext = {\n\t\tregistry,\n\t\topts: resolveSerializeOptions(options),\n\t\tmarkOrder: registry ? buildMarkOrder(registry) : undefined,\n\t};\n\tconst body: string = serializeBlocks(doc.children, ctx);\n\treturn finalizeDocument(body);\n}\n\n/**\n * Closes the assembled document with a single trailing newline, dropping any\n * leading/trailing blank lines. It intentionally does NOT touch the interior:\n * each block serializer is responsible for emitting clean lines, and\n * `serializeBlocks` already joins blocks with exactly one blank line. Trimming\n * only the document boundaries is provably code-safe, since a document never\n * begins or ends inside a code body (blocks open and close on their own\n * delimiters), so significant blank lines and trailing spaces inside a\n * `code_block` survive verbatim at any nesting depth.\n */\nfunction finalizeDocument(markdown: string): string {\n\tconst trimmed: string = markdown.trim();\n\treturn trimmed.length > 0 ? `${trimmed}\\n` : '';\n}\n"],"mappings":"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"}