Skip to content

fix: stop blanking public pages (homepage white screen)#31

Merged
study8677 merged 1 commit into
mainfrom
fix/homepage-blank-static-copy
May 22, 2026
Merged

fix: stop blanking public pages (homepage white screen)#31
study8677 merged 1 commit into
mainfrom
fix/homepage-blank-static-copy

Conversation

@study8677
Copy link
Copy Markdown
Owner

Root cause

_replace_static_site_copy used 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:

  • the comment's closing --> (→ unterminated comment → browser swallows the rest of the document)
  • the module <script src="/assets/index-*.js"> (→ React never boots)
  • the <body> tag

So 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

  • TestClient: /, /console, /en/services, /blog/* → 200, contain module script + #root + <body>, comment balanced.
  • Headless browser render of backend-served / HTML: #root mounts, React renders (no blank page).

…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>
@study8677 study8677 merged commit 8b606d5 into main May 22, 2026
Copy link
Copy Markdown
Owner Author

Code Review — fix: stop blanking public pages (homepage white screen)

总体评价:这是一个诊断准确、改动最小的 hotfix。根因分析清晰,注释完整解释了"为什么",并附带了一个不那么明显的 lambda 小改进。建议合并(已合并),但有两点值得在后续补强。


问题清单

级别 文件 & 行号 描述 建议
🟡 建议 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 result

Code Review by Claude Code — 2026-05-22


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant