59 lines
4.6 KiB
Markdown
59 lines
4.6 KiB
Markdown
# ecss 架构
|
||
|
||
[English](architecture.en.md)
|
||
|
||
## 定位
|
||
|
||
`ecss` 是“规则如何赢、最终属性值是什么”的通用纯计算层。它把 consumer 提供的 property schemas、subjects、stylesheets、inline declarations 与 parent computed style 转换成 computed values、custom properties、active properties、specified properties、provenance 和 diagnostics。
|
||
|
||
```text
|
||
consumer schemas + subject adapter + stylesheet + parent style
|
||
│
|
||
▼
|
||
selector match → candidate collection → cascade winner
|
||
│
|
||
▼
|
||
CSS-wide/custom-property resolution → normalize/validate
|
||
│
|
||
▼
|
||
computed style + specified properties + provenance + diagnostics
|
||
```
|
||
|
||
`ecss` 不知道 computed values 最终如何显示。TP 可以把最终文本属性贡献转换成 retained surface patch;Ebox 可以把最终 Box/Flex/Grid 属性解释成 measurement、layout 与 painting 后果;普通调用者也可以完全不用 TP/Ebox。
|
||
|
||
## Package schema 与显式 surface
|
||
|
||
每个 owning package 一次创建不可变 `ecss-schema-package`;具体 surface 再用 `ecss-schema-set-compose` 原子组合所需 package。组合阶段统一拒绝重复 package、canonical/canonical、canonical/alias 与 alias/alias 冲突,不存在进程全局 mutable registry 或 last-wins 注册。两个应用因此可以在同一 Emacs 中组合不同 property vocabulary 而互不污染。
|
||
|
||
Alias 只属于声明归一化入口,进入 cascade 前消失;同一声明中 alias/canonical 重复或 shorthand 与其输出 longhand 冲突会立即失败。Schema set 同时保存 owner、impact 与 projection facts,computed style 直接引用该 set,不建立第二棵 computed tree。Package/schema set 不提供 mutator,公共查询返回 detached 数据。
|
||
|
||
Stylesheet 仍是每个调用者显式拥有的可变 authoring 对象。同一 stylesheet 中的 UA、user 与 author origin 分别维护 layer order;rule 添加是原子的,一次失败不会留下半添加 layer 或错误 source order。
|
||
|
||
## Subject 与 adapter
|
||
|
||
简单场景直接使用 `ecss-subject`。已有树模型通过 `ecss-subject-adapter-create` 提供 type、id、classes、attributes、states、parent 与 children callback,不需要把业务节点复制成 ECSS node。selector query 与 stylesheet 都调用同一个 parser、matcher 和 specificity 实现,因此不会出现“查询能匹配但样式规则不能匹配”的两套语义。
|
||
|
||
## Cascade 顺序
|
||
|
||
候选值按 CSS 顺序比较:relevance/match、origin+importance、cascade layer、specificity、scope proximity、source order、declaration order。标准 origin level 是 UA normal、user normal、author normal、animation、author important、user important、UA important、transition。normal layer 后声明者优先且 unlayered 高于 layered;important layer 反向,inline author declaration 在 author origin 内保持最高优先级。
|
||
|
||
`revert` 删除当前整个 origin 后重新选择,不区分 normal 与 important;`revert-layer` 删除当前 origin 中的整个 layer 后重新选择。invalid-at-computed-value 不会退回较低候选,而是使用 inherited/initial fallback,并在 provenance 中记录 invalid winner。
|
||
|
||
## Value source 边界
|
||
|
||
ECSS 不自动调用属性里的 function,也不定义自己的 reactive/computed wrapper。调用者需要求值时,显式向 `ecss-compute-style` 传入 `:value-resolver`。resolver 接收 value、property、subject,ECSS 对每个被选中的 source 只调用一次,resolver 返回值不会被二次执行。resolver error 直接向外传播;由于 computation 是纯计算,不存在需要 ECSS 回滚的 Buffer 或 runtime state。
|
||
|
||
## Custom properties
|
||
|
||
Custom properties 使用 `--name` symbol,通过普通 cascade 选出 raw value,默认从 parent computed style 继承,再用 `ecss-var` 解析。引用可以嵌套在 list/vector 中;缺失值与 cycle 可使用引用处 fallback。cycle 不破坏整个 computed style,而产生 deterministic diagnostic,并把受影响 value 标记为 invalid-at-computed-value。
|
||
|
||
## 三包边界
|
||
|
||
```text
|
||
ecss: selector / stylesheet / cascade / computed values
|
||
tp: text-property contributions / reactive runtime / diff / transaction / buffer commit
|
||
ebox: box semantics / measurement / flex-grid layout / painting / dirty ownership
|
||
```
|
||
|
||
允许的依赖方向是 Ebox 消费 `ecss` 与 TP;`ecss` 和 TP 可以彼此完全独立使用。`ecss` public API 不出现 TP object/binding/mount、Ebox node、marker、patch 或 buffer mutation。
|