Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

packages/layout: registerLayout 的 inputs 声明面与组件实现不符 —— page-header 漏 icon(文档 demo 今天就吃假 unknown-prop),navigation-renderer 的 items 声明成 object 而 prop 是数组 #3972

Closed

Description

@yinlianghui

发现于 #3900 的实现(PR 见下方引用),不在该 PR 处理 —— #3900 的完成范围被维护者明确框成「page-header 一行注册 flag + 钉子」,这里是同一个注册文件里另外两个键的声明面缺陷,属另一类动作。两条都有实测诊断输出,不是推断。

现象一:page-header 的 inputs 漏了组件真实渲染的 icon

注册(packages/layout/src/index.ts)只声明 title / subtitle。但 icon 三面齐全:

  • 渲染器读它:packages/layout/src/PageHeader.tsx:117 取参,:224-226 渲染(字符串走 LazyIcon name={icon},也接受 React node)。
  • spec 声明它:@objectstack/spec/ui 的 PageHeaderProps 有 icon。
  • 文档 demo 写它:examples/schema-catalog/src/schemas/layout-page-header/pageheader-with-actions.json 里 "icon": "users",而这是 content/docs/layout/page-header.mdx 唯一的 live demo。

于是 manifest 门今天就对这份 demo 报一条假警告。实测(把该 demo 喂给按 page.tsx 的 getJsxManifest() 同样方式构造的 manifest,再走 validateTree):

{
  "severity": "warning",
  "code": "unknown-prop",
  "message": "page-header has no prop \"icon\"",
  "tag": "page-header"
}

这条与 #3900 无关、在 #3900 修复前后都存在(两次实测输出一致),所以 #3900 的钉子刻意只按 not-a-container 这个 code 过滤,没有把它一起钉住 —— 就是为了这一条被修时那个钉子不会翻红。

注意方向,不要无脑抄全 spec 的键。 breadcrumb spec 有、这个 legacy 渲染器不读(全文件只在一句注释和一个 aria-label 里出现过字样),声明它就变成 #3829 那种「声明了却零读点」的反向缺陷。要的是一次按渲染器实际读点的审计:读了且 spec 有 → 声明;读了但 spec 没有 → 按 #3226 定下的调子处理(不要在声明面开第二套方言);没读 → 不声明。

同文件既有的 packages/layout/src/__tests__/page-header-authorable-keys.test.tsx 那条「declares nothing @objectstack/spec does not」是单向的:补 icon 不会让它翻红(spec 有),但它从来管不到「漏声明」这一侧 —— 和 #3900 是同一个不对称的另一处体现。

现象二:navigation-renderer 把 items 声明成 type: 'object',而 prop 是数组

注册里 { name: 'items', type: 'object' },而 NavigationRendererProps.items 是 NavigationItem[](packages/layout/src/NavigationRenderer.tsx:108)。packages/sdui-parser/src/validate.ts 的 checkType 对 'object' 判 typeof value === 'object' && value !== null && !Array.isArray(value),对 'array' 判 Array.isArray —— 所以正确的写法 items: [...] 会拿到 type-mismatch。实测:

{
  "severity": "warning",
  "code": "type-mismatch",
  "message": "navigation-renderer prop \"items\" expected an object",
  "tag": "navigation-renderer"
}

ManifestInputType 里有 'array',所以这不是 #3832 那个「ComponentInput.type 表达不了 spec 联合类型」的表达力问题,单纯是声明写错了一个可表达的类型。

可达性诚实标注: 本仓没有任何 JSON 元数据把 navigation-renderer 当 schema 节点写(全仓 grep 只命中注册本身,以及 #3900 加的那条阳性对照测试)。所以这条今天的实际受害者是仓外按 packages/layout/README.md 列出的键作 schema 驱动的消费者,不是仓内 demo —— 与现象一「文档 demo 今天就中」不同级,分诊时请分别判。之所以放在同一条:两者是同一文件、同一族(声明面与实现不符 → manifest 门对正确写法报假诊断)、同一次审计就能扫完,分成两个孪生单没有收益。

建议

一次改动扫完 registerLayout() 的四个 inputs 块(page-header / responsive-grid / navigation-renderer / app-schema-renderer),逐键对齐三面:渲染器读点 × spec 声明 × ManifestInputType 表达。并按 #3900 的做法补双向钉子:声明的键过 manifest 门放行,未声明/写错类型的键仍报 unknown-prop / type-mismatch —— 只钉前者的话,把诊断弄哑一样是绿的。

关联:#3900(发现于此实现,只处理 isContainer)、#3226(同文件 inputs 收窄的前情,建立了「声明面即作者面」的调子)、#3829(page:header.icon:spec 声明、渲染器零读点,同一个键的反向缺陷)、#3832(ComponentInput.type 表达力,不同根因)

Activity

  1. os-zhuang commented on Aug 9, 2026

    @os-zhuang
    Contributor

    Triage: pm:queue.

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  2. yinlianghui commented on Aug 9, 2026

    @yinlianghui
    ContributorAuthor

    PM 分诊(session_01GTRjn8xBqp75dk7kFupVRt):晋级 pm:queue —— layout 声明面两处与实现不符,同文件同族合一单正确:①page-header 漏声明渲染器真读且 spec 也声明的 icon(文档 demo 今天就吃 unknown-prop,PR3973 实测修 flag 前后都在);②navigation-renderer 的 items 声明 type:'object' 而实现是数组(正确写法反被报 type-mismatch)。第二条可达性弱已如实标注。前置 #3900(PR #3973)已验收入队,合入后可派;派发时沿其钉子形态(examples/schema-catalog 端到端 + layout 注册级)。


    Generated by Claude Code

  3. self-assigned this
    on Aug 9, 2026
  4. yinlianghui commented on Aug 9, 2026

    @yinlianghui
    ContributorAuthor

    🔒 认领(objectui 分片 PM,session_01GTRjn8xBqp75dk7kFupVRt,批次 5):前置 #3900(PR #3973)已落 main。

    • 分支:claude/issue-3972-layout-inputs-declaration
    • 范围:①page-header 注册 inputs 补声明 icon(渲染器真读且 spec 声明,文档 demo 的 unknown-prop 消失);②navigation-renderer 的 items 声明修正为数组形状(正确写法不再报 type-mismatch);钉子沿 PR3973 形态(schema-catalog 端到端 + layout 注册级,两方向)。
    • 文件面:packages/layout/src/index.ts + 测试;与在飞各单不相交。

    Generated by Claude Code

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions