Some checks failed
CI / build-check-test (push) Has been cancelled
Document main/upstream-sync/feature branch strategy, add sync/push scripts, track .pi/agent extensions and webui in git, and disable startup changelog via showChangelogOnStartup. Co-authored-by: Cursor <cursoragent@cursor.com>
68 lines
2.1 KiB
TypeScript
68 lines
2.1 KiB
TypeScript
import hljs from "highlight.js/lib/core";
|
|
import javascript from "highlight.js/lib/languages/javascript";
|
|
import typescript from "highlight.js/lib/languages/typescript";
|
|
import python from "highlight.js/lib/languages/python";
|
|
import bash from "highlight.js/lib/languages/bash";
|
|
import json from "highlight.js/lib/languages/json";
|
|
import markdown from "highlight.js/lib/languages/markdown";
|
|
import css from "highlight.js/lib/languages/css";
|
|
import xml from "highlight.js/lib/languages/xml";
|
|
import { Marked, type Tokens } from "marked";
|
|
import "highlight.js/styles/github.min.css";
|
|
|
|
hljs.registerLanguage("javascript", javascript);
|
|
hljs.registerLanguage("typescript", typescript);
|
|
hljs.registerLanguage("python", python);
|
|
hljs.registerLanguage("bash", bash);
|
|
hljs.registerLanguage("json", json);
|
|
hljs.registerLanguage("markdown", markdown);
|
|
hljs.registerLanguage("css", css);
|
|
hljs.registerLanguage("xml", xml);
|
|
hljs.registerLanguage("html", xml);
|
|
|
|
function escapeMarkdownCode(raw: string): string {
|
|
return String(raw)
|
|
.replace(/&/g, "&")
|
|
.replace(/</g, "<")
|
|
.replace(/>/g, ">")
|
|
.replace(/"/g, """);
|
|
}
|
|
|
|
function renderAssistantCodeBlock(token: Tokens.Code): string {
|
|
const langSlug = (((token.lang || "").match(/^\S+/) || [""])[0]).trim().toLowerCase();
|
|
const codeRaw = String(token.text ?? "").replace(/\n+$/, "");
|
|
const skipHl = !!token.escaped;
|
|
|
|
let innerHtml: string;
|
|
if (skipHl) {
|
|
innerHtml = codeRaw;
|
|
} else {
|
|
try {
|
|
if (langSlug && hljs.getLanguage(langSlug)) {
|
|
innerHtml = hljs.highlight(codeRaw, { language: langSlug }).value;
|
|
} else {
|
|
innerHtml = hljs.highlightAuto(codeRaw).value;
|
|
}
|
|
} catch {
|
|
innerHtml = escapeMarkdownCode(codeRaw);
|
|
}
|
|
}
|
|
|
|
const safeLangSlug = /^[a-z][a-z0-9_-]*$/i.test(langSlug) ? langSlug : "";
|
|
const codeClass = safeLangSlug ? `hljs language-${safeLangSlug}` : "hljs";
|
|
return `<pre class="assistant-pre"><code class="${codeClass}">${innerHtml}</code></pre>\n`;
|
|
}
|
|
|
|
const marked = new Marked({
|
|
breaks: true,
|
|
gfm: true,
|
|
renderer: {
|
|
code: renderAssistantCodeBlock,
|
|
},
|
|
});
|
|
|
|
export function renderMarkdown(text: string): string {
|
|
if (!text) return "";
|
|
return marked.parse(text) as string;
|
|
}
|