????????在Web開發中,經常需要處理大量的HTML內容,尤其是在展示文章預覽、動態加載內容或限制顯示長度等場景中。直接截斷HTML字符串可能會導致頁面布局混亂、樣式錯誤或標簽不完整等問題。為了安全地截斷HTML內容,我們可以利用jsdom
庫來解析HTML,并構建截斷后的HTML字符串。
1、引入JSDOM庫
????????首先,確保已經安裝了jsdom
庫。如果尚未安裝,可以使用npm(Node.js的包管理器)進行安裝:
npm install jsdom
2、安全截斷HTML內容的策略
安全截斷HTML內容的關鍵在于確保截斷后的HTML依然保持結構的完整性。以下是一個使用jsdom
庫來實現安全截斷HTML內容的策略:
- 使用JSDOM解析HTML:創建一個
JSDOM
實例來解析HTML內容,并獲取到解析后的DOM樹。 - 遍歷DOM樹:從DOM樹的根節點開始,逐個遍歷子節點。
- 處理文本節點:當遇到文本節點時,檢查其長度是否超過最大長度限制。如果超過,則截斷文本并添加省略號;否則,直接添加文本內容。
- 處理元素節點:當遇到元素節點時,首先檢查整個元素(包括其內容)的長度是否超過最大長度限制。如果未超過,則直接添加該元素的outerHTML;如果超過,則需要進一步處理。
- 處理元素節點的內部文本:對于超過長度限制的元素節點,需要遍歷其內部的文本節點,并嘗試截斷文本。由于直接截斷元素可能會導致未關閉的標簽,因此我們只截斷內部的文本內容,并保留元素的開放標簽。
- 返回截斷后的HTML:遍歷完成后,返回截斷后的HTML字符串。
3、具體實現方法
????????下面是使用上述策略實現安全截斷HTML內容的示例代碼:
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