ebox/docs/user/ebox-api-reference.zh.md
2026-08-26 00:09:53 +08:00

30 KiB
Raw Blame History

Ebox 公共 API 参考

English

本文是独立 Ebox 包面向用户的完整清单覆盖节点模型、property、布局 辅助函数、渲染/发布、selector、滚动、测量、DSL 和可选 native 模块。 ebox--* 名称与没有在本文说明的模块辅助函数属于实现细节。加载 (require 'ebox) 后,也可以通过 ebox-public-api 查看门面入口清单。

Ebox 负责 box node、样式归一化、测量、布局、渲染、语义更新规划、selector 适配、Grid 和可选 Rust reflow 加速器。TP 负责 live buffer 发布、物理 diff、 revision 和 rollbackECSS 负责 selector 解析、匹配与 cascade。Ebox 不提供 Component、应用状态、UI control 或应用生命周期。

1. 安装与加载

Ebox 需要 Emacs 29.1 或更新版本,以及 ECSS 和 TP。使用同级源码 checkout

(add-to-list 'load-path "/path/to/github/ecss")
(add-to-list 'load-path "/path/to/github/tp")
(add-to-list 'load-path "/path/to/github/ebox")
(require 'ebox)

加载 Ebox 会加载 Elisp 布局/runtime 模块,但不会创建 buffer、在当前 buffer 启用 mode、构建 Rust 或修改当前编辑 buffer。可选 native 模块只在其工作流 或合资格的 native 路径需要时加载。

2. 常规生命周期

公共工作流如下:

(let ((root
       (ebox-column
        (ebox-create :id "status" :content "Ready" :width '(240))
        (ebox-create :content "调用者拥有的 source tree"))))
  ;; 纯 materialization返回多行带属性字符串。
  (ebox-render root)

  ;; retained TP surface返回 live buffer。
  (ebox-render-to-buffer "*Ebox Demo*" root)

  ;; 后续构造新的声明式根树并原子发布。
  (ebox-commit
   "*Ebox Demo*"
   (ebox-column
    (ebox-create :id "status" :content "Updated" :width '(240))
    (ebox-create :content "未修改调用者的 source tree。"))))

ebox-render 不产生 live buffer 副作用。没有 active stylesheet 和 inline 继承样式依赖的静态树可以使用隔离的 pure materialization依赖 stylesheet 的 pure render 使用临时 TP materialization。两者都遵守同一个公共字符串 契约。两个 buffer 入口都使用 retained TP surface。Ebox 会在分配 runtime identity 前复制声明式输入,因此同一 source tree 可以挂载到多个 buffer。

ebox-display-buffer 是同时需要展示 buffer 时的便捷包装;它会先删除其他 window再切换到渲染后的 buffer。如果窗口选择由调用方负责应使用 ebox-render-to-buffer

3. 节点与组合

Box 与简单布局构造器

(ebox-create &rest properties)
(ebox-concat node-1 node-2)       ; 两个节点横向排列
(ebox-stack node-1 node-2)        ; 两个节点纵向排列
(ebox-row &rest nodes)             ; 多个节点横向排列;单个 Range 仍保留 row parent
(ebox-column &rest nodes)          ; 多个节点纵向排列;单个 Range 仍保留 column parent
(ebox-spacer &rest properties)    ; 空白 box

ebox-create 返回声明式 box node。:content 是字符串内容;容器子节点通常 交给 ebox-rowebox-columnebox-flexebox-gridebox-concatebox-stack 接受两个节点;超过两个子节点时使用 row/column。nil 子节点会 被忽略;空 row/column 会变成 spacer。

row 中省略或 auto 的宽度按子节点自身的 intrinsic width 参与横向拼接; 父级 viewport 不会被重复当成每个子节点的宽度。显式 viewportstretch 或 definite width 仍按指定 containing block 解析。column 会把较窄的布局 行补齐到自己的 containing block但带视觉 box 的子节点会在自己的 used width 上绘制边框和 padding。

:key 是兄弟节点范围内的稳定业务 identity:id 是 logical selector/update 标识;:host-ref 是应用拥有的不透明锚点,用于 host-reference 查询和逻辑 candidate replacement。一个 source tree 内的非 nil host-ref 必须唯一。

Flex

(ebox-flex
 :width '(480)
 :flex-flow '(row wrap)
 :gap '(1 (12))
 (ebox-flex-item (ebox-create :content "A")
                 :flex '(1 1 auto)
                 :align-self 'center)
 (ebox-create :content "B" :flex-grow 2))

容器 property 是 :flex-direction:flex-wrap:flex-flow:justify-content:align-items:align-content:gap:row-gap:column-gap,另加 :width:height、padding、border、paint 等普通 box property。默认方向是 row、nowrap主轴是 flex-start交叉轴是 stretch。

item property 是 :order:flex:flex-grow:flex-shrink:flex-basis:align-self。它们可以直接放在 child box 上,也可以通过 ebox-flex-item 附加。传给 ebox-flex-item 的非 item property 会在 child 外包一层普通 box。

Flex preferred/min/max size 支持 Ebox 子集:automin-contentmax-contentfit-contentstretchcontainmax-size 还支持 nonefit-content 可以带数字或 viewport 相对限制。这些是 Ebox 布局值, 不表示完整浏览器 CSS 兼容性。

Grid

(ebox-grid
 :width '(640)
 :grid-template-columns '((200) 1fr 1fr)
 :grid-template-rows '(1 1)
 :gap '(1 (12))
 (ebox-grid-item
  (ebox-create :content "Header")
  :grid-column '(1 :span 3))
 (ebox-create :content "Main" :grid-column 1 :grid-row 2)
 (ebox-create :content "Aside" :grid-column 2 :grid-row 2))

ebox-grid-fr 构造分数轨道:(ebox-grid-fr 2) 返回 (fr 2)。Grid 轨道支持 固定尺寸、auto(fr FACTOR)1fr 这样的 symbol、minmaxrepeat。 没有显式给出的行列使用隐式轨道;:grid-auto-columns:grid-auto-rows:grid-auto-flowrowcolumn)控制隐式放置。

Grid placement 从 1 开始。:grid-column:grid-row 接受正整数起点、 (start :span 正整数),或 start 小于 end(start end):grid-column-span:grid-row-span 接受正整数。ebox-grid-item 是便捷 包装器placement property 也可以直接放在 child node 上。

4. 单位、box property 与文本属性

尺寸单位

含义
普通横向数字,例如 12 字符列数,按当前 display 的空格宽度转换。
单元素横向 list例如 '(240) 绝对像素。
纵向数字,例如 3 行数。
(viewport)viewport 当前 viewport 的像素宽度。
(viewport-height)viewport-height 当前 viewport 的行高。
automin-contentmax-contentfit-contentstretchcontain 在对应 property 与 formatting context 支持时使用 intrinsic/preferred width。

:box-sizing 默认是 border-box,也支持 content-box。宽度 property 是 :width:min-width:max-width;高度 property 是 :height:min-height:max-height。几何负值会被拒绝。依赖 viewport 的节点要在 viewport context 中渲染,或通过 ebox-rerender-buffer-with-context 重排。

Box、paint 与文本 property

以下名称可用于 ebox-create。Stylesheet 规则使用其中的 style/geometry propertyebox-region-update 接受其目标支持的可变 content/style/scroll 子集。Direct update 不会添加 child 或修改 selector metadata结构变化使用 ebox-commit 或 logical candidate。结构 metadata、:content:surface-properties 是节点/render 输入,不是 stylesheet declaration。表中 同时列出 canonical 名称与兼容别名。

范围 Property
Content/geometry :content:box-sizing:width:min-width:max-width:height:min-height:max-height
Padding :padding:padding-inline:padding-blocklonghand :padding-block-start:padding-inline-end:padding-block-end:padding-inline-start;别名 :padding-top:padding-right:padding-bottom:padding-left,以及 :padding-right-pixel:padding-left-pixel:padding-top-height:padding-bottom-height
Margin :margin:margin-inline:margin-blocklonghand :margin-block-start:margin-inline-end:margin-block-end:margin-inline-start;别名 :margin-top:margin-right:margin-bottom:margin-left,以及 :margin-right-pixel:margin-left-pixel:margin-top-height:margin-bottom-height
Border :border:border-top:border-right:border-bottom:border-left:border-width:border-style:border-colorside longhand :border-*-width:border-*-style:border-*-color;兼容别名 :border-top-p:border-bottom-p:border-left-pixel:border-right-pixel
Paint :color:background-color、别名 :bgcolor
Typography :font:font-family:font-height 和别名 :font-size:font-weight:font-slant
Text/layout :text-alignleftcenterright)、:vertical-aligntopcenter/middlebottom)、:overflowscrollhiddenvisible)、:wrap-modewordcharkp 或 nil:visibilityvisiblehidden
Structural style :display 会在 node/layout context 中计算;有效的 display tuple 通常由布局构造器选择。
Flex container/item :flex-direction:flex-wrap:flex-flow:justify-content:align-items:align-content:gap:row-gap:column-gap(别名 :grid-row-gap:grid-column-gapitem 名称 :order:flex:flex-grow:flex-shrink:flex-basis:align-self
Grid container/item :grid-template-columns:grid-template-rows:grid-auto-columns:grid-auto-rows:grid-auto-flow:justify-itemsitem placement :grid-column:grid-row:grid-column-span:grid-row-span
额外文本属性 :surface-properties 接受偶数长度的 Emacs text-property plist应用到不含换行的渲染字符内层非 nil 属性优先。

Box 字体入口是 :font,不是 :face:font 接受 Emacs face symbol、face 名称字符串或 face plisttypography longhand 会合并到该 face。:visibility 'hidden 会隐藏 ink但保留布局 footprint 与 metadata。:overflow 'visible 会发布超出高度的可见行;hidden 会裁剪;scroll 暴露有限窗口,并在内容 高于 box 时启用 Ebox 滚动。

Padding 与 margin 使用 CSS 的 14 值展开。横向值使用上述横向单位,顶部和 底部使用行单位。左右 border 是像素几何;上下 border 通过 Emacs overline/ underline face 实现,因此宽度是存在性标志而非任意像素厚度。

Node metadata 与 selector 输入

这些输入用于标识节点,不会直接改变几何:

输入 含义
:id logical selector/update id。symbol 和其他标量会归一化为字符串;直接 update 解析时应保持 id 唯一。
:key reconciliation 使用的稳定兄弟 identity同时作为内建 selector :key attribute 暴露。
:class 一个 class token 或 class token 列表,用于 selector matching。
:selector-state 一个 state token 或 state token 列表,用于匹配 :hover:active 等 state pseudo。
:selector-attributes 显式 attribute alist例如 ((role . button))content、布局值和 runtime 字段不会自动推断。
:host-ref 应用拥有的唯一不透明 anchor用于 ebox-host-ref-positionebox-host-ref-bounds 和 host-ref candidate replacement。
:scroll-offset scroll region 的初始/受控行偏移。交互优先使用滚动命令update 必须使用 live region handle。

:id:key:host-ref 不是 stylesheet declaration。:class:selector-state:selector-attributes 是 selector metadata不是通用 应用状态。

5. Stylesheet 与 cascade

多数节点只需 inline property。需要 selector 驱动样式时使用隔离的 Ebox stylesheet

(ebox-style-reset-rules)
(ebox-style-add-rule
 ".card"
 '(:color "#1F2937"
   :background-color "#F8FAFC"
   :padding '(1 (12)))
 :layer 'base)
(ebox-style-add-rule
 ".card:has(> .warning)"
 '(:border-color "#DC2626")
 :layer 'state)

ebox-style-add-rule 接受 selector string 或 AST、Ebox declaration plist 以及 ECSS cascade 关键字 :origin:layer:scopeebox-style-reset-rules 清空 stylesheet。规则属于已加载的全局 Ebox style registry改变规则不会自动发布已有 mounted buffer因此规则变化后要对 目标 buffer rerender 或 commit。ebox-style-cascade-active-p 可检查当前 是否存在规则。

基于 ECSS 的 style domain 包含 color 与 typography inheritance、computed value、cascade layer、custom-property declaration以及 paint/geometry/ structure dirty 分类。Ebox 只解释本文列出的 property百分比、绝对定位、 z-index、阴影、border radius、浏览器级 bidi 和完整浏览器 typography 不属于 本包。

名称以 -- 开头的 custom property 可以由 ECSS style domain 携带,但除非宿主 集成把它解析为本文支持的 Ebox property否则不会影响 Ebox 输出。

6. 渲染、identity 与更新

Region id 与 logical handle

ebox-region-ids 会从未渲染树或已渲染字符串按文档顺序返回 region id。需要 低层 source 映射时,在第一次 mount 前捕获:

(let* ((root (ebox-column
              (ebox-create :id "title" :content "Title")
              (ebox-create :id "body" :content "Body")))
       (ids (ebox-region-ids root)))
  (ebox-render-to-buffer "*Ebox Demo*" root)
  ids)

应用更新优先使用 logical id 与不透明 handle

(let ((handle (ebox-region-resolve "*Ebox Demo*" "body")))
  (ebox-region-update handle :content "Changed" :color "#166534"))

ebox-region-resolve 在 buffer 不存在、logical id 缺失或 id 有歧义时发出 错误。Handle 绑定一个 retained TP surface对象移除或 buffer kill 后会 stale。 数字 region id 是渲染 metadata不能作为 ebox-region-update 的参数。

Direct 与 selector 更新

ebox-region-update 接受可变 content/style/scroll property 关键字;除非处于 显式 batch否则返回已提交的 update report。它先构造隔离 candidate规划 最小安全 Ebox owner再请求 TP 发布一次。它不会添加 child也不会修改 :id:class:key 或其他 selector metadata。非法 declaration、render 失败、publication 失败或 callback 失败都会保留原 buffer/runtime/report。

ebox-selector-update-buffer 把 property 应用到 buffer 中所有可编辑的 selector match返回

(:selector SELECTOR
 :matched INTEGER
 :updated INTEGER
 :skipped ((:node-id ID :reason no-region) ...)
 :reports (REPORT ...))

显式多更新 batch 只有在应用确实拥有该边界时才使用较低层 incremental batch 函数;一般场景使用 ebox-selector-update-buffer

Logical candidate

Candidate 是基于当前已发布 runtime 的一次性 transaction。多个稳定 subtree 需要一起替换并只提交一次时使用:

(let* ((buffer (get-buffer "*Ebox Demo*"))
       (candidate (ebox-candidate-begin buffer))
       (match (car (ebox-selector-query-buffer buffer "#body"))))
  (ebox-candidate-replace
   candidate
   (plist-get match :node-id)
   (ebox-create :id "body" :content "Candidate replacement"))
  (ebox-commit buffer candidate))

如果框架的 semantic owner 与 backend anchor 分离,可在选择更宽的发布 owner 之前使用只读函数 ebox-range-ref-present-p。当 semantic Range 嵌套在 material anchor 内、当前 Ebox publication 没有独立地址时,它返回 nil。

ebox-candidate-replace-host-ref 使用应用拥有的 :host-ref,不需要 runtime node id。两个 replacement 函数都接受可选的 old-semantic-keynew-semantic-key,用于有限的 detached identity 复用。Candidate 在 commit 时 sealed不能复用若捕获的 runtime 或 buffer tick 发生变化,它也会 stale。

ebox-candidate-patch-host-paint 比较前后 declarative Host 输出;只有全部变化 都属于 node-local paint 时才记录属性 patch。它保留子树与 runtime identity 并在一次受影响子树遍历中更新继承前景;需要普通子树替换时返回 nil。

ebox-candidate-replace-root 使用私有且绑定 candidate 的 root 地址。它只接受 一个声明式节点、清除调用方 runtime identity并采用 last-wins 语义。最终 root replacement 会吸收其前后记录的 descendant node/host-ref operation不添加 wrapper也不暴露公共 reference。

ebox-child-range 在 material child list 中创建非节点 segment descriptor。 其非 nil ref 在 root 内全局唯一items 直接参与 parent 的 key、selector、style 与 layout scope。ebox-candidate-replace-range-ref 接受 proper declarative node list只替换该 base payloadempty payload 仍可寻址。

Host-reference 位置

(ebox-host-ref-position "*Ebox Demo*" 'toolbar)
;; => 第一个 live 字符位置,或 nil
(ebox-host-ref-bounds "*Ebox Demo*" 'toolbar)
;; => (START . END),不含 margin或 nil

位置与 bounds 属于当前 publication generation每次更新后都要重新获取。 Host-reference table 与 logical selector id 是两套不同的机制。

Report 与 viewport reflow

如果上层框架在调用 Ebox 前需要先分配新的 view tree可以把整个输入 callback 纳入 Ebox 的 render GC budget

(ebox-call-with-render-burst
 (lambda ()
   (let ((next-root (build-framework-view)))
     (ebox-commit buffer next-root))))

优先使用能保证异常清理的 ebox-call-with-render-burst。如果操作无法表达为 一次函数调用,ebox-render-burst-begin 会返回交给 ebox-render-burst-end 的不透明 token调用方必须使用 unwind-protect,并按 后进先出顺序结束嵌套 token。交互 burst 与 Ebox commit 共用 deferred state 在最外层 end 后 0.2 秒恢复调用方 GC 设置;新 burst 会取消并取代待执行的 restore。Batch burst 立即精确恢复 threshold 与 percentage且不会在边界主动 执行 GC。这些函数只定义 allocation/GC ownership不会 publish、commit也 不会暴露 Ebox runtime state。

ebox-buffer-update-report 返回 mounted buffer 上一次成功报告的 defensive copy目标缺失或不是 Ebox runtime 时会报错。首次 mount 在第一次 update 前没有 update report。报告包含 Ebox strategy、publication scope、TP surface revision、物理 operation 和 reconciliation 事实。

完整签名是 (ebox-commit BUFFER NEXT-ROOT &optional FRAMEWORK-PUBLISH FRAMEWORK-ROLLBACK)。buffer、TP surface 与 Ebox runtime 一致后publish 接收 report若后续 phase 失败rollback 最多一次接收同一个 report其 error/quit 会被隔离。:framework-participant-state:framework-participant-diagnostics:scroll-finalization-diagnostics 是只读 outcome 字段。

当 root 依赖新的 viewport 时使用 ebox-rerender-buffer-with-context

(ebox-rerender-buffer-with-context
 (get-buffer "*Ebox Demo*")
 800                         ; viewport 像素宽度
 30)                         ; 可选 viewport 行高

该调用保留 node/region identity并通过 viewport dirty planning 处理变化。 (viewport)(viewport-height) 从该 context 解析。纯渲染时也可以在 render 外部动态绑定 ebox-viewport-width(像素)与 ebox-viewport-height (行数)。不要原地修改已经发布的 node tree。

可见的 mounted buffer 会自动跟随展示它的 window。Ebox 通过 retained 增量路径 立即发布每个 size event。Emacs hook 串行执行并拒绝重入;这里没有第二套宿主 hook、timer 或 viewport queue。 ebox-viewport-window-width 返回 controller 使用的同一个显示安全像素宽度; 宿主不应再安装第二套 resize hook 或宽度算法。 旧的 ebox-viewport-resize-delay 已删除;立即发布不再需要迁移 timer 配置。

7. Selector

ebox-selector-parse 委托 ECSS 并返回结构化 AST ebox-selector-match-node-p 匹配单个声明式节点;ebox-selector-query-all 从未 mounted tree 返回按文档顺序的 matchebox-selector-query-buffer 查询 live buffer 的 retained runtime并给每条 match 添加 :buffer,可编辑节点 还会添加 :region-handle

ECSS 支持的 selector 语法包括:

  • selector list、compound type/id/class selector
  • attribute presence 与 =~=|=^=$=*=,以及 i/s flag
  • 通过 :selector-state 提供的 :hover:active 等 state pseudo
  • :is(...):where(...):not(...) 与 relational :has(...)
  • 空格 descendant、子节点 >、相邻兄弟 +、一般兄弟 ~ combinator。

Ebox 的 node type 会映射为 selector typeboxrowcolumnflexgriditem:id:key 是内建 attribute额外 attribute 必须显式 传入,例如 :selector-attributes '((role . button))。可见 content、布局 值和内部 runtime slot 不会被推断成 selector attribute。

(ebox-selector-query-buffer "*Ebox Demo*" ".toolbar > box.action")
(ebox-selector-query-buffer "*Ebox Demo*" "div:has(> .warning)")
(ebox-selector-update-buffer "*Ebox Demo*" "[role=button]"
                             :color "#2563EB")

兼容别名 ebox-select-allebox-update-selector 分别指向 ebox-selector-query-bufferebox-selector-update-buffer

8. 滚动与 viewport state

设置 :overflow 'scroll(默认值)和有限的 :height 创建滚动窗口:

(ebox-create
 :id "log"
 :width '(420)
 :height 8
 :overflow 'scroll
 :content (mapconcat #'identity lines "\n"))

ebox-scroll-downebox-scroll-upebox-scroll-page-downebox-scroll-page-up 操作 point 所在的最内层滚动区域;找不到可消费该命令 的 Ebox region 时委托普通 Emacs scrolling。ebox-wheel-scroll-downebox-wheel-scroll-up 接受 mouse eventebox-wheel-smooth-scroll 非 nil 时会分步动画,否则委托 mwheel-scrollebox-buffer-mode 在本地安装 ebox-scroll-mapebox-render-to-buffer 会在返回的 buffer 上启用该 mode。

ebox-scroll-state 接受数字 region id返回用于 source-model 映射的只读 state plist。可用事实包括 :scroll-offset、content height/lines 与缓存的 visible lines。把 plist 当作 diagnostic/read-only 数据;用 ebox-region-update:scroll-offset 或滚动命令改变位置。

Scroll content 会惰性预取,并按有界 slice 渲染。安全的 retained update 会 保留缓存 scroll state发布失败时它与其他 runtime 状态一起 rollback。

9. 测量与缓存配置

ebox-string-pixel-width 返回字符串第一行的 display 像素宽度,同时考虑 text scale 和固定 display space它也是布局使用的公共测量原语。 ebox-display-signature 返回测量缓存使用的当前 display 输入。 如果在正常 display-signature 信号之外修改了字体或 named face可调用 ebox-clear-cache

主要 customization 变量如下:

分组 变量与默认值
Render cache ebox-render-cache-max-entries 2048ebox-render-cache-max-bytes 32 MiBebox-render-root-cache-max-entries 16ebox-render-root-cache-max-bytes 8 MiB
键盘/鼠标滚动 ebox-scroll-step 1ebox-wheel-scroll-step 1ebox-wheel-smooth-scroll nilebox-wheel-smooth-scroll-interval 0.016ebox-wheel-smooth-scroll-lines-per-tick 4ebox-wheel-smooth-scroll-target-ticks 8。键盘以 point 为 anchor滚轮以 event 位置为 anchor剩余行沿嵌套 owner 向外冒泡。交互式、内容完整且无 chrome 的根 document owner 可在 idle 时一次 materialize之后使用 Emacs 原生 window line start普通更新/resize 只预热 retained index不启动第二次 native publication嵌套/lazy/chrome owner 继续走事务化 Ebox publication。
Lazy scroll ebox-scroll-lazy-prefix-lookahead-lines 8ebox-scroll-lazy-idle-prefetch-lines 128ebox-scroll-lazy-idle-prefetch-slice-lines 16ebox-scroll-lazy-idle-prefetch-delay 0.15
Runtime prewarm ebox-runtime-idle-prewarm tebox-runtime-idle-prewarm-delay 0.1ebox-runtime-idle-prewarm-prefix-resume-delay 2.0ebox-runtime-idle-prewarm-slice-size 32ebox-native-buffer-scroll t仅 initial/visible-window handoff严格 root-owner proof
预测 reflow ebox-runtime-idle-reflow-cache-prewarm tebox-runtime-idle-reflow-cache-prewarm-delay 0.15
Reflow GC ebox-reflow-cache-prewarm-gc-cons-threshold autoebox-reflow-cache-prewarm-gc-auto-frame-budget 0.2ebox-reflow-cache-prewarm-gc-auto-min-threshold 64 MiBebox-reflow-cache-prewarm-gc-auto-max-threshold 1 GiBebox-reflow-cache-prewarm-gc-auto-initial-threshold 512 MiBebox-reflow-cache-prewarm-gc-auto-target-layouts 24ebox-reflow-cache-prewarm-gc-cons-percentage 0.1
Visual verification ebox-visual-check-output-dir 指向可选 screenshot/report 使用的临时目录。

Idle prewarm 不会发布 buffer text 或 runtime state。宿主应用不希望后台准备 工作时,可把对应的 boolean 设为 nil。

10. 独立 .ebox DSL

ebox-build 编译数据型 list form。支持的 tag 是 box/eboxrowcolumnflexitemgridgrid-itemspacer

(ebox-build
 '(grid :width (640)
        :grid-template-columns ((200) 1fr 1fr)
        :gap (1 (12))
        (grid-item :grid-column (1 :span 3)
                   (box :content "Header"))
        (box :content "Main")))

box 下的直接字符串会合并为换行内容child form 会变成默认纵向 child layout。rowcolumn 可以接收 box property 并包住 child layoutflex 接收容器 propertyitem 接收 flex item propertygrid-item 必须有一个 childspacer 不能有 child。

.ebox 文件中,结构 form 保持不加 quoteproperty 位置的 list 和 symbol 常量要作为 data quote例如 :gap '(1 (12)):justify-content 'center 要执行的 Elisp property expression 保持不 quote交给同级 playground runner 求值。

11. 可选 Rust reflow

Native 模块是加速器不是正确性的依赖。Rust 边界只接收有界的数值布局工作; Ebox 保留完全等价的 Elisp fallback加载时绝不构建 Rust。

(ebox-native-status)       ; 显示 toolchain、路径、ABI 与加载诊断
(ebox-native-build)        ; 异步构建/安装
(ebox-native-build t)      ; 先清理 Ebox 私有 Cargo cache

仓库命令是 make native-build。使用 ebox-native-reflow-module-path 配置 module 文件或目录。Session 限制为 ebox-native-reflow-max-jobs 512、 ebox-native-reflow-max-results 512、ebox-native-reflow-max-result-bytes 64 MiB。模块缺失或 ABI 不兼容时继续使用 Elisp原因可由 ebox-native-status 查看。

ebox-byte-compile 会重新编译所有 active Ebox Elisp 源码,但不会构建 Rust。 成功后如需当前进程加载新的 .elc,请重启 Emacs。

12. 公共函数清单

下表覆盖门面清单中的公共函数;其下列出的 style-rule 函数是模块级公共 style API。

函数 用途
ebox-createebox-build 创建节点或编译 .ebox list DSL。
ebox-concatebox-stackebox-rowebox-columnebox-spacer 组合简单横向/纵向布局与空白 box。
ebox-flexebox-flex-item 构建 Flex 容器与 item metadata。
ebox-gridebox-grid-frebox-grid-item 构建 Grid、分数轨道和 placement metadata。
ebox-renderebox-render-to-bufferebox-display-buffer 纯 materialization、retained mount 与展示包装。
ebox-commitebox-buffer-update-reportebox-rerender-buffer-with-contextebox-viewport-window-width 原子根提交、报告查询、viewport-context rerender 与统一的显示安全宽度采样。
ebox-region-idsebox-region-resolveebox-region-update Region 映射、logical handle 查询与直接更新。
ebox-child-rangeebox-range-ref-present-pebox-candidate-beginebox-candidate-replaceebox-candidate-replace-range-refebox-candidate-replace-rootebox-candidate-replace-host-refebox-candidate-patch-host-paint 持久 material child segment、backend anchor 查询、子树替换与 retained Host paint transaction。
ebox-host-ref-boundsebox-host-ref-position Host-reference 的 live bounds 与首位置。
ebox-selector-parseebox-selector-match-node-pebox-selector-query-allebox-selector-query-bufferebox-selector-update-buffer ECSS selector 编译、匹配、查询与批量更新。
ebox-select-allebox-update-selector 两个 buffer selector 函数的兼容别名。
ebox-buffer-modeebox-scroll-mapebox-scroll-downebox-scroll-upebox-scroll-page-downebox-scroll-page-upebox-wheel-scroll-downebox-wheel-scroll-upebox-scroll-state 交互滚动、本地 keymap 与只读滚动状态。
ebox-string-pixel-widthebox-display-signatureebox-clear-cache Display-aware 测量与缓存管理。
ebox-native-buildebox-native-statusebox-byte-compile 可选 native 工作流与 Elisp byte compile。

加载 (require 'ebox) 后可用的 style inspection/rule 入口还包括 ebox-style-add-ruleebox-style-reset-rulesebox-style-cascade-active-pebox-style-computeebox-style-expand-shorthandsebox-style-compile-declarationsebox-style-merge-declarationsebox-style-compute-subjectebox-style-propertyebox-style-canonical-nameebox-style-dirty-kind。前两个是应用通常使用的入口;其余函数供需要检查 或准备 ECSS-backed style data 的集成使用。

13. 验证与支持边界

在仓库根目录运行:

make load EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs
make compile EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs
make check EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs
make docs-contract-tests EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs
make native-rust-tests

聚焦目标包括 make core-testsmake grid-testsmake surface-testsmake selector-testsmake dsl-testsmake flex-testsmake visual-check-tests。可运行的 .ebox 示例由同级 ebox-playground 包负责ETAF 负责 Component、state、control 和应用行为。本包不要调用 私有 ebox--* 函数,也不要在 Ebox 任务中编辑历史 Ebox checkout。