78 lines
2.6 KiB
TypeScript
78 lines
2.6 KiB
TypeScript
import type { Root, RootContent } from "hast";
|
|
import { dom, styling, text, type Class, type Node, type RedrawableHTML } from "#shared/dom.util";
|
|
import prose, { a, blockquote, tag, h1, h2, h3, h4, h5, hr, li, small, table, td, th, callout, type Prose } from "#shared/proses";
|
|
import { heading } from "hast-util-heading";
|
|
import { headingRank } from "hast-util-heading-rank";
|
|
import { parseId } from "#shared/general.util";
|
|
import { async } from "#shared/components.util";
|
|
|
|
export function renderMarkdown(markdown: Root, proses: Record<string, Prose>)
|
|
{
|
|
return dom('div', {}, markdown.children.map(e => renderContent(e, proses)));
|
|
}
|
|
export function renderMDAsText(markdown: string): string
|
|
{
|
|
return useMarkdown().text(markdown);
|
|
}
|
|
|
|
function renderContent(node: RootContent, proses: Record<string, Prose>): Node
|
|
{
|
|
if(node.type === 'text' && node.value.length > 0 && node.value !== '\n')
|
|
{
|
|
return text(node.value);
|
|
}
|
|
else if(node.type === 'comment' && node.value.length > 0 && node.value !== '\n')
|
|
{
|
|
return undefined;
|
|
}
|
|
else if(node.type === 'element')
|
|
{
|
|
const children = node.children.map(e => renderContent(e, proses)), properties = { ...node.properties, class: node.properties.className as string | string[] };
|
|
if(node.tagName in proses)
|
|
return prose(node.tagName, proses[node.tagName] ?? { class: '' }, children, properties);
|
|
else
|
|
return dom(node.tagName as keyof HTMLElementTagNameMap, properties, children);
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
export interface MDProperties
|
|
{
|
|
class?: Class;
|
|
style?: string | Record<string, string>;
|
|
tags?: Record<string, Prose>;
|
|
}
|
|
export function markdownReference(content: string, filter?: string, properties?: MDProperties)
|
|
{
|
|
const state = async('large', useMarkdown().parse(content).then(data => {
|
|
if(filter)
|
|
{
|
|
const start = data?.children.findIndex(e => heading(e) && parseId(e.properties.id as string | undefined) === filter) ?? -1;
|
|
|
|
if(start !== -1)
|
|
{
|
|
let end = start;
|
|
const rank = headingRank(data.children[start]!)!;
|
|
while(end < data.children.length)
|
|
{
|
|
end++;
|
|
if(heading(data.children[end]) && headingRank(data.children[end]!)! <= rank)
|
|
break;
|
|
}
|
|
data = { ...data, children: data.children.slice(start, end) };
|
|
}
|
|
}
|
|
|
|
const el = renderMarkdown(data, Object.assign({}, { a, blockquote, tag, callout, h1, h2, h3, h4, h5, hr, li, small, table, td, th }, properties?.tags));
|
|
|
|
if(properties) styling(el, properties);
|
|
|
|
return el;
|
|
}));
|
|
return state;
|
|
}
|
|
export default function(content: string, filter?: string, properties?: MDProperties)
|
|
{
|
|
return markdownReference(content, filter, properties).current;
|
|
} |