@localix-ai/flowdown 0.5.0 → 0.5.1

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 (47) hide show
  1. package/README.md +8 -4
  2. package/dist/core/blocks.js +3 -2
  3. package/dist/core/blocks.js.map +1 -1
  4. package/dist/core/continues.js +15 -0
  5. package/dist/core/continues.js.map +1 -0
  6. package/dist/core/fence-scan.js +10 -1
  7. package/dist/core/fence-scan.js.map +1 -1
  8. package/dist/core/file-tree-parse.js +1 -1
  9. package/dist/core/file-tree-parse.js.map +1 -1
  10. package/dist/core/heal.js +1 -1
  11. package/dist/core/heal.js.map +1 -1
  12. package/dist/document/fence.js +3 -2
  13. package/dist/document/fence.js.map +1 -1
  14. package/dist/dom/index.js +25 -7
  15. package/dist/dom/index.js.map +1 -1
  16. package/dist/element/index.d.ts +6 -0
  17. package/dist/element/index.js.map +1 -1
  18. package/dist/engine/blocks.js +11 -0
  19. package/dist/engine/blocks.js.map +1 -1
  20. package/dist/engine/inlines.js +40 -5
  21. package/dist/engine/inlines.js.map +1 -1
  22. package/dist/react/code-block.js +15 -2
  23. package/dist/react/code-block.js.map +1 -1
  24. package/dist/react/draw.js +1 -0
  25. package/dist/react/draw.js.map +1 -1
  26. package/dist/react/markdown.js +4 -2
  27. package/dist/react/markdown.js.map +1 -1
  28. package/dist/react/scrolls.js +62 -0
  29. package/dist/react/scrolls.js.map +1 -0
  30. package/dist/react/table.js +6 -20
  31. package/dist/react/table.js.map +1 -1
  32. package/dist/react/use-smooth-text.js +2 -1
  33. package/dist/react/use-smooth-text.js.map +1 -1
  34. package/dist/render/labels.d.ts +5 -0
  35. package/dist/render/labels.js +3 -0
  36. package/dist/render/labels.js.map +1 -1
  37. package/dist/render/tree.js +2 -0
  38. package/dist/render/tree.js.map +1 -1
  39. package/dist/render/view.d.ts +4 -1
  40. package/dist/render/view.js +6 -2
  41. package/dist/render/view.js.map +1 -1
  42. package/dist/render/views.js +2 -2
  43. package/dist/render/views.js.map +1 -1
  44. package/dist/styles.css +12 -1
  45. package/dist/tui/wrap.js +5 -4
  46. package/dist/tui/wrap.js.map +1 -1
  47. package/package.json +3 -2
@@ -21,6 +21,12 @@ export interface MarkdownElement extends HTMLElement {
21
21
  /** The reply is still arriving; the same as the `streaming` attribute. */
22
22
  streaming: boolean;
23
23
  }
24
+ declare global {
25
+ interface HTMLElementTagNameMap {
26
+ /** The element under its default name, so `querySelector('flow-down')` has `markdown`. */
27
+ 'flow-down': MarkdownElement;
28
+ }
29
+ }
24
30
  /**
25
31
  * Registers the element under `name`. `options` are what every such element is drawn with: a
26
32
  * highlighter, math, raw HTML, labels. Registering a name twice keeps the first.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/element/index.ts"],"sourcesContent":["/**\n * `@localix-ai/flowdown/element`: Markdown as an element of the page's own, for anything that writes HTML\n * (Vue, Svelte, Solid, Angular, a template, a plain page).\n *\n * import { defineMarkdownElement } from '@localix-ai/flowdown/element'\n * import '@localix-ai/flowdown/styles.css'\n *\n * defineMarkdownElement()\n *\n * <flow-down streaming></flow-down>\n * element.markdown = text\n *\n * The text is the `markdown` property; the `streaming` attribute says the reply is still arriving.\n * Text written inside the element is shown until the property is first set. The document is drawn\n * in the page, not in a shadow tree, so the page's stylesheet and theme reach it.\n */\nimport { mount, type Mounted, type MountOptions } from '../dom'\n\nexport type { MountOptions } from '../dom'\n\nexport interface MarkdownElement extends HTMLElement {\n /** The Markdown shown. */\n markdown: string\n /** The reply is still arriving; the same as the `streaming` attribute. */\n streaming: boolean\n}\n\n/**\n * Registers the element under `name`. `options` are what every such element is drawn with: a\n * highlighter, math, raw HTML, labels. Registering a name twice keeps the first.\n */\nexport function defineMarkdownElement(name = 'flow-down', options: MountOptions = {}): void {\n // Read here, not at import: a server that renders the page has no elements to extend.\n if (typeof customElements === 'undefined' || customElements.get(name)) return\n\n class Element extends HTMLElement implements MarkdownElement {\n static observedAttributes = ['streaming']\n #text: string | null = null\n #mounted: Mounted | null = null\n\n get markdown(): string {\n return this.#text ?? ''\n }\n set markdown(value: string) {\n this.#text = value === null || value === undefined ? '' : String(value)\n this.#show()\n }\n\n get streaming(): boolean {\n return this.hasAttribute('streaming')\n }\n set streaming(value: boolean) {\n this.toggleAttribute('streaming', Boolean(value))\n }\n\n connectedCallback(): void {\n if (this.#mounted) return\n // What the page wrote inside the element is its first text.\n if (this.#text === null) this.#text = this.textContent ?? ''\n this.textContent = ''\n this.#mounted = mount(this, options)\n this.#show()\n }\n\n disconnectedCallback(): void {\n this.#mounted?.destroy()\n this.#mounted = null\n }\n\n attributeChangedCallback(): void {\n this.#show()\n }\n\n #show(): void {\n this.#mounted?.update(this.#text ?? '', { streaming: this.streaming })\n }\n }\n\n customElements.define(name, Element)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA+BA,SAAgB,sBAAsB,OAAO,aAAa,UAAwB,CAAC,GAAS;CAE1F,IAAI,OAAO,mBAAmB,eAAe,eAAe,IAAI,IAAI,GAAG;CAEvE,MAAM,gBAAgB,YAAuC;EAC3D,OAAO,qBAAqB,CAAC,WAAW;EACxC,QAAuB;EACvB,WAA2B;EAE3B,IAAI,WAAmB;GACrB,OAAO,KAAK,SAAS;EACvB;EACA,IAAI,SAAS,OAAe;GAC1B,KAAK,QAAQ,UAAU,QAAQ,UAAU,KAAA,IAAY,KAAK,OAAO,KAAK;GACtE,KAAK,MAAM;EACb;EAEA,IAAI,YAAqB;GACvB,OAAO,KAAK,aAAa,WAAW;EACtC;EACA,IAAI,UAAU,OAAgB;GAC5B,KAAK,gBAAgB,aAAa,QAAQ,KAAK,CAAC;EAClD;EAEA,oBAA0B;GACxB,IAAI,KAAK,UAAU;GAEnB,IAAI,KAAK,UAAU,MAAM,KAAK,QAAQ,KAAK,eAAe;GAC1D,KAAK,cAAc;GACnB,KAAK,WAAW,MAAM,MAAM,OAAO;GACnC,KAAK,MAAM;EACb;EAEA,uBAA6B;GAC3B,KAAK,UAAU,QAAQ;GACvB,KAAK,WAAW;EAClB;EAEA,2BAAiC;GAC/B,KAAK,MAAM;EACb;EAEA,QAAc;GACZ,KAAK,UAAU,OAAO,KAAK,SAAS,IAAI,EAAE,WAAW,KAAK,UAAU,CAAC;EACvE;CACF;CAEA,eAAe,OAAO,MAAM,OAAO;AACrC"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/element/index.ts"],"sourcesContent":["/**\n * `@localix-ai/flowdown/element`: Markdown as an element of the page's own, for anything that writes HTML\n * (Vue, Svelte, Solid, Angular, a template, a plain page).\n *\n * import { defineMarkdownElement } from '@localix-ai/flowdown/element'\n * import '@localix-ai/flowdown/styles.css'\n *\n * defineMarkdownElement()\n *\n * <flow-down streaming></flow-down>\n * element.markdown = text\n *\n * The text is the `markdown` property; the `streaming` attribute says the reply is still arriving.\n * Text written inside the element is shown until the property is first set. The document is drawn\n * in the page, not in a shadow tree, so the page's stylesheet and theme reach it.\n */\nimport { mount, type Mounted, type MountOptions } from '../dom'\n\nexport type { MountOptions } from '../dom'\n\nexport interface MarkdownElement extends HTMLElement {\n /** The Markdown shown. */\n markdown: string\n /** The reply is still arriving; the same as the `streaming` attribute. */\n streaming: boolean\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n /** The element under its default name, so `querySelector('flow-down')` has `markdown`. */\n 'flow-down': MarkdownElement\n }\n}\n\n/**\n * Registers the element under `name`. `options` are what every such element is drawn with: a\n * highlighter, math, raw HTML, labels. Registering a name twice keeps the first.\n */\nexport function defineMarkdownElement(name = 'flow-down', options: MountOptions = {}): void {\n // Read here, not at import: a server that renders the page has no elements to extend.\n if (typeof customElements === 'undefined' || customElements.get(name)) return\n\n class Element extends HTMLElement implements MarkdownElement {\n static observedAttributes = ['streaming']\n #text: string | null = null\n #mounted: Mounted | null = null\n\n get markdown(): string {\n return this.#text ?? ''\n }\n set markdown(value: string) {\n this.#text = value === null || value === undefined ? '' : String(value)\n this.#show()\n }\n\n get streaming(): boolean {\n return this.hasAttribute('streaming')\n }\n set streaming(value: boolean) {\n this.toggleAttribute('streaming', Boolean(value))\n }\n\n connectedCallback(): void {\n if (this.#mounted) return\n // What the page wrote inside the element is its first text.\n if (this.#text === null) this.#text = this.textContent ?? ''\n this.textContent = ''\n this.#mounted = mount(this, options)\n this.#show()\n }\n\n disconnectedCallback(): void {\n this.#mounted?.destroy()\n this.#mounted = null\n }\n\n attributeChangedCallback(): void {\n this.#show()\n }\n\n #show(): void {\n this.#mounted?.update(this.#text ?? '', { streaming: this.streaming })\n }\n }\n\n customElements.define(name, Element)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAsCA,SAAgB,sBAAsB,OAAO,aAAa,UAAwB,CAAC,GAAS;CAE1F,IAAI,OAAO,mBAAmB,eAAe,eAAe,IAAI,IAAI,GAAG;CAEvE,MAAM,gBAAgB,YAAuC;EAC3D,OAAO,qBAAqB,CAAC,WAAW;EACxC,QAAuB;EACvB,WAA2B;EAE3B,IAAI,WAAmB;GACrB,OAAO,KAAK,SAAS;EACvB;EACA,IAAI,SAAS,OAAe;GAC1B,KAAK,QAAQ,UAAU,QAAQ,UAAU,KAAA,IAAY,KAAK,OAAO,KAAK;GACtE,KAAK,MAAM;EACb;EAEA,IAAI,YAAqB;GACvB,OAAO,KAAK,aAAa,WAAW;EACtC;EACA,IAAI,UAAU,OAAgB;GAC5B,KAAK,gBAAgB,aAAa,QAAQ,KAAK,CAAC;EAClD;EAEA,oBAA0B;GACxB,IAAI,KAAK,UAAU;GAEnB,IAAI,KAAK,UAAU,MAAM,KAAK,QAAQ,KAAK,eAAe;GAC1D,KAAK,cAAc;GACnB,KAAK,WAAW,MAAM,MAAM,OAAO;GACnC,KAAK,MAAM;EACb;EAEA,uBAA6B;GAC3B,KAAK,UAAU,QAAQ;GACvB,KAAK,WAAW;EAClB;EAEA,2BAAiC;GAC/B,KAAK,MAAM;EACb;EAEA,QAAc;GACZ,KAAK,UAAU,OAAO,KAAK,SAAS,IAAI,EAAE,WAAW,KAAK,UAAU,CAAC;EACvE;CACF;CAEA,eAAe,OAAO,MAAM,OAAO;AACrC"}
@@ -57,6 +57,13 @@ const reTableDelimiterCell = /^[ \t]*(:?)-+(:?)[ \t]*$/;
57
57
  const reFootnoteDefinition = /^\[\^([^\]\s]+)\]:[ \t]*/;
58
58
  const reTaskMarker = /^\[([ xX])\](?=[ \t\n])/;
59
59
  const isSpaceOrTab = (code) => code === C_SPACE || code === C_TAB;
60
+ /**
61
+ * How deep blocks may hold blocks. A quote in a quote in a list is three; a hundred is past
62
+ * anything written to be read, and it bounds the depth of the tree every pass after this one
63
+ * walks: without it a line of twenty thousand `>` overflowed the stack. A line that would go
64
+ * deeper is read as text of the block it is in.
65
+ */
66
+ const MAX_NESTING = 100;
60
67
  /** Whether a block holds other blocks; a list holds only items. */
61
68
  const isContainer = (type) => type === "root" || type === "blockquote" || type === "item" || type === "list" || type === "footnoteDefinition";
62
69
  /** Whether a block takes the lines after its first as they are. */
