import emojifyText from './emojify-text'; const fauxDiv = document.createElement('div'); function enhanceContent(content, opts = {}) { const { emojis, postEnhanceDOM = () => {} } = opts; let enhancedContent = content; const dom = document.createElement('div'); dom.innerHTML = enhancedContent; // Add target="_blank" to all links with no target="_blank" // E.g. `note` in `account` const links = Array.from(dom.querySelectorAll('a:not([target="_blank"])')); links.forEach((link) => { link.setAttribute('target', '_blank'); }); // EMOJIS // ====== // Convert :shortcode: to let textNodes = extractTextNodes(dom); textNodes.forEach((node) => { let html = node.nodeValue; if (emojis) { html = emojifyText(html, emojis); } fauxDiv.innerHTML = html; const nodes = Array.from(fauxDiv.childNodes); node.replaceWith(...nodes); }); // INLINE CODE // =========== // Convert `code` to code textNodes = extractTextNodes(dom); textNodes.forEach((node) => { let html = node.nodeValue; if (/`[^`]+`/g.test(html)) { html = html.replaceAll(/(`[^]+?`)/g, '$1'); } fauxDiv.innerHTML = html; const nodes = Array.from(fauxDiv.childNodes); node.replaceWith(...nodes); }); // CODE BLOCKS // =========== // Convert ```code``` to
code
const blocks = Array.from(dom.querySelectorAll('p')).filter((p) => /^```[^]+```$/g.test(p.innerText.trim()), ); blocks.forEach((block) => { const pre = document.createElement('pre'); // Replace
with newlines block.querySelectorAll('br').forEach((br) => br.replaceWith('\n')); pre.innerHTML = `${block.innerText.trim()}`; block.replaceWith(pre); }); if (postEnhanceDOM) { postEnhanceDOM(dom); // mutate dom } enhancedContent = dom.innerHTML; return enhancedContent; } function extractTextNodes(dom) { const textNodes = []; const walk = document.createTreeWalker( dom, NodeFilter.SHOW_TEXT, null, false, ); let node; while ((node = walk.nextNode())) { textNodes.push(node); } return textNodes; } export default enhanceContent;