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.

ObjectMap 把顶层 schema.style 当 MapLibre style URL 读 —— 与 BaseSchema.style(内联 CSS)撞车,而 types 里 mapStyle 这个名字正是为避开它才起的 #5017

Closed

Description

@yinlianghui

发现于 #5002 的实施(plugin-map README 重写)。Filed unassigned, not claiming.

现象

packages/plugin-map/src/ObjectMap.tsx:198-199,地图样式按三个拼法依次取,顶层 style 排第一:

const style: string | undefined =
  (schema as any).style || (schema as any).mapStyle || (schema as any).map?.style;

而 style 在 schema 基面上已经有一个完全不同的含义:BaseSchema.style 是内联 CSS(packages/types/src/zod/base.zod.ts:80,z.record(z.string(), z.union([z.string(), z.number()])),describe 为 'Inline CSS styles'),每个节点都可以合法地写它。

于是在一个 object-map / map 节点上写基面允许的 style: { height: '400px' },这个对象会被当作地图样式一路交给 MapGL 的 mapStyle prop(ObjectMap.tsx:675)。它不经过 MapConfigSchema —— 那次 safeParse 只看 schema.map(:222),顶层的 style / mapStyle 是在 :198 单独取的,直接 spread 进返回值(:211 / :226 / :243),所以既没有校验也没有诊断。

为什么这条特别值得记

@object-ui/types 自己已经写明了这个坑,并且为它改过名:

packages/types/src/objectql.ts:1820-1824
MapLibre style URL/spec. … Named mapStyle (not style) to avoid colliding with BaseSchema.style (inline CSS properties).

也就是说声明面为避开撞车专门起了 mapStyle,而消费端仍然优先读那个被避开的名字。声明与消费在同一件事上给出相反的答案,这正是「declared = enforced」要拦的形状。

观察到的三个拼法

拼法 是否声明 是否被读
schema.style 已声明,但声明的是内联 CSS 读,优先级最高
schema.mapStyle ObjectMapSchema 声明为 MapLibre style(objectql.ts:1825) 读,第二优先
schema.map.style MapConfigSchema 声明(ObjectMap.tsx:49) 读,最后

现有钉子只钉了后两条(ObjectMap.styleFallback.test.tsx:39-59、ObjectMap.filterConfig.test.tsx:153-163 钉 map.style),顶层 style 这一腿没有测试,也没有任何一处仓内 metadata 使用它 —— 所以今天没人踩到,但它是每个节点都能写的合法基面键。

可能的修法(供分诊定向,未实施)

  1. 删掉 schema.style 那一腿,只保留 mapStyle(声明面的名字)与 map.style(声明的配置块)。风险:若有 in-flight 的 ObjectView 路径依赖顶层 style,需先查 —— ObjectView.tsx:770-776 把 viewOptions.map 摊平到顶层,所以顶层拼法这条路是活的,要确认它有没有可能摊出 style。
  2. 保留但收窄为字符串(typeof === 'string'),对象形态落回 CSS 语义并诊断。仍留着两个含义共用一个键。
  3. 统一到 map.style 单一入口,mapStyle 走弃用期。

范围与 #5002 不相交(#5002 只重写 README,并且只教了 map.style 一个拼法,没有教这两个顶层别名)。

分级

交 PM 分诊。这是"declared 与 consumed 打架"的合同面缺陷,不是 README 文案问题。

Activity

  1. added theissue type on Aug 17, 2026
  2. os-zhuang commented on Aug 17, 2026

    @os-zhuang
    Contributor

    Triage: pm:queue, type Bug — declared-vs-consumed conflict on a contract face: @object-ui/types itself documents that mapStyle was named to avoid BaseSchema.style (inline CSS), yet the consumer reads the avoided name first, so legal base-face CSS on a map node is handed to MapGL as a style URL. Restoring the declared invariant = immediate-action class, no decision needed.

    PM-suggested route (mechanism assumption — test it, falsification welcome): option 1, delete the schema.style leg, keep mapStyle + map.style. Non-negotiable precondition from the card's own risk note: first verify ObjectView.tsx:770-776's flattening of viewOptions.map cannot emit a top-level style — if it can, stop and report instead of shipping a breakage.

    Serial constraints: file surface is packages/plugin-map/src/ObjectMap.tsx — same file as anything that comes out of #5018's ruling and the open map findings (#5003). Hard-serialize with any in-flight ObjectMap.tsx work; #5002 (README only) does not conflict. Note on #5018 adjacency: its item-3 ruling (top-level vs map block canonicalization) may later supersede the shape here — the pin this card adds should assert "CSS-meaning style is never consumed as a map style", which survives either outcome.

    This comment is from the triage seat Routine — session session_01CNcg2rhY7jLn5g5TEbhK4Z.


    Generated by Claude Code

  3. yinlianghui commented on Aug 18, 2026

    @yinlianghui
    ContributorAuthor

    PM 状态(2026-08-18,session session_01GTRjn8xBqp75dk7kFupVRt):pm:blocked

    Blocked-by: #5156

    机器可读行在本评论(未改正文,理由:硬串行是短期态,PR #5156 预计当日落)。依据:


    Generated by Claude Code

  4. self-assigned this
    on Aug 18, 2026
  5. yinlianghui commented on Aug 18, 2026

    @yinlianghui
    ContributorAuthor

    解锁 + 认领(objectui 分片 PM,session session_01GTRjn8xBqp75dk7kFupVRt,批次 23):Blocked-by PR #5156 已清 —— 该 PR 已 MERGED(main 578e02516),pm:blocked 摘除,按停牌评论 5325383033 的解锁条款回队并即刻认领。派 os-dev 席位,分支 claude/issue-5017-style-leg,基线取含 578e02516 的 main 实 sha。

    执行口径(承接分诊评论 5317411990 的 option 1 + 前置核验,并按 PR #5156 落地后的新地形收紧):


    Generated by Claude Code

  6. yinlianghui commented on Aug 18, 2026

    @yinlianghui
    ContributorAuthor

    PM 交接(条件释放)(session session_01GTRjn8xBqp75dk7kFupVRt,2026-08-18):维护者指示本 PM 会话下班收工。本卡执行席位刚派发(分支 claude/issue-5017-style-leg 尚未 push、未开 PR)。处置条款:

    1. 若稍后出现该分支的 draft PR:任一 PM 可按认领评论 5325569468 的执行口径直接做标准验收三件套。特别注意其中的不可协商前置核验(摊平可达性三面测量,verdict c ⇒ needs_decision 而非动刀)—— 验收时核对报告/PR body 里该测量确实做了。
    2. 若无 draft PR 出现:本认领即告释放,本卡回到可认领态;基线必须含 578e02516(PR fix(types,plugin-map): declare what ObjectMap reads; the map block outranks the flat spelling #5156)。
    3. 执行口径与 PM 代裁以认领评论为准,不随会话结束失效。

    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

Labels

bugSomething isn't workingpm:queue

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions