995b752e70
Per-domain thinking trees were interleaved with sliced analysis, so a finished reply still looked like unfinished checklists. One collapsed thinking panel and one full body restores the reading order. Co-authored-by: Cursor <cursoragent@cursor.com>
55 lines
1.8 KiB
TypeScript
55 lines
1.8 KiB
TypeScript
const FENCE = /(```[\s\S]*?```)/;
|
||
const DEFINITION_LINE = /^(.{2,80}?)[::](.+)$/u;
|
||
|
||
function isSkippableLine(line: string): boolean {
|
||
return /^(#{1,6}\s|>\s|[-*+]\s|\d+[.)]\s|\|)/.test(line) || line.startsWith("```");
|
||
}
|
||
|
||
function isDefinitionLine(block: string): boolean {
|
||
const trimmed = block.trim();
|
||
if (!trimmed || trimmed.includes("\n") || isSkippableLine(trimmed)) return false;
|
||
const match = DEFINITION_LINE.exec(trimmed);
|
||
if (!match) return false;
|
||
const body = match[2]?.trim() ?? "";
|
||
return body.length >= 4;
|
||
}
|
||
|
||
function toListItem(block: string): string {
|
||
const trimmed = block.trim();
|
||
const match = DEFINITION_LINE.exec(trimmed);
|
||
if (!match) return trimmed;
|
||
return `- **${match[1].trim()}**:${match[2].trim()}`;
|
||
}
|
||
|
||
function promoteProse(text: string): string {
|
||
const blocks = text.split(/\n{2,}/);
|
||
const out: string[] = [];
|
||
let index = 0;
|
||
while (index < blocks.length) {
|
||
if (isDefinitionLine(blocks[index] ?? "")) {
|
||
let end = index;
|
||
while (end < blocks.length && isDefinitionLine(blocks[end] ?? "")) end += 1;
|
||
if (end - index >= 2) {
|
||
out.push(blocks.slice(index, end).map((block) => toListItem(block)).join("\n"));
|
||
index = end;
|
||
continue;
|
||
}
|
||
}
|
||
const lines = (blocks[index] ?? "").split("\n").map((line) => line.trim()).filter(Boolean);
|
||
if (lines.length >= 2 && lines.every(isDefinitionLine)) {
|
||
out.push(lines.map((line) => toListItem(line)).join("\n"));
|
||
} else {
|
||
out.push(blocks[index] ?? "");
|
||
}
|
||
index += 1;
|
||
}
|
||
return out.join("\n\n");
|
||
}
|
||
|
||
export function promoteDefinitionLists(text: string): string {
|
||
if (!text.includes(":") && !text.includes(":")) return text;
|
||
return text.split(FENCE).map((chunk, index) => (
|
||
index % 2 === 1 ? chunk : promoteProse(chunk)
|
||
)).join("");
|
||
}
|