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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 11:02:55