# -*- coding: utf-8 -*- """ 离屏验证:思考/压缩气泡内代码朴素渲染(去"紫+边框")+ 正文代码块不受影响 背景:压缩摘要充满代码,finishTimelineMessage 对全部 pre code 做 hljs 高亮后, .code-block-wrapper 的浅色语法色(#a626a4 紫)+ 1px 边框 + 语言栏让定格后的 压缩气泡观感"紫色带边框"。修复:.think-content 作用域内代码统一朴素灰、 无边框、无头部、无 min-width;正文气泡代码块保持原样。 """ import os, sys, json sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) os.environ["QT_QPA_PLATFORM"] = "offscreen" os.environ["QTWEBENGINE_CHROMIUM_FLAGS"] = "--disable-gpu" os.environ.setdefault("HAOCODE_RENDER", "software") from PyQt6.QtWidgets import QApplication # noqa: E402 铁律:WebEngine 先于 QApplication 创建导入 from PyQt6.QtCore import QTimer, QUrl # noqa: E402 from PyQt6.QtWebEngineWidgets import QWebEngineView # noqa: E402 RESULTS = [] def check(name, cond, extra=""): RESULTS.append((name, bool(cond))) print(f"{'PASS' if cond else 'FAIL'} {name} {extra if not cond else ''}", flush=True) GRAY = "rgb(119, 119, 119)" # #777 PURPLE = "rgb(166, 38, 164)" # #a626a4(正文代码块关键字色,保持) SUMMARY = ("## 摘要\n说明文字。\n```python\nimport os\ndef run():\n return \"x\"\n```\n" "另外 `flowkit` 与 `read_file` 是工具名。") TEST_JS = r""" (function(){ try { var out = {}; var SUM = __SUMMARY__; // ---------- 压缩气泡:定格 + finish(触发全量 hljs 兜底)后探测 ---------- createMessage('m1','assistant','','Assistant'); compactionStarted('m1','pre_prompt'); compactionFinished('m1',{summary:SUM,before:100,after:50,duration_ms:10,path:'pre_prompt'}); finishMessage('m1'); (function(){ var block = document.querySelector('#m1 .compaction-think'); if (!block) { out.m1 = 'NO-BLOCK'; return; } var wrap = block.querySelector('.code-block-wrapper'); if (!wrap) { out.m1 = 'NO-WRAP'; return; } var cs = getComputedStyle(wrap); out.m1_border = cs.borderTopWidth; out.m1_minw = cs.minWidth; var hdr = wrap.querySelector('.code-header'); out.m1_header_display = hdr ? getComputedStyle(hdr).display : 'NO-HDR'; var kw = wrap.querySelector('.hljs-keyword'); out.m1_kw_color = kw ? getComputedStyle(kw).color : 'NO-KW-SPAN'; var pre = wrap.querySelector('pre code'); out.m1_pre_color = pre ? getComputedStyle(pre).color : 'NO-PRE'; var ic = block.querySelector('p code'); out.m1_inline_color = ic ? getComputedStyle(ic).color : 'NO-INLINE'; })(); // ---------- 对照组:正文消息的代码块保持原样(边框+语法色) ---------- createMessage('m2','assistant','','Assistant'); appendToken('m2','前文。\n```python\nimport os\ndef run():\n return "x"\n```\n后文。'); finishMessage('m2'); (function(){ var w = document.querySelector('#m2 .code-block-wrapper'); if (!w) { out.m2 = 'NO-WRAP'; return; } var cs = getComputedStyle(w); out.m2_border = cs.borderTopWidth; var hdr = w.querySelector('.code-header'); out.m2_header_display = hdr ? getComputedStyle(hdr).display : 'NO-HDR'; var kw = w.querySelector('.hljs-keyword'); out.m2_kw_color = kw ? getComputedStyle(kw).color : 'NO-KW-SPAN'; })(); return JSON.stringify(out); } catch(e) { return 'JSERR:' + e.message + ' @' + ((e.stack||'').split('\n')[1]||''); } })() """.replace("__SUMMARY__", json.dumps(SUMMARY, ensure_ascii=False)) app = QApplication(sys.argv) _js = {"v": None} view = QWebEngineView(); view.resize(1000, 700) _index = os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "ui", "web", "index.html")) def _run(): view.page().runJavaScript(TEST_JS, lambda v: _js.update(v=v)) view.loadFinished.connect(lambda ok: QTimer.singleShot(1500, _run)) QTimer.singleShot(9000, app.quit) view.load(QUrl.fromLocalFile(_index)) app.exec() try: r = json.loads(_js["v"]) except Exception: r = None print(f"DOM 结果解析失败: {_js['v']!r}", flush=True) check("T.DOM 返回", isinstance(r, dict), repr(_js["v"])[:300]) if isinstance(r, dict): # 压缩气泡内:朴素化 check("T.压缩气泡代码块边框=0", r.get("m1_border") == "0px", r) check("T.压缩气泡代码块min-width=0", r.get("m1_minw") == "0px", r) check("T.压缩气泡代码头部=隐藏", r.get("m1_header_display") == "none", r) check("T.压缩气泡关键字色=#777(去紫)", r.get("m1_kw_color") == GRAY, r.get("m1_kw_color")) check("T.压缩气泡pre代码色=#777", r.get("m1_pre_color") == GRAY, r.get("m1_pre_color")) check("T.压缩气泡内联代码色=#777(去粉)", r.get("m1_inline_color") == GRAY, r.get("m1_inline_color")) # 正文对照:保持原样 check("T.正文代码块边框=1px(不变)", r.get("m2_border") == "1px", r) check("T.正文代码头部=可见(不变)", r.get("m2_header_display") not in ("none", "NO-HDR"), r) check("T.正文关键字色=#a626a4(不变)", r.get("m2_kw_color") == PURPLE, r.get("m2_kw_color")) failed = [n for n, ok in RESULTS if not ok] print(f"\n===== {len(RESULTS) - len(failed)}/{len(RESULTS)} PASS =====", flush=True) print("ALL PASS" if not failed else f"FAILED: {failed}", flush=True) sys.exit(0 if not failed else 1)