extract 文本结果忽略 text-transform,与页面显示大小写不一致

Aperta Adatta ai principianti
#597 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@kesmeey ci sta già lavorando.

Dal 5/11/2026.

  • #613 di @kesmeey — aperta

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
76/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
css, javascript, playwright, typescript

Direzione di ricerca

Leggi tools/extract/collector.ts e segui come raccoglie i nodi di testo e gestisce white-space; la discrepanza segnalata è che il testo estratto ignora text-transform calcolato. Inizia riproducendo in Chromium i casi della tabella con maiuscole e minuscole, poi confronta il risultato dell’estrazione con innerText. Il lavoro è completato quando il risultato corrisponde alle maiuscole e minuscole visualizzate e il testo ordinario rimane invariato; aggiungi un test di regressione per entrambi i casi.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

本报告由 OpenAI Codex(AI)生成并经用户授权提交。以下结果来自实际执行的隔离 Chromium 测试。

环境与验证范围

  • 本地基线:c134fbb65949e17a3d11b35dddcb77599a9dea8e;Chrome for Testing 156.0.8078.4、Linux、Node.js 24。
  • 提交前重新读取 main,相关生产文件与本地完全一致。
  • 直接打包并运行生产 TS 模块,Playwright 提供真实点击、输入及 Chromium;没有复制缺陷实现。
  • 没有运行完整安装版扩展、后台录制/observation、daemon 或 CLI。以下属于生产模块的真实浏览器复现,不声称完整产品端到端通过。

最小复现

<table id="t"><tr><td style="text-transform:uppercase">paid</td></tr></table>

生产 collector 和 normalizer 返回 {"c1":"paid"};真实 Chromium 的 innerText 和页面呈现是 PAID。

反向对照:text-transform:lowercase 配合原文 PAID,浏览器显示 paid,提取仍为 PAID。没有 text-transform 的普通单元格提取与 innerText 一致。

预期:若按 #382 所述读取 rendered text,普通文本节点应保留应用 text-transform 后的显示内容。此处不是要求 OCR 或 CSS 伪元素生成内容;若该差异属于有意保留底层文本,建议在文档说明此例外。

原因线索与范围

tools/extract/collector.ts 自行遍历 text node 并处理 white-space,但没有应用 computed text-transform。本复现仅验证 ASCII upper/lower,不声称已验证所有语言的大小写、capitalize 或完整 CSS 文本算法。

本次检索公开 issue/所有状态 PR 的 text-transform、extract 等关键词,暂未找到相同报告。Related: #382 的 rendered-text 支持;#453 涉及隐藏内容而非文本转换。

独立浏览器复现脚本

在仓库根目录保存下面脚本为 reproduce-case.mjs,然后运行:

npm install --prefix /tmp/bsk-audit-runtime --no-audit --no-fund esbuild playwright
/tmp/bsk-audit-runtime/node_modules/.bin/playwright install chromium
node reproduce-case.mjs

要求环境能启动 Chromium;默认依赖路径为 /tmp/bsk-audit-runtime,可用 BSK_AUDIT_RUNTIME 指定。脚本中的断言用于确认当前差异;修复后预期会失败,不能把它作为修复后的回归断言。所有脚本均已实际执行并以退出码 0 完成。

完整脚本
import {createRequire} from 'node:module';
import {resolve} from 'node:path';
import {writeFile} from 'node:fs/promises';
const require=createRequire(resolve(process.env.BSK_AUDIT_RUNTIME || '/tmp/bsk-audit-runtime','package.json'));
const {build}=require('esbuild');
const {chromium}=require('playwright');
const root=process.cwd();
const bundle=await build({stdin:{contents:"export {collectExtractDom} from './apps/extension/src/tools/extract/collector'; export {validateExtract} from './apps/extension/src/tools/extract/validation'; export {normalizeExtract} from './apps/extension/src/tools/extract/normalize';",resolveDir:root,loader:'ts'},bundle:true,write:false,format:'iife',globalName:'Audit',platform:'browser',tsconfigRaw:{compilerOptions:{baseUrl:root,paths:{'@/*':['apps/extension/src/*']}}}});
const browser=await chromium.launch({channel:'chromium',headless:true,args:['--no-sandbox']});
try {
 const page=await browser.newPage();
 await page.setContent('<!doctype html><body>');
 await page.addScriptTag({content:bundle.outputFiles[0].text});
const read=async(html)=>page.evaluate(html=>{
 document.body.innerHTML=html;
 const options=Audit.validateExtract({session_id:'audit',action:'table',selector:'#t'});
 const raw=Audit.collectExtractDom.call(document.documentElement,options);
 const el=document.querySelector('#t'),r=el.getBoundingClientRect();
 return {rendered:el.innerText,width:r.width,height:r.height,error:raw.error,result:raw.error?null:Audit.normalizeExtract(raw,options,1,{page_url:location.href,frame_url:location.href,frame_id:'root',title:'audit',captured_at:raw.captured_at})};
},html);
const upper=await read('<table id="t"><tr><td style="text-transform:uppercase">paid</td></tr></table>');
const lower=await read('<table id="t"><tr><td style="text-transform:lowercase">PAID</td></tr></table>');
const control=await read('<table id="t"><tr><td>paid</td></tr></table>');
if (!(upper.rendered==='PAID' && upper.result.rows[0].c1==='paid' && lower.rendered==='paid' && lower.result.rows[0].c1==='PAID' && control.rendered===control.result.rows[0].c1)) throw Error('Unexpected result');
console.log(JSON.stringify({upper,lower,control},null,2));
} finally {await browser.close();}
Lingua principale
TypeScript
Stelle
10.1k
Fork
732
Merge medio
2g 2h
PR unite (30g)
92

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di Tencent/BrowserSkill

Tutte le issue di Tencent/BrowserSkill

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.