* Manual post-processing for Node.js environments (without DOM) * @param {string} html - HTML to post-process * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided) * @returns {string} Post-processed HTML
(html, instanceHighlighter)
| 711 | * @returns {string} Post-processed HTML |
| 712 | */ |
| 713 | static postProcessHTMLManual(html, instanceHighlighter) { |
| 714 | let processed = html; |
| 715 | |
| 716 | // Process unordered lists |
| 717 | processed = processed.replace(/((?:<div>(?: )*<li class="bullet-list">.*?<\/li><\/div>\s*)+)/gs, (match) => { |
| 718 | const divs = match.match(/<div>(?: )*<li class="bullet-list">.*?<\/li><\/div>/gs) || []; |
| 719 | if (divs.length > 0) { |
| 720 | const items = divs.map(div => { |
| 721 | // Extract indentation and list item |
| 722 | const indentMatch = div.match(/<div>((?: )*)<li/); |
| 723 | const listItemMatch = div.match(/<li class="bullet-list">.*?<\/li>/); |
| 724 | |
| 725 | if (indentMatch && listItemMatch) { |
| 726 | const indentation = indentMatch[1]; |
| 727 | const listItem = listItemMatch[0]; |
| 728 | // Insert indentation at the start of the list item content |
| 729 | return listItem.replace(/<li class="bullet-list">/, `<li class="bullet-list">${indentation}`); |
| 730 | } |
| 731 | return listItemMatch ? listItemMatch[0] : ''; |
| 732 | }).filter(Boolean); |
| 733 | |
| 734 | return '<ul>' + items.join('') + '</ul>'; |
| 735 | } |
| 736 | return match; |
| 737 | }); |
| 738 | |
| 739 | // Process ordered lists |
| 740 | processed = processed.replace(/((?:<div>(?: )*<li class="ordered-list">.*?<\/li><\/div>\s*)+)/gs, (match) => { |
| 741 | const divs = match.match(/<div>(?: )*<li class="ordered-list">.*?<\/li><\/div>/gs) || []; |
| 742 | if (divs.length > 0) { |
| 743 | const items = divs.map(div => { |
| 744 | // Extract indentation and list item |
| 745 | const indentMatch = div.match(/<div>((?: )*)<li/); |
| 746 | const listItemMatch = div.match(/<li class="ordered-list">.*?<\/li>/); |
| 747 | |
| 748 | if (indentMatch && listItemMatch) { |
| 749 | const indentation = indentMatch[1]; |
| 750 | const listItem = listItemMatch[0]; |
| 751 | // Insert indentation at the start of the list item content |
| 752 | return listItem.replace(/<li class="ordered-list">/, `<li class="ordered-list">${indentation}`); |
| 753 | } |
| 754 | return listItemMatch ? listItemMatch[0] : ''; |
| 755 | }).filter(Boolean); |
| 756 | |
| 757 | return '<ol>' + items.join('') + '</ol>'; |
| 758 | } |
| 759 | return match; |
| 760 | }); |
| 761 | |
| 762 | // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code |
| 763 | const codeBlockRegex = /<div><span class="code-fence">(```[^<]*)<\/span><\/div>(.*?)<div><span class="code-fence">(```)<\/span><\/div>/gs; |
| 764 | processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => { |
| 765 | // Extract the content between fences |
| 766 | const lines = content.match(/<div>(.*?)<\/div>/gs) || []; |
| 767 | const codeContent = lines.map(line => { |
| 768 | // Extract text from each div - content is already escaped |
| 769 | const text = line.replace(/<div>(.*?)<\/div>/s, '$1') |
| 770 | .replace(/ /g, ' '); |