@lobehub/ui
Version:
Lobe UI is an open-source UI component library for building AIGC web apps
1 lines • 3.77 kB
Source Map (JSON)
{"version":3,"file":"remarkBr.mjs","names":[],"sources":["../../../src/Markdown/plugins/remarkBr.ts"],"sourcesContent":["import { visit } from 'unist-util-visit';\n\n/**\n * Remark plugin to handle <br> and <br/> tags in markdown text\n * This plugin converts <br> and <br/> tags to proper HTML elements\n * without requiring allowHtml to be enabled\n */\nexport const remarkBr = () => {\n return (tree: any) => {\n // First try to process html nodes that might contain ONLY br tags\n visit(tree, 'html', (node, index, parent) => {\n if (!node.value || typeof node.value !== 'string') return;\n\n // Only handle standalone br tags, not complex HTML containing br tags\n const brRegex = /^\\s*<\\s*br\\s*\\/?>\\s*$/gi;\n if (brRegex.test(node.value)) {\n // Replace the html node with a break node\n parent.children.splice(index, 1, { type: 'break' });\n return index;\n }\n });\n\n // Also process text nodes\n visit(tree, 'text', (node, index = 0, parent) => {\n if (!node.value || typeof node.value !== 'string') return;\n\n // Check if the text contains <br> or <br/> tags\n const brRegex = /<\\s*br\\s*\\/?>/gi;\n\n if (!brRegex.test(node.value)) return;\n\n // Reset regex lastIndex for split operation\n brRegex.lastIndex = 0;\n\n // Split the text by br tags, but keep the matched tags\n const parts: string[] = [];\n const matches: string[] = [];\n let lastIndex = 0;\n let match;\n\n while ((match = brRegex.exec(node.value)) !== null) {\n // Add text before the match\n if (match.index > lastIndex) {\n parts.push(node.value.slice(lastIndex, match.index));\n }\n\n // Store the matched br tag\n matches.push(match[0]);\n lastIndex = match.index + match[0].length;\n }\n\n // Add remaining text after the last match\n if (lastIndex < node.value.length) {\n parts.push(node.value.slice(lastIndex));\n }\n\n // Create new nodes\n const newNodes: any[] = [];\n\n for (const [i, part] of parts.entries()) {\n // Add text node if not empty\n if (part) {\n newNodes.push({\n type: 'text',\n value: part,\n });\n }\n\n // Add br element if we have a corresponding match\n if (i < matches.length) {\n newNodes.push({\n type: 'break',\n });\n }\n }\n\n // Replace the original text node with the new nodes\n if (newNodes.length > 0) {\n parent.children.splice(index, 1, ...newNodes);\n return index + newNodes.length - 1; // Skip the newly added nodes\n }\n });\n };\n};\n"],"mappings":";;;;;;;AAOA,MAAa,iBAAiB;CAC5B,QAAQ,SAAc;EAEpB,MAAM,MAAM,SAAS,MAAM,OAAO,WAAW;GAC3C,IAAI,CAAC,KAAK,SAAS,OAAO,KAAK,UAAU,UAAU;GAInD,IAAI,0BAAQ,KAAK,KAAK,KAAK,GAAG;IAE5B,OAAO,SAAS,OAAO,OAAO,GAAG,EAAE,MAAM,QAAQ,CAAC;IAClD,OAAO;GACT;EACF,CAAC;EAGD,MAAM,MAAM,SAAS,MAAM,QAAQ,GAAG,WAAW;GAC/C,IAAI,CAAC,KAAK,SAAS,OAAO,KAAK,UAAU,UAAU;GAGnD,MAAM,UAAU;GAEhB,IAAI,CAAC,QAAQ,KAAK,KAAK,KAAK,GAAG;GAG/B,QAAQ,YAAY;GAGpB,MAAM,QAAkB,CAAC;GACzB,MAAM,UAAoB,CAAC;GAC3B,IAAI,YAAY;GAChB,IAAI;GAEJ,QAAQ,QAAQ,QAAQ,KAAK,KAAK,KAAK,OAAO,MAAM;IAElD,IAAI,MAAM,QAAQ,WAChB,MAAM,KAAK,KAAK,MAAM,MAAM,WAAW,MAAM,KAAK,CAAC;IAIrD,QAAQ,KAAK,MAAM,EAAE;IACrB,YAAY,MAAM,QAAQ,MAAM,EAAE,CAAC;GACrC;GAGA,IAAI,YAAY,KAAK,MAAM,QACzB,MAAM,KAAK,KAAK,MAAM,MAAM,SAAS,CAAC;GAIxC,MAAM,WAAkB,CAAC;GAEzB,KAAK,MAAM,CAAC,GAAG,SAAS,MAAM,QAAQ,GAAG;IAEvC,IAAI,MACF,SAAS,KAAK;KACZ,MAAM;KACN,OAAO;IACT,CAAC;IAIH,IAAI,IAAI,QAAQ,QACd,SAAS,KAAK,EACZ,MAAM,QACR,CAAC;GAEL;GAGA,IAAI,SAAS,SAAS,GAAG;IACvB,OAAO,SAAS,OAAO,OAAO,GAAG,GAAG,QAAQ;IAC5C,OAAO,QAAQ,SAAS,SAAS;GACnC;EACF,CAAC;CACH;AACF"}