refactor: migrate examples to the canonical Ebox DSL

This commit is contained in:
Kinneyzhang 2026-08-27 12:14:51 +08:00
parent f571c89d70
commit 94bac1c7c7
11 changed files with 1976 additions and 1379 deletions

View File

@ -41,7 +41,7 @@
- Imagery/iconography: Text-only.
## Components
- Existing components to reuse: `ebox-create`, `ebox-column`, `ebox-row`, `ebox-flex`, `ebox-grid`, and `ebox-spacer`.
- Author forms to reuse: String, `text`, `box`, `row`, `column`, `flex`, and `grid`. Empty `box` nodes express spacing directly without another public form.
- New/changed components: Header band, property section bands, track-function cards, implicit-track/flow cards, gap/placement cards, alignment cards, and public-contract footer.
- Variants and states: Static semantic color families only.
- Token/component ownership: Palette values and example composition live in `.ebox` fixtures; the runner owns only parsing and rendering. The migrated references remain data files, so adding a layout does not add a fixture-specific Elisp branch.

View File

@ -41,7 +41,7 @@
- 图像与图标:纯文本。
## 组件
- 复用的现有组件:`ebox-create`、`ebox-column`、`ebox-row`、`ebox-flex`、`ebox-grid` 和 `ebox-spacer`
- 复用的作者 formString、`text`、`box`、`row`、`column`、`flex` 和 `grid`。空 `box` 直接表达间距,不再引入另一个公共 form
- 新增/调整的组件:标题带、能力分区标题带、固定/分数轨道卡片、放置卡片和公开契约页脚。
- 变体与状态:仅使用静态语义色组。
- Token/组件归属:配色值和示例组合放在 `.ebox` fixture 中;运行器只负责解析和渲染。迁移来的参考仍然是数据文件,新增布局不需要在 Elisp 中增加针对 fixture 的分支。

View File

