From c8fdd81d6ae7028b1d592e59b8db22418166d471 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 6 Oct 2026 19:35:56 +0800 Subject: [PATCH] =?UTF-8?q?fix(admin):=20=E4=BF=AE=E5=A4=8D=E5=BF=AB?= =?UTF-8?q?=E6=8D=B7=E7=BC=96=E8=BE=91=E7=BB=84=E6=8F=8F=E8=BF=B0=E8=A2=AB?= =?UTF-8?q?=20esc=5Fhtml=20=E8=BD=AC=E4=B9=89=E6=88=90=E5=8F=AF=E8=A7=81?= =?UTF-8?q?=E6=A0=87=E7=AD=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 「付费参数」组的说明文字 `
…
` 整段被显示 成了纯文本标签。原因:fields_html() 对 $desc 做了 esc_html(),而该 参数传入的是一段自带
的 HTML,转义后标签就变成了可见字符。 改为按参考主题的做法原样输出 $desc,责任前移到调用方: - pay 组:esc_html__() 转义文字,外层 div 由模板给出; - filter 组:同样自带
包裹, 以保住原有样式(此前样式靠 fields_html 里的外层 div 提供)。 字段标题仍保持 esc_html(),因为 filter 那组的标题来自设置项。 新增契约断言锁住这个契约:不得再 esc_html($desc),两个调用点必须 各自转义/包裹;同时保留「字段标题仍转义」的断言。 验证:node --test tests/widget-system/*.test.cjs 445 项全部通过 (原有 444 项 + 新增 1 项);php -l 无语法错误。 --- src/Admin/Native/PostListEnhance.php | 8 ++++++-- .../post-list-quick-edit-contract.test.cjs | 11 +++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Admin/Native/PostListEnhance.php b/src/Admin/Native/PostListEnhance.php index 9f3fc707..f0274c8f 100644 --- a/src/Admin/Native/PostListEnhance.php +++ b/src/Admin/Native/PostListEnhance.php @@ -347,12 +347,15 @@ class PostListEnhance { return ''; } - return $this->fields_html($fields, 'filter', __('高级筛选', 'aksrt'), __('让文章实现更加精细化的分类,同时方便用户进行文章筛选', 'aksrt')); + return $this->fields_html($fields, 'filter', __('高级筛选', 'aksrt'), '
' . esc_html__('让文章实现更加精细化的分类,同时方便用户进行文章筛选', 'aksrt') . '
'); } /** * Render one field group: the shared builder for every quick-edit box. * + * $desc 是调用方预先转义好的 HTML 片段,这里原样输出(付费参数那组 + * 自带
,转义会把标签显示成文字)。 + * * @param array> $fields */ private function fields_html(array $fields, string $id, string $title = '', string $desc = ''): string { @@ -430,8 +433,9 @@ class PostListEnhance { return ''; } + // $desc 由调用方传入并保证安全(均为代码内常量),故原样输出: + // 付费参数那组自带
,转义会让标签直接显示成文字。 $legend = $title !== '' ? '' . esc_html($title) . '' : ''; - $desc = $desc !== '' ? '
' . esc_html($desc) . '
' : ''; return '
' . $legend . '
' . $item_html . '
' . $desc . '
'; } diff --git a/tests/widget-system/post-list-quick-edit-contract.test.cjs b/tests/widget-system/post-list-quick-edit-contract.test.cjs index d2fd2545..b33d41f8 100644 --- a/tests/widget-system/post-list-quick-edit-contract.test.cjs +++ b/tests/widget-system/post-list-quick-edit-contract.test.cjs @@ -56,6 +56,17 @@ test('quick-edit markup is emitted without kses stripping the controls', () => { assert.match(list, /
{ + // 组描述由调用方预先转义后整体传入(付费参数那组自带
), + // 渲染处若再 esc_html,标签会直接显示成文字。 + assert.doesNotMatch(list, /esc_html\(\$desc\)/) + // 两个调用点都必须自带转义/HTML 包裹,不能传裸翻译串。 + assert.match(list, /'
' \. esc_html__\('批量设置付费参数/) + assert.match(list, /'
' \. esc_html__\('让文章实现更加精细化/) + // 仍来自设置项的字段标题必须保持转义。 + assert.match(list, /esc_html\(\$title_html\)/) +}) test('number fields support the full operation set', () => { for (const op of ['ignore', 'set', 'plus', 'subtract', 'multiply', 'division']) { assert.match(list, new RegExp(`value="${op}"`), `${op} operation exists`)