| 1758 | | 1758 | |
| 1759 | // Replace line breaks with <br> in unknown elements | 1759 | // Replace line breaks with <br> in unknown elements |
| 1760 | if (node instanceof HTMLUnknownElement) { | 1760 | if (node instanceof HTMLUnknownElement) { |
| 1761 | node.innerHTML = node.innerHTML.trim().replaceAll('\n', '<br>'); | 1761 | node.innerHTML = node.innerHTML.trim(); |
| | 1762 | |
| | 1763 | /** @type {Text[]} */ |
| | 1764 | const candidates = []; |
| | 1765 | const walker = document.createTreeWalker(node, NodeFilter.SHOW_TEXT); |
| | 1766 | while (walker.nextNode()) { |
| | 1767 | const textNode = /** @type {Text} */ (walker.currentNode); |
| | 1768 | if (!textNode.data.includes('\n')) continue; |
| | 1769 | |
| | 1770 | // Skip if this text node is within a <pre> (any ancestor) |
| | 1771 | if (textNode.parentElement && textNode.parentElement.closest('pre')) continue; |
| | 1772 | |
| | 1773 | candidates.push(textNode); |
| | 1774 | } |
| | 1775 | |
| | 1776 | for (const textNode of candidates) { |
| | 1777 | const parts = textNode.data.split('\n'); |
| | 1778 | const frag = document.createDocumentFragment(); |
| | 1779 | parts.forEach((part, idx) => { |
| | 1780 | if (part.length) { |
| | 1781 | frag.appendChild(document.createTextNode(part)); |
| | 1782 | } |
| | 1783 | if (idx < parts.length - 1) { |
| | 1784 | frag.appendChild(document.createElement('br')); |
| | 1785 | } |
| | 1786 | }); |
| | 1787 | textNode.replaceWith(frag); |
| | 1788 | } |
| 1762 | } | 1789 | } |
| 1763 | | 1790 | |
| 1764 | const isMediaAllowed = isExternalMediaAllowed(); | 1791 | const isMediaAllowed = isExternalMediaAllowed(); |