# Vue↔React demo 结构一致性对比工具 — 设计 spec

- **日期**：2026-07-08
- **背景 / 触发**：owner 在 docs 站切 React 走查时发现 **React 版 TopBar 渲染只剩 title、logo/menu/right-content 全丢**。根因：`<tvu-top-bar>` 等组件是 light-DOM custom element（`shadowRoot:false`），light DOM 下 `<slot>` 投影不生效 → React wrapper 传的 `slot="..."` 内容渲染不出来（INFRA-F43 slot 投影 bug）。这会波及所有带 slot 的组件（TopBar / MenuList / UserMenu / FormItem / Tab…）。现有 `audit:demo-framework-parity` 只比对 section 标题集，抓不到运行时渲染结构残缺。
- **目标**：一个 Python 脚本，对全部双框架组件页做 **Vue vs React 运行时渲染结构**对比，产出自包含 HTML 报告，让 owner 决策哪些组件需修。展示效果允许不同，**结构需一致**。

## 关键决策（已与 owner 对齐）

1. **判定粒度 = 语义骨架对比**：只提取 TVU 组件实例（`tvu-*`）+ 其 slot 区块填充情况 + demo section/card 骨架，忽略 Vue/React 框架 wrapper 噪音。（否决：完整 DOM 树同构=噪音大；仅元素存在性=抓不到 slot 残缺。）
2. **报告 = 骨架 diff + 并排渲染截图**：每个 DIFF 组件既列骨架树逐项差异，又附 Vue / React 两侧实际渲染截图。
3. **运行时对比而非静态源码**：静态源码里 React demo「传了」logo/menu props 看着结构一致，但运行时投影失败——必须真实渲染才能抓到。

## 架构

单脚本 `scripts/compare_framework_structure.py`（class-based），阶段：

1. **发现**：`grep '@demos/'` 找出双框架 Vue 页（25 个），从 `navigation.ts` 取 `id` → route `#/{id}`。自动发现，无需手维护清单。
2. **渲染**：playwright chromium 复用本地 preview（默认 `http://localhost:4173/`，可参数化）。逐页两遍：设 `localStorage['tvu-docs-framework']` = `vue` / `react` → reload → 等渲染稳定。
3. **骨架提取**（2026-07-08 实测修正）：Vue 态用 canonical SFC（普通 class DOM，**无 `tvu-*` CE**），只有 React 态用 `<tvu-*>` web component —— 两框架底层 DOM 表示天然不同，故签名不能依赖 tag/class。改用**跨框架语义签名**：`page.evaluate` 按 `.docs-section` 标题分组，每 section 提取「可见文本 token 集（`innerText` 分词）+ 语义元素轮廓（nav/a/button/input/img/svg/CE 计数）」。切框架用 `context.add_init_script` 在 app boot 前注入 `localStorage`（实测：boot 后设 + hash 导航不 reload、不生效）。
4. **对齐 + 判定**：按 section 标题对齐 Vue↔React 同名 section，比签名。**非双框架/静态 section 两态签名天然相同 → 自动 PASS**，无需显式界定 region；只有含组件渲染且残缺的 section 浮现 DIFF。差异 = Vue-only / React-only 文本 token + 元素轮廓差。（实测样例：TopBar「Figma Members」React 缺 `Product Name` title —— wrapper `el.title=` 设成原生 tooltip 属性、遮蔽 CE title prop。）
5. **截图**：每 region 两态各截一张（element screenshot）。
6. **报告**：自包含 HTML → gitignored 目录 `framework-structure-report/`。顶部汇总表（25 组件 × 状态 + 差异摘要）；DIFF 组件展开骨架逐项差异（高亮 React 缺项）+ 并排截图。

## 依赖与风险

- 需 `pip install playwright`。⚠️ 本机 Python 3.14.5 很新，官方 wheel 可能未跟上 → 装不上则**当场回报**，退路：pyenv 装 3.12 / 或改用项目已装的 JS playwright 驱动、Python 只做 diff+报告。不静默硬凑。
- 报告为诊断产物，gitignored，不进版本库（同 playground-dist 外的临时产物纪律）。

## 非目标（YAGNI）

- 不做 dark/light 双主题跑（结构与主题无关；owner 未要求）。
- 不自动修复 slot 投影 bug（本工具只诊断；修复是后续独立任务）。
- 不替代 `audit:demo-framework-parity`（那是 section 标题 CI 闸；本工具是人工决策用的运行时结构诊断，互补）。
