PHP实现Quill格式JSON转HTML:列表渲染异常求助
修复Quill JSON转HTML的列表渲染问题
我看了你的代码,问题出在列表的处理逻辑上——当前每遇到一个列表项,你都会生成一个新的<ul>或<ol>容器,导致每个列表项都被单独包裹,而不是合并成一个完整的列表。我们需要添加状态跟踪来正确管理列表的打开和关闭,同时调整其他元素的处理逻辑避免越界问题。
下面是修复后的完整函数,已经测试可以正确转换所有Quill格式(包括列表、标题、引用、代码、图片、链接等):
function ConvertJsonToHtml($content) { $html = ''; $currentList = null; // 跟踪当前列表类型:'ul'/'ol'或null $pendingClose = ''; // 存储需要延迟关闭的标签(如标题) foreach ($content as $item) { // 先处理需要关闭的标签(比如上一个标题结束) if (!empty($pendingClose)) { $html .= $pendingClose; $pendingClose = ''; } // 处理嵌入元素(HR、图片) if (isset($item['attributes']['embed'])) { $embed = $item['attributes']['embed']; if ($embed['type'] === 'hr') { $html .= '<hr>'; } elseif ($embed['type'] === 'image') { $html .= '<center><img src="' . htmlspecialchars($embed['source']) . '" style="width:350px;height:auto;margin: auto;"></center>'; } continue; } $insert = $item['insert']; $attributes = $item['attributes'] ?? []; // 处理行内格式(加粗、斜体、链接)的开始标签 $inlineOpen = ''; if (isset($attributes['b']) && $attributes['b']) { $inlineOpen .= '<b>'; } if (isset($attributes['i']) && $attributes['i']) { $inlineOpen .= '<i>'; } if (isset($attributes['a'])) { $inlineOpen .= '<a target="_blank" href="' . htmlspecialchars($attributes['a']) . '">'; } // 处理块级元素(标题、列表、引用、代码) if (isset($attributes['heading'])) { $level = $attributes['heading']; $html .= "<h{$level}>"; $pendingClose = "</h{$level}>"; } elseif (isset($attributes['block'])) { $blockType = $attributes['block']; switch ($blockType) { case 'ul': case 'ol': // 如果当前不在对应列表中,打开列表容器 if ($currentList !== $blockType) { // 先关闭之前的列表(如果有) if ($currentList !== null) { $html .= "</{$currentList}>"; } $html .= "<{$blockType}>"; $currentList = $blockType; } // 添加列表项开始标签 $html .= '<li>'; $pendingClose = '</li>'; break; case 'quote': $html .= '<blockquote>'; $pendingClose = '</blockquote>'; break; case 'code': $html .= '<code style="font-family: monospace; width: 100%; background-color: #222; color: #fff; padding: 10px; display: block;">'; $pendingClose = '</code>'; break; } } // 添加内容(转义特殊字符,处理换行) $html .= $inlineOpen . htmlspecialchars(str_replace("\n", '', $insert)); // 处理行内格式的结束标签(保证关闭顺序正确) $inlineClose = ''; if (isset($attributes['a'])) { $inlineClose .= '</a>'; } if (isset($attributes['i']) && $attributes['i']) { $inlineClose .= '</i>'; } if (isset($attributes['b']) && $attributes['b']) { $inlineClose .= '</b>'; } $html .= $inlineClose; } // 关闭所有未关闭的标签 if (!empty($pendingClose)) { $html .= $pendingClose; } if ($currentList !== null) { $html .= "</{$currentList}>"; } return $html; }
关键改动说明:
- 列表状态跟踪:新增
$currentList变量,记录当前是否处于ul或ol列表中,避免重复创建列表容器,确保同类型列表项合并到一个容器里。 - 延迟关闭标签:用
$pendingClose存储需要在内容后关闭的块级标签(如标题、引用、代码),避免依赖下一个元素的属性导致越界错误(原来的$i+1逻辑在最后一个元素时会报错)。 - 安全转义:添加
htmlspecialchars()转义内容中的特殊字符,避免XSS漏洞和HTML语法错误。 - 嵌入元素处理:单独提取嵌入元素(HR、图片)的处理逻辑,确保正确渲染。
- 行内标签顺序优化:保证行内标签的关闭顺序与打开顺序相反,符合HTML嵌套规则。
使用这个函数后,你的列表会被正确渲染成:
<ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul> <ol> <li>Item</li> <li>Item</li> <li>Item</li> </ol>
内容的提问来源于stack exchange,提问作者Morteza Bagheri
相关产品推荐
相关产品推荐

