AI摘要
文章讨论了Typecho平台中AISummary和Panorama两个插件的冲突问题。核心问题是两个插件都使用了Widget_Abstract_Contents::contentEx钩子,导致后加载的插件覆盖了前一个插件的处理结果。文章提出了修改AISummary插件的customContent方法,以支持钩子链式调用,从而解决两个插件的冲突问题。具体修改包括添加$lastResult参数,优先使用上一个插件的处理结果,保持返回逻辑,以实现两个插件处理逻辑的叠加执行。

测试了插件后,发现文字的短代码会转换成 <p> 标签,无法适配。

首先考虑是 其他插件的原因,经过排查发现是:AISummary 插件。

两个插件冲突的核心原因是:都使用了 Widget_Abstract_Contents::contentEx 钩子,且后加载的插件会覆盖前一个插件的处理结果(Typecho 钩子默认按插件激活顺序执行,后执行的插件如果直接返回内容,会忽略前一个插件的处理)。

问题所在

AISummary 插件的 customContent 方法处理完摘要后直接返回内容,没有传递给下一个插件。Panorama 插件的 parse 方法虽然判断了 $lastResult ,但如果 AISummary 先执行,会导致 Panorama 无法获取原始内容进行短代码解析。

解决方案

修改 AISummary 插件的 customContent 方法,支持钩子链式调用

需要让 AISummary 插件处理完后,将结果传递给下一个插件(Panorama),而不是直接返回。

找到 AISummary 插件下的 Plugin.php 中的:

    public static function customContent($content, $widget)
    {
        $options = Typecho_Widget::widget('Widget_Options')->plugin('AISummary');
        // 不启用的话直接 return
        if ($options->summaryStyle === '0') return $content;
        // 获取用户自定义的字段
        $summaryField = $options->field;
        $customSummary = $widget->fields->$summaryField;
        if (empty($customSummary)) return $content;
        $pureSummary = str_replace("{{text}}", $customSummary, $options->prefix);
        if ($options->summaryStyle === '1') {
            $summaryString = '<blockquote class="aisummary">' . $pureSummary . "</blockquote>";
            $content = $summaryString . $content;
        } else if ($options->summaryStyle === '2') {
            $summaryString = '<div class="aisummary">' . $pureSummary . "</div>";
            $content = $summaryString . $content;
        }

        // 废弃方案:使用 markdown 添加文本
        // $markdownTag = "<!--markdown-->";
        // Check if the content starts with the markdown tag
        // if (strpos($content, $markdownTag) === 0) {
        // Create the summary string
        // $summaryString = "> " . $customSummary . "\n";
        // $content = substr_replace($content, $summaryString, strlen($markdownTag), 0);
        // }

        return $content;
    }

修改为:

public static function customContent($content, $widget, $lastResult)
{
    // 关键:优先使用上一个插件的处理结果(如果有)
    $content = empty($lastResult) ? $content : $lastResult;
    
    $options = Typecho_Widget::widget('Widget_Options')->plugin('AISummary');
    // 不启用的话直接 return 传递过来的内容
    if ($options->summaryStyle === '0') return $content;
    
    // 获取用户自定义的字段
    $summaryField = $options->field;
    $customSummary = $widget->fields->$summaryField;
    if (empty($customSummary)) return $content;
    
    $pureSummary = str_replace("{{text}}", $customSummary, $options->prefix);
    if ($options->summaryStyle === '1') {
        $summaryString = '<blockquote class="aisummary">' . $pureSummary . "</blockquote>";
        $content = $summaryString . $content;
    } else if ($options->summaryStyle === '2') {
        $summaryString = '<div class="aisummary">' . $pureSummary . "</div>";
        $content = $summaryString . $content;
    }

    return $content;
}

修改说明

添加 $lastResult 参数:Typecho 钩子的 contentEx 方法默认支持 3 个参数($content, $widget, $lastResult),$lastResult 是上一个插件处理后的结果。

优先使用 $lastResult :如果有上一个插件处理过内容(比如 Panorama 先执行),就基于这个结果继续处理;如果没有,就用原始 $content

保持返回逻辑:处理完摘要后,返回修改后的内容,传递给下一个插件。

原理说明

TypechocontentEx 钩子是链式执行的,每个插件的处理结果会传递给下一个插件。修改前 AISummary 没有处理 $lastResult ,导致 Panorama 无法获取原始内容解析短代码;修改后 AISummary 支持链式调用,两个插件的处理逻辑会叠加执行。

Pannellum CSS CDN地址:
https://cdnjs.cloudflare.com/ajax/libs/pannellum/2.5.6/pannellum.css

Pannellum JavaScript CDN地址:
https://cdnjs.cloudflare.com/ajax/libs/pannellum/2.5.6/pannellum.js