From c3ea8aa8eacf0772bb8fdee02c52cab9ab105b18 Mon Sep 17 00:00:00 2001 From: Kinneyzhang Date: Wed, 26 Aug 2026 15:14:27 +0800 Subject: [PATCH] docs: classify Ebox DSL primitives and sugar --- AGENTS.md | 3 ++ docs/proposals/module-boundaries.en.md | 57 +++++++++++++++++++++++++- docs/proposals/module-boundaries.zh.md | 55 ++++++++++++++++++++++++- 3 files changed, 111 insertions(+), 4 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index ab75826..49880f3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -20,6 +20,9 @@ ETAF 当前性能工作的最终结果是:通用性能工具能解释每次操 不把偶然的调用顺序、示例名称或当前数据形状伪装成抽象。 - 一个模块只拥有一项完整职责,并为这项职责提供少量、精确、正交的接口。 接口之间通过明确数据契约组合,不读取彼此的内部状态,不复制彼此的规则。 +- 用户心智成本是公共 API 的硬指标。同一能力只能有一个规范名称和一条推荐路径; + 内部算法、后端节点、兼容别名和便捷 wrapper 不得伪装成并列公共概念。常用路径 + 只要求学习最小模型,高级能力通过逐层展开获得,不能让用户先理解包内部实现。 - 区分语义身份、视觉槽位、布局坐标、绘制层和发布权限。只有模型本身允许时 才能合并概念;不能为了减少代码把不同生命周期的身份混在一起。 - 复杂系统通过小模块的组合与复用逐步形成。新增能力应优先扩展已有模型的 diff --git a/docs/proposals/module-boundaries.en.md b/docs/proposals/module-boundaries.en.md index b2c0b2e..cd04523 100644 --- a/docs/proposals/module-boundaries.en.md +++ b/docs/proposals/module-boundaries.en.md @@ -8,6 +8,11 @@ This document defines only the target model, module owners, dependency direction completion criteria. Delivery sequencing belongs in a separate implementation plan; historical names and compatibility do not shape the target architecture. +User mental cost is a hard constraint: one capability has one canonical name and one +recommended spelling. Internal algorithms, backend nodes, wrappers, and compatibility +aliases never become peer public concepts. Ordinary applications learn Text, Box, and +Component first; Fragment, layout detail, and lower packages are progressively disclosed. + ## 1. Final model ```text @@ -92,7 +97,51 @@ child's `:outer` does not change ordering. `:outer` is consumed only by a normal They are Box modes, not Components or alternate Runtime node names. The only canonical surface is `(box :layout 'MODE ...)`; core provides no layout-name aliases. -### 2.5 Fragment +### 2.5 Ebox DSL primitives and sugar + +ETAF View and Ebox DSL are different layers: ETAF has Text/Box/Fragment/Component, +while Ebox receives lowered content and layout. The target Ebox DSL has one structural +tag: + +```elisp +(box :layout MODE ...) +``` + +An Ebox box may be a content leaf or own children and a layout context. A Range +descriptor is an incremental backend protocol, not an authoring node. A bare string is +content-literal shorthand, not a node type. + +Current tags classify as follows: + +| Current tag | Classification | Target expression | +| --- | --- | --- | +| `ebox` | compatibility alias for `box` | remove; use `box` | +| `spacer` | empty-Box convenience sugar | remove; use a childless `box` | +| `row` | layout-tag sugar | `(box :layout 'row ...)` | +| `column` | layout-tag sugar | `(box :layout 'column ...)` | +| `flex` | layout-tag sugar | `(box :layout 'flex ...)` | +| `grid` | layout-tag sugar | `(box :layout 'grid ...)` | +| `item` | Flex-child participation sugar | put flex/order/align-self properties on the child Box | +| `grid-item` | Grid-child placement sugar | put grid placement properties on the child Box | + +Item wrappers are therefore unnecessary. Parent-participation properties belong to +the child Box and are validated by the parent layout mode: + +```elisp +(box :layout 'flex + (box :flex-grow 1 :content "A")) + +(box :layout 'grid + (box :grid-column '(1 :span 2) :content "Header")) +``` + +These are low-level Ebox examples, so Ebox `:content` is valid. ETAF View continues to +use Text/children and does not expose `:content`. + +The target Ebox DSL retains none of those aliases or sugar tags. Ebox still implements +the layout algorithms independently, but algorithm kinds are not authoring node kinds. + +### 2.6 Fragment Fragment is a nonvisual structural Range. It may contain zero, one, or many sibling Views, creates no Box or layout context, and may carry only a stable `:key` plus @@ -101,7 +150,7 @@ children. Runtime may retain and replace its Range independently. A Component call has no fixed outer/layout properties. Its root Text/Box determines participation. A transparent Component returning a Fragment may have multiple roots. -### 2.6 Strings, content, and empty Boxes +### 2.7 Strings, content, and empty Boxes Strings under a Box normalize to Text, so `(box "text")` equals `(box (text "text"))`. ETAF does not expose `(box :content ...)`; `:content` remains an @@ -269,6 +318,10 @@ Current code still registers `text`, `fragment`, `container`, `row`, `column`, ` `:layout 'normal` are not implemented, and the target public View does not retain `raw-ebox`. +Current Ebox DSL still accepts `box`, `ebox`, `row`, `column`, `flex`, `item`, `grid`, +`grid-item`, and `spacer`. The target Ebox DSL keeps only `box`; all other tags are +removed or represented as Box properties according to the table above. + This is a clean redesign: old Host names and old `.etaf` sources need not continue to run, and no long-lived compatibility layer is added. Formal architecture/user docs must not present target syntax as delivered before implementation is complete. diff --git a/docs/proposals/module-boundaries.zh.md b/docs/proposals/module-boundaries.zh.md index d102caa..dc34695 100644 --- a/docs/proposals/module-boundaries.zh.md +++ b/docs/proposals/module-boundaries.zh.md @@ -7,6 +7,10 @@ 本文只定义目标模型、模块 owner、依赖方向和完成条件。实现顺序属于单独的 实施计划;历史名称和兼容策略不参与目标架构设计。 +用户心智成本是本提案的硬约束:同一能力只有一个规范名称和一种推荐写法;内部 +算法、后端节点、wrapper 和兼容别名不能作为并列公共概念。普通应用只需学习 +Text、Box、Component;Fragment、布局细节和底层包通过渐进披露进入。 + ## 1. 最终模型 ETAF 的表示链只有四层: @@ -117,7 +121,50 @@ run-in、list-item 或任意匿名盒规则。Ebox 可以把 `normal` 映射为 (box :layout 'grid ...) ``` -### 2.5 Fragment +### 2.5 Ebox DSL 的基础节点与语法糖 + +ETAF View 和 Ebox DSL 是两层不同接口:ETAF 有 Text/Box/Fragment/Component; +Ebox 只接收已经降低的内容与布局。目标 Ebox DSL 只有一个基础结构 tag: + +```elisp +(box :layout MODE ...) +``` + +Ebox `box` 可以是 content leaf,也可以包含 children 并建立布局上下文。Range +descriptor 是增量后端协议,不是作者 DSL 节点;裸字符串只是 content literal +简写,也不是节点类型。 + +当前 DSL 的其他 tag 必须明确分类,不能与基础节点并列: + +| 当前 tag | 分类 | 目标表达 | +| --- | --- | --- | +| `ebox` | `box` 的兼容别名 | 删除,统一写 `box` | +| `spacer` | 空 Box 便捷糖 | 删除,使用无 children 的 `box` | +| `row` | layout tag 糖 | `(box :layout 'row ...)` | +| `column` | layout tag 糖 | `(box :layout 'column ...)` | +| `flex` | layout tag 糖 | `(box :layout 'flex ...)` | +| `grid` | layout tag 糖 | `(box :layout 'grid ...)` | +| `item` | Flex child participation 糖 | 把 `:flex-*`、`:order`、`:align-self` 直接写在 child Box | +| `grid-item` | Grid child placement 糖 | 把 `:grid-*` placement 直接写在 child Box | + +因此 `item` 和 `grid-item` 不是必要 wrapper。父级参与属性属于 child Box,并由 +父级 layout mode 验证: + +```elisp +(box :layout 'flex + (box :flex-grow 1 :content "A")) + +(box :layout 'grid + (box :grid-column '(1 :span 2) :content "Header")) +``` + +以上示例是 Ebox 低层 DSL,因此可以使用 Ebox 的 `:content`;ETAF View 仍然只用 +Text/children,不暴露 `:content`。 + +目标 Ebox DSL 不保留上述兼容别名或糖。布局算法仍由 Ebox 分别实现,但节点 +分类只保留 `box`;算法种类不等于作者节点种类。 + +### 2.6 Fragment `Fragment` 是无视觉 wrapper 的结构 Range: @@ -130,7 +177,7 @@ Component call 本身没有 `:outer` 或 `:layout`。它的根 Text/Box 决定 布局;返回 Fragment 的透明 Component 可以产生多个兄弟节点,因此不存在单一的 “Component 外部盒子”。 -### 2.6 字符串、content 与空 Box +### 2.7 字符串、content 与空 Box Box 子节点中的字符串规范化为 Text: @@ -336,6 +383,10 @@ Component identity、依赖所有权、TP 优先级和 generation authority 不 `flex`、`grid` 和 `spacer`,并提供 `raw-ebox`;目标 `box`、`:outer`、 `:layout 'normal` 尚未实现,目标公共 View 也不保留 `raw-ebox`。 +当前 Ebox DSL 仍接受 `box`、`ebox`、`row`、`column`、`flex`、`item`、`grid`、 +`grid-item` 和 `spacer`。目标 Ebox DSL 只保留 `box`;其他 tag 按上表删除或改为 +Box 属性。 + 这是干净重设计,不要求旧 Host 名称或旧 `.etaf` 文件继续运行,也不增加长期 兼容层。实现完成前,正式架构和用户指南不得把目标语法描述成当前 API。