import React from "react";
import { cn } from "@/lib/utils";
/**
* 轻量 Markdown 渲染器(无依赖)
* 用于渲染 GitHub Release Notes 这类常见格式:
* 标题、无序/有序列表、引用、代码块、粗体、行内代码、链接、分隔线、段落
*/
function renderInline(text: string, keyPrefix: string): React.ReactNode[] {
const parts: React.ReactNode[] = [];
const regex = /(\*\*[^*]+\*\*|`[^`]+`|\[[^\]]+\]\([^)]+\))/g;
let last = 0;
let m: RegExpExecArray | null;
let i = 0;
while ((m = regex.exec(text)) !== null) {
if (m.index > last) {
parts.push(text.slice(last, m.index));
}
const tok = m[0];
if (tok.startsWith("**")) {
parts.push(
{tok.slice(2, -2)}
);
} else if (tok.startsWith("`")) {
parts.push(
{tok.slice(1, -1)}
);
} else {
const link = tok.match(/^\[([^\]]+)\]\(([^)]+)\)$/);
if (link) {
parts.push(
{link[1]}
);
} else {
parts.push(tok);
}
}
last = m.index + tok.length;
i += 1;
}
if (last < text.length) {
parts.push(text.slice(last));
}
return parts;
}
export function MarkdownLite({
text,
className,
}: {
text: string;
className?: string;
}) {
const lines = text.split(/\r?\n/);
const blocks: React.ReactNode[] = [];
let key = 0;
let inCode = false;
let codeBuf: string[] = [];
const push = (node: React.ReactNode) => {
blocks.push(
{codeBuf.join("\n")}
);
codeBuf = [];
inCode = false;
} else {
inCode = true;
}
continue;
}
if (inCode) {
codeBuf.push(line);
continue;
}
const trimmed = line.trim();
if (!trimmed) continue; // 空行跳过
// 标题
const heading = trimmed.match(/^(#{1,4})\s+(.*)$/);
if (heading) {
const lv = heading[1].length;
const content = renderInline(heading[2], `h${key}`);
const cls = {
1: "text-xl font-bold tracking-tight",
2: "text-lg font-bold tracking-tight",
3: "text-base font-semibold",
4: "text-sm font-semibold",
}[lv as 1 | 2 | 3 | 4];
push({renderInline(trimmed.replace(/^>\s?/, ""), `q${key}`)}); continue; } // 无序列表 const ul = trimmed.match(/^[-*]\s+(.*)$/); if (ul) { push(
{renderInline(trimmed, `p${key}`)}
); } return