import type { Definition, Root, RootContent } from 'mdast' import { fromMarkdown } from 'mdast-util-from-markdown' import { gfmFromMarkdown } from 'mdast-util-gfm' import { gfm } from 'micromark-extension-gfm' // An answer's Markdown read into a tree, which the chat draws as React elements, never as HTML, the // way the markdown plugin draws a document: GitHub-flavored, links https only, HTML as its text // except
. Pure, so the reading can be checked in a test. /** A
models put in a table cell, or anywhere, for a line break. */ const LINE_BREAK = /^$/i export function parseMarkdown(source: string): Root { return fromMarkdown(source, { extensions: [gfm()], mdastExtensions: [gfmFromMarkdown()] }) } /** The address a link opens, or null: main opens https links only, so nothing else is a link here. */ export function linkHref(url: string): string | null { try { return new URL(url).protocol === 'https:' ? url : null } catch { return null } } export function isLineBreak(html: string): boolean { return LINE_BREAK.test(html) } /** The definitions reference links point at, by the label mdast gives both, wherever they sit. */ export function definitionsOf(tree: Root): Map { const found = new Map() const visit = (nodes: RootContent[]): void => { for (const node of nodes) { if (node.type === 'definition') { if (!found.has(node.identifier)) found.set(node.identifier, node) } else if ('children' in node) visit(node.children) } } visit(tree.children) return found }