使用JSDOM安全截断文章HTML内容

在Web开发中,经常需要处理大量的HTML内容,尤其是在展示文章预览、动态加载内容或限制显示长度等场景中。直接截断HTML字符串可能会导致页面布局混乱、样式错误或标签不完整等问题。为了安全地截断HTML内容,我们可以利用jsdom库来解析HTML,并构建截断后的HTML字符串。

1、引入JSDOM库

首先,确保已经安装了jsdom库。如果尚未安装,可以使用npm(Node.js的包管理器)进行安装:

bash 复制代码
npm install jsdom

2、安全截断HTML内容的策略

安全截断HTML内容的关键在于确保截断后的HTML依然保持结构的完整性。以下是一个使用jsdom库来实现安全截断HTML内容的策略:

  1. 使用JSDOM解析HTML :创建一个JSDOM实例来解析HTML内容,并获取到解析后的DOM树。
  2. 遍历DOM树:从DOM树的根节点开始,逐个遍历子节点。
  3. 处理文本节点:当遇到文本节点时,检查其长度是否超过最大长度限制。如果超过,则截断文本并添加省略号;否则,直接添加文本内容。
  4. 处理元素节点:当遇到元素节点时,首先检查整个元素(包括其内容)的长度是否超过最大长度限制。如果未超过,则直接添加该元素的outerHTML;如果超过,则需要进一步处理。
  5. 处理元素节点的内部文本:对于超过长度限制的元素节点,需要遍历其内部的文本节点,并尝试截断文本。由于直接截断元素可能会导致未关闭的标签,因此我们只截断内部的文本内容,并保留元素的开放标签。
  6. 返回截断后的HTML:遍历完成后,返回截断后的HTML字符串。

3、具体实现方法

下面是使用上述策略实现安全截断HTML内容的示例代码:

javascript 复制代码
const { JSDOM } = require('jsdom');  
  
function truncateHtml(html, maxLength) {  
  // 创建一个包含传入HTML的完整文档  
  const dom = new JSDOM(`<!DOCTYPE html><html><head></head><body>${html}</body></html>`);  
  const { document } = dom.window;  
    
  let totalLength = 0;  
  let truncatedHtml = '';  
  let currentNode = document.body.firstChild;  
    
  // 遍历DOM树  
  while (currentNode) {  
    if (currentNode.nodeType === Node.TEXT_NODE) { // 文本节点  
      const textContent = currentNode.textContent;  
      const remainingLength = maxLength - totalLength;  
  
      if (textContent.length > remainingLength) {  
        // 截断文本并添加省略号  
        truncatedHtml += textContent.substring(0, remainingLength) + '...';  
        break;  
      } else {  
        truncatedHtml += textContent;  
        totalLength += textContent.length;  
      }  
    } else if (currentNode.nodeType === Node.ELEMENT_NODE) { // 元素节点  
      // 检查整个元素(包括内容)的长度  
      const elementHtml = currentNode.outerHTML;  
      if (totalLength + elementHtml.length <= maxLength) {  
        truncatedHtml += elementHtml;  
        totalLength += elementHtml.length;  
      } else {  
        // 如果超过长度限制,则截断元素内的文本节点  
        const clone = currentNode.cloneNode(false); // 不复制子节点  
        truncatedHtml += '<' + clone.nodeName + '>'; // 添加开放标签  
          
        // 遍历子节点并尝试截断文本  
        for (let child of currentNode.childNodes) {  
          if (child.nodeType === Node.TEXT_NODE) {  
            const textClone = child.cloneNode(true); // 复制文本节点  
            const textContent = textClone.textContent;  
            const textLength = textContent.length;  
            if (totalLength + textLength <= maxLength) {  
              truncatedHtml += textContent;  
              totalLength += textLength;  
            } else {  
              truncatedHtml += textContent.substring(0, maxLength - totalLength) + '...';  
              break;  
            }  
          }  
        }  
          
        // 跳出循环,因为已经处理了超过长度的元素  
        break;  
      }  
    }  
      
    currentNode = currentNode.nextSibling;  
  }  
    
  // 返回截断后的HTML  
  return truncatedHtml;  
}  
  
// 使用示例  
const pageContent = '<p>这是一篇<b>很长</b>的文章,包含<a href="#">多个</a>HTML<br>标签。</p>';  
const truncatedContent = truncateHtml(pageContent, 50);  
console.log
相关推荐
m0_748247551 小时前
Web 应用项目开发全流程解析与实战经验分享
开发语言·前端·php
m0_748255022 小时前
前端常用算法集合
前端·算法
真的很上进2 小时前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
web130933203982 小时前
vue elementUI form组件动态添加el-form-item并且动态添加rules必填项校验方法
前端·vue.js·elementui
NiNg_1_2343 小时前
Echarts连接数据库,实时绘制图表详解
前端·数据库·echarts
如若1233 小时前
对文件内的文件名生成目录,方便查阅
java·前端·python
滚雪球~4 小时前
npm error code ETIMEDOUT
前端·npm·node.js
沙漏无语4 小时前
npm : 无法加载文件 D:\Nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js
supermapsupport4 小时前
iClient3D for Cesium在Vue中快速实现场景卷帘
前端·vue.js·3d·cesium·supermap
brrdg_sefg4 小时前
WEB 漏洞 - 文件包含漏洞深度解析
前端·网络·安全