fix: stop blanking public pages (homepage white screen)#31
Merged
Conversation
…ain> _replace_static_site_copy matched `<main id="static-site-copy">.*?</main>`, but that bare tag first appears as literal text *inside the head comment* that documents the static-copy mechanism. With DOTALL the match ran from the comment to the real </main>, swallowing the comment's closing `-->`, the module <script src=/assets/index-*.js>, and <body> — leaving an unterminated comment that the browser swallows to EOF. Result: every public route (/, /en/*, /blog/*, /console) rendered a blank white page; /app/ was spared only because it skips static-copy replacement. Anchor the regex to the real element (which carries translate="yes"), so the comment mention no longer matches. Use a callable replacement to avoid backreference interpretation in the HTML payload. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Owner
Author
Code Review —
|
| 级别 | 文件 & 行号 | 描述 | 建议 |
|---|---|---|---|
| 🟡 建议 | app.py:893 |
修复依赖 translate="yes" 属性作为区分真实元素与注释文本的唯一锚点。若后续模板调整去掉该属性,或注释里的示例文本带上该属性,同样的 bug 会静默复现。 |
考虑在真实 <main> 上额外加一个专用 data 属性(如 data-dynamic-slot="true"),并以此作为正则锚点,语义上更明确,也不依赖翻译行为属性。 |
| 🟡 建议 | tests/ |
没有针对此回归的单元测试。_replace_static_site_copy 是纯函数,极易测试,且此 bug 曾直接导致首页白屏。 |
在 tests/test_web.py(或新文件)中添加:1)正常替换用例;2)包含 head 注释文本的用例(验证不发生错误匹配)。 |
| 🟢 优化 | app.py:893 |
[^>]* 允许额外属性,有一定前向兼容性,但 .*?</main> 在 DOTALL 下仍会匹配到第一个 </main> 标签。若 static_copy 本身含嵌套 <main> 元素,替换将在错误位置截断。 |
评估实际 static_copy 的结构;如可能包含嵌套 <main>,可改用计数器方案或为目标元素加唯一 ID 前缀。当前场景应无问题,记录为低优先级技术债。 |
亮点
- 根因分析到位:PR 描述精确还原了"注释文本 → 正则从注释内部开始匹配 → 吞掉
-->→ 浏览器视为未闭合注释 → 文档后半截消失"的完整链路。 - 注释写得好:新增的 5 行注释解释了"为什么不能用裸
<main id="static-site-copy">",符合项目"只注释 WHY"的编码规范,未来维护者不会误删这个"奇怪的"额外条件。 lambda _match: static_copy是个隐性改进:re.sub的字符串替换会解释\1、\g<name>等反向引用。若static_copy(来自外部 HTML 内容)恰好含有反斜杠序列,字符串替换会崩溃或产生错误输出;改为 callable 完全绕过此问题,更健壮。- 改动最小:仅修改 9 行,不引入任何新依赖或抽象,符合 hotfix 应有的风格。
后续建议(回归测试示例)
# tests/test_web.py(或新增 test_app_helpers.py)
def test_replace_static_site_copy_normal():
html = '<html><main id="static-site-copy" translate="yes">OLD</main></html>'
result = _replace_static_site_copy(html, "<main>NEW</main>")
assert "NEW" in result
assert "OLD" not in result
def test_replace_static_site_copy_ignores_comment_text():
"""注释里出现裸标签时不应触发错误替换。"""
html = (
'<!-- Example: <main id="static-site-copy"> -->'
'<main id="static-site-copy" translate="yes">REAL</main>'
)
result = _replace_static_site_copy(html, "<main>REPLACED</main>")
assert "REPLACED" in result
assert "REAL" not in result
assert "<!--" in result # 注释完整保留
def test_replace_static_site_copy_with_backslash_in_content():
"""static_copy 含反斜杠时不应 re.sub 解释失败。"""
html = '<main id="static-site-copy" translate="yes">OLD</main>'
tricky = r"path\to\file"
result = _replace_static_site_copy(html, tricky)
assert tricky in resultCode Review by Claude Code — 2026-05-22
Generated by Claude Code
study8677
added a commit
that referenced
this pull request
May 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Root cause
_replace_static_site_copyused the regex<main id="static-site-copy">.*?</main>(DOTALL). That bare tag first appears as literal text inside the head comment documenting the static-copy / Chrome-Translate mechanism. The match therefore ran from inside the comment to the real</main>, swallowing:-->(→ unterminated comment → browser swallows the rest of the document)<script src="/assets/index-*.js">(→ React never boots)<body>tagSo every public route (
/,/en/*,/blog/*,/console) served a blank white page./app/was spared only because it skips static-copy replacement.Fix
Anchor the regex to the real element (which carries
translate="yes"), so the in-comment mention no longer matches. Use a callable replacement to avoid backreference interpretation in the HTML payload.Verified
/,/console,/en/services,/blog/*→ 200, contain module script +#root+<body>, comment balanced./HTML:#rootmounts, React renders (no blank page).