feat: retain Row and Column within canonical Box identity
This commit is contained in:
parent
b530b0513c
commit
53001719c4
@ -587,7 +587,7 @@ style-rule functions immediately below are public module-level style APIs.
|
|||||||
|
|
||||||
| Function | Use |
|
| Function | Use |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `ebox-text-create`, `ebox-normal-layout-create`, `ebox-box-create` | Framework-integration port for typed TextNode, Normal LayoutConfig, and BoxNode values. |
|
| `ebox-text-create`, `ebox-normal-layout-create`, `ebox-row-layout-create`, `ebox-column-layout-create`, `ebox-box-create` | Framework-integration port for typed TextNode, Normal/Row/Column LayoutConfig, and BoxNode values. |
|
||||||
| `ebox-create`, `ebox-build` | Create a legacy node or compile the `.ebox` list DSL during migration. |
|
| `ebox-create`, `ebox-build` | Create a legacy node or compile the `.ebox` list DSL during migration. |
|
||||||
| `ebox-concat`, `ebox-stack`, `ebox-row`, `ebox-column`, `ebox-spacer` | Compose simple horizontal/vertical layouts and blank boxes. |
|
| `ebox-concat`, `ebox-stack`, `ebox-row`, `ebox-column`, `ebox-spacer` | Compose simple horizontal/vertical layouts and blank boxes. |
|
||||||
| `ebox-flex`, `ebox-flex-item` | Build flex containers and item metadata. |
|
| `ebox-flex`, `ebox-flex-item` | Build flex containers and item metadata. |
|
||||||
|
|||||||
@ -533,7 +533,7 @@ style API。
|
|||||||
|
|
||||||
| 函数 | 用途 |
|
| 函数 | 用途 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `ebox-text-create`、`ebox-normal-layout-create`、`ebox-box-create` | 框架集成使用的 typed TextNode、Normal LayoutConfig 与 BoxNode 端口。 |
|
| `ebox-text-create`、`ebox-normal-layout-create`、`ebox-row-layout-create`、`ebox-column-layout-create`、`ebox-box-create` | 框架集成使用的 typed TextNode、Normal/Row/Column LayoutConfig 与 BoxNode 端口。 |
|
||||||
| `ebox-create`、`ebox-build` | 迁移期间创建旧节点或编译 `.ebox` list DSL。 |
|
| `ebox-create`、`ebox-build` | 迁移期间创建旧节点或编译 `.ebox` list DSL。 |
|
||||||
| `ebox-concat`、`ebox-stack`、`ebox-row`、`ebox-column`、`ebox-spacer` | 组合简单横向/纵向布局与空白 box。 |
|
| `ebox-concat`、`ebox-stack`、`ebox-row`、`ebox-column`、`ebox-spacer` | 组合简单横向/纵向布局与空白 box。 |
|
||||||
| `ebox-flex`、`ebox-flex-item` | 构建 Flex 容器与 item metadata。 |
|
| `ebox-flex`、`ebox-flex-item` | 构建 Flex 容器与 item metadata。 |
|
||||||
|
|||||||
@ -73,8 +73,8 @@
|
|||||||
"Return non-nil when PROPERTY belongs to canonical Text measurement."
|
"Return non-nil when PROPERTY belongs to canonical Text measurement."
|
||||||
(eq (plist-get property :group) 'typography))
|
(eq (plist-get property :group) 'typography))
|
||||||
|
|
||||||
(defun ebox-canonical--normal-box-property-p (property)
|
(defun ebox-canonical--box-frame-property-p (property)
|
||||||
"Return non-nil when PROPERTY belongs to Normal Box geometry/participation."
|
"Return non-nil when PROPERTY belongs to Box geometry or participation."
|
||||||
(let ((contexts (plist-get property :contexts))
|
(let ((contexts (plist-get property :contexts))
|
||||||
(group (plist-get property :group))
|
(group (plist-get property :group))
|
||||||
(name (plist-get property :name)))
|
(name (plist-get property :name)))
|
||||||
@ -96,6 +96,16 @@
|
|||||||
"Return the canonical Normal layout config."
|
"Return the canonical Normal layout config."
|
||||||
(ebox-layout-config--create :kind 'normal :props nil))
|
(ebox-layout-config--create :kind 'normal :props nil))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun ebox-row-layout-create ()
|
||||||
|
"Return the canonical Row layout config."
|
||||||
|
(ebox-layout-config--create :kind 'row :props nil))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun ebox-column-layout-create ()
|
||||||
|
"Return the canonical Column layout config."
|
||||||
|
(ebox-layout-config--create :kind 'column :props nil))
|
||||||
|
|
||||||
(defun ebox-node-kind (node)
|
(defun ebox-node-kind (node)
|
||||||
"Return canonical NODE kind, or nil for a legacy runtime node."
|
"Return canonical NODE kind, or nil for a legacy runtime node."
|
||||||
(and (listp node) (plist-get node :ebox-kind)))
|
(and (listp node) (plist-get node :ebox-kind)))
|
||||||
@ -128,7 +138,7 @@
|
|||||||
"Return canonical BoxNode NODE's retained canonical children."
|
"Return canonical BoxNode NODE's retained canonical children."
|
||||||
(unless (ebox-box-node-p node)
|
(unless (ebox-box-node-p node)
|
||||||
(error "Expected canonical BoxNode, got %S" node))
|
(error "Expected canonical BoxNode, got %S" node))
|
||||||
(plist-get node :ebox-canonical-children))
|
(plist-get node :children))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun ebox-text-create (&rest plist)
|
(defun ebox-text-create (&rest plist)
|
||||||
@ -159,9 +169,8 @@
|
|||||||
"Create a canonical BoxNode from evaluated PLIST.
|
"Create a canonical BoxNode from evaluated PLIST.
|
||||||
|
|
||||||
`:layout' must occur exactly once as an `ebox-layout-config'.
|
`:layout' must occur exactly once as an `ebox-layout-config'.
|
||||||
`:children' is a list of canonical nodes. This first vertical slice supports
|
`:children' is a list of canonical nodes. Normal layout accepts zero or one
|
||||||
Normal layout with zero or one child; later slices extend the same typed port
|
child. Row and Column layouts accept any number of children."
|
||||||
to the other Layout variants."
|
|
||||||
(ebox-canonical--validate-plist plist "ebox-box-create")
|
(ebox-canonical--validate-plist plist "ebox-box-create")
|
||||||
(let* ((layout (ebox-canonical--required-field
|
(let* ((layout (ebox-canonical--required-field
|
||||||
plist :layout "Ebox Box"))
|
plist :layout "Ebox Box"))
|
||||||
@ -189,23 +198,30 @@ to the other Layout variants."
|
|||||||
children)
|
children)
|
||||||
(error "Ebox Box children must be canonical Text/Box nodes: %S"
|
(error "Ebox Box children must be canonical Text/Box nodes: %S"
|
||||||
children))
|
children))
|
||||||
(unless (eq (ebox-layout-config-kind layout) 'normal)
|
(unless (memq (ebox-layout-config-kind layout) '(normal row column))
|
||||||
(error "Ebox Box Layout is not implemented in this slice: %S"
|
(error "Ebox Box Layout is not implemented: %S"
|
||||||
(ebox-layout-config-kind layout)))
|
(ebox-layout-config-kind layout)))
|
||||||
(when (> (length children) 1)
|
(unless (null (ebox-layout-config-props layout))
|
||||||
|
(error "Ebox Box Layout properties are not implemented: %S"
|
||||||
|
(ebox-layout-config-props layout)))
|
||||||
|
(when (and (eq (ebox-layout-config-kind layout) 'normal)
|
||||||
|
(> (length children) 1))
|
||||||
(error "Ebox Box Normal layout currently accepts at most one child"))
|
(error "Ebox Box Normal layout currently accepts at most one child"))
|
||||||
(ebox-canonical--assert-property-role
|
(ebox-canonical--assert-property-role
|
||||||
props #'ebox-canonical--normal-box-property-p "Ebox Box")
|
props #'ebox-canonical--box-frame-property-p "Ebox Box")
|
||||||
(let ((node
|
(let ((node (apply #'ebox-create props)))
|
||||||
(apply #'ebox-create
|
|
||||||
(append props
|
|
||||||
(when children
|
|
||||||
(list :ebox-content-node (car children)))))))
|
|
||||||
(plist-put node :ebox-kind 'box)
|
(plist-put node :ebox-kind 'box)
|
||||||
(plist-put node :ebox-layout-config layout)
|
(plist-put node :ebox-layout-config layout)
|
||||||
(plist-put node :ebox-canonical-children children)
|
(plist-put node :children children)
|
||||||
(plist-put node :ebox-source-handle source-handle)
|
(plist-put node :ebox-source-handle source-handle)
|
||||||
(plist-put node :display (list outer 'flow))
|
;; Children own their text formatting. The Box frame consumes their
|
||||||
|
;; already-laid-out output and must not wrap or justify it a second time.
|
||||||
|
(plist-put node :wrap-mode nil)
|
||||||
|
(plist-put node :display
|
||||||
|
(list outer
|
||||||
|
(pcase (ebox-layout-config-kind layout)
|
||||||
|
('normal 'flow)
|
||||||
|
(kind kind))))
|
||||||
node)))
|
node)))
|
||||||
|
|
||||||
(provide 'ebox-canonical)
|
(provide 'ebox-canonical)
|
||||||
|
|||||||
@ -570,8 +570,8 @@ grapheme."
|
|||||||
('box
|
('box
|
||||||
(when-let* ((region-id (ebox-get node :region-id)))
|
(when-let* ((region-id (ebox-get node :region-id)))
|
||||||
(puthash region-id node ebox--region-box-table))
|
(puthash region-id node ebox--region-box-table))
|
||||||
(ebox--flex-recache-source-boxes
|
(dolist (child (ebox-tree-node-children node))
|
||||||
(plist-get node :ebox-content-node)))
|
(ebox--flex-recache-source-boxes child)))
|
||||||
('concat
|
('concat
|
||||||
(dolist (child (ebox--layout-children node))
|
(dolist (child (ebox--layout-children node))
|
||||||
(ebox--flex-recache-source-boxes child)))
|
(ebox--flex-recache-source-boxes child)))
|
||||||
|
|||||||
@ -7744,7 +7744,7 @@ the surface is allowed to reuse retained TP objects."
|
|||||||
"Return non-nil when path-copied NODE keeps the published line count."
|
"Return non-nil when path-copied NODE keeps the published line count."
|
||||||
(and (eq (plist-get node :ebox-type) 'box)
|
(and (eq (plist-get node :ebox-type) 'box)
|
||||||
(numberp (ebox-get node :width))
|
(numberp (ebox-get node :width))
|
||||||
(null (plist-get node :ebox-content-node))
|
(null (ebox-tree-node-children node))
|
||||||
(= (length spans)
|
(= (length spans)
|
||||||
(with-current-buffer buffer
|
(with-current-buffer buffer
|
||||||
(length (ebox-string-lines (ebox--format-content node)))))))
|
(length (ebox-string-lines (ebox--format-content node)))))))
|
||||||
|
|||||||
136
ebox-layout.el
136
ebox-layout.el
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
(declare-function ebox--render-grid "ebox-grid" (node))
|
(declare-function ebox--render-grid "ebox-grid" (node))
|
||||||
(declare-function ebox--render-flex "ebox-flex" (node))
|
(declare-function ebox--render-flex "ebox-flex" (node))
|
||||||
|
(declare-function ebox-layout-config-kind "ebox-canonical" (config))
|
||||||
(declare-function ebox--render-with-cache
|
(declare-function ebox--render-with-cache
|
||||||
"ebox-incremental" (node &optional force cache-probe))
|
"ebox-incremental" (node &optional force cache-probe))
|
||||||
(declare-function ebox-create "ebox" (&rest plist))
|
(declare-function ebox-create "ebox" (&rest plist))
|
||||||
@ -236,6 +237,7 @@ and its formatted content exactly fills the used height."
|
|||||||
(when (and (not ebox--flat-preformatted-box-fast-path-disabled)
|
(when (and (not ebox--flat-preformatted-box-fast-path-disabled)
|
||||||
(not (eq (ebox-get box :visibility) 'hidden))
|
(not (eq (ebox-get box :visibility) 'hidden))
|
||||||
(null (ebox--box-content-node box))
|
(null (ebox--box-content-node box))
|
||||||
|
(not (plist-member box :children))
|
||||||
(stringp (ebox-get box :content))
|
(stringp (ebox-get box :content))
|
||||||
(eq (ebox-get box :vertical-align) 'top)
|
(eq (ebox-get box :vertical-align) 'top)
|
||||||
(equal (or (ebox-get box :min-height) 0) 0)
|
(equal (or (ebox-get box :min-height) 0) 0)
|
||||||
@ -883,6 +885,11 @@ FALLBACK is used for nil, auto, or unavailable viewport-height values."
|
|||||||
"Return BOX's lazy child layout node, if any."
|
"Return BOX's lazy child layout node, if any."
|
||||||
(plist-get box :ebox-content-node))
|
(plist-get box :ebox-content-node))
|
||||||
|
|
||||||
|
(defun ebox--box-layout-kind (box)
|
||||||
|
"Return canonical BOX's typed layout kind, or nil for a legacy box."
|
||||||
|
(when-let* ((config (plist-get box :ebox-layout-config)))
|
||||||
|
(ebox-layout-config-kind config)))
|
||||||
|
|
||||||
(defun ebox--box-content-cache-context ()
|
(defun ebox--box-content-cache-context ()
|
||||||
"Return the current render context for lazy box content caching."
|
"Return the current render context for lazy box content caching."
|
||||||
(list ebox-viewport-width
|
(list ebox-viewport-width
|
||||||
@ -891,43 +898,79 @@ FALLBACK is used for nil, auto, or unavailable viewport-height values."
|
|||||||
ebox--inline-auto-width-intrinsic-p
|
ebox--inline-auto-width-intrinsic-p
|
||||||
ebox--render-region-id))
|
ebox--render-region-id))
|
||||||
|
|
||||||
(defun ebox--render-box-content-node (box node)
|
(defun ebox--render-box-content-cached (box renderer)
|
||||||
"Render NODE as BOX content, using the render-pass cache when available."
|
"Return BOX content from RENDERER, reusing the render-pass cache."
|
||||||
(let* ((content-viewport (ebox--wrapper-content-viewport-pixel box))
|
|
||||||
(content
|
|
||||||
(if (null ebox--box-content-render-cache)
|
(if (null ebox--box-content-render-cache)
|
||||||
(ebox--render-node-as-box-content node box)
|
(funcall renderer)
|
||||||
(let* ((context (ebox--box-content-cache-context))
|
(let* ((context (ebox--box-content-cache-context))
|
||||||
(entries (gethash box ebox--box-content-render-cache))
|
(entries (gethash box ebox--box-content-render-cache))
|
||||||
(cached (assoc context entries)))
|
(cached (assoc context entries)))
|
||||||
(if cached
|
(if cached
|
||||||
(cdr cached)
|
(cdr cached)
|
||||||
(let ((rendered
|
(let ((rendered (funcall renderer)))
|
||||||
(ebox--render-node-as-box-content node box)))
|
|
||||||
(puthash box
|
(puthash box
|
||||||
(cons (cons context rendered) entries)
|
(cons (cons context rendered) entries)
|
||||||
ebox--box-content-render-cache)
|
ebox--box-content-render-cache)
|
||||||
rendered))))))
|
rendered)))))
|
||||||
|
|
||||||
|
(defun ebox--record-box-content-width-exact (box content composite-p)
|
||||||
|
"Record exact width for BOX CONTENT when COMPOSITE-P is non-nil."
|
||||||
|
(let ((content-viewport (ebox--wrapper-content-viewport-pixel box)))
|
||||||
|
(when (and content-viewport
|
||||||
|
composite-p
|
||||||
|
(not ebox--intrinsic-layout-measurement)
|
||||||
|
(equal (gethash content ebox--rendered-uniform-width-table)
|
||||||
|
content-viewport))
|
||||||
|
(plist-put box :ebox-content-width-exact-p t))))
|
||||||
|
|
||||||
|
(defun ebox--render-box-content-node (box node)
|
||||||
|
"Render NODE as BOX content, using the render-pass cache when available."
|
||||||
|
(let ((content
|
||||||
|
(ebox--render-box-content-cached
|
||||||
|
box (lambda () (ebox--render-node-as-box-content node box)))))
|
||||||
;; A child layout has already resolved wrapping, alignment, and overflow
|
;; A child layout has already resolved wrapping, alignment, and overflow
|
||||||
;; against CONTENT-VIEWPORT. Preserve that fact on the owning box so the
|
;; against CONTENT-VIEWPORT. Preserve that fact on the owning box so the
|
||||||
;; generic string formatter does not traverse the same propertized output
|
;; generic string formatter does not traverse the same propertized output
|
||||||
;; a second time. Intrinsic measurement is deliberately excluded: it
|
;; a second time. Intrinsic measurement is deliberately excluded: it
|
||||||
;; produces a natural-width probe, not final box content.
|
;; produces a natural-width probe, not final box content.
|
||||||
(when (and content-viewport
|
(ebox--record-box-content-width-exact
|
||||||
(not (eq (and (listp node) (plist-get node :ebox-type))
|
box content
|
||||||
'box))
|
(not (eq (and (listp node) (plist-get node :ebox-type)) 'box)))
|
||||||
(not ebox--intrinsic-layout-measurement)
|
content))
|
||||||
(equal (gethash content ebox--rendered-uniform-width-table)
|
|
||||||
content-viewport))
|
(defun ebox--render-box-layout-children (box)
|
||||||
(plist-put box :ebox-content-width-exact-p t))
|
"Render canonical BOX children through its typed LayoutConfig."
|
||||||
|
(let* ((kind (ebox--box-layout-kind box))
|
||||||
|
(children (plist-get box :children))
|
||||||
|
(content
|
||||||
|
(ebox--render-box-content-cached
|
||||||
|
box
|
||||||
|
(lambda ()
|
||||||
|
(pcase kind
|
||||||
|
('normal
|
||||||
|
(if children
|
||||||
|
(ebox--render-node-as-box-content (car children) box)
|
||||||
|
""))
|
||||||
|
('row
|
||||||
|
(ebox--call-with-box-content-context
|
||||||
|
box (lambda () (ebox--render-row-children children))))
|
||||||
|
('column
|
||||||
|
(ebox--call-with-box-content-context
|
||||||
|
box (lambda () (ebox--render-column-children children))))
|
||||||
|
(_ (error "Ebox Box has unsupported LayoutConfig: %S" kind)))))))
|
||||||
|
(ebox--record-box-content-width-exact
|
||||||
|
box content (memq kind '(row column)))
|
||||||
content))
|
content))
|
||||||
|
|
||||||
(defun ebox--box-content (box)
|
(defun ebox--box-content (box)
|
||||||
"Return BOX content, rendering any lazy child layout content if present."
|
"Return BOX content, rendering any lazy child layout content if present."
|
||||||
(ebox--propertize-typography
|
(ebox--propertize-typography
|
||||||
(or (when-let* ((node (ebox--box-content-node box)))
|
(cond
|
||||||
(ebox--render-box-content-node box node))
|
((plist-member box :children)
|
||||||
(ebox-get box :content))
|
(ebox--render-box-layout-children box))
|
||||||
|
((when-let* ((node (ebox--box-content-node box)))
|
||||||
|
(ebox--render-box-content-node box node)))
|
||||||
|
(t (ebox-get box :content)))
|
||||||
box))
|
box))
|
||||||
|
|
||||||
(defun ebox--line-min-content-pixel (line)
|
(defun ebox--line-min-content-pixel (line)
|
||||||
@ -1039,6 +1082,21 @@ property parsers."
|
|||||||
(min (or max-width 999999999)
|
(min (or max-width 999999999)
|
||||||
(max 0 preferred-width))))))
|
(max 0 preferred-width))))))
|
||||||
|
|
||||||
|
(defun ebox--call-with-box-content-context (props function)
|
||||||
|
"Call FUNCTION in the content viewport established by box PROPS."
|
||||||
|
(let ((content-viewport (ebox--wrapper-content-viewport-pixel props)))
|
||||||
|
(cond
|
||||||
|
((eq (ebox-get props :width) 'max-content)
|
||||||
|
(let ((ebox-viewport-width nil)
|
||||||
|
(ebox--intrinsic-layout-measurement t)
|
||||||
|
(ebox--inline-auto-width-intrinsic-p nil))
|
||||||
|
(funcall function)))
|
||||||
|
(content-viewport
|
||||||
|
(let ((ebox-viewport-width content-viewport)
|
||||||
|
(ebox--inline-auto-width-intrinsic-p nil))
|
||||||
|
(funcall function)))
|
||||||
|
(t (funcall function)))))
|
||||||
|
|
||||||
(defun ebox--render-node-as-box-content (node props)
|
(defun ebox--render-node-as-box-content (node props)
|
||||||
"Render NODE as preformatted content for a box with PROPS.
|
"Render NODE as preformatted content for a box with PROPS.
|
||||||
When PROPS establish a content-box viewport, nested auto and `(viewport)'
|
When PROPS establish a content-box viewport, nested auto and `(viewport)'
|
||||||
@ -1046,19 +1104,11 @@ widths resolve against that inner content box instead of the outer caller
|
|||||||
viewport. A max-content wrapper instead measures the composite NODE without
|
viewport. A max-content wrapper instead measures the composite NODE without
|
||||||
an inherited viewport."
|
an inherited viewport."
|
||||||
(let ((content-viewport (ebox--wrapper-content-viewport-pixel props)))
|
(let ((content-viewport (ebox--wrapper-content-viewport-pixel props)))
|
||||||
(cond
|
(ebox--call-with-box-content-context
|
||||||
((eq (ebox-get props :width) 'max-content)
|
props
|
||||||
(let ((ebox-viewport-width nil)
|
(lambda ()
|
||||||
(ebox--intrinsic-layout-measurement t)
|
(if (and content-viewport
|
||||||
(ebox--inline-auto-width-intrinsic-p nil))
|
(hash-table-p ebox--render-cache-table)
|
||||||
(ebox-render node)))
|
|
||||||
(content-viewport
|
|
||||||
(let ((ebox-viewport-width content-viewport)
|
|
||||||
;; A definite wrapper establishes a new containing block. Its
|
|
||||||
;; child layout must resume normal cross-axis stretch semantics,
|
|
||||||
;; even when the wrapper itself is an item of an intrinsic row.
|
|
||||||
(ebox--inline-auto-width-intrinsic-p nil))
|
|
||||||
(if (and (hash-table-p ebox--render-cache-table)
|
|
||||||
(not ebox--intrinsic-layout-measurement)
|
(not ebox--intrinsic-layout-measurement)
|
||||||
(null ebox--render-region-id)
|
(null ebox--render-region-id)
|
||||||
(fboundp 'ebox--render-cache-probe)
|
(fboundp 'ebox--render-cache-probe)
|
||||||
@ -1077,9 +1127,7 @@ an inherited viewport."
|
|||||||
:scroll-lookahead
|
:scroll-lookahead
|
||||||
ebox--scroll-window-initial-lookahead-lines-override
|
ebox--scroll-window-initial-lookahead-lines-override
|
||||||
:scroll-disabled ebox--scroll-window-render-disabled)))
|
:scroll-disabled ebox--scroll-window-render-disabled)))
|
||||||
(ebox-render node))))
|
(ebox-render node))))))
|
||||||
(t
|
|
||||||
(ebox-render node)))))
|
|
||||||
|
|
||||||
(defun ebox--resolve-size-content-pixel (box value fallback)
|
(defun ebox--resolve-size-content-pixel (box value fallback)
|
||||||
"Resolve a horizontal size VALUE to BOX content pixels.
|
"Resolve a horizontal size VALUE to BOX content pixels.
|
||||||
@ -1702,8 +1750,8 @@ A sole child Range keeps a material row parent so the Range stays addressable."
|
|||||||
:display '(block row)
|
:display '(block row)
|
||||||
:children nodes))))
|
:children nodes))))
|
||||||
|
|
||||||
(defun ebox--render-concat (node)
|
(defun ebox--render-row-children (children)
|
||||||
"Render a concat NODE to a string (internal, called by `ebox-render').
|
"Render flat row CHILDREN to one multi-line string.
|
||||||
Auto-width children are rendered at intrinsic inline size while explicit
|
Auto-width children are rendered at intrinsic inline size while explicit
|
||||||
viewport/definite widths keep their containing-block semantics. Shorter
|
viewport/definite widths keep their containing-block semantics. Shorter
|
||||||
children are padded with blank lines so all reach the same height before
|
children are padded with blank lines so all reach the same height before
|
||||||
@ -1716,7 +1764,7 @@ horizontal concatenation."
|
|||||||
;; the ambient containing block.
|
;; the ambient containing block.
|
||||||
(let ((ebox--inline-auto-width-intrinsic-p t))
|
(let ((ebox--inline-auto-width-intrinsic-p t))
|
||||||
(ebox--render-with-cache child)))
|
(ebox--render-with-cache child)))
|
||||||
(ebox--layout-children node)))
|
children))
|
||||||
(max-h (if rendered
|
(max-h (if rendered
|
||||||
(apply #'max (mapcar #'ebox-string-height rendered))
|
(apply #'max (mapcar #'ebox-string-height rendered))
|
||||||
0))
|
0))
|
||||||
@ -1729,6 +1777,10 @@ horizontal concatenation."
|
|||||||
(ebox-lines-join (apply #'cl-mapcar #'concat line-lists))
|
(ebox-lines-join (apply #'cl-mapcar #'concat line-lists))
|
||||||
"")))
|
"")))
|
||||||
|
|
||||||
|
(defun ebox--render-concat (node)
|
||||||
|
"Render a legacy concat NODE to a string."
|
||||||
|
(ebox--render-row-children (ebox--layout-children node)))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun ebox-stack (node1 node2)
|
(defun ebox-stack (node1 node2)
|
||||||
"Return a lazy stack node that places NODE1 above NODE2 vertically.
|
"Return a lazy stack node that places NODE1 above NODE2 vertically.
|
||||||
@ -3074,8 +3126,8 @@ only used for incomplete lazy prefixes."
|
|||||||
formatted-lines
|
formatted-lines
|
||||||
(seq-take formatted-lines target-lines))))))))))
|
(seq-take formatted-lines target-lines))))))))))
|
||||||
|
|
||||||
(defun ebox--render-stack (node)
|
(defun ebox--render-column-children (children)
|
||||||
"Render a stack NODE to a string (internal, called by `ebox-render').
|
"Render flat column CHILDREN to one multi-line string.
|
||||||
|
|
||||||
Stack leaves are rendered independently. When a containing-block viewport is
|
Stack leaves are rendered independently. When a containing-block viewport is
|
||||||
bound, narrower rows are padded to that available width, while wider definite
|
bound, narrower rows are padded to that available width, while wider definite
|
||||||
@ -3089,7 +3141,7 @@ ambient horizontal viewport."
|
|||||||
(let ((rendered (ebox--render-with-cache leaf)))
|
(let ((rendered (ebox--render-with-cache leaf)))
|
||||||
(cons rendered
|
(cons rendered
|
||||||
(ebox--string-max-pixel-width rendered))))
|
(ebox--string-max-pixel-width rendered))))
|
||||||
(ebox--stack-leaves node)))
|
children))
|
||||||
(max-w (if rendered-items
|
(max-w (if rendered-items
|
||||||
(apply #'max (mapcar #'cdr rendered-items))
|
(apply #'max (mapcar #'cdr rendered-items))
|
||||||
0))
|
0))
|
||||||
@ -3115,6 +3167,10 @@ ambient horizontal viewport."
|
|||||||
(ebox--record-rendered-uniform-width rendered target-w)
|
(ebox--record-rendered-uniform-width rendered target-w)
|
||||||
rendered))))
|
rendered))))
|
||||||
|
|
||||||
|
(defun ebox--render-stack (node)
|
||||||
|
"Render a legacy stack NODE to a string."
|
||||||
|
(ebox--render-column-children (ebox--stack-leaves node)))
|
||||||
|
|
||||||
(provide 'ebox-layout)
|
(provide 'ebox-layout)
|
||||||
|
|
||||||
;;; ebox-layout.el ends here
|
;;; ebox-layout.el ends here
|
||||||
|
|||||||
@ -1621,6 +1621,8 @@ Rust still verifies the dynamic equal-width and nonempty-line proof per frame."
|
|||||||
(defun ebox-native-reflow--compile-box
|
(defun ebox-native-reflow--compile-box
|
||||||
(box &optional child-override child-override-p child-resolved-p)
|
(box &optional child-override child-override-p child-resolved-p)
|
||||||
"Compile normalized Ebox BOX to strict layout IR."
|
"Compile normalized Ebox BOX to strict layout IR."
|
||||||
|
(when (plist-member box :children)
|
||||||
|
(error "Native reflow does not yet compile typed Box children"))
|
||||||
(let* ((source-child (plist-get box :ebox-content-node))
|
(let* ((source-child (plist-get box :ebox-content-node))
|
||||||
(child (if (or child-override-p child-resolved-p)
|
(child (if (or child-override-p child-resolved-p)
|
||||||
child-override
|
child-override
|
||||||
@ -1910,8 +1912,9 @@ backend has a matching two-dimensional layout contract."
|
|||||||
((plist-get node :ebox-child-sequence) nil)
|
((plist-get node :ebox-child-sequence) nil)
|
||||||
((eq (plist-get node :ebox-type) 'grid) nil)
|
((eq (plist-get node :ebox-type) 'grid) nil)
|
||||||
((eq (plist-get node :ebox-type) 'box)
|
((eq (plist-get node :ebox-type) 'box)
|
||||||
|
(and (not (plist-member node :children))
|
||||||
(ebox-native-reflow--native-node-supported-p
|
(ebox-native-reflow--native-node-supported-p
|
||||||
(plist-get node :ebox-content-node)))
|
(plist-get node :ebox-content-node))))
|
||||||
((memq (plist-get node :ebox-type) '(concat stack))
|
((memq (plist-get node :ebox-type) '(concat stack))
|
||||||
(cl-every #'ebox-native-reflow--native-node-supported-p
|
(cl-every #'ebox-native-reflow--native-node-supported-p
|
||||||
(ebox--layout-children node)))
|
(ebox--layout-children node)))
|
||||||
|
|||||||
@ -242,7 +242,7 @@ Scoped rules remain tree-dependent because scope distance reads ancestors."
|
|||||||
(defun ebox-surface--style-consuming-node-p (node)
|
(defun ebox-surface--style-consuming-node-p (node)
|
||||||
"Return non-nil when NODE owns a paintable style surface."
|
"Return non-nil when NODE owns a paintable style surface."
|
||||||
(and (eq (plist-get node :ebox-type) 'box)
|
(and (eq (plist-get node :ebox-type) 'box)
|
||||||
(null (plist-get node :ebox-content-node))
|
(null (ebox-tree-node-children node))
|
||||||
(> (length (or (plist-get node :content) "")) 0)))
|
(> (length (or (plist-get node :content) "")) 0)))
|
||||||
|
|
||||||
(defun ebox-surface--inline-inheritance-required-p (root)
|
(defun ebox-surface--inline-inheritance-required-p (root)
|
||||||
|
|||||||
48
ebox-tree.el
48
ebox-tree.el
@ -139,7 +139,9 @@ This is an optimization for snapshot capture, not buffer runtime state.")
|
|||||||
"Return NODE's direct child nodes without assigning runtime ids."
|
"Return NODE's direct child nodes without assigning runtime ids."
|
||||||
(pcase (and (listp node) (plist-get node :ebox-type))
|
(pcase (and (listp node) (plist-get node :ebox-type))
|
||||||
('box
|
('box
|
||||||
(delq nil (list (plist-get node :ebox-content-node))))
|
(if (plist-member node :children)
|
||||||
|
(plist-get node :children)
|
||||||
|
(delq nil (list (plist-get node :ebox-content-node)))))
|
||||||
('concat
|
('concat
|
||||||
(ebox-tree-layout-children node))
|
(ebox-tree-layout-children node))
|
||||||
('stack
|
('stack
|
||||||
@ -246,7 +248,8 @@ still copied while every nested value remains shared."
|
|||||||
(setq copy
|
(setq copy
|
||||||
(ebox-tree--replace-direct-child-property
|
(ebox-tree--replace-direct-child-property
|
||||||
copy property replacements)))
|
copy property replacements)))
|
||||||
(when (and (memq type '(concat stack flex grid))
|
(when (and (or (memq type '(concat stack flex grid))
|
||||||
|
(and (eq type 'box) (plist-member copy :children)))
|
||||||
(plist-member copy :children))
|
(plist-member copy :children))
|
||||||
(let* ((children (plist-get copy :children))
|
(let* ((children (plist-get copy :children))
|
||||||
(replaced
|
(replaced
|
||||||
@ -393,10 +396,17 @@ Record its identities in NODE-ID-SET and REGION-ID-SET."
|
|||||||
node node-id-set region-id-set)))
|
node node-id-set region-id-set)))
|
||||||
(pcase (plist-get node :ebox-type)
|
(pcase (plist-get node :ebox-type)
|
||||||
('box
|
('box
|
||||||
|
(if (plist-member node :children)
|
||||||
|
(plist-put shell :children
|
||||||
|
(mapcar
|
||||||
|
(lambda (child)
|
||||||
|
(ebox-tree--runtime-identity-skeleton
|
||||||
|
child node-id-set region-id-set))
|
||||||
|
(plist-get node :children)))
|
||||||
(when-let* ((child (plist-get node :ebox-content-node)))
|
(when-let* ((child (plist-get node :ebox-content-node)))
|
||||||
(plist-put shell :ebox-content-node
|
(plist-put shell :ebox-content-node
|
||||||
(ebox-tree--runtime-identity-skeleton
|
(ebox-tree--runtime-identity-skeleton
|
||||||
child node-id-set region-id-set))))
|
child node-id-set region-id-set)))))
|
||||||
((or 'concat 'stack)
|
((or 'concat 'stack)
|
||||||
(plist-put shell :children
|
(plist-put shell :children
|
||||||
(mapcar
|
(mapcar
|
||||||
@ -809,8 +819,10 @@ candidate runtime index agree."
|
|||||||
"Return NODE's logical children without internal layout adapters."
|
"Return NODE's logical children without internal layout adapters."
|
||||||
(pcase (and (listp node) (plist-get node :ebox-type))
|
(pcase (and (listp node) (plist-get node :ebox-type))
|
||||||
('box
|
('box
|
||||||
|
(if (plist-member node :children)
|
||||||
|
(plist-get node :children)
|
||||||
(when-let* ((content-node (plist-get node :ebox-content-node)))
|
(when-let* ((content-node (plist-get node :ebox-content-node)))
|
||||||
(ebox-tree--semantic-layout-leaves content-node)))
|
(ebox-tree--semantic-layout-leaves content-node))))
|
||||||
((or 'concat 'stack)
|
((or 'concat 'stack)
|
||||||
(ebox-tree--semantic-layout-leaves node))
|
(ebox-tree--semantic-layout-leaves node))
|
||||||
('flex
|
('flex
|
||||||
@ -924,9 +936,11 @@ not only the public update ids."
|
|||||||
(let ((region-ids
|
(let ((region-ids
|
||||||
(pcase (plist-get node :ebox-type)
|
(pcase (plist-get node :ebox-type)
|
||||||
('box
|
('box
|
||||||
(cons (ebox--ensure-region-id node)
|
(cons
|
||||||
(ebox-tree-node-all-region-ids
|
(ebox--ensure-region-id node)
|
||||||
(plist-get node :ebox-content-node))))
|
(apply #'append
|
||||||
|
(mapcar #'ebox-tree-node-all-region-ids
|
||||||
|
(ebox-tree-node-children node)))))
|
||||||
('concat
|
('concat
|
||||||
(apply #'append
|
(apply #'append
|
||||||
(mapcar #'ebox-tree-node-all-region-ids
|
(mapcar #'ebox-tree-node-all-region-ids
|
||||||
@ -969,8 +983,10 @@ cannot be inspected and reports no conflict."
|
|||||||
(pcase (plist-get node :ebox-type)
|
(pcase (plist-get node :ebox-type)
|
||||||
('box
|
('box
|
||||||
(or (and inherited (plist-get node paint-key) t)
|
(or (and inherited (plist-get node paint-key) t)
|
||||||
(ebox-tree-node-paint-conflict-p
|
(cl-some
|
||||||
(plist-get node :ebox-content-node) paint-key t)))
|
(lambda (child)
|
||||||
|
(ebox-tree-node-paint-conflict-p child paint-key t))
|
||||||
|
(ebox-tree-node-children node))))
|
||||||
('concat
|
('concat
|
||||||
(cl-some (lambda (child)
|
(cl-some (lambda (child)
|
||||||
(ebox-tree-node-paint-conflict-p child paint-key t))
|
(ebox-tree-node-paint-conflict-p child paint-key t))
|
||||||
@ -1010,10 +1026,12 @@ wrapper's visible content is produced by the flex renderer."
|
|||||||
('box
|
('box
|
||||||
(or (when (equal (ebox-get node :region-id) region-id)
|
(or (when (equal (ebox-get node :region-id) region-id)
|
||||||
(list node))
|
(list node))
|
||||||
(when-let* ((path (ebox-tree-node-path-to-region
|
(catch 'found
|
||||||
(plist-get node :ebox-content-node)
|
(dolist (child (ebox-tree-node-children node))
|
||||||
region-id)))
|
(when-let* ((path
|
||||||
(append path (list node)))))
|
(ebox-tree-node-path-to-region child region-id)))
|
||||||
|
(throw 'found (append path (list node)))))
|
||||||
|
nil)))
|
||||||
('concat
|
('concat
|
||||||
(catch 'found
|
(catch 'found
|
||||||
(dolist (child (ebox-tree-layout-children node))
|
(dolist (child (ebox-tree-layout-children node))
|
||||||
@ -1060,8 +1078,8 @@ wrapper's visible content is produced by the flex renderer."
|
|||||||
(pcase (plist-get node :ebox-type)
|
(pcase (plist-get node :ebox-type)
|
||||||
('box
|
('box
|
||||||
(or (ebox--box-visible-overflow-p node)
|
(or (ebox--box-visible-overflow-p node)
|
||||||
(ebox-tree-node-visible-overflow-p
|
(cl-some #'ebox-tree-node-visible-overflow-p
|
||||||
(plist-get node :ebox-content-node))))
|
(ebox-tree-node-children node))))
|
||||||
('concat
|
('concat
|
||||||
(cl-some #'ebox-tree-node-visible-overflow-p
|
(cl-some #'ebox-tree-node-visible-overflow-p
|
||||||
(ebox-tree-layout-children node)))
|
(ebox-tree-layout-children node)))
|
||||||
|
|||||||
11
ebox.el
11
ebox.el
@ -650,8 +650,11 @@ Use this to capture ids *before* inserting into a buffer:
|
|||||||
(let ((type (plist-get node :ebox-type)))
|
(let ((type (plist-get node :ebox-type)))
|
||||||
(cond
|
(cond
|
||||||
((eq type 'box)
|
((eq type 'box)
|
||||||
(cons (ebox--ensure-region-id node)
|
(cons
|
||||||
(ebox-region-ids (plist-get node :ebox-content-node))))
|
(ebox--ensure-region-id node)
|
||||||
|
(apply #'append
|
||||||
|
(mapcar #'ebox-region-ids
|
||||||
|
(ebox-tree-node-children node)))))
|
||||||
((eq type 'concat)
|
((eq type 'concat)
|
||||||
(apply #'append
|
(apply #'append
|
||||||
(mapcar #'ebox-region-ids
|
(mapcar #'ebox-region-ids
|
||||||
@ -4171,7 +4174,7 @@ REGION-ID and CHANGED-KEYS describe one update; CHANGES describes a batch."
|
|||||||
:content)
|
:content)
|
||||||
(stringp (cadr expanded))
|
(stringp (cadr expanded))
|
||||||
(numberp (ebox-get candidate-box :width))
|
(numberp (ebox-get candidate-box :width))
|
||||||
(null (plist-get candidate-box :ebox-content-node))
|
(null (ebox-tree-node-children candidate-box))
|
||||||
(not (ebox-style-cascade-active-p))
|
(not (ebox-style-cascade-active-p))
|
||||||
(not (plist-get state :cascade-required-p))
|
(not (plist-get state :cascade-required-p))
|
||||||
(null (plist-get state :scroll-region-ids))))
|
(null (plist-get state :scroll-region-ids))))
|
||||||
@ -4587,7 +4590,9 @@ through dirty-set and patch-set execution before falling back to root rerender."
|
|||||||
ebox-candidate-patch-host-paint
|
ebox-candidate-patch-host-paint
|
||||||
ebox-clear-cache
|
ebox-clear-cache
|
||||||
ebox-column
|
ebox-column
|
||||||
|
ebox-column-layout-create
|
||||||
ebox-normal-layout-create
|
ebox-normal-layout-create
|
||||||
|
ebox-row-layout-create
|
||||||
ebox-text-create
|
ebox-text-create
|
||||||
ebox-box-create
|
ebox-box-create
|
||||||
ebox-commit
|
ebox-commit
|
||||||
|
|||||||
@ -16,6 +16,14 @@
|
|||||||
"Return rendered display pixel widths for NODE line by line."
|
"Return rendered display pixel widths for NODE line by line."
|
||||||
(mapcar #'ebox--string-pixel-width (ebox-string-lines (ebox-render node))))
|
(mapcar #'ebox--string-pixel-width (ebox-string-lines (ebox-render node))))
|
||||||
|
|
||||||
|
(defun ebox-dsl-test--tree-count (node predicate)
|
||||||
|
"Count nodes below NODE for which PREDICATE returns non-nil."
|
||||||
|
(if (or (stringp node) (not (listp node)))
|
||||||
|
0
|
||||||
|
(+ (if (funcall predicate node) 1 0)
|
||||||
|
(cl-loop for child in (ebox-tree-node-children node)
|
||||||
|
sum (ebox-dsl-test--tree-count child predicate)))))
|
||||||
|
|
||||||
(ert-deftest ebox-style-expands-ebox-aliases-to-canonical-longhands ()
|
(ert-deftest ebox-style-expands-ebox-aliases-to-canonical-longhands ()
|
||||||
"Existing Ebox aliases should normalize to CSS-like longhand properties."
|
"Existing Ebox aliases should normalize to CSS-like longhand properties."
|
||||||
(let ((style (ebox-style-compute
|
(let ((style (ebox-style-compute
|
||||||
@ -172,6 +180,86 @@
|
|||||||
(should (equal (ebox-box-node-children box) (list text)))
|
(should (equal (ebox-box-node-children box) (list text)))
|
||||||
(should (string= (ebox-dsl-test--plain box) "A"))))
|
(should (string= (ebox-dsl-test--plain box) "A"))))
|
||||||
|
|
||||||
|
(ert-deftest ebox-canonical-row-box-retains-and-renders-typed-children ()
|
||||||
|
"A Row Box should retain one Box identity around all typed children."
|
||||||
|
(let* ((left (ebox-text-create :value "A" :source-handle 'left))
|
||||||
|
(right (ebox-text-create :value "B" :source-handle 'right))
|
||||||
|
(box (ebox-box-create :layout (ebox-row-layout-create)
|
||||||
|
:children (list left right)
|
||||||
|
:source-handle 'row)))
|
||||||
|
(should (ebox-box-node-p box))
|
||||||
|
(should (eq (ebox-node-source-handle box) 'row))
|
||||||
|
(should (eq (ebox-layout-config-kind (ebox-box-node-layout box)) 'row))
|
||||||
|
(should (equal (ebox-box-node-children box) (list left right)))
|
||||||
|
(should (eq (ebox-tree-node-children box)
|
||||||
|
(ebox-box-node-children box)))
|
||||||
|
(should (= (ebox-dsl-test--tree-count box (lambda (_node) t)) 3))
|
||||||
|
(should (= (ebox-dsl-test--tree-count box #'ebox-node-kind) 3))
|
||||||
|
(should-not (plist-member box :ebox-content-node))
|
||||||
|
(should (equal (ebox--computed-display box) '(block row)))
|
||||||
|
(should (string= (ebox-dsl-test--plain box) "AB"))))
|
||||||
|
|
||||||
|
(ert-deftest ebox-canonical-column-box-retains-and-renders-typed-children ()
|
||||||
|
"A Column Box should retain one Box identity around all typed children."
|
||||||
|
(let* ((top (ebox-text-create :value "A"))
|
||||||
|
(bottom (ebox-text-create :value "B"))
|
||||||
|
(box (ebox-box-create :layout (ebox-column-layout-create)
|
||||||
|
:children (list top bottom))))
|
||||||
|
(should (ebox-box-node-p box))
|
||||||
|
(should (eq (ebox-layout-config-kind (ebox-box-node-layout box)) 'column))
|
||||||
|
(should (equal (ebox-box-node-children box) (list top bottom)))
|
||||||
|
(should (eq (ebox-tree-node-children box)
|
||||||
|
(ebox-box-node-children box)))
|
||||||
|
(should (= (ebox-dsl-test--tree-count box (lambda (_node) t)) 3))
|
||||||
|
(should (= (ebox-dsl-test--tree-count box #'ebox-node-kind) 3))
|
||||||
|
(should-not (plist-member box :ebox-content-node))
|
||||||
|
(should (equal (ebox--computed-display box) '(block column)))
|
||||||
|
(should (string= (ebox-dsl-test--plain box) "A\nB"))))
|
||||||
|
|
||||||
|
(ert-deftest ebox-canonical-row-and-column-never-collapse-single-child-boxes ()
|
||||||
|
"A one-child Row or Column should preserve its canonical Box boundary."
|
||||||
|
(let* ((child (ebox-text-create :value "A"))
|
||||||
|
(row (ebox-box-create :layout (ebox-row-layout-create)
|
||||||
|
:children (list child)))
|
||||||
|
(column (ebox-box-create :layout (ebox-column-layout-create)
|
||||||
|
:children (list child))))
|
||||||
|
(should (ebox-box-node-p row))
|
||||||
|
(should (ebox-box-node-p column))
|
||||||
|
(should-not (eq row child))
|
||||||
|
(should-not (eq column child))
|
||||||
|
(should (equal (ebox-tree-node-children row) (list child)))
|
||||||
|
(should (equal (ebox-tree-node-children column) (list child)))
|
||||||
|
(should (= (ebox-dsl-test--tree-count row (lambda (_node) t)) 2))
|
||||||
|
(should (= (ebox-dsl-test--tree-count column (lambda (_node) t)) 2))
|
||||||
|
(should (string= (ebox-dsl-test--plain row) "A"))
|
||||||
|
(should (string= (ebox-dsl-test--plain column) "A"))))
|
||||||
|
|
||||||
|
(ert-deftest ebox-canonical-empty-row-and-column-have-no-runtime-child ()
|
||||||
|
"Empty Row and Column Boxes should not synthesize layout identities."
|
||||||
|
(dolist (layout (list (ebox-row-layout-create)
|
||||||
|
(ebox-column-layout-create)))
|
||||||
|
(let ((box (ebox-box-create :layout layout :children nil)))
|
||||||
|
(should (ebox-box-node-p box))
|
||||||
|
(should-not (ebox-tree-node-children box))
|
||||||
|
(should (= (ebox-dsl-test--tree-count box (lambda (_node) t)) 1))
|
||||||
|
(should (= (ebox-dsl-test--tree-count box #'ebox-node-kind) 1))
|
||||||
|
(should (string= (ebox-dsl-test--plain box) "")))))
|
||||||
|
|
||||||
|
(ert-deftest ebox-canonical-box-copy-keeps-one-authoritative-child-list ()
|
||||||
|
"A copied Box should expose exactly its copied runtime children."
|
||||||
|
(let* ((left (ebox-text-create :value "A"))
|
||||||
|
(right (ebox-text-create :value "B"))
|
||||||
|
(source (ebox-box-create :layout (ebox-row-layout-create)
|
||||||
|
:children (list left right)))
|
||||||
|
(copy (ebox-tree-copy-node-structure source))
|
||||||
|
(copied-children (ebox-tree-node-children copy)))
|
||||||
|
(should (eq copied-children (ebox-box-node-children copy)))
|
||||||
|
(should-not (eq copied-children (ebox-box-node-children source)))
|
||||||
|
(should-not (eq (car copied-children) left))
|
||||||
|
(should-not (eq (cadr copied-children) right))
|
||||||
|
(should (= (ebox-dsl-test--tree-count copy (lambda (_node) t)) 3))
|
||||||
|
(should (= (ebox-dsl-test--tree-count copy #'ebox-node-kind) 3))))
|
||||||
|
|
||||||
(ert-deftest ebox-canonical-box-rejects-paint-only-properties ()
|
(ert-deftest ebox-canonical-box-rejects-paint-only-properties ()
|
||||||
"Canonical Box geometry should not duplicate paint-only state."
|
"Canonical Box geometry should not duplicate paint-only state."
|
||||||
(should-error
|
(should-error
|
||||||
|
|||||||
@ -170,6 +170,8 @@
|
|||||||
("ebox-grid-item" . "defun")
|
("ebox-grid-item" . "defun")
|
||||||
("ebox-grid" . "defun")
|
("ebox-grid" . "defun")
|
||||||
("ebox-normal-layout-create" . "defun")
|
("ebox-normal-layout-create" . "defun")
|
||||||
|
("ebox-row-layout-create" . "defun")
|
||||||
|
("ebox-column-layout-create" . "defun")
|
||||||
("ebox-text-create" . "defun")
|
("ebox-text-create" . "defun")
|
||||||
("ebox-box-create" . "defun")
|
("ebox-box-create" . "defun")
|
||||||
("ebox-build" . "defun")
|
("ebox-build" . "defun")
|
||||||
@ -208,6 +210,8 @@
|
|||||||
ebox-clear-cache
|
ebox-clear-cache
|
||||||
ebox-column
|
ebox-column
|
||||||
ebox-normal-layout-create
|
ebox-normal-layout-create
|
||||||
|
ebox-row-layout-create
|
||||||
|
ebox-column-layout-create
|
||||||
ebox-text-create
|
ebox-text-create
|
||||||
ebox-box-create
|
ebox-box-create
|
||||||
ebox-commit
|
ebox-commit
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user