convert($text); } catch (CommonMarkException) { return ""; } } // 创建DOM文档 $dom = new DOMDocument('1.0', 'UTF-8'); libxml_use_internal_errors(true); $dom->loadHTML(mb_convert_encoding($text, 'HTML-ENTITIES', 'UTF-8')); libxml_clear_errors(); // 获取body元素 $body = $dom->getElementsByTagName('body')->item(0); $truncatedHtml = ''; $currentLength = 0; // 递归函数来遍历节点并截取内容 self::traverseNodes($body, $currentLength, $length, $truncatedHtml); // 如果是Markdown,转换回Markdown及还原特殊标记 if ($isMd) { // 转换回Markdown try { $converter = new HtmlConverter(); $truncatedHtml = $converter->convert($truncatedHtml); } catch (\Exception) { return ""; } // 还原特殊标记 if (!empty($placeholders)) { $truncatedHtml = preg_replace('/@P?H?:*\s*$/', '', $truncatedHtml); $preCount = substr_count($truncatedHtml, '@PH::'); $sufCount = substr_count($truncatedHtml, '::PH@'); $diffCount = $preCount - $sufCount; if ($diffCount > 0) { $truncatedHtml .= str_repeat('::PH@', $diffCount); } $truncatedHtml = strtr($truncatedHtml, $placeholders); } } return $truncatedHtml; } /** * 递归遍历节点 * @param $node * @param $currentLength * @param $length * @param $truncatedHtml * @return void */ private static function traverseNodes($node, &$currentLength, $length, &$truncatedHtml) { foreach ($node->childNodes as $child) { if ($currentLength >= $length) { break; } if ($child->nodeType === XML_TEXT_NODE) { $textContent = $child->textContent; $remainingLength = $length - $currentLength; if (mb_strlen($textContent) > $remainingLength) { $truncatedHtml .= htmlspecialchars(mb_substr($textContent, 0, $remainingLength) . '...'); $currentLength += $remainingLength; } else { $truncatedHtml .= htmlspecialchars($textContent); $currentLength += mb_strlen($textContent); } } elseif ($child->nodeType === XML_ELEMENT_NODE) { $truncatedHtml .= '<' . $child->nodeName; // 添加属性 if ($child->hasAttributes()) { foreach ($child->attributes as $attr) { $truncatedHtml .= ' ' . $attr->nodeName . '="' . htmlspecialchars($attr->nodeValue) . '"'; } } $truncatedHtml .= '>'; self::traverseNodes($child, $currentLength, $length, $truncatedHtml); if ($currentLength < $length || $child->firstChild) { $truncatedHtml .= 'nodeName . '>'; } } } } }