@@ -137,6 +144,7 @@ const parseBlocks = (input, context) => {
137
144
  startLine,
138
145
  endLine: startLine,
139
146
  startOffset: 0,
147
+ depth: 0,
140
148
  ordered: false,
141
149
  bullet: 0,
142
150
  start: 0,
@@ -279,6 +287,7 @@ const parseBlocks = (input, context) => {
279
287
  const child = block(type, lineNumber);
280
288
  child.startOffset = (starts[lineNumber - 1] ?? 0) + nextNonspace;
281
289
  child.parent = tip;
290
+ child.depth = tip.depth + 1;
282
291
  tip.children.push(child);
283
292
  tip = child;
284
293
  return child;
@@ -397,6 +406,7 @@ const parseBlocks = (input, context) => {
397
406
  }
398
407
  switch (first) {
399
408
  case C_GREATERTHAN:
409
+ if (container.depth >= MAX_NESTING) return 0;
400
410
  advanceNextNonspace();
401
411
  advanceOffset(1, false);
402
412
  if (isSpaceOrTab(line.charCodeAt(offset))) advanceOffset(1, true);
@@ -486,6 +496,7 @@ const parseBlocks = (input, context) => {
486
496
  advanceOffset(line.length - offset, false);
487
497
  return 2;
488
498
  }
499
+ if (container.depth >= 99) return 0;
489
500
  if (gfm && first === C_OPEN_BRACKET && line.charCodeAt(nextNonspace + 1) === 94) {
490
501
  const found = reFootnoteDefinition.exec(line.slice(nextNonspace));
491
502
  if (found !== null) {
@@ -1 +1 @@
1
- {"version":3,"file":"blocks.js","names":[],"sources":["../../src/engine/blocks.ts"],"sourcesContent":["/**\n * The block pass: a document read line by line into its blocks, by the algorithm in the\n * CommonMark spec. Each line is matched against the containers still open (a quote's `>`, a list\n * item's indent), then tried as the start of a new block, then added to the block it belongs to.\n * The text of paragraphs, headings and cells is kept as written; the inline pass reads it once\n * the whole document is known, since a link can refer to a definition further down.\n */\nimport { unescapeString } from './entities'\nimport {\n CLOSETAG,\n normalizeLabel,\n OPENTAG,\n parseInlines,\n parseReference,\n type InlineContext,\n} from './inlines'\nimport type { Align, Node, Position } from './types'\n\n/** A block while the document is read. */\ninterface Block {\n type: string\n parent: Block | null\n children: Block[]\n open: boolean\n lastLineBlank: boolean\n /** The lines added so far, each with its line ending. */\n text: string\n startLine: number\n endLine: number\n /** Where the block starts in the document. */\n startOffset: number\n // A list and its items.\n ordered: boolean\n bullet: number\n start: number\n delimiter: number\n padding: number\n markerOffset: number\n tight: boolean\n // A code block.\n fenced: boolean\n fenceChar: number\n fenceLength: number\n fenceOffset: number\n /** Which of the seven kinds of HTML block this is. */\n htmlType: number\n /** A heading's level. */\n level: number\n /** A table's alignments and its rows as written; a footnote's label. */\n align: Align[] | null\n rows: string[] | null\n label: string\n}\n\nconst C_TAB = 9\nconst C_SPACE = 32\nconst C_HASH = 35\nconst C_DOLLAR = 36\nconst C_ASTERISK = 42\nconst C_PLUS = 43\nconst C_DASH = 45\nconst C_COLON = 58\nconst C_LESSTHAN = 60\nconst C_EQUALS = 61\nconst C_GREATERTHAN = 62\nconst C_OPEN_BRACKET = 91\nconst C_BACKSLASH = 92\nconst C_UNDERSCORE = 95\nconst C_BACKTICK = 96\nconst C_PIPE = 124\nconst C_TILDE = 126\n\nconst reHtmlBlockOpen = [\n /./,\n /^<(?:script|pre|textarea|style)(?:\\s|>|$)/i,\n /^<!--/,\n /^<[?]/,\n /^<![A-Za-z]/,\n /^<!\\[CDATA\\[/,\n /^<[/]?(?:address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[123456]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul)(?:\\s|[/]?[>]|$)/i,\n new RegExp(`^(?:${OPENTAG}|${CLOSETAG})\\\\s*$`, 'i'),\n] as const\nconst reHtmlBlockClose = [\n /./,\n /<\\/(?:script|pre|textarea|style)>/i,\n /-->/,\n /\\?>/,\n />/,\n /\\]\\]>/,\n] as const\n\nconst reThematicBreak = /^(?:\\*[ \\t]*){3,}$|^(?:_[ \\t]*){3,}$|^(?:-[ \\t]*){3,}$/\nconst reOrderedListMarker = /^(\\d{1,9})([.)])/\nconst reAtxHeadingMarker = /^#{1,6}(?:[ \\t]+|$)/\nconst reCodeFence = /^`{3,}(?!.*`)|^~{3,}/\nconst reClosingCodeFence = /^(?:`{3,}|~{3,})(?=[ \\t]*$)/\n/** A display formula's fence, read only when an extension asks for it: `$$` alone on its line. */\nconst reMathFence = /^\\${2,}(?!.*\\$)/\nconst reClosingMathFence = /^\\${2,}(?=[ \\t]*$)/\nconst reSetextHeadingLine = /^(?:=+|-+)[ \\t]*$/\nconst reLineEnding = /\\r\\n|\\n|\\r/g\nconst reTableDelimiterCell = /^[ \\t]*(:?)-+(:?)[ \\t]*$/\nconst reFootnoteDefinition = /^\\[\\^([^\\]\\s]+)\\]:[ \\t]*/\nconst reTaskMarker = /^\\[([ xX])\\](?=[ \\t\\n])/\n\nconst isSpaceOrTab = (code: number): boolean => code === C_SPACE || code === C_TAB\n\n/** Whether a block holds other blocks; a list holds only items. */\nconst isContainer = (type: string): boolean =>\n type === 'root' ||\n type === 'blockquote' ||\n type === 'item' ||\n type === 'list' ||\n type === 'footnoteDefinition'\n\n/** Whether a block takes the lines after its first as they are. */\nconst acceptsLines = (type: string): boolean =>\n type === 'paragraph' || type === 'code' || type === 'html'\n\n/**\n * A table row cut into its cells: on each `|` that is not escaped, without the outer pipes. Each\n * cell is one cut of the row, joined from pieces only where an escaped pipe (`\\\\|`) is taken out.\n */\nconst splitRow = (row: string): string[] => {\n const cells: string[] = []\n let line = row.trim()\n if (line.charCodeAt(0) === C_PIPE) line = line.slice(1)\n /** The cell's text before `from`: what came before an escaped pipe, and that pipe. */\n let cell = ''\n let from = 0\n for (let pipe = line.indexOf('|'); pipe !== -1; pipe = line.indexOf('|', pipe + 1)) {\n if (pipe > 0 && line.charCodeAt(pipe - 1) === C_BACKSLASH)\n cell += `${line.slice(from, pipe - 1)}|`\n else {\n cells.push((cell + line.slice(from, pipe)).trim())\n cell = ''\n }\n from = pipe + 1\n }\n const last = (cell + line.slice(from)).trim()\n // Text after the last pipe is a cell; nothing after it is the row's closing pipe.\n if (last !== '' || line.charCodeAt(line.length - 1) !== C_PIPE || line === '') cells.push(last)\n return cells\n}\n\n/** The alignments a table's delimiter row (`| :-- | --: |`) gives, or null when it is not one. */\nconst parseDelimiterRow = (row: string): Align[] | null => {\n if (row.indexOf('|') === -1) return null\n const cells = splitRow(row)\n const align: Align[] = []\n for (const cell of cells) {\n const found = reTableDelimiterCell.exec(cell)\n if (found === null) return null\n align.push(found[1] ? (found[2] ? 'center' : 'left') : found[2] ? 'right' : null)\n }\n return align.length === 0 ? null : align\n}\n\nexport interface BlockResult {\n root: Node\n /** The footnotes defined, in the order they are first referred to. */\n footnotes: Node[]\n}\n\n/** Parses a whole document into its tree. */\nexport const parseBlocks = (input: string, context: InlineContext): BlockResult => {\n const gfm = context.gfm\n // Where each line starts and ends in the document (its ending left out): a node's position is\n // counted from these, and a line's text is cut from the document only when it is read.\n const starts: number[] = []\n const ends: number[] = []\n // Most text has no carriage return: its lines are found by a plain search, not a pattern.\n const onlyLf = input.indexOf('\\r') === -1\n if (onlyLf) {\n for (let at = 0; ;) {\n const ending = input.indexOf('\\n', at)\n starts.push(at)\n if (ending === -1) {\n ends.push(input.length)\n break\n }\n ends.push(ending)\n at = ending + 1\n }\n } else {\n for (let at = 0; ;) {\n reLineEnding.lastIndex = at\n const ending = reLineEnding.exec(input)\n starts.push(at)\n if (ending === null) {\n ends.push(input.length)\n break\n }\n ends.push(ending.index)\n at = ending.index + ending[0].length\n }\n }\n let count = starts.length\n // A final line ending ends the last line; it does not start an empty one.\n if (count > 0 && starts[count - 1] === ends[count - 1]) count--\n /** No NUL in the document: a line is then the document's own text, with nothing to replace. */\n const noNul = input.indexOf('\\u0000') === -1\n\n const block = (type: string, startLine: number): Block => ({\n type,\n parent: null,\n children: [],\n open: true,\n lastLineBlank: false,\n text: '',\n startLine,\n endLine: startLine,\n startOffset: 0,\n ordered: false,\n bullet: 0,\n start: 0,\n delimiter: 0,\n padding: 0,\n markerOffset: 0,\n tight: true,\n fenced: false,\n fenceChar: 0,\n fenceLength: 0,\n fenceOffset: 0,\n htmlType: 0,\n level: 0,\n align: null,\n rows: null,\n label: '',\n })\n\n const doc = block('root', 1)\n let tip: Block = doc\n let oldtip: Block = doc\n let lastMatchedContainer: Block = doc\n let allClosed = true\n let line = ''\n let lineNumber = 0\n let offset = 0\n let column = 0\n let nextNonspace = 0\n let nextNonspaceColumn = 0\n let indent = 0\n let indented = false\n let blank = false\n let partiallyConsumedTab = false\n\n const findNextNonspace = (): void => {\n let index = offset\n let cols = column\n let code = line.charCodeAt(index)\n while (code === C_SPACE || code === C_TAB) {\n cols += code === C_SPACE ? 1 : 4 - (cols % 4)\n code = line.charCodeAt(++index)\n }\n blank = index >= line.length\n nextNonspace = index\n nextNonspaceColumn = cols\n indent = cols - column\n indented = indent >= 4\n }\n\n const advanceNextNonspace = (): void => {\n offset = nextNonspace\n column = nextNonspaceColumn\n partiallyConsumedTab = false\n }\n\n /** Moves past `amount` characters, or that many columns: a tab is up to four columns wide. */\n const advanceOffset = (amount: number, columns: boolean): void => {\n let left = amount\n while (left > 0 && offset < line.length) {\n if (line.charCodeAt(offset) === C_TAB) {\n const toTab = 4 - (column % 4)\n if (columns) {\n partiallyConsumedTab = toTab > left\n const step = toTab > left ? left : toTab\n column += step\n if (!partiallyConsumedTab) offset++\n left -= step\n } else {\n partiallyConsumedTab = false\n column += toTab\n offset++\n left--\n }\n } else {\n partiallyConsumedTab = false\n offset++\n column++\n left--\n }\n }\n }\n\n const addLine = (): void => {\n if (partiallyConsumedTab) {\n // The rest of a tab that a container's indent took part of.\n offset++\n tip.text += ' '.repeat(4 - (column % 4))\n }\n tip.text += `${line.slice(offset)}\\n`\n }\n\n const removeChild = (child: Block): void => {\n const siblings = child.parent?.children\n if (siblings === undefined) return\n const index = siblings.lastIndexOf(child)\n if (index !== -1) siblings.splice(index, 1)\n child.parent = null\n }\n\n /** Whether a block ends with a blank line before its next sibling. */\n const gapAfter = (child: Block, next: Block | undefined): boolean =>\n next !== undefined && child.endLine !== next.startLine - 1\n\n const takeReferences = (paragraph: Block): void => {\n let content = paragraph.text\n while (content.charCodeAt(0) === C_OPEN_BRACKET) {\n const taken = parseReference(content, context.refs)\n if (taken === 0) break\n content = content.slice(taken)\n }\n paragraph.text = content\n }\n\n const finalize = (closing: Block, endLine: number): void => {\n const above = closing.parent\n closing.open = false\n closing.endLine = endLine\n switch (closing.type) {\n case 'paragraph':\n takeReferences(closing)\n // A paragraph that was only definitions leaves nothing behind.\n if (/^[ \\t\\n]*$/.test(closing.text)) removeChild(closing)\n break\n case 'code':\n if (closing.fenced) {\n const newline = closing.text.indexOf('\\n')\n closing.label = unescapeString(closing.text.slice(0, newline).trim())\n closing.text = closing.text.slice(newline + 1)\n } else closing.text = closing.text.replace(/(?:\\n *)+$/, '\\n')\n break\n case 'list': {\n const items = closing.children\n closing.tight = true\n for (let index = 0; index < items.length && closing.tight; index++) {\n const item = items[index] as Block\n if (gapAfter(item, items[index + 1])) closing.tight = false\n const inner = item.children\n for (let child = 0; child < inner.length && closing.tight; child++)\n if (gapAfter(inner[child] as Block, inner[child + 1])) closing.tight = false\n }\n const last = items[items.length - 1]\n if (last !== undefined) closing.endLine = last.endLine\n break\n }\n case 'item': {\n const last = closing.children[closing.children.length - 1]\n closing.endLine = last === undefined ? closing.startLine : last.endLine\n break\n }\n default:\n }\n if (above !== null) tip = above\n }\n\n const addChild = (type: string): Block => {\n // oxlint-disable-next-line no-unmodified-loop-condition -- `finalize` moves `tip` up.\n while (!isContainer(tip.type) || (tip.type === 'list' && type !== 'item'))\n finalize(tip, lineNumber - 1)\n const child = block(type, lineNumber)\n child.startOffset = (starts[lineNumber - 1] ?? 0) + nextNonspace\n child.parent = tip\n tip.children.push(child)\n tip = child\n return child\n }\n\n const closeUnmatchedBlocks = (): void => {\n if (allClosed) return\n while (oldtip !== lastMatchedContainer) {\n const parent = oldtip.parent as Block\n finalize(oldtip, lineNumber - 1)\n oldtip = parent\n }\n allClosed = true\n }\n\n /** Reads a list marker at the next non-space character into a new item's data, or null. */\n const parseListMarker = (container: Block): Block | null => {\n if (indent >= 4) return null\n const rest = line.slice(nextNonspace)\n const first = rest.charCodeAt(0)\n const item = block('item', lineNumber)\n let markerLength = 1\n if (first === C_ASTERISK || first === C_PLUS || first === C_DASH) item.bullet = first\n else {\n const found = reOrderedListMarker.exec(rest)\n if (found === null) return null\n // Only a list that starts at 1 can interrupt a paragraph.\n if (container.type === 'paragraph' && found[1] !== '1') return null\n item.ordered = true\n item.start = parseInt(found[1] as string, 10)\n item.delimiter = (found[2] as string).charCodeAt(0)\n markerLength = found[0].length\n }\n const after = line.charCodeAt(nextNonspace + markerLength)\n if (!Number.isNaN(after) && !isSpaceOrTab(after)) return null\n // An empty item cannot interrupt a paragraph.\n if (container.type === 'paragraph' && /^[ \\t]*$/.test(line.slice(nextNonspace + markerLength)))\n return null\n\n advanceNextNonspace()\n advanceOffset(markerLength, true)\n const spacesStartColumn = column\n const spacesStartOffset = offset\n do {\n advanceOffset(1, true)\n // oxlint-disable-next-line no-unmodified-loop-condition -- `advanceOffset` moves `column`.\n } while (column - spacesStartColumn < 5 && isSpaceOrTab(line.charCodeAt(offset)))\n const blankItem = offset >= line.length\n const spaces = column - spacesStartColumn\n if (spaces >= 5 || spaces < 1 || blankItem) {\n item.padding = markerLength + 1\n column = spacesStartColumn\n offset = spacesStartOffset\n if (isSpaceOrTab(line.charCodeAt(offset))) advanceOffset(1, true)\n } else item.padding = markerLength + spaces\n item.markerOffset = indent\n return item\n }\n\n /**\n * Whether an open block goes on with this line: 0 when it does, 1 when it does not, 2 when the\n * line closed it and is used up.\n */\n const continues = (container: Block): number => {\n switch (container.type) {\n case 'blockquote':\n if (indented || line.charCodeAt(nextNonspace) !== C_GREATERTHAN) return 1\n advanceNextNonspace()\n advanceOffset(1, false)\n if (isSpaceOrTab(line.charCodeAt(offset))) advanceOffset(1, true)\n return 0\n case 'item':\n if (blank) {\n if (container.children.length === 0) return 1\n advanceNextNonspace()\n } else if (indent >= container.markerOffset + container.padding)\n advanceOffset(container.markerOffset + container.padding, true)\n else return 1\n return 0\n case 'footnoteDefinition':\n if (blank) advanceNextNonspace()\n else if (indent >= 4) advanceOffset(4, true)\n else return 1\n return 0\n case 'code':\n if (container.fenced) {\n if (indent <= 3 && line.charCodeAt(nextNonspace) === container.fenceChar) {\n const found = (\n container.fenceChar === C_DOLLAR ? reClosingMathFence : reClosingCodeFence\n ).exec(line.slice(nextNonspace))\n if (found !== null && found[0].length >= container.fenceLength) {\n finalize(container, lineNumber)\n return 2\n }\n }\n // Indentation up to the fence's own is not part of the code.\n let skip = container.fenceOffset\n while (skip > 0 && isSpaceOrTab(line.charCodeAt(offset))) {\n advanceOffset(1, true)\n skip--\n }\n } else if (indent >= 4) advanceOffset(4, true)\n else if (blank) advanceNextNonspace()\n else return 1\n return 0\n case 'html':\n return blank && (container.htmlType === 6 || container.htmlType === 7) ? 1 : 0\n case 'paragraph':\n case 'table':\n return blank ? 1 : 0\n case 'heading':\n case 'thematicBreak':\n return 1\n default:\n return 0\n }\n }\n\n /**\n * Tries the line as the start of a new block: 0 when it starts none, 1 when it starts a\n * container (the rest of the line is tried again), 2 when it starts a leaf.\n */\n const startBlock = (container: Block): number => {\n const first = line.charCodeAt(nextNonspace)\n if (indented) {\n // Four columns of indent start code, except where the line can go on a paragraph.\n if (tip.type !== 'paragraph' && !blank) {\n advanceOffset(4, true)\n closeUnmatchedBlocks()\n addChild('code')\n return 2\n }\n return 0\n }\n switch (first) {\n case C_GREATERTHAN:\n advanceNextNonspace()\n advanceOffset(1, false)\n if (isSpaceOrTab(line.charCodeAt(offset))) advanceOffset(1, true)\n closeUnmatchedBlocks()\n addChild('blockquote')\n return 1\n case C_HASH: {\n const found = reAtxHeadingMarker.exec(line.slice(nextNonspace))\n if (found === null) return 0\n advanceNextNonspace()\n advanceOffset(found[0].length, false)\n closeUnmatchedBlocks()\n const heading = addChild('heading')\n heading.level = found[0].trim().length\n heading.text = line\n .slice(offset)\n .replace(/^[ \\t]*#+[ \\t]*$/, '')\n .replace(/[ \\t]+#+[ \\t]*$/, '')\n advanceOffset(line.length - offset, false)\n return 2\n }\n case C_DOLLAR:\n case C_BACKTICK:\n case C_TILDE: {\n if (first === C_DOLLAR && !context.math) return 0\n const found = (first === C_DOLLAR ? reMathFence : reCodeFence).exec(\n line.slice(nextNonspace),\n )\n if (found === null) return 0\n closeUnmatchedBlocks()\n const code = addChild('code')\n code.fenced = true\n code.fenceLength = found[0].length\n code.fenceChar = first\n code.fenceOffset = indent\n advanceNextNonspace()\n advanceOffset(code.fenceLength, false)\n return 2\n }\n case C_LESSTHAN: {\n const rest = line.slice(nextNonspace)\n for (let type = 1; type <= 7; type++) {\n if (\n (reHtmlBlockOpen[type] as RegExp).test(rest) &&\n // The seventh kind (any complete tag) cannot interrupt a paragraph.\n (type < 7 ||\n (container.type !== 'paragraph' &&\n !(!allClosed && !blank && tip.type === 'paragraph')))\n ) {\n closeUnmatchedBlocks()\n // The line is kept whole: an HTML block is passed through with its indentation.\n addChild('html').htmlType = type\n return 2\n }\n }\n return 0\n }\n default:\n }\n\n if (container.type === 'paragraph') {\n // A table: the paragraph's last line is its header, this line the row of dashes under it.\n if (gfm && (first === C_PIPE || first === C_DASH || first === C_COLON)) {\n const align = parseDelimiterRow(line.slice(nextNonspace))\n if (align !== null) {\n const content = container.text\n const cut = content.lastIndexOf('\\n', content.length - 2)\n const header = content.slice(cut + 1, -1)\n if (splitRow(header).length === align.length) {\n closeUnmatchedBlocks()\n if (cut === -1) {\n tip = container.parent as Block\n removeChild(container)\n } else {\n container.text = content.slice(0, cut + 1)\n finalize(container, lineNumber - 2)\n }\n const table = addChild('table')\n table.startLine = lineNumber - 1\n table.startOffset = starts[lineNumber - 2] ?? 0\n table.align = align\n table.rows = [header]\n advanceOffset(line.length - offset, false)\n return 2\n }\n }\n }\n // A setext heading: the paragraph so far, underlined.\n if (first === C_EQUALS || first === C_DASH) {\n if (reSetextHeadingLine.test(line.slice(nextNonspace))) {\n closeUnmatchedBlocks()\n takeReferences(container)\n if (container.text.length > 0) {\n container.type = 'heading'\n container.level = first === C_EQUALS ? 1 : 2\n advanceOffset(line.length - offset, false)\n return 2\n }\n }\n }\n }\n\n if (\n (first === C_ASTERISK || first === C_DASH || first === C_UNDERSCORE) &&\n reThematicBreak.test(line.slice(nextNonspace))\n ) {\n closeUnmatchedBlocks()\n addChild('thematicBreak')\n advanceOffset(line.length - offset, false)\n return 2\n }\n\n if (gfm && first === C_OPEN_BRACKET && line.charCodeAt(nextNonspace + 1) === 94 /* ^ */) {\n const found = reFootnoteDefinition.exec(line.slice(nextNonspace))\n if (found !== null) {\n closeUnmatchedBlocks()\n advanceNextNonspace()\n advanceOffset(found[0].length, false)\n const definition = addChild('footnoteDefinition')\n definition.label = found[1] as string\n const key = normalizeLabel(`[${definition.label}]`)\n if (!context.footnotes.has(key)) context.footnotes.set(key, definition.label)\n return 1\n }\n }\n\n if (\n first === C_ASTERISK ||\n first === C_PLUS ||\n first === C_DASH ||\n (first >= 48 && first <= 57)\n ) {\n const item = parseListMarker(container)\n if (item === null) return 0\n closeUnmatchedBlocks()\n // An item goes on the list it fits: the same kind of marker.\n if (\n tip.type !== 'list' ||\n tip.ordered !== item.ordered ||\n tip.bullet !== item.bullet ||\n tip.delimiter !== item.delimiter\n ) {\n const list = addChild('list')\n list.ordered = item.ordered\n list.bullet = item.bullet\n list.delimiter = item.delimiter\n list.start = item.start\n }\n const added = addChild('item')\n added.ordered = item.ordered\n added.padding = item.padding\n added.markerOffset = item.markerOffset\n return 1\n }\n return 0\n }\n\n const incorporateLine = (text: string): void => {\n let container: Block = doc\n oldtip = tip\n offset = 0\n column = 0\n blank = false\n partiallyConsumedTab = false\n lineNumber++\n line = noNul || text.indexOf('\\u0000') === -1 ? text : text.replace(/\\0/g, '�')\n\n // The open blocks this line goes on with, from the outermost in.\n for (;;) {\n const last = container.children[container.children.length - 1]\n if (last === undefined || !last.open) break\n container = last\n findNextNonspace()\n const result = continues(container)\n if (result === 2) return\n if (result === 1) {\n container = container.parent as Block\n break\n }\n }\n allClosed = container === oldtip\n lastMatchedContainer = container\n\n // New blocks the rest of the line starts, until it is down to a leaf or to text.\n let matchedLeaf = container.type !== 'paragraph' && acceptsLines(container.type)\n while (!matchedLeaf) {\n findNextNonspace()\n const result = blank ? 0 : startBlock(container)\n if (result === 0) {\n advanceNextNonspace()\n break\n }\n container = tip\n if (result === 2) matchedLeaf = true\n }\n\n if (!allClosed && !blank && tip.type === 'paragraph') {\n // A lazy continuation line: text that goes on a paragraph inside containers it did not mark.\n addLine()\n return\n }\n closeUnmatchedBlocks()\n const type = container.type\n if (blank) {\n const last = container.children[container.children.length - 1]\n if (last !== undefined) last.lastLineBlank = true\n }\n const lastLineBlank =\n blank &&\n !(\n type === 'blockquote' ||\n (type === 'code' && container.fenced) ||\n (type === 'item' && container.children.length === 0 && container.startLine === lineNumber)\n )\n for (let above: Block | null = container; above !== null; above = above.parent)\n above.lastLineBlank = lastLineBlank\n\n if (acceptsLines(type)) {\n addLine()\n // The first five kinds of HTML block end on the line that holds their closing sequence.\n if (\n type === 'html' &&\n container.htmlType >= 1 &&\n container.htmlType <= 5 &&\n (reHtmlBlockClose[container.htmlType] as RegExp).test(line.slice(offset))\n )\n finalize(container, lineNumber)\n } else if (offset < line.length && !blank) {\n if (type === 'table') (container.rows as string[]).push(line.slice(offset))\n else {\n addChild('paragraph')\n advanceNextNonspace()\n addLine()\n }\n }\n }\n\n /**\n * The lines of a fenced code block at the top of the document, taken without the work a line\n * gets elsewhere: from the line after `index`, every line up to one that may close the fence\n * goes into the code as it is written, in one cut of the document. Returns the last line taken.\n *\n * A line may close the fence when, after at most three spaces, it starts with the fence's\n * character; that line, and whatever follows a fence that did not close, is read the long way.\n */\n const takeFencedLines = (code: Block, index: number): number => {\n const fenceChar = code.fenceChar\n let next = index + 1\n for (; next < count; next++) {\n let at = starts[next] as number\n if (input.charCodeAt(at) === C_SPACE) {\n at++\n if (input.charCodeAt(at) === C_SPACE) {\n at++\n if (input.charCodeAt(at) === C_SPACE) at++\n }\n }\n if (input.charCodeAt(at) === fenceChar) break\n }\n const last = next - 1\n if (last === index) return index\n const taken = input.slice(starts[index + 1] as number, ends[last] as number)\n code.text += `${onlyLf ? taken : taken.replace(reLineEnding, '\\n')}\\n`\n lineNumber += last - index\n return last\n }\n\n for (let index = 0; index < count; index++) {\n incorporateLine(input.slice(starts[index] as number, ends[index] as number))\n // Inside a container, or under an indented fence, each line has a prefix to take off first.\n if (tip.fenced && tip.parent === doc && tip.fenceOffset === 0 && noNul)\n index = takeFencedLines(tip, index)\n }\n // oxlint-disable-next-line no-unmodified-loop-condition -- `finalize` moves `tip` up.\n while (tip !== doc) finalize(tip, count)\n finalize(doc, count)\n\n // The second pass: every block's text read into inlines, now that every definition is known.\n // Footnote definitions leave the flow: they are drawn together at the end of the document.\n const definitions = new Map<string, Block>()\n\n const kids = (from: Block): Node[] => {\n const out: Node[] = []\n for (const child of from.children) {\n if (child.type === 'footnoteDefinition') {\n const key = normalizeLabel(`[${child.label}]`)\n if (!definitions.has(key)) definitions.set(key, child)\n } else out.push(build(child))\n }\n return out\n }\n\n const cells = (row: string, align: Align[], header: boolean): Node => {\n const parts = splitRow(row)\n const children: Node[] = []\n for (let index = 0; index < align.length; index++)\n children.push({\n type: 'tableCell',\n header,\n cellAlign: align[index] ?? null,\n children: parseInlines(parts[index] ?? '', context),\n })\n return { type: 'tableRow', children }\n }\n\n /** Where a block sits in the document: from its first character to the end of its last line. */\n const place = (from: Block): Position => {\n const last = Math.min(Math.max(from.endLine, from.startLine), starts.length)\n const lastStart = starts[last - 1] ?? 0\n const length = (ends[last - 1] ?? 0) - lastStart\n return {\n start: {\n line: from.startLine,\n column: from.startOffset - (starts[from.startLine - 1] ?? 0) + 1,\n offset: from.startOffset,\n },\n end: { line: last, column: length + 1, offset: lastStart + length },\n }\n }\n\n const build = (from: Block): Node => {\n switch (from.type) {\n case 'paragraph':\n return {\n type: 'paragraph',\n position: place(from),\n children: parseInlines(from.text, context),\n }\n case 'heading':\n return {\n type: 'heading',\n depth: from.level,\n position: place(from),\n children: parseInlines(from.text, context),\n }\n case 'thematicBreak':\n return { type: 'thematicBreak', position: place(from) }\n case 'code': {\n if (from.fenceChar === C_DOLLAR) {\n const node: Node = {\n type: 'math',\n position: place(from),\n value: from.text.replace(/\\n$/, ''),\n }\n if (from.label !== '') node.meta = from.label\n return node\n }\n const node: Node = { type: 'code', position: place(from), value: from.text }\n if (from.label !== '') {\n const space = from.label.search(/[ \\t]/)\n node.lang = space === -1 ? from.label : from.label.slice(0, space)\n if (space !== -1) node.meta = from.label.slice(space + 1).trim()\n }\n return node\n }\n case 'html':\n return { type: 'html', position: place(from), value: from.text.replace(/(?:\\n *)+$/, '') }\n case 'table': {\n const align = from.align as Align[]\n const rows = from.rows as string[]\n return {\n type: 'table',\n position: place(from),\n align,\n children: rows.map((row, index) => cells(row, align, index === 0)),\n }\n }\n case 'list': {\n const node: Node = {\n type: 'list',\n position: place(from),\n ordered: from.ordered,\n spread: !from.tight,\n children: kids(from),\n }\n for (const item of node.children as Node[]) item.spread = !from.tight\n if (from.ordered) node.start = from.start\n return node\n }\n case 'item': {\n const node: Node = { type: 'listItem', position: place(from), children: [] }\n const first = from.children[0]\n if (gfm && first !== undefined && first.type === 'paragraph') {\n const task = reTaskMarker.exec(first.text)\n if (task !== null) {\n node.checked = task[1] !== ' '\n first.text = first.text.slice(task[0].length + 1)\n }\n }\n node.children = kids(from)\n return node\n }\n default:\n return { type: from.type, position: place(from), children: kids(from) }\n }\n }\n\n const root: Node = { type: 'root', children: kids(doc) }\n\n // The footnotes referred to, in the order of their first reference. Reading one can refer to\n // more, so the list is walked as it grows.\n const footnotes: Node[] = []\n for (let index = 0; ; index++) {\n let key: string | undefined\n let at = 0\n for (const used of context.footnoteUses.keys()) if (at++ === index) key = used\n if (key === undefined) break\n const from = definitions.get(key)\n if (from === undefined) continue\n footnotes.push({\n type: 'footnoteDefinition',\n identifier: normalizeLabel(`[${from.label}]`).toLowerCase(),\n label: from.label,\n index: index + 1,\n position: place(from),\n children: kids(from),\n })\n }\n for (const node of footnotes)\n node.count = context.footnoteUses.get(normalizeLabel(`[${node.label}]`)) ?? 1\n return { root, footnotes }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"blocks.js","names":[],"sources":["../../src/engine/blocks.ts"],"sourcesContent":["/**\n * The block pass: a document read line by line into its blocks, by the algorithm in the\n * CommonMark spec. Each line is matched against the containers still open (a quote's `>`, a list\n * item's indent), then tried as the start of a new block, then added to the block it belongs to.\n * The text of paragraphs, headings and cells is kept as written; the inline pass reads it once\n * the whole document is known, since a link can refer to a definition further down.\n */\nimport { unescapeString } from './entities'\nimport {\n CLOSETAG,\n normalizeLabel,\n OPENTAG,\n parseInlines,\n parseReference,\n type InlineContext,\n} from './inlines'\nimport type { Align, Node, Position } from './types'\n\n/** A block while the document is read. */\ninterface Block {\n type: string\n parent: Block | null\n children: Block[]\n open: boolean\n lastLineBlank: boolean\n /** The lines added so far, each with its line ending. */\n text: string\n startLine: number\n endLine: number\n /** Where the block starts in the document. */\n startOffset: number\n /** How many blocks hold this one: 0 for the document. */\n depth: number\n // A list and its items.\n ordered: boolean\n bullet: number\n start: number\n delimiter: number\n padding: number\n markerOffset: number\n tight: boolean\n // A code block.\n fenced: boolean\n fenceChar: number\n fenceLength: number\n fenceOffset: number\n /** Which of the seven kinds of HTML block this is. */\n htmlType: number\n /** A heading's level. */\n level: number\n /** A table's alignments and its rows as written; a footnote's label. */\n align: Align[] | null\n rows: string[] | null\n label: string\n}\n\nconst C_TAB = 9\nconst C_SPACE = 32\nconst C_HASH = 35\nconst C_DOLLAR = 36\nconst C_ASTERISK = 42\nconst C_PLUS = 43\nconst C_DASH = 45\nconst C_COLON = 58\nconst C_LESSTHAN = 60\nconst C_EQUALS = 61\nconst C_GREATERTHAN = 62\nconst C_OPEN_BRACKET = 91\nconst C_BACKSLASH = 92\nconst C_UNDERSCORE = 95\nconst C_BACKTICK = 96\nconst C_PIPE = 124\nconst C_TILDE = 126\n\nconst reHtmlBlockOpen = [\n /./,\n /^<(?:script|pre|textarea|style)(?:\\s|>|$)/i,\n /^<!--/,\n /^<[?]/,\n /^<![A-Za-z]/,\n /^<!\\[CDATA\\[/,\n /^<[/]?(?:address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[123456]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul)(?:\\s|[/]?[>]|$)/i,\n new RegExp(`^(?:${OPENTAG}|${CLOSETAG})\\\\s*$`, 'i'),\n] as const\nconst reHtmlBlockClose = [\n /./,\n /<\\/(?:script|pre|textarea|style)>/i,\n /-->/,\n /\\?>/,\n />/,\n /\\]\\]>/,\n] as const\n\nconst reThematicBreak = /^(?:\\*[ \\t]*){3,}$|^(?:_[ \\t]*){3,}$|^(?:-[ \\t]*){3,}$/\nconst reOrderedListMarker = /^(\\d{1,9})([.)])/\nconst reAtxHeadingMarker = /^#{1,6}(?:[ \\t]+|$)/\nconst reCodeFence = /^`{3,}(?!.*`)|^~{3,}/\nconst reClosingCodeFence = /^(?:`{3,}|~{3,})(?=[ \\t]*$)/\n/** A display formula's fence, read only when an extension asks for it: `$$` alone on its line. */\nconst reMathFence = /^\\${2,}(?!.*\\$)/\nconst reClosingMathFence = /^\\${2,}(?=[ \\t]*$)/\nconst reSetextHeadingLine = /^(?:=+|-+)[ \\t]*$/\nconst reLineEnding = /\\r\\n|\\n|\\r/g\nconst reTableDelimiterCell = /^[ \\t]*(:?)-+(:?)[ \\t]*$/\nconst reFootnoteDefinition = /^\\[\\^([^\\]\\s]+)\\]:[ \\t]*/\nconst reTaskMarker = /^\\[([ xX])\\](?=[ \\t\\n])/\n\nconst isSpaceOrTab = (code: number): boolean => code === C_SPACE || code === C_TAB\n\n/**\n * How deep blocks may hold blocks. A quote in a quote in a list is three; a hundred is past\n * anything written to be read, and it bounds the depth of the tree every pass after this one\n * walks: without it a line of twenty thousand `>` overflowed the stack. A line that would go\n * deeper is read as text of the block it is in.\n */\nconst MAX_NESTING = 100\n\n/** Whether a block holds other blocks; a list holds only items. */\nconst isContainer = (type: string): boolean =>\n type === 'root' ||\n type === 'blockquote' ||\n type === 'item' ||\n type === 'list' ||\n type === 'footnoteDefinition'\n\n/** Whether a block takes the lines after its first as they are. */\nconst acceptsLines = (type: string): boolean =>\n type === 'paragraph' || type === 'code' || type === 'html'\n\n/**\n * A table row cut into its cells: on each `|` that is not escaped, without the outer pipes. Each\n * cell is one cut of the row, joined from pieces only where an escaped pipe (`\\\\|`) is taken out.\n */\nconst splitRow = (row: string): string[] => {\n const cells: string[] = []\n let line = row.trim()\n if (line.charCodeAt(0) === C_PIPE) line = line.slice(1)\n /** The cell's text before `from`: what came before an escaped pipe, and that pipe. */\n let cell = ''\n let from = 0\n for (let pipe = line.indexOf('|'); pipe !== -1; pipe = line.indexOf('|', pipe + 1)) {\n if (pipe > 0 && line.charCodeAt(pipe - 1) === C_BACKSLASH)\n cell += `${line.slice(from, pipe - 1)}|`\n else {\n cells.push((cell + line.slice(from, pipe)).trim())\n cell = ''\n }\n from = pipe + 1\n }\n const last = (cell + line.slice(from)).trim()\n // Text after the last pipe is a cell; nothing after it is the row's closing pipe.\n if (last !== '' || line.charCodeAt(line.length - 1) !== C_PIPE || line === '') cells.push(last)\n return cells\n}\n\n/** The alignments a table's delimiter row (`| :-- | --: |`) gives, or null when it is not one. */\nconst parseDelimiterRow = (row: string): Align[] | null => {\n if (row.indexOf('|') === -1) return null\n const cells = splitRow(row)\n const align: Align[] = []\n for (const cell of cells) {\n const found = reTableDelimiterCell.exec(cell)\n if (found === null) return null\n align.push(found[1] ? (found[2] ? 'center' : 'left') : found[2] ? 'right' : null)\n }\n return align.length === 0 ? null : align\n}\n\nexport interface BlockResult {\n root: Node\n /** The footnotes defined, in the order they are first referred to. */\n footnotes: Node[]\n}\n\n/** Parses a whole document into its tree. */\nexport const parseBlocks = (input: string, context: InlineContext): BlockResult => {\n const gfm = context.gfm\n // Where each line starts and ends in the document (its ending left out): a node's position is\n // counted from these, and a line's text is cut from the document only when it is read.\n const starts: number[] = []\n const ends: number[] = []\n // Most text has no carriage return: its lines are found by a plain search, not a pattern.\n const onlyLf = input.indexOf('\\r') === -1\n if (onlyLf) {\n for (let at = 0; ;) {\n const ending = input.indexOf('\\n', at)\n starts.push(at)\n if (ending === -1) {\n ends.push(input.length)\n break\n }\n ends.push(ending)\n at = ending + 1\n }\n } else {\n for (let at = 0; ;) {\n reLineEnding.lastIndex = at\n const ending = reLineEnding.exec(input)\n starts.push(at)\n if (ending === null) {\n ends.push(input.length)\n break\n }\n ends.push(ending.index)\n at = ending.index + ending[0].length\n }\n }\n let count = starts.length\n // A final line ending ends the last line; it does not start an empty one.\n if (count > 0 && starts[count - 1] === ends[count - 1]) count--\n /** No NUL in the document: a line is then the document's own text, with nothing to replace. */\n const noNul = input.indexOf('\\u0000') === -1\n\n const block = (type: string, startLine: number): Block => ({\n type,\n parent: null,\n children: [],\n open: true,\n lastLineBlank: false,\n text: '',\n startLine,\n endLine: startLine,\n startOffset: 0,\n depth: 0,\n ordered: false,\n bullet: 0,\n start: 0,\n delimiter: 0,\n padding: 0,\n markerOffset: 0,\n tight: true,\n fenced: false,\n fenceChar: 0,\n fenceLength: 0,\n fenceOffset: 0,\n htmlType: 0,\n level: 0,\n align: null,\n rows: null,\n label: '',\n })\n\n const doc = block('root', 1)\n let tip: Block = doc\n let oldtip: Block = doc\n let lastMatchedContainer: Block = doc\n let allClosed = true\n let line = ''\n let lineNumber = 0\n let offset = 0\n let column = 0\n let nextNonspace = 0\n let nextNonspaceColumn = 0\n let indent = 0\n let indented = false\n let blank = false\n let partiallyConsumedTab = false\n\n const findNextNonspace = (): void => {\n let index = offset\n let cols = column\n let code = line.charCodeAt(index)\n while (code === C_SPACE || code === C_TAB) {\n cols += code === C_SPACE ? 1 : 4 - (cols % 4)\n code = line.charCodeAt(++index)\n }\n blank = index >= line.length\n nextNonspace = index\n nextNonspaceColumn = cols\n indent = cols - column\n indented = indent >= 4\n }\n\n const advanceNextNonspace = (): void => {\n offset = nextNonspace\n column = nextNonspaceColumn\n partiallyConsumedTab = false\n }\n\n /** Moves past `amount` characters, or that many columns: a tab is up to four columns wide. */\n const advanceOffset = (amount: number, columns: boolean): void => {\n let left = amount\n while (left > 0 && offset < line.length) {\n if (line.charCodeAt(offset) === C_TAB) {\n const toTab = 4 - (column % 4)\n if (columns) {\n partiallyConsumedTab = toTab > left\n const step = toTab > left ? left : toTab\n column += step\n if (!partiallyConsumedTab) offset++\n left -= step\n } else {\n partiallyConsumedTab = false\n column += toTab\n offset++\n left--\n }\n } else {\n partiallyConsumedTab = false\n offset++\n column++\n left--\n }\n }\n }\n\n const addLine = (): void => {\n if (partiallyConsumedTab) {\n // The rest of a tab that a container's indent took part of.\n offset++\n tip.text += ' '.repeat(4 - (column % 4))\n }\n tip.text += `${line.slice(offset)}\\n`\n }\n\n const removeChild = (child: Block): void => {\n const siblings = child.parent?.children\n if (siblings === undefined) return\n const index = siblings.lastIndexOf(child)\n if (index !== -1) siblings.splice(index, 1)\n child.parent = null\n }\n\n /** Whether a block ends with a blank line before its next sibling. */\n const gapAfter = (child: Block, next: Block | undefined): boolean =>\n next !== undefined && child.endLine !== next.startLine - 1\n\n const takeReferences = (paragraph: Block): void => {\n let content = paragraph.text\n while (content.charCodeAt(0) === C_OPEN_BRACKET) {\n const taken = parseReference(content, context.refs)\n if (taken === 0) break\n content = content.slice(taken)\n }\n paragraph.text = content\n }\n\n const finalize = (closing: Block, endLine: number): void => {\n const above = closing.parent\n closing.open = false\n closing.endLine = endLine\n switch (closing.type) {\n case 'paragraph':\n takeReferences(closing)\n // A paragraph that was only definitions leaves nothing behind.\n if (/^[ \\t\\n]*$/.test(closing.text)) removeChild(closing)\n break\n case 'code':\n if (closing.fenced) {\n const newline = closing.text.indexOf('\\n')\n closing.label = unescapeString(closing.text.slice(0, newline).trim())\n closing.text = closing.text.slice(newline + 1)\n } else closing.text = closing.text.replace(/(?:\\n *)+$/, '\\n')\n break\n case 'list': {\n const items = closing.children\n closing.tight = true\n for (let index = 0; index < items.length && closing.tight; index++) {\n const item = items[index] as Block\n if (gapAfter(item, items[index + 1])) closing.tight = false\n const inner = item.children\n for (let child = 0; child < inner.length && closing.tight; child++)\n if (gapAfter(inner[child] as Block, inner[child + 1])) closing.tight = false\n }\n const last = items[items.length - 1]\n if (last !== undefined) closing.endLine = last.endLine\n break\n }\n case 'item': {\n const last = closing.children[closing.children.length - 1]\n closing.endLine = last === undefined ? closing.startLine : last.endLine\n break\n }\n default:\n }\n if (above !== null) tip = above\n }\n\n const addChild = (type: string): Block => {\n // oxlint-disable-next-line no-unmodified-loop-condition -- `finalize` moves `tip` up.\n while (!isContainer(tip.type) || (tip.type === 'list' && type !== 'item'))\n finalize(tip, lineNumber - 1)\n const child = block(type, lineNumber)\n child.startOffset = (starts[lineNumber - 1] ?? 0) + nextNonspace\n child.parent = tip\n child.depth = tip.depth + 1\n tip.children.push(child)\n tip = child\n return child\n }\n\n const closeUnmatchedBlocks = (): void => {\n if (allClosed) return\n while (oldtip !== lastMatchedContainer) {\n const parent = oldtip.parent as Block\n finalize(oldtip, lineNumber - 1)\n oldtip = parent\n }\n allClosed = true\n }\n\n /** Reads a list marker at the next non-space character into a new item's data, or null. */\n const parseListMarker = (container: Block): Block | null => {\n if (indent >= 4) return null\n const rest = line.slice(nextNonspace)\n const first = rest.charCodeAt(0)\n const item = block('item', lineNumber)\n let markerLength = 1\n if (first === C_ASTERISK || first === C_PLUS || first === C_DASH) item.bullet = first\n else {\n const found = reOrderedListMarker.exec(rest)\n if (found === null) return null\n // Only a list that starts at 1 can interrupt a paragraph.\n if (container.type === 'paragraph' && found[1] !== '1') return null\n item.ordered = true\n item.start = parseInt(found[1] as string, 10)\n item.delimiter = (found[2] as string).charCodeAt(0)\n markerLength = found[0].length\n }\n const after = line.charCodeAt(nextNonspace + markerLength)\n if (!Number.isNaN(after) && !isSpaceOrTab(after)) return null\n // An empty item cannot interrupt a paragraph.\n if (container.type === 'paragraph' && /^[ \\t]*$/.test(line.slice(nextNonspace + markerLength)))\n return null\n\n advanceNextNonspace()\n advanceOffset(markerLength, true)\n const spacesStartColumn = column\n const spacesStartOffset = offset\n do {\n advanceOffset(1, true)\n // oxlint-disable-next-line no-unmodified-loop-condition -- `advanceOffset` moves `column`.\n } while (column - spacesStartColumn < 5 && isSpaceOrTab(line.charCodeAt(offset)))\n const blankItem = offset >= line.length\n const spaces = column - spacesStartColumn\n if (spaces >= 5 || spaces < 1 || blankItem) {\n item.padding = markerLength + 1\n column = spacesStartColumn\n offset = spacesStartOffset\n if (isSpaceOrTab(line.charCodeAt(offset))) advanceOffset(1, true)\n } else item.padding = markerLength + spaces\n item.markerOffset = indent\n return item\n }\n\n /**\n * Whether an open block goes on with this line: 0 when it does, 1 when it does not, 2 when the\n * line closed it and is used up.\n */\n const continues = (container: Block): number => {\n switch (container.type) {\n case 'blockquote':\n if (indented || line.charCodeAt(nextNonspace) !== C_GREATERTHAN) return 1\n advanceNextNonspace()\n advanceOffset(1, false)\n if (isSpaceOrTab(line.charCodeAt(offset))) advanceOffset(1, true)\n return 0\n case 'item':\n if (blank) {\n if (container.children.length === 0) return 1\n advanceNextNonspace()\n } else if (indent >= container.markerOffset + container.padding)\n advanceOffset(container.markerOffset + container.padding, true)\n else return 1\n return 0\n case 'footnoteDefinition':\n if (blank) advanceNextNonspace()\n else if (indent >= 4) advanceOffset(4, true)\n else return 1\n return 0\n case 'code':\n if (container.fenced) {\n if (indent <= 3 && line.charCodeAt(nextNonspace) === container.fenceChar) {\n const found = (\n container.fenceChar === C_DOLLAR ? reClosingMathFence : reClosingCodeFence\n ).exec(line.slice(nextNonspace))\n if (found !== null && found[0].length >= container.fenceLength) {\n finalize(container, lineNumber)\n return 2\n }\n }\n // Indentation up to the fence's own is not part of the code.\n let skip = container.fenceOffset\n while (skip > 0 && isSpaceOrTab(line.charCodeAt(offset))) {\n advanceOffset(1, true)\n skip--\n }\n } else if (indent >= 4) advanceOffset(4, true)\n else if (blank) advanceNextNonspace()\n else return 1\n return 0\n case 'html':\n return blank && (container.htmlType === 6 || container.htmlType === 7) ? 1 : 0\n case 'paragraph':\n case 'table':\n return blank ? 1 : 0\n case 'heading':\n case 'thematicBreak':\n return 1\n default:\n return 0\n }\n }\n\n /**\n * Tries the line as the start of a new block: 0 when it starts none, 1 when it starts a\n * container (the rest of the line is tried again), 2 when it starts a leaf.\n */\n const startBlock = (container: Block): number => {\n const first = line.charCodeAt(nextNonspace)\n if (indented) {\n // Four columns of indent start code, except where the line can go on a paragraph.\n if (tip.type !== 'paragraph' && !blank) {\n advanceOffset(4, true)\n closeUnmatchedBlocks()\n addChild('code')\n return 2\n }\n return 0\n }\n switch (first) {\n case C_GREATERTHAN:\n if (container.depth >= MAX_NESTING) return 0\n advanceNextNonspace()\n advanceOffset(1, false)\n if (isSpaceOrTab(line.charCodeAt(offset))) advanceOffset(1, true)\n closeUnmatchedBlocks()\n addChild('blockquote')\n return 1\n case C_HASH: {\n const found = reAtxHeadingMarker.exec(line.slice(nextNonspace))\n if (found === null) return 0\n advanceNextNonspace()\n advanceOffset(found[0].length, false)\n closeUnmatchedBlocks()\n const heading = addChild('heading')\n heading.level = found[0].trim().length\n heading.text = line\n .slice(offset)\n .replace(/^[ \\t]*#+[ \\t]*$/, '')\n .replace(/[ \\t]+#+[ \\t]*$/, '')\n advanceOffset(line.length - offset, false)\n return 2\n }\n case C_DOLLAR:\n case C_BACKTICK:\n case C_TILDE: {\n if (first === C_DOLLAR && !context.math) return 0\n const found = (first === C_DOLLAR ? reMathFence : reCodeFence).exec(\n line.slice(nextNonspace),\n )\n if (found === null) return 0\n closeUnmatchedBlocks()\n const code = addChild('code')\n code.fenced = true\n code.fenceLength = found[0].length\n code.fenceChar = first\n code.fenceOffset = indent\n advanceNextNonspace()\n advanceOffset(code.fenceLength, false)\n return 2\n }\n case C_LESSTHAN: {\n const rest = line.slice(nextNonspace)\n for (let type = 1; type <= 7; type++) {\n if (\n (reHtmlBlockOpen[type] as RegExp).test(rest) &&\n // The seventh kind (any complete tag) cannot interrupt a paragraph.\n (type < 7 ||\n (container.type !== 'paragraph' &&\n !(!allClosed && !blank && tip.type === 'paragraph')))\n ) {\n closeUnmatchedBlocks()\n // The line is kept whole: an HTML block is passed through with its indentation.\n addChild('html').htmlType = type\n return 2\n }\n }\n return 0\n }\n default:\n }\n\n if (container.type === 'paragraph') {\n // A table: the paragraph's last line is its header, this line the row of dashes under it.\n if (gfm && (first === C_PIPE || first === C_DASH || first === C_COLON)) {\n const align = parseDelimiterRow(line.slice(nextNonspace))\n if (align !== null) {\n const content = container.text\n const cut = content.lastIndexOf('\\n', content.length - 2)\n const header = content.slice(cut + 1, -1)\n if (splitRow(header).length === align.length) {\n closeUnmatchedBlocks()\n if (cut === -1) {\n tip = container.parent as Block\n removeChild(container)\n } else {\n container.text = content.slice(0, cut + 1)\n finalize(container, lineNumber - 2)\n }\n const table = addChild('table')\n table.startLine = lineNumber - 1\n table.startOffset = starts[lineNumber - 2] ?? 0\n table.align = align\n table.rows = [header]\n advanceOffset(line.length - offset, false)\n return 2\n }\n }\n }\n // A setext heading: the paragraph so far, underlined.\n if (first === C_EQUALS || first === C_DASH) {\n if (reSetextHeadingLine.test(line.slice(nextNonspace))) {\n closeUnmatchedBlocks()\n takeReferences(container)\n if (container.text.length > 0) {\n container.type = 'heading'\n container.level = first === C_EQUALS ? 1 : 2\n advanceOffset(line.length - offset, false)\n return 2\n }\n }\n }\n }\n\n if (\n (first === C_ASTERISK || first === C_DASH || first === C_UNDERSCORE) &&\n reThematicBreak.test(line.slice(nextNonspace))\n ) {\n closeUnmatchedBlocks()\n addChild('thematicBreak')\n advanceOffset(line.length - offset, false)\n return 2\n }\n\n // A list and its item are two blocks.\n if (container.depth >= MAX_NESTING - 1) return 0\n\n if (gfm && first === C_OPEN_BRACKET && line.charCodeAt(nextNonspace + 1) === 94 /* ^ */) {\n const found = reFootnoteDefinition.exec(line.slice(nextNonspace))\n if (found !== null) {\n closeUnmatchedBlocks()\n advanceNextNonspace()\n advanceOffset(found[0].length, false)\n const definition = addChild('footnoteDefinition')\n definition.label = found[1] as string\n const key = normalizeLabel(`[${definition.label}]`)\n if (!context.footnotes.has(key)) context.footnotes.set(key, definition.label)\n return 1\n }\n }\n\n if (\n first === C_ASTERISK ||\n first === C_PLUS ||\n first === C_DASH ||\n (first >= 48 && first <= 57)\n ) {\n const item = parseListMarker(container)\n if (item === null) return 0\n closeUnmatchedBlocks()\n // An item goes on the list it fits: the same kind of marker.\n if (\n tip.type !== 'list' ||\n tip.ordered !== item.ordered ||\n tip.bullet !== item.bullet ||\n tip.delimiter !== item.delimiter\n ) {\n const list = addChild('list')\n list.ordered = item.ordered\n list.bullet = item.bullet\n list.delimiter = item.delimiter\n list.start = item.start\n }\n const added = addChild('item')\n added.ordered = item.ordered\n added.padding = item.padding\n added.markerOffset = item.markerOffset\n return 1\n }\n return 0\n }\n\n const incorporateLine = (text: string): void => {\n let container: Block = doc\n oldtip = tip\n offset = 0\n column = 0\n blank = false\n partiallyConsumedTab = false\n lineNumber++\n line = noNul || text.indexOf('\\u0000') === -1 ? text : text.replace(/\\0/g, '�')\n\n // The open blocks this line goes on with, from the outermost in.\n for (;;) {\n const last = container.children[container.children.length - 1]\n if (last === undefined || !last.open) break\n container = last\n findNextNonspace()\n const result = continues(container)\n if (result === 2) return\n if (result === 1) {\n container = container.parent as Block\n break\n }\n }\n allClosed = container === oldtip\n lastMatchedContainer = container\n\n // New blocks the rest of the line starts, until it is down to a leaf or to text.\n let matchedLeaf = container.type !== 'paragraph' && acceptsLines(container.type)\n while (!matchedLeaf) {\n findNextNonspace()\n const result = blank ? 0 : startBlock(container)\n if (result === 0) {\n advanceNextNonspace()\n break\n }\n container = tip\n if (result === 2) matchedLeaf = true\n }\n\n if (!allClosed && !blank && tip.type === 'paragraph') {\n // A lazy continuation line: text that goes on a paragraph inside containers it did not mark.\n addLine()\n return\n }\n closeUnmatchedBlocks()\n const type = container.type\n if (blank) {\n const last = container.children[container.children.length - 1]\n if (last !== undefined) last.lastLineBlank = true\n }\n const lastLineBlank =\n blank &&\n !(\n type === 'blockquote' ||\n (type === 'code' && container.fenced) ||\n (type === 'item' && container.children.length === 0 && container.startLine === lineNumber)\n )\n for (let above: Block | null = container; above !== null; above = above.parent)\n above.lastLineBlank = lastLineBlank\n\n if (acceptsLines(type)) {\n addLine()\n // The first five kinds of HTML block end on the line that holds their closing sequence.\n if (\n type === 'html' &&\n container.htmlType >= 1 &&\n container.htmlType <= 5 &&\n (reHtmlBlockClose[container.htmlType] as RegExp).test(line.slice(offset))\n )\n finalize(container, lineNumber)\n } else if (offset < line.length && !blank) {\n if (type === 'table') (container.rows as string[]).push(line.slice(offset))\n else {\n addChild('paragraph')\n advanceNextNonspace()\n addLine()\n }\n }\n }\n\n /**\n * The lines of a fenced code block at the top of the document, taken without the work a line\n * gets elsewhere: from the line after `index`, every line up to one that may close the fence\n * goes into the code as it is written, in one cut of the document. Returns the last line taken.\n *\n * A line may close the fence when, after at most three spaces, it starts with the fence's\n * character; that line, and whatever follows a fence that did not close, is read the long way.\n */\n const takeFencedLines = (code: Block, index: number): number => {\n const fenceChar = code.fenceChar\n let next = index + 1\n for (; next < count; next++) {\n let at = starts[next] as number\n if (input.charCodeAt(at) === C_SPACE) {\n at++\n if (input.charCodeAt(at) === C_SPACE) {\n at++\n if (input.charCodeAt(at) === C_SPACE) at++\n }\n }\n if (input.charCodeAt(at) === fenceChar) break\n }\n const last = next - 1\n if (last === index) return index\n const taken = input.slice(starts[index + 1] as number, ends[last] as number)\n code.text += `${onlyLf ? taken : taken.replace(reLineEnding, '\\n')}\\n`\n lineNumber += last - index\n return last\n }\n\n for (let index = 0; index < count; index++) {\n incorporateLine(input.slice(starts[index] as number, ends[index] as number))\n // Inside a container, or under an indented fence, each line has a prefix to take off first.\n if (tip.fenced && tip.parent === doc && tip.fenceOffset === 0 && noNul)\n index = takeFencedLines(tip, index)\n }\n // oxlint-disable-next-line no-unmodified-loop-condition -- `finalize` moves `tip` up.\n while (tip !== doc) finalize(tip, count)\n finalize(doc, count)\n\n // The second pass: every block's text read into inlines, now that every definition is known.\n // Footnote definitions leave the flow: they are drawn together at the end of the document.\n const definitions = new Map<string, Block>()\n\n const kids = (from: Block): Node[] => {\n const out: Node[] = []\n for (const child of from.children) {\n if (child.type === 'footnoteDefinition') {\n const key = normalizeLabel(`[${child.label}]`)\n if (!definitions.has(key)) definitions.set(key, child)\n } else out.push(build(child))\n }\n return out\n }\n\n const cells = (row: string, align: Align[], header: boolean): Node => {\n const parts = splitRow(row)\n const children: Node[] = []\n for (let index = 0; index < align.length; index++)\n children.push({\n type: 'tableCell',\n header,\n cellAlign: align[index] ?? null,\n children: parseInlines(parts[index] ?? '', context),\n })\n return { type: 'tableRow', children }\n }\n\n /** Where a block sits in the document: from its first character to the end of its last line. */\n const place = (from: Block): Position => {\n const last = Math.min(Math.max(from.endLine, from.startLine), starts.length)\n const lastStart = starts[last - 1] ?? 0\n const length = (ends[last - 1] ?? 0) - lastStart\n return {\n start: {\n line: from.startLine,\n column: from.startOffset - (starts[from.startLine - 1] ?? 0) + 1,\n offset: from.startOffset,\n },\n end: { line: last, column: length + 1, offset: lastStart + length },\n }\n }\n\n const build = (from: Block): Node => {\n switch (from.type) {\n case 'paragraph':\n return {\n type: 'paragraph',\n position: place(from),\n children: parseInlines(from.text, context),\n }\n case 'heading':\n return {\n type: 'heading',\n depth: from.level,\n position: place(from),\n children: parseInlines(from.text, context),\n }\n case 'thematicBreak':\n return { type: 'thematicBreak', position: place(from) }\n case 'code': {\n if (from.fenceChar === C_DOLLAR) {\n const node: Node = {\n type: 'math',\n position: place(from),\n value: from.text.replace(/\\n$/, ''),\n }\n if (from.label !== '') node.meta = from.label\n return node\n }\n const node: Node = { type: 'code', position: place(from), value: from.text }\n if (from.label !== '') {\n const space = from.label.search(/[ \\t]/)\n node.lang = space === -1 ? from.label : from.label.slice(0, space)\n if (space !== -1) node.meta = from.label.slice(space + 1).trim()\n }\n return node\n }\n case 'html':\n return { type: 'html', position: place(from), value: from.text.replace(/(?:\\n *)+$/, '') }\n case 'table': {\n const align = from.align as Align[]\n const rows = from.rows as string[]\n return {\n type: 'table',\n position: place(from),\n align,\n children: rows.map((row, index) => cells(row, align, index === 0)),\n }\n }\n case 'list': {\n const node: Node = {\n type: 'list',\n position: place(from),\n ordered: from.ordered,\n spread: !from.tight,\n children: kids(from),\n }\n for (const item of node.children as Node[]) item.spread = !from.tight\n if (from.ordered) node.start = from.start\n return node\n }\n case 'item': {\n const node: Node = { type: 'listItem', position: place(from), children: [] }\n const first = from.children[0]\n if (gfm && first !== undefined && first.type === 'paragraph') {\n const task = reTaskMarker.exec(first.text)\n if (task !== null) {\n node.checked = task[1] !== ' '\n first.text = first.text.slice(task[0].length + 1)\n }\n }\n node.children = kids(from)\n return node\n }\n default:\n return { type: from.type, position: place(from), children: kids(from) }\n }\n }\n\n const root: Node = { type: 'root', children: kids(doc) }\n\n // The footnotes referred to, in the order of their first reference. Reading one can refer to\n // more, so the list is walked as it grows.\n const footnotes: Node[] = []\n for (let index = 0; ; index++) {\n let key: string | undefined\n let at = 0\n for (const used of context.footnoteUses.keys()) if (at++ === index) key = used\n if (key === undefined) break\n const from = definitions.get(key)\n if (from === undefined) continue\n footnotes.push({\n type: 'footnoteDefinition',\n identifier: normalizeLabel(`[${from.label}]`).toLowerCase(),\n label: from.label,\n index: index + 1,\n position: place(from),\n children: kids(from),\n })\n }\n for (const node of footnotes)\n node.count = context.footnoteUses.get(normalizeLabel(`[${node.label}]`)) ?? 1\n return { root, footnotes }\n}\n"],"mappings":";;;;;;;;;;AAwDA,MAAM,QAAQ;AACd,MAAM,UAAU;AAChB,MAAM,SAAS;AACf,MAAM,WAAW;AACjB,MAAM,aAAa;AACnB,MAAM,SAAS;AACf,MAAM,SAAS;AACf,MAAM,UAAU;AAChB,MAAM,aAAa;AACnB,MAAM,WAAW;AACjB,MAAM,gBAAgB;AACtB,MAAM,iBAAiB;AACvB,MAAM,cAAc;AACpB,MAAM,eAAe;AACrB,MAAM,aAAa;AACnB,MAAM,SAAS;AACf,MAAM,UAAU;AAEhB,MAAM,kBAAkB;CACtB;CACA;CACA;CACA;CACA;CACA;CACA;CACA,IAAI,OAAO,OAAO,QAAQ,GAAG,SAAS,SAAS,GAAG;AACpD;AACA,MAAM,mBAAmB;CACvB;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAM,kBAAkB;AACxB,MAAM,sBAAsB;AAC5B,MAAM,qBAAqB;AAC3B,MAAM,cAAc;AACpB,MAAM,qBAAqB;;AAE3B,MAAM,cAAc;AACpB,MAAM,qBAAqB;AAC3B,MAAM,sBAAsB;AAC5B,MAAM,eAAe;AACrB,MAAM,uBAAuB;AAC7B,MAAM,uBAAuB;AAC7B,MAAM,eAAe;AAErB,MAAM,gBAAgB,SAA0B,SAAS,WAAW,SAAS;;;;;;;AAQ7E,MAAM,cAAc;;AAGpB,MAAM,eAAe,SACnB,SAAS,UACT,SAAS,gBACT,SAAS,UACT,SAAS,UACT,SAAS;;AAGX,MAAM,gBAAgB,SACpB,SAAS,eAAe,SAAS,UAAU,SAAS;;;;;AAMtD,MAAM,YAAY,QAA0B;CAC1C,MAAM,QAAkB,CAAC;CACzB,IAAI,OAAO,IAAI,KAAK;CACpB,IAAI,KAAK,WAAW,CAAC,MAAM,QAAQ,OAAO,KAAK,MAAM,CAAC;;CAEtD,IAAI,OAAO;CACX,IAAI,OAAO;CACX,KAAK,IAAI,OAAO,KAAK,QAAQ,GAAG,GAAG,SAAS,IAAI,OAAO,KAAK,QAAQ,KAAK,OAAO,CAAC,GAAG;EAClF,IAAI,OAAO,KAAK,KAAK,WAAW,OAAO,CAAC,MAAM,aAC5C,QAAQ,GAAG,KAAK,MAAM,MAAM,OAAO,CAAC,EAAE;OACnC;GACH,MAAM,MAAM,OAAO,KAAK,MAAM,MAAM,IAAI,EAAA,CAAG,KAAK,CAAC;GACjD,OAAO;EACT;EACA,OAAO,OAAO;CAChB;CACA,MAAM,QAAQ,OAAO,KAAK,MAAM,IAAI,EAAA,CAAG,KAAK;CAE5C,IAAI,SAAS,MAAM,KAAK,WAAW,KAAK,SAAS,CAAC,MAAM,UAAU,SAAS,IAAI,MAAM,KAAK,IAAI;CAC9F,OAAO;AACT;;AAGA,MAAM,qBAAqB,QAAgC;CACzD,IAAI,IAAI,QAAQ,GAAG,MAAM,IAAI,OAAO;CACpC,MAAM,QAAQ,SAAS,GAAG;CAC1B,MAAM,QAAiB,CAAC;CACxB,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,QAAQ,qBAAqB,KAAK,IAAI;EAC5C,IAAI,UAAU,MAAM,OAAO;EAC3B,MAAM,KAAK,MAAM,KAAM,MAAM,KAAK,WAAW,SAAU,MAAM,KAAK,UAAU,IAAI;CAClF;CACA,OAAO,MAAM,WAAW,IAAI,OAAO;AACrC;;AASA,MAAa,eAAe,OAAe,YAAwC;CACjF,MAAM,MAAM,QAAQ;CAGpB,MAAM,SAAmB,CAAC;CAC1B,MAAM,OAAiB,CAAC;CAExB,MAAM,SAAS,MAAM,QAAQ,IAAI,MAAM;CACvC,IAAI,QACF,KAAK,IAAI,KAAK,KAAM;EAClB,MAAM,SAAS,MAAM,QAAQ,MAAM,EAAE;EACrC,OAAO,KAAK,EAAE;EACd,IAAI,WAAW,IAAI;GACjB,KAAK,KAAK,MAAM,MAAM;GACtB;EACF;EACA,KAAK,KAAK,MAAM;EAChB,KAAK,SAAS;CAChB;MAEA,KAAK,IAAI,KAAK,KAAM;EAClB,aAAa,YAAY;EACzB,MAAM,SAAS,aAAa,KAAK,KAAK;EACtC,OAAO,KAAK,EAAE;EACd,IAAI,WAAW,MAAM;GACnB,KAAK,KAAK,MAAM,MAAM;GACtB;EACF;EACA,KAAK,KAAK,OAAO,KAAK;EACtB,KAAK,OAAO,QAAQ,OAAO,EAAE,CAAC;CAChC;CAEF,IAAI,QAAQ,OAAO;CAEnB,IAAI,QAAQ,KAAK,OAAO,QAAQ,OAAO,KAAK,QAAQ,IAAI;;CAExD,MAAM,QAAQ,MAAM,QAAQ,IAAQ,MAAM;CAE1C,MAAM,SAAS,MAAc,eAA8B;EACzD;EACA,QAAQ;EACR,UAAU,CAAC;EACX,MAAM;EACN,eAAe;EACf,MAAM;EACN;EACA,SAAS;EACT,aAAa;EACb,OAAO;EACP,SAAS;EACT,QAAQ;EACR,OAAO;EACP,WAAW;EACX,SAAS;EACT,cAAc;EACd,OAAO;EACP,QAAQ;EACR,WAAW;EACX,aAAa;EACb,aAAa;EACb,UAAU;EACV,OAAO;EACP,OAAO;EACP,MAAM;EACN,OAAO;CACT;CAEA,MAAM,MAAM,MAAM,QAAQ,CAAC;CAC3B,IAAI,MAAa;CACjB,IAAI,SAAgB;CACpB,IAAI,uBAA8B;CAClC,IAAI,YAAY;CAChB,IAAI,OAAO;CACX,IAAI,aAAa;CACjB,IAAI,SAAS;CACb,IAAI,SAAS;CACb,IAAI,eAAe;CACnB,IAAI,qBAAqB;CACzB,IAAI,SAAS;CACb,IAAI,WAAW;CACf,IAAI,QAAQ;CACZ,IAAI,uBAAuB;CAE3B,MAAM,yBAA+B;EACnC,IAAI,QAAQ;EACZ,IAAI,OAAO;EACX,IAAI,OAAO,KAAK,WAAW,KAAK;EAChC,OAAO,SAAS,WAAW,SAAS,OAAO;GACzC,QAAQ,SAAS,UAAU,IAAI,IAAK,OAAO;GAC3C,OAAO,KAAK,WAAW,EAAE,KAAK;EAChC;EACA,QAAQ,SAAS,KAAK;EACtB,eAAe;EACf,qBAAqB;EACrB,SAAS,OAAO;EAChB,WAAW,UAAU;CACvB;CAEA,MAAM,4BAAkC;EACtC,SAAS;EACT,SAAS;EACT,uBAAuB;CACzB;;CAGA,MAAM,iBAAiB,QAAgB,YAA2B;EAChE,IAAI,OAAO;EACX,OAAO,OAAO,KAAK,SAAS,KAAK,QAC/B,IAAI,KAAK,WAAW,MAAM,MAAM,OAAO;GACrC,MAAM,QAAQ,IAAK,SAAS;GAC5B,IAAI,SAAS;IACX,uBAAuB,QAAQ;IAC/B,MAAM,OAAO,QAAQ,OAAO,OAAO;IACnC,UAAU;IACV,IAAI,CAAC,sBAAsB;IAC3B,QAAQ;GACV,OAAO;IACL,uBAAuB;IACvB,UAAU;IACV;IACA;GACF;EACF,OAAO;GACL,uBAAuB;GACvB;GACA;GACA;EACF;CAEJ;CAEA,MAAM,gBAAsB;EAC1B,IAAI,sBAAsB;GAExB;GACA,IAAI,QAAQ,IAAI,OAAO,IAAK,SAAS,CAAE;EACzC;EACA,IAAI,QAAQ,GAAG,KAAK,MAAM,MAAM,EAAE;CACpC;CAEA,MAAM,eAAe,UAAuB;EAC1C,MAAM,WAAW,MAAM,QAAQ;EAC/B,IAAI,aAAa,KAAA,GAAW;EAC5B,MAAM,QAAQ,SAAS,YAAY,KAAK;EACxC,IAAI,UAAU,IAAI,SAAS,OAAO,OAAO,CAAC;EAC1C,MAAM,SAAS;CACjB;;CAGA,MAAM,YAAY,OAAc,SAC9B,SAAS,KAAA,KAAa,MAAM,YAAY,KAAK,YAAY;CAE3D,MAAM,kBAAkB,cAA2B;EACjD,IAAI,UAAU,UAAU;EACxB,OAAO,QAAQ,WAAW,CAAC,MAAM,gBAAgB;GAC/C,MAAM,QAAQ,eAAe,SAAS,QAAQ,IAAI;GAClD,IAAI,UAAU,GAAG;GACjB,UAAU,QAAQ,MAAM,KAAK;EAC/B;EACA,UAAU,OAAO;CACnB;CAEA,MAAM,YAAY,SAAgB,YAA0B;EAC1D,MAAM,QAAQ,QAAQ;EACtB,QAAQ,OAAO;EACf,QAAQ,UAAU;EAClB,QAAQ,QAAQ,MAAhB;GACE,KAAK;IACH,eAAe,OAAO;IAEtB,IAAI,aAAa,KAAK,QAAQ,IAAI,GAAG,YAAY,OAAO;IACxD;GACF,KAAK;IACH,IAAI,QAAQ,QAAQ;KAClB,MAAM,UAAU,QAAQ,KAAK,QAAQ,IAAI;KACzC,QAAQ,QAAQ,eAAe,QAAQ,KAAK,MAAM,GAAG,OAAO,CAAC,CAAC,KAAK,CAAC;KACpE,QAAQ,OAAO,QAAQ,KAAK,MAAM,UAAU,CAAC;IAC/C,OAAO,QAAQ,OAAO,QAAQ,KAAK,QAAQ,cAAc,IAAI;IAC7D;GACF,KAAK,QAAQ;IACX,MAAM,QAAQ,QAAQ;IACtB,QAAQ,QAAQ;IAChB,KAAK,IAAI,QAAQ,GAAG,QAAQ,MAAM,UAAU,QAAQ,OAAO,SAAS;KAClE,MAAM,OAAO,MAAM;KACnB,IAAI,SAAS,MAAM,MAAM,QAAQ,EAAE,GAAG,QAAQ,QAAQ;KACtD,MAAM,QAAQ,KAAK;KACnB,KAAK,IAAI,QAAQ,GAAG,QAAQ,MAAM,UAAU,QAAQ,OAAO,SACzD,IAAI,SAAS,MAAM,QAAiB,MAAM,QAAQ,EAAE,GAAG,QAAQ,QAAQ;IAC3E;IACA,MAAM,OAAO,MAAM,MAAM,SAAS;IAClC,IAAI,SAAS,KAAA,GAAW,QAAQ,UAAU,KAAK;IAC/C;GACF;GACA,KAAK,QAAQ;IACX,MAAM,OAAO,QAAQ,SAAS,QAAQ,SAAS,SAAS;IACxD,QAAQ,UAAU,SAAS,KAAA,IAAY,QAAQ,YAAY,KAAK;IAChE;GACF;EAEF;EACA,IAAI,UAAU,MAAM,MAAM;CAC5B;CAEA,MAAM,YAAY,SAAwB;EAExC,OAAO,CAAC,YAAY,IAAI,IAAI,KAAM,IAAI,SAAS,UAAU,SAAS,QAChE,SAAS,KAAK,aAAa,CAAC;EAC9B,MAAM,QAAQ,MAAM,MAAM,UAAU;EACpC,MAAM,eAAe,OAAO,aAAa,MAAM,KAAK;EACpD,MAAM,SAAS;EACf,MAAM,QAAQ,IAAI,QAAQ;EAC1B,IAAI,SAAS,KAAK,KAAK;EACvB,MAAM;EACN,OAAO;CACT;CAEA,MAAM,6BAAmC;EACvC,IAAI,WAAW;EACf,OAAO,WAAW,sBAAsB;GACtC,MAAM,SAAS,OAAO;GACtB,SAAS,QAAQ,aAAa,CAAC;GAC/B,SAAS;EACX;EACA,YAAY;CACd;;CAGA,MAAM,mBAAmB,cAAmC;EAC1D,IAAI,UAAU,GAAG,OAAO;EACxB,MAAM,OAAO,KAAK,MAAM,YAAY;EACpC,MAAM,QAAQ,KAAK,WAAW,CAAC;EAC/B,MAAM,OAAO,MAAM,QAAQ,UAAU;EACrC,IAAI,eAAe;EACnB,IAAI,UAAU,cAAc,UAAU,UAAU,UAAU,QAAQ,KAAK,SAAS;OAC3E;GACH,MAAM,QAAQ,oBAAoB,KAAK,IAAI;GAC3C,IAAI,UAAU,MAAM,OAAO;GAE3B,IAAI,UAAU,SAAS,eAAe,MAAM,OAAO,KAAK,OAAO;GAC/D,KAAK,UAAU;GACf,KAAK,QAAQ,SAAS,MAAM,IAAc,EAAE;GAC5C,KAAK,YAAa,MAAM,EAAE,CAAY,WAAW,CAAC;GAClD,eAAe,MAAM,EAAE,CAAC;EAC1B;EACA,MAAM,QAAQ,KAAK,WAAW,eAAe,YAAY;EACzD,IAAI,CAAC,OAAO,MAAM,KAAK,KAAK,CAAC,aAAa,KAAK,GAAG,OAAO;EAEzD,IAAI,UAAU,SAAS,eAAe,WAAW,KAAK,KAAK,MAAM,eAAe,YAAY,CAAC,GAC3F,OAAO;EAET,oBAAoB;EACpB,cAAc,cAAc,IAAI;EAChC,MAAM,oBAAoB;EAC1B,MAAM,oBAAoB;EAC1B;GACE,cAAc,GAAG,IAAI;SAEd,SAAS,oBAAoB,KAAK,aAAa,KAAK,WAAW,MAAM,CAAC;EAC/E,MAAM,YAAY,UAAU,KAAK;EACjC,MAAM,SAAS,SAAS;EACxB,IAAI,UAAU,KAAK,SAAS,KAAK,WAAW;GAC1C,KAAK,UAAU,eAAe;GAC9B,SAAS;GACT,SAAS;GACT,IAAI,aAAa,KAAK,WAAW,MAAM,CAAC,GAAG,cAAc,GAAG,IAAI;EAClE,OAAO,KAAK,UAAU,eAAe;EACrC,KAAK,eAAe;EACpB,OAAO;CACT;;;;;CAMA,MAAM,aAAa,cAA6B;EAC9C,QAAQ,UAAU,MAAlB;GACE,KAAK;IACH,IAAI,YAAY,KAAK,WAAW,YAAY,MAAM,eAAe,OAAO;IACxE,oBAAoB;IACpB,cAAc,GAAG,KAAK;IACtB,IAAI,aAAa,KAAK,WAAW,MAAM,CAAC,GAAG,cAAc,GAAG,IAAI;IAChE,OAAO;GACT,KAAK;IACH,IAAI,OAAO;KACT,IAAI,UAAU,SAAS,WAAW,GAAG,OAAO;KAC5C,oBAAoB;IACtB,OAAO,IAAI,UAAU,UAAU,eAAe,UAAU,SACtD,cAAc,UAAU,eAAe,UAAU,SAAS,IAAI;SAC3D,OAAO;IACZ,OAAO;GACT,KAAK;IACH,IAAI,OAAO,oBAAoB;SAC1B,IAAI,UAAU,GAAG,cAAc,GAAG,IAAI;SACtC,OAAO;IACZ,OAAO;GACT,KAAK;IACH,IAAI,UAAU,QAAQ;KACpB,IAAI,UAAU,KAAK,KAAK,WAAW,YAAY,MAAM,UAAU,WAAW;MACxE,MAAM,SACJ,UAAU,cAAc,WAAW,qBAAqB,mBAAA,CACxD,KAAK,KAAK,MAAM,YAAY,CAAC;MAC/B,IAAI,UAAU,QAAQ,MAAM,EAAE,CAAC,UAAU,UAAU,aAAa;OAC9D,SAAS,WAAW,UAAU;OAC9B,OAAO;MACT;KACF;KAEA,IAAI,OAAO,UAAU;KACrB,OAAO,OAAO,KAAK,aAAa,KAAK,WAAW,MAAM,CAAC,GAAG;MACxD,cAAc,GAAG,IAAI;MACrB;KACF;IACF,OAAO,IAAI,UAAU,GAAG,cAAc,GAAG,IAAI;SACxC,IAAI,OAAO,oBAAoB;SAC/B,OAAO;IACZ,OAAO;GACT,KAAK,QACH,OAAO,UAAU,UAAU,aAAa,KAAK,UAAU,aAAa,KAAK,IAAI;GAC/E,KAAK;GACL,KAAK,SACH,OAAO,QAAQ,IAAI;GACrB,KAAK;GACL,KAAK,iBACH,OAAO;GACT,SACE,OAAO;EACX;CACF;;;;;CAMA,MAAM,cAAc,cAA6B;EAC/C,MAAM,QAAQ,KAAK,WAAW,YAAY;EAC1C,IAAI,UAAU;GAEZ,IAAI,IAAI,SAAS,eAAe,CAAC,OAAO;IACtC,cAAc,GAAG,IAAI;IACrB,qBAAqB;IACrB,SAAS,MAAM;IACf,OAAO;GACT;GACA,OAAO;EACT;EACA,QAAQ,OAAR;GACE,KAAK;IACH,IAAI,UAAU,SAAS,aAAa,OAAO;IAC3C,oBAAoB;IACpB,cAAc,GAAG,KAAK;IACtB,IAAI,aAAa,KAAK,WAAW,MAAM,CAAC,GAAG,cAAc,GAAG,IAAI;IAChE,qBAAqB;IACrB,SAAS,YAAY;IACrB,OAAO;GACT,KAAK,QAAQ;IACX,MAAM,QAAQ,mBAAmB,KAAK,KAAK,MAAM,YAAY,CAAC;IAC9D,IAAI,UAAU,MAAM,OAAO;IAC3B,oBAAoB;IACpB,cAAc,MAAM,EAAE,CAAC,QAAQ,KAAK;IACpC,qBAAqB;IACrB,MAAM,UAAU,SAAS,SAAS;IAClC,QAAQ,QAAQ,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC;IAChC,QAAQ,OAAO,KACZ,MAAM,MAAM,CAAC,CACb,QAAQ,oBAAoB,EAAE,CAAC,CAC/B,QAAQ,mBAAmB,EAAE;IAChC,cAAc,KAAK,SAAS,QAAQ,KAAK;IACzC,OAAO;GACT;GACA,KAAK;GACL,KAAK;GACL,KAAK,SAAS;IACZ,IAAI,UAAU,YAAY,CAAC,QAAQ,MAAM,OAAO;IAChD,MAAM,SAAS,UAAU,WAAW,cAAc,YAAA,CAAa,KAC7D,KAAK,MAAM,YAAY,CACzB;IACA,IAAI,UAAU,MAAM,OAAO;IAC3B,qBAAqB;IACrB,MAAM,OAAO,SAAS,MAAM;IAC5B,KAAK,SAAS;IACd,KAAK,cAAc,MAAM,EAAE,CAAC;IAC5B,KAAK,YAAY;IACjB,KAAK,cAAc;IACnB,oBAAoB;IACpB,cAAc,KAAK,aAAa,KAAK;IACrC,OAAO;GACT;GACA,KAAK,YAAY;IACf,MAAM,OAAO,KAAK,MAAM,YAAY;IACpC,KAAK,IAAI,OAAO,GAAG,QAAQ,GAAG,QAC5B,IACG,gBAAgB,KAAK,CAAY,KAAK,IAAI,MAE1C,OAAO,KACL,UAAU,SAAS,eAClB,EAAE,CAAC,aAAa,CAAC,SAAS,IAAI,SAAS,eAC3C;KACA,qBAAqB;KAErB,SAAS,MAAM,CAAC,CAAC,WAAW;KAC5B,OAAO;IACT;IAEF,OAAO;GACT;EAEF;EAEA,IAAI,UAAU,SAAS,aAAa;GAElC,IAAI,QAAQ,UAAU,UAAU,UAAU,UAAU,UAAU,UAAU;IACtE,MAAM,QAAQ,kBAAkB,KAAK,MAAM,YAAY,CAAC;IACxD,IAAI,UAAU,MAAM;KAClB,MAAM,UAAU,UAAU;KAC1B,MAAM,MAAM,QAAQ,YAAY,MAAM,QAAQ,SAAS,CAAC;KACxD,MAAM,SAAS,QAAQ,MAAM,MAAM,GAAG,EAAE;KACxC,IAAI,SAAS,MAAM,CAAC,CAAC,WAAW,MAAM,QAAQ;MAC5C,qBAAqB;MACrB,IAAI,QAAQ,IAAI;OACd,MAAM,UAAU;OAChB,YAAY,SAAS;MACvB,OAAO;OACL,UAAU,OAAO,QAAQ,MAAM,GAAG,MAAM,CAAC;OACzC,SAAS,WAAW,aAAa,CAAC;MACpC;MACA,MAAM,QAAQ,SAAS,OAAO;MAC9B,MAAM,YAAY,aAAa;MAC/B,MAAM,cAAc,OAAO,aAAa,MAAM;MAC9C,MAAM,QAAQ;MACd,MAAM,OAAO,CAAC,MAAM;MACpB,cAAc,KAAK,SAAS,QAAQ,KAAK;MACzC,OAAO;KACT;IACF;GACF;GAEA,IAAI,UAAU,YAAY,UAAU,QAC9B;QAAA,oBAAoB,KAAK,KAAK,MAAM,YAAY,CAAC,GAAG;KACtD,qBAAqB;KACrB,eAAe,SAAS;KACxB,IAAI,UAAU,KAAK,SAAS,GAAG;MAC7B,UAAU,OAAO;MACjB,UAAU,QAAQ,UAAU,WAAW,IAAI;MAC3C,cAAc,KAAK,SAAS,QAAQ,KAAK;MACzC,OAAO;KACT;IACF;;EAEJ;EAEA,KACG,UAAU,cAAc,UAAU,UAAU,UAAU,iBACvD,gBAAgB,KAAK,KAAK,MAAM,YAAY,CAAC,GAC7C;GACA,qBAAqB;GACrB,SAAS,eAAe;GACxB,cAAc,KAAK,SAAS,QAAQ,KAAK;GACzC,OAAO;EACT;EAGA,IAAI,UAAU,SAAS,IAAiB,OAAO;EAE/C,IAAI,OAAO,UAAU,kBAAkB,KAAK,WAAW,eAAe,CAAC,MAAM,IAAY;GACvF,MAAM,QAAQ,qBAAqB,KAAK,KAAK,MAAM,YAAY,CAAC;GAChE,IAAI,UAAU,MAAM;IAClB,qBAAqB;IACrB,oBAAoB;IACpB,cAAc,MAAM,EAAE,CAAC,QAAQ,KAAK;IACpC,MAAM,aAAa,SAAS,oBAAoB;IAChD,WAAW,QAAQ,MAAM;IACzB,MAAM,MAAM,eAAe,IAAI,WAAW,MAAM,EAAE;IAClD,IAAI,CAAC,QAAQ,UAAU,IAAI,GAAG,GAAG,QAAQ,UAAU,IAAI,KAAK,WAAW,KAAK;IAC5E,OAAO;GACT;EACF;EAEA,IACE,UAAU,cACV,UAAU,UACV,UAAU,UACT,SAAS,MAAM,SAAS,IACzB;GACA,MAAM,OAAO,gBAAgB,SAAS;GACtC,IAAI,SAAS,MAAM,OAAO;GAC1B,qBAAqB;GAErB,IACE,IAAI,SAAS,UACb,IAAI,YAAY,KAAK,WACrB,IAAI,WAAW,KAAK,UACpB,IAAI,cAAc,KAAK,WACvB;IACA,MAAM,OAAO,SAAS,MAAM;IAC5B,KAAK,UAAU,KAAK;IACpB,KAAK,SAAS,KAAK;IACnB,KAAK,YAAY,KAAK;IACtB,KAAK,QAAQ,KAAK;GACpB;GACA,MAAM,QAAQ,SAAS,MAAM;GAC7B,MAAM,UAAU,KAAK;GACrB,MAAM,UAAU,KAAK;GACrB,MAAM,eAAe,KAAK;GAC1B,OAAO;EACT;EACA,OAAO;CACT;CAEA,MAAM,mBAAmB,SAAuB;EAC9C,IAAI,YAAmB;EACvB,SAAS;EACT,SAAS;EACT,SAAS;EACT,QAAQ;EACR,uBAAuB;EACvB;EACA,OAAO,SAAS,KAAK,QAAQ,IAAQ,MAAM,KAAK,OAAO,KAAK,QAAQ,OAAO,GAAG;EAG9E,SAAS;GACP,MAAM,OAAO,UAAU,SAAS,UAAU,SAAS,SAAS;GAC5D,IAAI,SAAS,KAAA,KAAa,CAAC,KAAK,MAAM;GACtC,YAAY;GACZ,iBAAiB;GACjB,MAAM,SAAS,UAAU,SAAS;GAClC,IAAI,WAAW,GAAG;GAClB,IAAI,WAAW,GAAG;IAChB,YAAY,UAAU;IACtB;GACF;EACF;EACA,YAAY,cAAc;EAC1B,uBAAuB;EAGvB,IAAI,cAAc,UAAU,SAAS,eAAe,aAAa,UAAU,IAAI;EAC/E,OAAO,CAAC,aAAa;GACnB,iBAAiB;GACjB,MAAM,SAAS,QAAQ,IAAI,WAAW,SAAS;GAC/C,IAAI,WAAW,GAAG;IAChB,oBAAoB;IACpB;GACF;GACA,YAAY;GACZ,IAAI,WAAW,GAAG,cAAc;EAClC;EAEA,IAAI,CAAC,aAAa,CAAC,SAAS,IAAI,SAAS,aAAa;GAEpD,QAAQ;GACR;EACF;EACA,qBAAqB;EACrB,MAAM,OAAO,UAAU;EACvB,IAAI,OAAO;GACT,MAAM,OAAO,UAAU,SAAS,UAAU,SAAS,SAAS;GAC5D,IAAI,SAAS,KAAA,GAAW,KAAK,gBAAgB;EAC/C;EACA,MAAM,gBACJ,SACA,EACE,SAAS,gBACR,SAAS,UAAU,UAAU,UAC7B,SAAS,UAAU,UAAU,SAAS,WAAW,KAAK,UAAU,cAAc;EAEnF,KAAK,IAAI,QAAsB,WAAW,UAAU,MAAM,QAAQ,MAAM,QACtE,MAAM,gBAAgB;EAExB,IAAI,aAAa,IAAI,GAAG;GACtB,QAAQ;GAER,IACE,SAAS,UACT,UAAU,YAAY,KACtB,UAAU,YAAY,KACrB,iBAAiB,UAAU,SAAS,CAAY,KAAK,KAAK,MAAM,MAAM,CAAC,GAExE,SAAS,WAAW,UAAU;EAClC,OAAO,IAAI,SAAS,KAAK,UAAU,CAAC,OAAO;GACzC,IAAI,SAAS,SAAS,UAAW,KAAkB,KAAK,KAAK,MAAM,MAAM,CAAC;QACrE;IACH,SAAS,WAAW;IACpB,oBAAoB;IACpB,QAAQ;GACV;EACF;CACF;;;;;;;;;CAUA,MAAM,mBAAmB,MAAa,UAA0B;EAC9D,MAAM,YAAY,KAAK;EACvB,IAAI,OAAO,QAAQ;EACnB,OAAO,OAAO,OAAO,QAAQ;GAC3B,IAAI,KAAK,OAAO;GAChB,IAAI,MAAM,WAAW,EAAE,MAAM,SAAS;IACpC;IACA,IAAI,MAAM,WAAW,EAAE,MAAM,SAAS;KACpC;KACA,IAAI,MAAM,WAAW,EAAE,MAAM,SAAS;IACxC;GACF;GACA,IAAI,MAAM,WAAW,EAAE,MAAM,WAAW;EAC1C;EACA,MAAM,OAAO,OAAO;EACpB,IAAI,SAAS,OAAO,OAAO;EAC3B,MAAM,QAAQ,MAAM,MAAM,OAAO,QAAQ,IAAc,KAAK,KAAe;EAC3E,KAAK,QAAQ,GAAG,SAAS,QAAQ,MAAM,QAAQ,cAAc,IAAI,EAAE;EACnE,cAAc,OAAO;EACrB,OAAO;CACT;CAEA,KAAK,IAAI,QAAQ,GAAG,QAAQ,OAAO,SAAS;EAC1C,gBAAgB,MAAM,MAAM,OAAO,QAAkB,KAAK,MAAgB,CAAC;EAE3E,IAAI,IAAI,UAAU,IAAI,WAAW,OAAO,IAAI,gBAAgB,KAAK,OAC/D,QAAQ,gBAAgB,KAAK,KAAK;CACtC;CAEA,OAAO,QAAQ,KAAK,SAAS,KAAK,KAAK;CACvC,SAAS,KAAK,KAAK;CAInB,MAAM,8BAAc,IAAI,IAAmB;CAE3C,MAAM,QAAQ,SAAwB;EACpC,MAAM,MAAc,CAAC;EACrB,KAAK,MAAM,SAAS,KAAK,UACvB,IAAI,MAAM,SAAS,sBAAsB;GACvC,MAAM,MAAM,eAAe,IAAI,MAAM,MAAM,EAAE;GAC7C,IAAI,CAAC,YAAY,IAAI,GAAG,GAAG,YAAY,IAAI,KAAK,KAAK;EACvD,OAAO,IAAI,KAAK,MAAM,KAAK,CAAC;EAE9B,OAAO;CACT;CAEA,MAAM,SAAS,KAAa,OAAgB,WAA0B;EACpE,MAAM,QAAQ,SAAS,GAAG;EAC1B,MAAM,WAAmB,CAAC;EAC1B,KAAK,IAAI,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SACxC,SAAS,KAAK;GACZ,MAAM;GACN;GACA,WAAW,MAAM,UAAU;GAC3B,UAAU,aAAa,MAAM,UAAU,IAAI,OAAO;EACpD,CAAC;EACH,OAAO;GAAE,MAAM;GAAY;EAAS;CACtC;;CAGA,MAAM,SAAS,SAA0B;EACvC,MAAM,OAAO,KAAK,IAAI,KAAK,IAAI,KAAK,SAAS,KAAK,SAAS,GAAG,OAAO,MAAM;EAC3E,MAAM,YAAY,OAAO,OAAO,MAAM;EACtC,MAAM,UAAU,KAAK,OAAO,MAAM,KAAK;EACvC,OAAO;GACL,OAAO;IACL,MAAM,KAAK;IACX,QAAQ,KAAK,eAAe,OAAO,KAAK,YAAY,MAAM,KAAK;IAC/D,QAAQ,KAAK;GACf;GACA,KAAK;IAAE,MAAM;IAAM,QAAQ,SAAS;IAAG,QAAQ,YAAY;GAAO;EACpE;CACF;CAEA,MAAM,SAAS,SAAsB;EACnC,QAAQ,KAAK,MAAb;GACE,KAAK,aACH,OAAO;IACL,MAAM;IACN,UAAU,MAAM,IAAI;IACpB,UAAU,aAAa,KAAK,MAAM,OAAO;GAC3C;GACF,KAAK,WACH,OAAO;IACL,MAAM;IACN,OAAO,KAAK;IACZ,UAAU,MAAM,IAAI;IACpB,UAAU,aAAa,KAAK,MAAM,OAAO;GAC3C;GACF,KAAK,iBACH,OAAO;IAAE,MAAM;IAAiB,UAAU,MAAM,IAAI;GAAE;GACxD,KAAK,QAAQ;IACX,IAAI,KAAK,cAAc,UAAU;KAC/B,MAAM,OAAa;MACjB,MAAM;MACN,UAAU,MAAM,IAAI;MACpB,OAAO,KAAK,KAAK,QAAQ,OAAO,EAAE;KACpC;KACA,IAAI,KAAK,UAAU,IAAI,KAAK,OAAO,KAAK;KACxC,OAAO;IACT;IACA,MAAM,OAAa;KAAE,MAAM;KAAQ,UAAU,MAAM,IAAI;KAAG,OAAO,KAAK;IAAK;IAC3E,IAAI,KAAK,UAAU,IAAI;KACrB,MAAM,QAAQ,KAAK,MAAM,OAAO,OAAO;KACvC,KAAK,OAAO,UAAU,KAAK,KAAK,QAAQ,KAAK,MAAM,MAAM,GAAG,KAAK;KACjE,IAAI,UAAU,IAAI,KAAK,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC,CAAC,CAAC,KAAK;IACjE;IACA,OAAO;GACT;GACA,KAAK,QACH,OAAO;IAAE,MAAM;IAAQ,UAAU,MAAM,IAAI;IAAG,OAAO,KAAK,KAAK,QAAQ,cAAc,EAAE;GAAE;GAC3F,KAAK,SAAS;IACZ,MAAM,QAAQ,KAAK;IACnB,MAAM,OAAO,KAAK;IAClB,OAAO;KACL,MAAM;KACN,UAAU,MAAM,IAAI;KACpB;KACA,UAAU,KAAK,KAAK,KAAK,UAAU,MAAM,KAAK,OAAO,UAAU,CAAC,CAAC;IACnE;GACF;GACA,KAAK,QAAQ;IACX,MAAM,OAAa;KACjB,MAAM;KACN,UAAU,MAAM,IAAI;KACpB,SAAS,KAAK;KACd,QAAQ,CAAC,KAAK;KACd,UAAU,KAAK,IAAI;IACrB;IACA,KAAK,MAAM,QAAQ,KAAK,UAAoB,KAAK,SAAS,CAAC,KAAK;IAChE,IAAI,KAAK,SAAS,KAAK,QAAQ,KAAK;IACpC,OAAO;GACT;GACA,KAAK,QAAQ;IACX,MAAM,OAAa;KAAE,MAAM;KAAY,UAAU,MAAM,IAAI;KAAG,UAAU,CAAC;IAAE;IAC3E,MAAM,QAAQ,KAAK,SAAS;IAC5B,IAAI,OAAO,UAAU,KAAA,KAAa,MAAM,SAAS,aAAa;KAC5D,MAAM,OAAO,aAAa,KAAK,MAAM,IAAI;KACzC,IAAI,SAAS,MAAM;MACjB,KAAK,UAAU,KAAK,OAAO;MAC3B,MAAM,OAAO,MAAM,KAAK,MAAM,KAAK,EAAE,CAAC,SAAS,CAAC;KAClD;IACF;IACA,KAAK,WAAW,KAAK,IAAI;IACzB,OAAO;GACT;GACA,SACE,OAAO;IAAE,MAAM,KAAK;IAAM,UAAU,MAAM,IAAI;IAAG,UAAU,KAAK,IAAI;GAAE;EAC1E;CACF;CAEA,MAAM,OAAa;EAAE,MAAM;EAAQ,UAAU,KAAK,GAAG;CAAE;CAIvD,MAAM,YAAoB,CAAC;CAC3B,KAAK,IAAI,QAAQ,IAAK,SAAS;EAC7B,IAAI;EACJ,IAAI,KAAK;EACT,KAAK,MAAM,QAAQ,QAAQ,aAAa,KAAK,GAAG,IAAI,SAAS,OAAO,MAAM;EAC1E,IAAI,QAAQ,KAAA,GAAW;EACvB,MAAM,OAAO,YAAY,IAAI,GAAG;EAChC,IAAI,SAAS,KAAA,GAAW;EACxB,UAAU,KAAK;GACb,MAAM;GACN,YAAY,eAAe,IAAI,KAAK,MAAM,EAAE,CAAC,CAAC,YAAY;GAC1D,OAAO,KAAK;GACZ,OAAO,QAAQ;GACf,UAAU,MAAM,IAAI;GACpB,UAAU,KAAK,IAAI;EACrB,CAAC;CACH;CACA,KAAK,MAAM,QAAQ,WACjB,KAAK,QAAQ,QAAQ,aAAa,IAAI,eAAe,IAAI,KAAK,MAAM,EAAE,CAAC,KAAK;CAC9E,OAAO;EAAE;EAAM;CAAU;AAC3B"}
@@ -1,4 +1,5 @@
1
1
  import { ENTITY, decodeEntity, isEscapable, normalizeUri, unescapeString } from "./entities.js";
2
+ import { toText } from "./visit.js";
2
3
  // src/engine/inlines.ts
3
4
  /**
4
5
  * The inline pass: the text of one block read into emphasis, links, code spans and the rest, by
@@ -289,6 +290,8 @@ const addBracket = (node, index, image) => {
289
290
  bracketAfter: false
290
291
  };
291
292
  };
293
+ /** How deep the parentheses of a link destination may nest. */
294
+ const MAX_PARENS = 32;
292
295
  /** A link destination at the current place, or null. */
293
296
  const parseLinkDestination = () => {
294
297
  const braced = match(reLinkDestinationBraces);
@@ -302,7 +305,7 @@ const parseLinkDestination = () => {
302
305
  if (code === C_BACKSLASH && isEscapable(subject.charCodeAt(pos + 1))) pos += 2;
303
306
  else if (code === C_OPEN_PAREN) {
304
307
  pos++;
305
- depth++;
308
+ if (++depth > MAX_PARENS) return null;
306
309
  } else if (code === C_CLOSE_PAREN) {
307
310
  if (depth < 1) break;
308
311
  pos++;
@@ -607,10 +610,42 @@ const linkify = (nodes) => {
607
610
  return out ?? nodes;
608
611
  };
609
612
  /**
613
+ * How deep emphasis, links and images may nest. Thousands of `*` around a word are thousands of
614
+ * nodes one inside another, and every pass after this one walks the tree by calling itself: past
615
+ * the limit the rest is kept as its text.
616
+ */
617
+ const MAX_NESTING = 100;
618
+ /** The text under `parent`, read without a call per level. */
619
+ const flat = (parent) => {
620
+ let out = "";
621
+ const open = [];
622
+ let node = parent.first;
623
+ for (;;) if (node === null) {
624
+ const up = open.pop();
625
+ if (up === void 0) return out;
626
+ node = up.next;
627
+ } else if (node.first !== null) {
628
+ open.push(node);
629
+ node = node.first;
630
+ } else {
631
+ if (node.type === "softbreak" || node.type === "break") out += "\n";
632
+ else if (node.type === "node") out += node.node === null ? "" : toText(node.node);
633
+ else out += node.value;
634
+ node = node.next;
635
+ }
636
+ };
637
+ /**
610
638
  * The finished nodes under a parent, with text that ended up side by side joined. `links` is
611
639
  * whether bare addresses in the text become links: not inside a link, which cannot hold another.
612
640
  */
613
- const finish = (parent, links) => {
641
+ const finish = (parent, links, depth = 0) => {
642
+ if (depth >= MAX_NESTING) {
643
+ const value = flat(parent);
644
+ return value === "" ? [] : [{
645
+ type: "text",
646
+ value
647
+ }];
648
+ }
614
649
  const out = [];
615
650
  let last;
616
651
  for (let node = parent.first; node !== null; node = node.next) {
@@ -632,11 +667,11 @@ const finish = (parent, links) => {
632
667
  type: "link",
633
668
  url: node.url,
634
669
  title: node.title,
635
- children: finish(node, false)
670
+ children: finish(node, false, depth + 1)
636
671
  };
637
672
  break;
638
673
  case "image": {
639
- const children = finish(node, false);
674
+ const children = finish(node, false, depth + 1);
640
675
  made = {
641
676
  type: "image",
642
677
  url: node.url,
@@ -650,7 +685,7 @@ const finish = (parent, links) => {
650
685
  case "delete":
651
686
  made = {
652
687
  type: node.type,
653
- children: finish(node, links)
688
+ children: finish(node, links, depth + 1)
654
689
  };
655
690
  break;
656
691
  case "softbreak":