import type { ReactNode } from 'react';
/**
* 身份组前后缀用的行内 Markdown:`code`、**粗体**、~~删除线~~、*斜体* / _斜体_、[文字](http(s) 链接)。
* 只生成 React 元素,不接受任何 HTML,链接只允许 http(s),所以别人写的前后缀不会注入脚本或样式。
* 没有闭合的符号按普通文字显示。
*/
const PATTERNS: { re: RegExp; render: (match: RegExpExecArray, key: string) => ReactNode }[] = [
{ re: /`([^`]+)`/y, render: (m, key) => {m[1]} },
{ re: /\*\*(.+?)\*\*(?!\*)/y, render: (m, key) => {parse(m[1]!, key)} },
{ re: /~~(.+?)~~/y, render: (m, key) => {parse(m[1]!, key)} },
{ re: /\*(?!\s)(.+?)\*/y, render: (m, key) => {parse(m[1]!, key)} },
{ re: /\b_(?!\s)(.+?)_\b/y, render: (m, key) => {parse(m[1]!, key)} },
{ re: /\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)/y, render: (m, key) => {parse(m[1]!, key)} },
];
function parse(source: string, prefix: string): ReactNode[] {
const out: ReactNode[] = [];
let plain = ''; let at = 0; let n = 0;
const flush = () => { if (plain) { out.push(plain); plain = ''; } };
while (at < source.length) {
let hit = false;
for (const { re, render } of PATTERNS) {
re.lastIndex = at;
const match = re.exec(source);
if (!match) continue;
flush(); out.push(render(match, `${prefix}.${n++}`)); at += match[0].length; hit = true;
break;
}
if (!hit) { plain += source[at]; at += 1; }
}
flush();
return out;
}
export function InlineMarkdown({ text }: { text: string }) {
return <>{parse(text, 'm')}>;
}