Fix ordered and unordered list rendering

Replace broken regex-based list wrapping with placeholder approach:
each list item type (OLI/ULI/TDI/TTI) gets a unique tag, then consecutive
runs are wrapped in the correct <ol>/<ul> container. Mixed task + regular
items in the same list work correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-07 00:19:26 -04:00
parent cd83464c5d
commit ccd53dae00
+16 -10
View File
@@ -84,18 +84,24 @@ function parseMarkdown(markdown) {
return '<h' + level + idAttr + '>' + text + '</h' + level + '>'; return '<h' + level + idAttr + '>' + text + '</h' + level + '>';
}); });
// Task lists — must run before general list processing // Lists — tag each item type with a placeholder, then wrap consecutive runs
html = html.replace(/^\s*-\s+\[x\]\s+(.+)$/gim, '<li class="task-item task-done"><span class="task-cb">&#x2611;</span> $1</li>'); html = html.replace(/^\s*\d+\.\s+(.+)$/gm, '%%OLI%%$1');
html = html.replace(/^\s*-\s+\[ \]\s+(.+)$/gm, '<li class="task-item task-todo"><span class="task-cb">&#x2610;</span> $1</li>'); html = html.replace(/^\s*[-*+]\s+\[x\]\s+(.+)$/gim, '%%TDI%%$1');
html = html.replace(/^\s*[-*+]\s+\[ \]\s+(.+)$/gm, '%%TTI%%$1');
html = html.replace(/^\s*[-*+]\s+(.+)$/gm, '%%ULI%%$1');
// Unordered lists (- item or * item) — wrap consecutive <li> in <ul> // Wrap consecutive ordered items in <ol>
html = html.replace(/^\s*[-*]\s+(.+)$/gm, '<li>$1</li>'); html = html.replace(/(%%OLI%%.+(\n%%OLI%%.+)*)/g, function(block) {
html = html.replace(/(<li>(?:(?!<li>|<\/ul>)[\s\S])*<\/li>(?:\n<li>(?:(?!<li>|<\/ul>)[\s\S])*<\/li>)*)/g, '<ul>$1</ul>'); return '<ol>' + block.replace(/%%OLI%%(.+)/g, '<li>$1</li>') + '</ol>';
});
// Ordered lists (1. item) — wrap in <ol> // Wrap consecutive unordered/task items in <ul>
html = html.replace(/(?:^\s*\d+\.\s+.+$\n?)+/gm, function(block) { html = html.replace(/((?:%%(?:ULI|TDI|TTI)%%).+(?:\n(?:%%(?:ULI|TDI|TTI)%%).+)*)/g, function(block) {
const items = block.trim().replace(/^\s*\d+\.\s+(.+)$/gm, '<li>$1</li>'); return '<ul>' + block
return '<ol>' + items + '</ol>'; .replace(/%%ULI%%(.+)/g, '<li>$1</li>')
.replace(/%%TDI%%(.+)/g, '<li class="task-item task-done"><span class="task-cb">&#x2611;</span> $1</li>')
.replace(/%%TTI%%(.+)/g, '<li class="task-item task-todo"><span class="task-cb">&#x2610;</span> $1</li>')
+ '</ul>';
}); });
// Blockquotes (> text) // Blockquotes (> text)