@ -167,7 +167,9 @@ CANVAS-BACKGROUND fills display space outside generated root lines."
(prog1
(progn
(ebox-playground--apply-preview-display-settings
(and (consp node) (plist-get node :bgcolor)))
(and (consp node)
(ebox-style-node-specified-value
node :background-color)))
(ebox-render-to-buffer buffer node))
(setq published-p t))
(unless published-p

View File

@ -1,7 +1,3 @@
(box :content "Playground file"
:box-sizing 'border-box
:padding '(1 (12))
:border t
:border-color "#2563EB"
:bgcolor "#EFF6FF"
:color "#1E3A8A")
(box :box-sizing 'border-box :padding '(1 (12)) :border t
:border-color "#2563EB" :bgcolor "#EFF6FF" :color "#1E3A8A"
"Playground file")

View File

@ -1,41 +1,29 @@
(box :layout 'column
(box :content "Ebox comprehensive DSL showcase\nThe outer sections omit :width so Playground viewport sizing drives the layout."
:padding '(1 (16)) :border "#334155"
:bgcolor "#F8FAFC" :color "#0F172A" :text-align 'center)
(column
(box :padding '(1 (16)) :border "#334155" :bgcolor "#F8FAFC" :color
"#0F172A" :text-align 'center
"Ebox comprehensive DSL showcase\nThe outer sections omit :width so Playground viewport sizing drives the layout.")
(box :width '(viewport) :height 1 :bgcolor "#F8FAFC")
(box :content "Width rule in this file\nContainer sections use auto width. Fixed widths remain only where the example demonstrates exact item sizing, basis, min-width, or max-width."
:padding '(0 (14)) :border "#64748B"
:bgcolor "#F8FAFC" :color "#111827" :wrap-mode 'word)
(box :padding '(0 (14)) :border "#64748B" :bgcolor "#F8FAFC" :color
"#111827" :wrap-mode 'word
"Width rule in this file\nContainer sections use auto width. Fixed widths remain only where the example demonstrates exact item sizing, basis, min-width, or max-width.")
(box :width '(viewport) :height 1 :bgcolor "#F8FAFC")
(box :layout 'flex
:margin '(1 0 0 1) :padding '(1 (8))
:border "#475569" :bgcolor "#F8FAFC"
:flex-flow '(row wrap)
:justify-content 'space-between :align-items 'center
:align-content 'flex-start :row-gap 1 :column-gap '(12)
(item
:order -1 :flex-basis '(270) :align-self 'flex-start
(box :content "item order -1\n:flex-basis 270\nalign-self start"
:width '(270) :padding '(0 (8))
:border "#BE185D" :bgcolor "#FCE7F3" :color "#831843"
:wrap-mode 'word))
(box :flex '(1 1 (220))
:content "Box :flex (1 1 220)\ngrow shrink basis"
:width '(220) :height 4
:padding '(0 (8)) :border "#1D4ED8"
:bgcolor "#DBEAFE" :color "#111827" :wrap-mode 'word)
(box :flex-grow 2 :flex-shrink 1 :flex-basis '(240)
:align-self 'center
:content "Box grow 2\nshrink 1\nbasis 240"
:width '(240) :height 4 :padding '(0 (8))
:border "#B45309" :bgcolor "#FEF3C7" :color "#78350F"
:wrap-mode 'word)
(box :flex-shrink 3 :flex-basis '(190) :align-self 'flex-end
:content "Box shrink 3\nbasis 190\nalign-self flex-end"
:width '(190) :height 4 :padding '(0 (8))
:border "#15803D" :bgcolor "#DCFCE7" :color "#14532D"
:wrap-mode 'word)))
(flex :margin '(1 0 0 1) :padding '(1 (8)) :border "#475569" :bgcolor
"#F8FAFC" :flex-flow '(row wrap) :justify-content
'space-between :align-items 'center :align-content 'flex-start
:row-gap 1 :column-gap '(12)
(box :order -1 :flex-basis '(270) :align-self 'flex-start
:width '(270) :padding '(0 (8)) :border "#BE185D"
:bgcolor "#FCE7F3" :color "#831843" :wrap-mode 'word
"Box order -1\n:flex-basis 270\nalign-self start")
(box :flex '(1 1 (220)) :width '(220) :height 4 :padding
'(0 (8)) :border "#1D4ED8" :bgcolor "#DBEAFE" :color
"#111827" :wrap-mode 'word
"Box :flex (1 1 220)\ngrow shrink basis")
(box :flex-grow 2 :flex-shrink 1 :flex-basis '(240) :align-self
'center :width '(240) :height 4 :padding '(0 (8)) :border
"#B45309" :bgcolor "#FEF3C7" :color "#78350F" :wrap-mode
'word "Box grow 2\nshrink 1\nbasis 240")
(box :flex-shrink 3 :flex-basis '(190) :align-self 'flex-end
:width '(190) :height 4 :padding '(0 (8)) :border
"#15803D" :bgcolor "#DCFCE7" :color "#14532D" :wrap-mode
'word "Box shrink 3\nbasis 190\nalign-self flex-end")))

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,98 +1,61 @@
(box :layout 'column
(box :content "Ebox Playground\nPixel-precise layout, composed only from public nodes."
:width '(720)
:padding '(1 (18))
:border "#8F432F"
:color "#252A2E"
:bgcolor "#FFFDF8"
:face 'bold
:text-align 'center)
(column
(box :width '(720) :padding '(1 (18)) :border "#8F432F" :color
"#252A2E" :bgcolor "#FFFDF8" :font-weight 'bold :text-align 'center
"Ebox Playground\nPixel-precise layout, composed only from public nodes.")
(box :width '(720) :height 1 :bgcolor "#FAF7F0")
(box :content "01 FIXED + FRACTIONAL\nA definite Grid width divides into one exact track and one flexible track."
:width '(720)
:padding '(0 (16))
:border "#C97252"
:border-bottom 'none
:color "#252A2E"
:bgcolor "#F1D4C9"
:wrap-mode 'word)
(box :layout 'grid
:width '(720)
:grid-template-columns '((220) 1fr)
:gap '(1 (12))
:border "#C97252"
:bgcolor "#FFF9F5"
(box :content "FIXED TRACK\n220 px stays exact"
:width '(220) :padding '(1 0) :text-align 'center
:color "#252A2E" :bgcolor "#F1D4C9")
(box :content "FRACTIONAL TRACK\n1fr receives the remaining width"
:width '(486) :padding '(1 0) :text-align 'center
:color "#252A2E" :bgcolor "#F9E8E0")
(box :content "The Grid owns one definite width; its tracks divide that space without competing viewport calculations."
:grid-column '(1 :span 2) :width '(718) :padding '(1 0)
:color "#663322" :bgcolor "#FFFDF8"
:text-align 'center :wrap-mode 'word))
(box :width '(720) :padding '(0 (16)) :border "#C97252"
:border-bottom 'none :color "#252A2E" :bgcolor "#F1D4C9"
:wrap-mode 'word
"01 FIXED + FRACTIONAL\nA definite Grid width divides into one exact track and one flexible track.")
(grid :width '(720) :grid-template-columns '((220) 1fr) :gap
'(1 (12)) :border "#C97252" :bgcolor "#FFF9F5"
(box :width '(220) :padding '(1 0) :text-align 'center :color
"#252A2E" :bgcolor "#F1D4C9"
"FIXED TRACK\n220 px stays exact")
(box :width '(486) :padding '(1 0) :text-align 'center :color
"#252A2E" :bgcolor "#F9E8E0"
"FRACTIONAL TRACK\n1fr receives the remaining width")
(box :grid-column '(1 :span 2) :width '(718) :padding '(1 0)
:color "#663322" :bgcolor "#FFFDF8" :text-align 'center
:wrap-mode 'word
"The Grid owns one definite width; its tracks divide that space without competing viewport calculations."))
(box :width '(720) :height 1 :bgcolor "#FAF7F0")
(box :content "02 EXPLICIT PLACEMENT\nSpan columns, target cells, and leave the remaining nodes to auto placement."
:width '(720)
:padding '(0 (16))
:border "#6D8A73"
:border-bottom 'none
:color "#252A2E"
:bgcolor "#DCEBDD"
:wrap-mode 'word)
(box :layout 'grid
:width '(720)
:grid-template-columns '((210) (210) 1fr)
:gap '(1 (10))
:border "#6D8A73"
:bgcolor "#F7FBF7"
(box :content "SPAN 1 → 3" :grid-column '(1 :span 2)
:width '(430) :padding '(1 0) :text-align 'center
:color "#24422D" :bgcolor "#DCEBDD")
(box :content "COLUMN 3" :grid-column 3 :grid-row 1
:width '(278) :padding '(1 0) :text-align 'center
:color "#24422D" :bgcolor "#C8DDCB")
(box :content "ROW 2 / COL 1" :grid-column 1 :grid-row 2
:width '(210) :padding '(1 0) :text-align 'center
:color "#24422D" :bgcolor "#EDF5EE")
(box :content "AUTO PLACED" :width '(210) :padding '(1 0)
:text-align 'center :color "#24422D" :bgcolor "#E3F0E5")
(box :content "STABLE CELLS" :width '(278) :padding '(1 0)
:text-align 'center :color "#24422D" :bgcolor "#D4E6D7"))
(box :width '(720) :padding '(0 (16)) :border "#6D8A73"
:border-bottom 'none :color "#252A2E" :bgcolor "#DCEBDD"
:wrap-mode 'word
"02 EXPLICIT PLACEMENT\nSpan columns, target cells, and leave the remaining nodes to auto placement.")
(grid :width '(720) :grid-template-columns '((210) (210) 1fr) :gap
'(1 (10)) :border "#6D8A73" :bgcolor "#F7FBF7"
(box :grid-column '(1 :span 2) :width '(430) :padding '(1 0)
:text-align 'center :color "#24422D" :bgcolor "#DCEBDD"
"SPAN 1 → 3")
(box :grid-column 3 :grid-row 1 :width '(278) :padding '(1 0)
:text-align 'center :color "#24422D" :bgcolor "#C8DDCB"
"COLUMN 3")
(box :grid-column 1 :grid-row 2 :width '(210) :padding '(1 0)
:text-align 'center :color "#24422D" :bgcolor "#EDF5EE"
"ROW 2 / COL 1")
(box :width '(210) :padding '(1 0) :text-align 'center :color
"#24422D" :bgcolor "#E3F0E5" "AUTO PLACED")
(box :width '(278) :padding '(1 0) :text-align 'center :color
"#24422D" :bgcolor "#D4E6D7" "STABLE CELLS"))
(box :width '(720) :height 1 :bgcolor "#FAF7F0")
(box :content "03 PUBLIC COMPOSITION\nColumn, Flex, and Grid share the same public node contract."
:width '(720)
:padding '(0 (16))
:border "#4E7890"
:border-bottom 'none
:color "#252A2E"
:bgcolor "#D9EAF2"
:wrap-mode 'word)
(box :layout 'flex
:width '(720)
:flex-flow '(row wrap)
:gap '(1 (12))
:padding '(1 (12))
:border "#4E7890"
:bgcolor "#F7FAFC"
(box :content "COLUMN\nvertical composition"
:flex-grow 1 :flex-shrink 1 :flex-basis '(200)
:min-width '(180) :padding '(1 (12))
:color "#193846" :bgcolor "#D9EAF2")
(box :content "FLEX\nwrap and distribute"
:flex-grow 1 :flex-shrink 1 :flex-basis '(200)
:min-width '(180) :padding '(1 (12))
:color "#3F3655" :bgcolor "#E7E2F1")
(box :content "GRID\nplace in two dimensions"
:flex-grow 1 :flex-shrink 1 :flex-basis '(200)
:min-width '(180) :padding '(1 (12))
:color "#6B3020" :bgcolor "#F1D4C9"))
(box :width '(720) :padding '(0 (16)) :border "#4E7890"
:border-bottom 'none :color "#252A2E" :bgcolor "#D9EAF2"
:wrap-mode 'word
"03 PUBLIC COMPOSITION\nColumn, Flex, and Grid share the same public node contract.")
(flex :width '(720) :flex-flow '(row wrap) :gap '(1 (12)) :padding
'(1 (12)) :border "#4E7890" :bgcolor "#F7FAFC"
(box :flex-grow 1 :flex-shrink 1 :flex-basis '(200) :min-width
'(180) :padding '(1 (12)) :color "#193846" :bgcolor
"#D9EAF2" "COLUMN\nvertical composition")
(box :flex-grow 1 :flex-shrink 1 :flex-basis '(200) :min-width
'(180) :padding '(1 (12)) :color "#3F3655" :bgcolor
"#E7E2F1" "FLEX\nwrap and distribute")
(box :flex-grow 1 :flex-shrink 1 :flex-basis '(200) :min-width
'(180) :padding '(1 (12)) :color "#6B3020" :bgcolor
"#F1D4C9" "GRID\nplace in two dimensions"))
(box :width '(720) :height 1 :bgcolor "#FAF7F0")
(box :content "PUBLIC CONTRACT ebox-create · ebox-column · ebox-flex · ebox-grid · ebox-spacer"
:width '(720)
:padding '(0 (16))
:border "#8D887F"
:color "#4D5651"
:bgcolor "#EEEAE2"
:wrap-mode 'word))
(box :width '(720) :padding '(0 (16)) :border "#8D887F" :color
"#4D5651" :bgcolor "#EEEAE2" :wrap-mode 'word
"AUTHOR FORMS String · text · box · row · column · flex · grid"))

View File

@ -1,65 +1,57 @@
(box :layout 'column
:margin-left 1 :margin-top 1 :padding '(1 2 1 2) :bgcolor "linen"
(box :content "Ebox Responsive Layout\nDrag the preview window: sections stretch to the current viewport, cards reflow, and text wraps without changing the window layout."
:padding '(1 (18)) :border "#334155" :text-align 'center
:color "#000" :bgcolor "ghost white")
(box :height 1)
(box :content "No explicit viewport width here\nThis page mostly omits :width. The Playground binds the current preview width while rendering, so auto width behaves like a responsive container."
:padding '(0 (16)) :border "#0F766E"
:bgcolor "#F0FDFA" :color "#134E4A" :wrap-mode 'word)
(box :height 1)
(box :content "Adaptive toolbar\nButtons below keep stable sizes. The row packs as many as fit and then wraps."
:padding '(0 (16)) :border "#EA580C" :border-bottom 'none
:bgcolor "#FFF7ED" :color "#431407" :wrap-mode 'word)
(box :layout 'flex :flex-flow '(row wrap) :column-gap '(8) :row-gap 1
:padding '(1 (8)) :border "#FDBA74" :bgcolor "#FFFBF5"
(box :content "Render" :width '(96) :padding '(0 (8))
:border "#EA580C" :bgcolor "#FED7AA" :color "#111827"
:text-align 'center)
(box :content "Save" :width '(88) :padding '(0 (8))
:border "#D97706" :bgcolor "#FEF3C7" :color "#111827"
:text-align 'center)
(box :content "Format" :width '(96) :padding '(0 (8))
:border "#16A34A" :bgcolor "#DCFCE7" :color "#14532D"
:text-align 'center)
(box :content "Sample" :width '(104) :padding '(0 (8))
:border "#0284C7" :bgcolor "#E0F2FE" :color "#0C4A6E"
:text-align 'center)
(box :content "Write" :width '(88) :padding '(0 (8))
:border "#9333EA" :bgcolor "#F3E8FF" :color "#3B0764"
:text-align 'center))
(box :height 1)
(box :content "Responsive cards\nEach card starts from a flex-basis, grows when space is available, and wraps to new rows when the preview becomes narrow."
:padding '(0 (16)) :border "#2563EB" :border-bottom 'none
:bgcolor "#EFF6FF" :color "#1E3A8A" :wrap-mode 'word)
(box :layout 'flex :flex-flow '(row wrap) :column-gap '(12) :row-gap 1
:padding '(1 (8)) :border "#93C5FD" :bgcolor "#F8FBFF"
:justify-content 'center
(box :flex '(1 1 (210))
:content "Overview\nThe row uses the current preview width automatically."
:min-width '(180) :max-width '(280)
:padding '(0 (10)) ;; :border "#2563EB"
:bgcolor "#DBEAFE" :color "#111827" :wrap-mode 'word)
(box :flex '(1 1 (210))
:content "Editor\nDrag slowly or quickly; resize rendering follows the viewport."
:min-width '(180) :max-width '(300)
:padding '(0 (10)) ;; :border "#4F46E5"
:bgcolor "#E0E7FF" :color "#111827" :wrap-mode 'word)
(box :flex '(1 1 (210))
:content "Preview\nThe preview updates from the current viewport width."
:min-width '(180) :max-width '(320)
:padding '(0 (10)) ;; :border "#7C3AED"
:bgcolor "#EDE9FE" :color "#111827" :wrap-mode 'word)
(box :flex '(1 1 (210))
:content "Flow\nCards keep readable widths instead of overflowing."
:min-width '(180) :max-width '(280)
:padding '(0 (10)) ;; :border "#0891B2"
:bgcolor "#CFFAFE" :color "#164E63" :wrap-mode 'word))
(box :height 1)
(box :content "What to watch\nNarrow preview: cards stack and text wraps. Wide preview: cards share a row and expand up to max-width. The source/preview split is preserved."
:padding '(0 (16)) :border "#475569"
:bgcolor "#F8FAFC" :color "#0F172A" :wrap-mode 'word))
(column :margin-left 1 :margin-top 1 :padding '(1 2 1 2) :bgcolor
"linen"
(box :padding '(1 (18)) :border "#334155" :text-align 'center
:color "#000" :bgcolor "ghost white"
"Ebox Responsive Layout\nDrag the preview window: sections stretch to the current viewport, cards reflow, and text wraps without changing the window layout.")
(box :height 1)
(box :padding '(0 (16)) :border "#0F766E" :bgcolor "#F0FDFA"
:color "#134E4A" :wrap-mode 'word
"No explicit viewport width here\nThis page mostly omits :width. The Playground binds the current preview width while rendering, so auto width behaves like a responsive container.")
(box :height 1)
(box :padding '(0 (16)) :border "#EA580C" :border-bottom 'none
:bgcolor "#FFF7ED" :color "#431407" :wrap-mode 'word
"Adaptive toolbar\nButtons below keep stable sizes. The row packs as many as fit and then wraps.")
(flex :flex-flow '(row wrap) :column-gap '(8) :row-gap 1
:padding '(1 (8)) :border "#FDBA74" :bgcolor "#FFFBF5"
(box :width '(96) :padding '(0 (8)) :border "#EA580C"
:bgcolor "#FED7AA" :color "#111827" :text-align
'center "Render")
(box :width '(88) :padding '(0 (8)) :border "#D97706"
:bgcolor "#FEF3C7" :color "#111827" :text-align
'center "Save")
(box :width '(96) :padding '(0 (8)) :border "#16A34A"
:bgcolor "#DCFCE7" :color "#14532D" :text-align
'center "Format")
(box :width '(104) :padding '(0 (8)) :border "#0284C7"
:bgcolor "#E0F2FE" :color "#0C4A6E" :text-align
'center "Sample")
(box :width '(88) :padding '(0 (8)) :border "#9333EA"
:bgcolor "#F3E8FF" :color "#3B0764" :text-align
'center "Write"))
(box :height 1)
(box :padding '(0 (16)) :border "#2563EB" :border-bottom 'none
:bgcolor "#EFF6FF" :color "#1E3A8A" :wrap-mode 'word
"Responsive cards\nEach card starts from a flex-basis, grows when space is available, and wraps to new rows when the preview becomes narrow.")
(flex :flex-flow '(row wrap) :column-gap '(12) :row-gap 1
:padding '(1 (8)) :border "#93C5FD" :bgcolor "#F8FBFF"
:justify-content 'center
(box :flex '(1 1 (210)) :min-width '(180) :max-width
'(280) :padding '(0 (10)) :bgcolor "#DBEAFE" :color
"#111827" :wrap-mode 'word
"Overview\nThe row uses the current preview width automatically.")
(box :flex '(1 1 (210)) :min-width '(180) :max-width
'(300) :padding '(0 (10)) :bgcolor "#E0E7FF" :color
"#111827" :wrap-mode 'word
"Editor\nDrag slowly or quickly; resize rendering follows the viewport.")
(box :flex '(1 1 (210)) :min-width '(180) :max-width
'(320) :padding '(0 (10)) :bgcolor "#EDE9FE" :color
"#111827" :wrap-mode 'word
"Preview\nThe preview updates from the current viewport width.")
(box :flex '(1 1 (210)) :min-width '(180) :max-width
'(280) :padding '(0 (10)) :bgcolor "#CFFAFE" :color
"#164E63" :wrap-mode 'word
"Flow\nCards keep readable widths instead of overflowing."))
(box :height 1)
(box :padding '(0 (16)) :border "#475569" :bgcolor "#F8FAFC"
:color "#0F172A" :wrap-mode 'word
"What to watch\nNarrow preview: cards stack and text wraps. Wide preview: cards share a row and expand up to max-width. The source/preview split is preserved."))

View File

@ -120,7 +120,7 @@ concurrent cache warming CPU work."
(completed-without-error nil)
(ebox-playground-flex-resize-evaluator--output-lines nil)
(checks nil))
(condition-case error-data
(condition-case-unless-debug error-data
(progn
(delete-other-windows)
(setq source

View File

@ -33,6 +33,13 @@
(ebox-playground-test--forms-named name child))
form))))
(defun ebox-playground-test--form-children (form)
"Return canonical author children from DSL FORM."
(let ((items (cdr form)))
(while (keywordp (car items))
(setq items (cddr items)))
items))
(defun ebox-playground-test--line-widths (text)
"Return rendered pixel widths for every line in TEXT."
(mapcar #'ebox-string-pixel-width
@ -115,15 +122,17 @@
ebox-playground-directory))))
(dolist (box (ebox-playground-test--boxes form))
(let ((properties (cdr box)))
(when (and (memq :content properties)
(when (and (cl-some #'stringp
(ebox-playground-test--form-children box))
(memq :bgcolor properties))
(should (memq :color properties))))))))
(ert-deftest ebox-playground-uses-only-public-layout-apis ()
"The example should build and render through the public Ebox entry point."
(let* ((node (ebox-playground-view))
(let* ((source (ebox-playground--read-file ebox-playground-default-file))
(node (ebox-playground-view))
(rendered (substring-no-properties (ebox-render node))))
(should (eq (plist-get node :ebox-type) 'stack))
(should (eq (car source) 'column))
(dolist (label '("Ebox Playground" "FIXED + FRACTIONAL"
"EXPLICIT PLACEMENT" "PUBLIC COMPOSITION"))
(should (string-match-p (regexp-quote label) rendered)))))
@ -234,7 +243,7 @@
(lambda (&optional _frame) 8)))
(with-temp-buffer
(setq buffer-file-name "/tmp/ebox-playground-viewport-render.ebox")
(insert "(box :content \"viewport\" :width '(viewport) :height 1)")
(insert "(box :width '(viewport) :height 1 \"viewport\")")
(ebox-dsl-mode)
(ebox-dsl-render)
(with-current-buffer preview
@ -281,7 +290,7 @@
(with-temp-buffer
(setq source (current-buffer)
buffer-file-name "/tmp/ebox-playground-two-window.ebox")
(insert "(box :content \"two windows\" :width '(viewport) :height 1)")
(insert "(box :width '(viewport) :height 1 \"two windows\")")
(ebox-dsl-mode)
(cl-letf (((symbol-function 'window-body-width)
(lambda (&optional _window _pixelwise) 987))
@ -313,7 +322,7 @@
(lambda (&optional _frame) 8)))
(with-temp-buffer
(setq buffer-file-name "/tmp/ebox-playground-viewport-resize.ebox")
(insert "(box :content \"viewport\" :width '(viewport) :height 1)")
(insert "(box :width '(viewport) :height 1 \"viewport\")")
(ebox-dsl-mode)
(ebox-dsl-render)
(setq window-width 1234)
@ -417,7 +426,7 @@
(error "Injected preview render failure"))))
(should-error
(ebox-playground--render-to-preview-buffer
preview (ebox-create :content "rollback"))))
preview (ebox-build '(box "rollback")))))
(with-current-buffer preview
(should-not truncate-lines)
(should (equal face-remapping-alist
@ -481,21 +490,21 @@
(let* ((ebox-viewport-width viewport)
(lines (ebox-string-lines
(ebox-render (ebox-playground-view path viewport))))
(spacer-lines
(separator-lines
(cl-remove-if-not
(lambda (line)
(equal (get-text-property 0 'display line)
`(space :width (,viewport))))
lines)))
(should (= (length spacer-lines) 11))
(dolist (line spacer-lines)
(should (= (length separator-lines) 11))
(dolist (line separator-lines)
(should (equal (get-text-property 0 'display line)
`(space :width (,viewport))))
(should (= (ebox-string-pixel-width line) viewport))
(should (equal (get-text-property 0 'face line)
'(:background "#FAF7F0"))))))))
(ert-deftest ebox-playground-public-layout-gallery-fixed-spacers-paint-the-canvas ()
(ert-deftest ebox-playground-public-layout-gallery-fixed-separators-paint-the-canvas ()
"The default public gallery fixed separators should keep canvas coverage."
(let* ((path (expand-file-name "examples/public-layout-gallery.ebox"
ebox-playground-directory))
@ -512,11 +521,11 @@
(ert-deftest ebox-playground-grid-reference-covers-public-properties ()
"The Grid reference should cover every public property and supported value form."
(let ((source (with-temp-buffer
(insert-file-contents
(expand-file-name "examples/grid-reference.ebox"
ebox-playground-directory))
(buffer-string))))
(let ((source
(prin1-to-string
(ebox-playground--read-file
(expand-file-name "examples/grid-reference.ebox"
ebox-playground-directory)))))
(dolist (property '(:grid-template-columns :grid-template-rows
:grid-auto-columns :grid-auto-rows :grid-auto-flow
:grid-row-gap :grid-column-gap :gap :row-gap
@ -565,7 +574,7 @@
(unwind-protect
(with-temp-buffer
(setq buffer-file-name "/tmp/ebox-playground-render-test.ebox")
(insert "(box :content \"Rendered from .ebox\" :width '(240))")
(insert "(box :width '(240) \"Rendered from .ebox\")")
(ebox-dsl-mode)
(ebox-dsl-render)
(should (eq (window-buffer (selected-window)) (current-buffer)))
@ -578,16 +587,19 @@
(ert-deftest ebox-playground-evaluates-property-expressions ()
"Evaluate executable property values while preserving quoted constants."
(let* ((form (ebox-playground--evaluate-form
'(box :content "Dynamic property values"
:width (ebox-playground-test--dynamic-width)
'(box :width (ebox-playground-test--dynamic-width)
:color (ebox-playground-test--dynamic-color)
:padding '(0 (4))
:text-align 'center)))
:text-align 'center
"Dynamic property values")))
(node (ebox-build form)))
(should (equal (plist-get node :width) 240))
(should (equal (plist-get node :color) "#123456"))
(should (equal (plist-get node :padding-left-pixel) 4))
(should (eq (plist-get node :text-align) 'center))))
(should (equal (ebox-style-node-specified-value node :width) '(240)))
(should (equal (ebox-style-node-specified-value node :color) "#123456"))
(should (equal
(ebox-style-node-specified-value node :padding-left)
'(4)))
(should (eq (ebox-style-node-specified-value node :text-align)
'center))))
(provide 'ebox-playground-tests)