Split streaming markdown into memoized blocks for mobile perf (#260)
Instead of re-parsing the entire markdown string on every streaming token, split at paragraph boundaries (double newlines) while keeping code fences intact. Each block renders as its own React.memo'd <Markdown> component so only the last active block re-renders.
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
function getFenceDelimiter(line: string) {
|
||||
const match = /^( {0,3})(`{3,}|~{3,})/.exec(line);
|
||||
return match?.[2] ?? null;
|
||||
}
|
||||
|
||||
export function splitMarkdownBlocks(text: string): string[] {
|
||||
if (text.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const blocks: string[] = [];
|
||||
let currentLines: string[] = [];
|
||||
let activeFenceCharacter: "`" | "~" | null = null;
|
||||
let activeFenceLength = 0;
|
||||
let sawBlockSeparator = false;
|
||||
|
||||
for (const line of text.split("\n")) {
|
||||
const isBlankLine = line.trim().length === 0;
|
||||
|
||||
if (!activeFenceCharacter && isBlankLine) {
|
||||
if (currentLines.length > 0) {
|
||||
sawBlockSeparator = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!activeFenceCharacter && sawBlockSeparator) {
|
||||
blocks.push(currentLines.join("\n"));
|
||||
currentLines = [];
|
||||
sawBlockSeparator = false;
|
||||
}
|
||||
|
||||
currentLines.push(line);
|
||||
|
||||
const fenceDelimiter = getFenceDelimiter(line);
|
||||
if (!fenceDelimiter) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!activeFenceCharacter) {
|
||||
activeFenceCharacter = fenceDelimiter[0] as "`" | "~";
|
||||
activeFenceLength = fenceDelimiter.length;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
fenceDelimiter[0] === activeFenceCharacter &&
|
||||
fenceDelimiter.length >= activeFenceLength
|
||||
) {
|
||||
activeFenceCharacter = null;
|
||||
activeFenceLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentLines.length > 0) {
|
||||
blocks.push(currentLines.join("\n"));
|
||||
}
|
||||
|
||||
return blocks.filter((block) => block.length > 0);
|
||||
}
|
||||
Reference in New Issue
Block a user