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
}