codemirror-languageservice
Version:
Integrate a Language Server Protocol compatible language service into CodeMirror
94 lines (86 loc) • 2.39 kB
text/typescript
import { type MarkedString, type MarkupContent } from 'vscode-languageserver-protocol'
import { type Promisable } from './types.js'
/**
* Process markdown into a DOM.
*
* @param parent
* The container DOM element to append the DOM nodes to.
* @param markdown
* The markdown to process.
* @param options
* Additional options.
*/
async function processMarkdown(
parent: ParentNode,
markdown: string,
options: fromMarkupContent.Options
): Promise<undefined> {
if (!markdown) {
return
}
const nodes = await options.markdownToDom(markdown)
if (!nodes) {
return
}
if (typeof nodes !== 'string' && Symbol.iterator in nodes) {
parent.append(...nodes)
} else {
parent.append(nodes)
}
}
export declare namespace fromMarkupContent {
interface Options {
/**
* Convert a markdown string to DOM.
*
* @param markdown
* The markdown to convert
* @returns
* DOM nodes or text to append to the resulting DOM container.
*/
markdownToDom: (
markdown: string
) => Promisable<Iterable<Node | string> | Node | null | string | undefined | void>
}
}
/**
* Convert LSP markup content or a marked string into a DOM.
*
* @param contents
* The LSP contents to process.
* @param parent
* The container node to append the DOM nodes to.
* @param options
* Additional options.
* @returns
* The parent container.
*/
export async function fromMarkupContent<Parent extends ParentNode>(
contents: MarkedString | MarkedString[] | MarkupContent,
parent: Parent,
options: fromMarkupContent.Options
): Promise<Parent> {
if (Array.isArray(contents)) {
for (const content of contents) {
await fromMarkupContent(content, parent, options)
}
} else if (typeof contents === 'string') {
await processMarkdown(parent, contents, options)
} else if ('kind' in contents) {
if (contents.kind === 'markdown') {
await processMarkdown(parent, contents.value, options)
} else {
const paragraph = document.createElement('p')
paragraph.append(contents.value)
parent.append(paragraph)
}
} else {
const pre = document.createElement('pre')
const code = document.createElement('code')
code.classList.add(`language-${contents.language}`)
code.append(contents.value)
pre.append(code)
parent.append(pre)
}
return parent
}