You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

获取带换行的渲染HTML文本及扩展场景的JavaScript解决方案

解决方案:HTML转带格式的文本(支持列表、表格)

我之前刚好处理过类似的需求,既要把渲染后的HTML转换成带正确换行的文本,还要兼容列表、无边框表格这类特殊场景,下面给你分享客户端和服务端两种JavaScript实现方案:

一、客户端浏览器端实现

利用浏览器原生的DOM API,我们可以递归遍历节点,根据元素的标签类型、计算样式来判断是否添加换行,同时处理列表和表格的格式:

function convertHtmlToText(element) {
  let text = '';
  const computedStyle = window.getComputedStyle(element);
  const isBlockElement = ['block', 'flex', 'grid', 'table', 'list-item'].includes(computedStyle.display);

  // 处理块级元素的前置换行(避免顶部多余换行)
  if (isBlockElement && element !== document.body) {
    text += '\n';
  }

  for (const child of element.childNodes) {
    switch (child.nodeType) {
      case Node.TEXT_NODE:
        // 保留文本的有效空格,去除首尾多余空白
        const trimmedText = child.textContent.trim();
        if (trimmedText) {
          text += trimmedText + ' ';
        }
        break;
      case Node.ELEMENT_NODE:
        switch (child.tagName.toLowerCase()) {
          case 'ul':
            // 处理无序列表:每个li前加"  • "
            for (const li of child.children) {
              text += `  • ${convertHtmlToText(li).trim()}\n`;
            }
            break;
          case 'ol':
            // 处理有序列表(可选,按需求调整)
            let index = 1;
            for (const li of child.children) {
              text += `  ${index}. ${convertHtmlToText(li).trim()}\n`;
              index++;
            }
            break;
          case 'table':
            // 处理无边框表格:单元格用空格分隔,每行换行
            for (const tr of child.querySelectorAll('tr')) {
              const cells = Array.from(tr.querySelectorAll('td, th')).map(cell => convertHtmlToText(cell).trim());
              text += cells.join('  ') + '\n';
            }
            break;
          default:
            // 递归处理其他元素
            text += convertHtmlToText(child);
            break;
        }
        break;
    }
  }

  // 处理块级元素的后置换行(避免底部多余换行)
  if (isBlockElement && element !== document.body) {
    text += '\n';
  }

  // 去除多余的连续换行,保留单个分隔
  return text.replace(/\n{2,}/g, '\n').trim();
}

// 使用示例:传入目标元素
const resultText = convertHtmlToText(document.getElementById('target-content'));
console.log(resultText);

这个方案的关键是通过getComputedStyle判断元素是否为块级,避免把内联的div错误添加换行;列表和表格则单独处理格式,保证输出符合要求。

二、服务端Node.js实现

如果需要在服务端处理,可以用jsdom模拟浏览器环境,逻辑和客户端基本一致:

首先安装依赖:

npm install jsdom

然后实现代码:

const { JSDOM } = require('jsdom');

function convertHtmlToText(htmlString) {
  const dom = new JSDOM(htmlString);
  const document = dom.window.document;

  function traverse(element) {
    let text = '';
    const computedStyle = dom.window.getComputedStyle(element);
    const isBlockElement = ['block', 'flex', 'grid', 'table', 'list-item'].includes(computedStyle.display);

    if (isBlockElement && element !== document.body) {
      text += '\n';
    }

    for (const child of element.childNodes) {
      switch (child.nodeType) {
        case Node.TEXT_NODE:
          const trimmedText = child.textContent.trim();
          if (trimmedText) {
            text += trimmedText + ' ';
          }
          break;
        case Node.ELEMENT_NODE:
          switch (child.tagName.toLowerCase()) {
            case 'ul':
              for (const li of child.children) {
                text += `  • ${traverse(li).trim()}\n`;
              }
              break;
            case 'ol':
              let index = 1;
              for (const li of child.children) {
                text += `  ${index}. ${traverse(li).trim()}\n`;
                index++;
              }
              break;
            case 'table':
              for (const tr of child.querySelectorAll('tr')) {
                const cells = Array.from(tr.querySelectorAll('td, th')).map(cell => traverse(cell).trim());
                text += cells.join('  ') + '\n';
              }
              break;
            default:
              text += traverse(child);
              break;
          }
          break;
      }
    }

    if (isBlockElement && element !== document.body) {
      text += '\n';
    }

    return text.replace(/\n{2,}/g, '\n').trim();
  }

  return traverse(document.body);
}

// 使用示例:传入HTML字符串
const html = `
<div style="display: inline">这是内联div,不换行</div>
<div style="display: block">这是块级div,会换行</div>
<ul>
  <li>列表项1</li>
  <li>列表项2</li>
</ul>
<table>
  <tr><th>表头1</th><th>表头2</th></tr>
  <tr><td>内容1</td><td>内容2</td></tr>
</table>
`;

console.log(convertHtmlToText(html));

扩展说明

  • 如果需要处理更复杂的表格(比如合并单元格),可以额外解析rowspan和colspan属性,补充对应数量的空格或占位文本;
  • 对于自定义的块级/内联元素,可以在isBlockElement的判断数组里添加对应的display值;
  • 可以根据需求调整列表的缩进(比如把" • "改成" • ")或表格的单元格分隔符(比如用\t代替空格)。

内容的提问来源于stack exchange,提问作者Etay Liberman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:33:16