fix: stabilize markdown code block selection and copy

This commit is contained in:
JOJO 2026-04-12 19:59:28 +08:00
parent 49bd994cfa
commit 78df2249cf

View File

@ -5,6 +5,18 @@ import renderMathInElement from 'katex/contrib/auto-render';
let latexRenderTimer: number | null = null;
const markdownCache = new Map<string, string>();
function stableHash(input: string): string {
let hash = 5381;
for (let i = 0; i < input.length; i += 1) {
hash = (hash * 33) ^ input.charCodeAt(i);
}
return (hash >>> 0).toString(36);
}
function buildCacheKey(text: string): string {
return `md_${text.length}_${stableHash(text)}`;
}
function wrapCodeBlocks(html: string, isStreaming = false) {
if (isStreaming) {
return html;
@ -16,7 +28,7 @@ function wrapCodeBlocks(html: string, isStreaming = false) {
(match, attributes, content) => {
const langMatch = attributes.match(/class="[^"]*language-(\w+)/);
const language = langMatch ? langMatch[1] : 'text';
const blockId = `code-${Date.now()}-${counter++}`;
const blockId = `code-${stableHash(`${attributes}|${content}|${counter++}`)}`;
const escapedContent = content
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
@ -50,7 +62,7 @@ export function renderMarkdown(text: string, isStreaming = false) {
});
if (!isStreaming) {
const cacheKey = `${text.length}_${text.substring(0, 100)}`;
const cacheKey = buildCacheKey(text);
if (markdownCache.has(cacheKey)) {
return markdownCache.get(cacheKey) as string;
}
@ -61,7 +73,7 @@ export function renderMarkdown(text: string, isStreaming = false) {
html = wrapCodeBlocks(html, isStreaming);
if (!isStreaming && text.length < 10000) {
const cacheKey = `${text.length}_${text.substring(0, 100)}`;
const cacheKey = buildCacheKey(text);
markdownCache.set(cacheKey, html);
if (markdownCache.size > 20) {
const firstKey = markdownCache.keys().next().value as string | undefined;