聊天网站文本自动转HTML列表与表格功能实现求助
修复文本转HTML列表/表格的实现方案
原代码存在的核心问题
- 未支持有序列表(包括用户提到的
1. Pizza2. Burgers这种无换行的连续编号文本) - 列表标签判断逻辑错误:用全局查找
<ul>来决定是否开启标签,会把多个独立列表合并成一个 - 表格未识别分隔线行(如
|---|---|),会错误转换成表头或数据单元格 - 未处理无换行的连续列表项
- 普通文本换行处理不够严谨,可能出现多余的
<br>标签
修复后的完整代码
function convertTextToHTML(text) { // 先拆分连在一起的列表项(比如1. Pizza2. Burgers)为独立行 text = text.replace(/(\d+\.\s?[^0-9]+)(?=\d+\.)/g, "$1\n"); text = text.replace(/(\*\s?[^*]+)(?=\*)/g, "$1\n"); const lines = text.split("\n"); let result = ""; let currentListType = null; // 跟踪当前列表类型:'ul' 或 'ol' let isTable = false; let tableHeaders = []; let isTableHeaderSet = false; for (let line of lines) { line = line.trim(); if (!line) { // 处理空行:先关闭当前的列表/表格,再添加换行 if (currentListType) { result += `</${currentListType}>`; currentListType = null; } if (isTable) { result += "</tbody></table>"; isTable = false; tableHeaders = []; isTableHeaderSet = false; } result += "<br>"; continue; } // 处理表格:匹配|开头结尾的行 if (line.startsWith("|") && line.endsWith("|")) { // 先关闭当前的列表 if (currentListType) { result += `</${currentListType}>`; currentListType = null; } const cells = line.split("|").slice(1, -1).map(cell => cell.trim()); // 判断是否是表格分隔线(全由-或:组成) const isSeparator = cells.every(cell => /^[-:]+$/.test(cell)); if (isSeparator) { isTableHeaderSet = true; continue; } isTable = true; if (!isTableHeaderSet && tableHeaders.length === 0) { // 生成表头 tableHeaders = cells.map(cell => `<th>${cell}</th>`); result += "<table border='1'><thead><tr>" + tableHeaders.join("") + "</tr></thead><tbody>"; } else { // 生成数据行 const tableCells = cells.map(cell => `<td>${cell}</td>`); result += "<tr>" + tableCells.join("") + "</tr>"; } } // 处理无序列表:*开头的行 else if (line.startsWith("*")) { // 先关闭当前的表格 if (isTable) { result += "</tbody></table>"; isTable = false; tableHeaders = []; isTableHeaderSet = false; } const content = line.slice(1).trim(); if (!currentListType || currentListType !== 'ul') { // 开启新的无序列表 if (currentListType) result += `</${currentListType}>`; currentListType = 'ul'; result += "<ul>"; } result += `<li>${content}</li>`; } // 处理有序列表:数字+.开头的行 else if (/^\d+\./.test(line)) { // 先关闭当前的表格 if (isTable) { result += "</tbody></table>"; isTable = false; tableHeaders = []; isTableHeaderSet = false; } const content = line.replace(/^\d+\.\s?/, "").trim(); if (!currentListType || currentListType !== 'ol') { // 开启新的有序列表 if (currentListType) result += `</${currentListType}>`; currentListType = 'ol'; result += "<ol>"; } result += `<li>${content}</li>`; } // 处理普通文本 else { // 先关闭当前的列表/表格 if (currentListType) { result += `</${currentListType}>`; currentListType = null; } if (isTable) { result += "</tbody></table>"; isTable = false; tableHeaders = []; isTableHeaderSet = false; } result += `${line}<br>`; } } // 循环结束后关闭未闭合的标签 if (currentListType) result += `</${currentListType}>`; if (isTable) result += "</tbody></table>"; return result; }
关键修复说明
- 拆分连续列表项:用正则把无换行的连续编号文本(如
1. Pizza2. Burgers)拆分成独立行,保证列表项能被正确识别 - 支持有序列表:通过正则匹配
数字+.开头的行,自动生成<ol>标签 - 修复列表逻辑:用
currentListType跟踪当前列表类型,避免多个独立列表被错误合并 - 表格分隔线处理:识别
|---|---|这种分隔线,跳过不转换,同时标记表头已就绪 - 空行处理:遇到空行时自动关闭当前的列表/表格,保证HTML结构正确
- 严谨的标签闭合:循环结束后检查并关闭所有未闭合的标签,避免结构错误
测试示例
输入文本:
今天想吃这些: 1. Pizza2. Burgers 3. Fries * 可乐 * 雪碧 | 食物 | 价格 | |------|------| | Pizza | $10 | | Burger | $8 | 以上就是全部啦!
转换后的HTML片段:
今天想吃这些:<br> <ol> <li>Pizza</li> <li>Burgers</li> <li>Fries</li> </ol> <br> <ul> <li>可乐</li> <li>雪碧</li> </ul> <br> <table border='1'><thead><tr><th>食物</th><th>价格</th></tr></thead><tbody> <tr><td>Pizza</td><td>$10</td></tr> <tr><td>Burger</td><td>$8</td></tr> </tbody></table> <br> 以上就是全部啦!<br>
内容的提问来源于stack exchange,提问作者Erzen Krasniqi
相关产品推荐
相关产品推荐

