fix: restore generic Ebox DSL file playground
Move the maintained gallery into a readable .ebox fixture and make ebox-playground own generic parsing, file mode, and public rendering. Keep the startup mode trigger deferred through the user's use-package configuration. Verified with ebox-playground make check (6/6), etaf-playground make check (6/6), exact use-package startup harness, and fullscreen GUI capture at /tmp/ebox-playground-dsl-gallery.png.
This commit is contained in:
parent
35f8eb80ef
commit
748a578c31
10
DESIGN.md
10
DESIGN.md
@ -3,8 +3,8 @@
|
||||
## Source of truth
|
||||
- Status: Active
|
||||
- Last refreshed: 2026-08-05
|
||||
- Primary product surfaces: The buffer opened by `ebox-playground-open` and its public layout example tree.
|
||||
- Evidence reviewed: `ebox-playground.el`, `tests/ebox-playground-tests.el`, `README.md`, `README.zh-CN.md`, the rendered current example, and `../emacs-box/examples/playground/flex-reference.ebox` rendered fullscreen in GUI Emacs.
|
||||
- Primary product surfaces: The `.ebox` files under `examples/`, the buffer opened by `ebox-playground-open`, and the generic file mode.
|
||||
- Evidence reviewed: `ebox-playground.el`, `examples/public-layout-gallery.ebox`, `tests/ebox-playground-tests.el`, `README.md`, `README.zh-CN.md`, and the rendered current example.
|
||||
|
||||
## Brand
|
||||
- Personality: Precise, modern, restrained, and educational.
|
||||
@ -29,7 +29,7 @@
|
||||
## Design principles
|
||||
- Principle 1: Mirror the Flex reference's title—explanation—example rhythm.
|
||||
- Principle 2: Use one restrained semantic accent per capability section.
|
||||
- Principle 3: Keep the example public-only and small enough to understand from one source file.
|
||||
- Principle 3: Keep the runner generic; put each concrete layout in a readable `.ebox` source file.
|
||||
- Tradeoffs: Prefer a compact representative gallery over exhaustive property coverage.
|
||||
|
||||
## Visual language
|
||||
@ -44,7 +44,7 @@
|
||||
- Existing components to reuse: `ebox-create`, `ebox-column`, `ebox-row`, `ebox-flex`, `ebox-grid`, and `ebox-spacer`.
|
||||
- New/changed components: Header band, capability section band, fixed/fractional track cards, placement cards, and public-contract footer.
|
||||
- Variants and states: Static semantic color families only.
|
||||
- Token/component ownership: Palette constants and example composition remain in `ebox-playground.el`; Ebox owns rendering.
|
||||
- Token/component ownership: Palette values and example composition live in `.ebox` fixtures; the runner owns only parsing and rendering.
|
||||
|
||||
## Accessibility
|
||||
- Target standard: High contrast and readable labels in ordinary GUI Emacs themes.
|
||||
@ -79,4 +79,4 @@
|
||||
- Test/screenshot expectations: `make check` passes and a fullscreen one-window screenshot shows complete, unclipped labeled sections.
|
||||
|
||||
## Open questions
|
||||
- [ ] Add more standalone examples only when each teaches a distinct public Ebox responsibility / maintainer / prevents fixture sprawl.
|
||||
- [ ] Add more standalone `.ebox` fixtures only when each teaches a distinct public Ebox responsibility / maintainer / prevents fixture sprawl.
|
||||
|
||||
@ -3,8 +3,8 @@
|
||||
## 真相来源
|
||||
- 状态:有效
|
||||
- 最近更新:2026-08-05
|
||||
- 主要产品界面:`ebox-playground-open` 打开的缓冲区及其公开布局示例树。
|
||||
- 已审阅证据:`ebox-playground.el`、`tests/ebox-playground-tests.el`、`README.md`、`README.zh-CN.md`、当前示例的实际渲染,以及在 GUI Emacs 中全屏渲染的 `../emacs-box/examples/playground/flex-reference.ebox`。
|
||||
- 主要产品界面:`examples/` 下的 `.ebox` 文件、`ebox-playground-open` 打开的缓冲区,以及通用文件模式。
|
||||
- 已审阅证据:`ebox-playground.el`、`examples/public-layout-gallery.ebox`、`tests/ebox-playground-tests.el`、`README.md`、`README.zh-CN.md` 和当前示例的实际渲染。
|
||||
|
||||
## 品牌
|
||||
- 个性:精确、现代、克制、适合教学。
|
||||
@ -29,7 +29,7 @@
|
||||
## 设计原则
|
||||
- 原则 1:延续 Flex 参考示例的“标题—解释—示例”节奏。
|
||||
- 原则 2:每个能力分区只使用一组克制的语义强调色。
|
||||
- 原则 3:示例只使用公开 API,并保持在一个源文件内即可理解的规模。
|
||||
- 原则 3:运行器保持通用;每个具体布局都放在易读的 `.ebox` 源文件中。
|
||||
- 取舍:优先紧凑且有代表性的画廊,而不是穷举所有属性。
|
||||
|
||||
## 视觉语言
|
||||
@ -44,7 +44,7 @@
|
||||
- 复用的现有组件:`ebox-create`、`ebox-column`、`ebox-row`、`ebox-flex`、`ebox-grid` 和 `ebox-spacer`。
|
||||
- 新增/调整的组件:标题带、能力分区标题带、固定/分数轨道卡片、放置卡片和公开契约页脚。
|
||||
- 变体与状态:仅使用静态语义色组。
|
||||
- Token/组件归属:配色常量和示例组合保留在 `ebox-playground.el`;Ebox 负责渲染。
|
||||
- Token/组件归属:配色值和示例组合放在 `.ebox` fixture 中;运行器只负责解析和渲染。
|
||||
|
||||
## 无障碍
|
||||
- 目标标准:在常见 GUI Emacs 主题下保持高对比度和标签可读性。
|
||||
@ -79,4 +79,4 @@
|
||||
- 测试/截图要求:`make check` 通过;单窗口 GUI 截图显示完整且未裁剪的标签分区。
|
||||
|
||||
## 开放问题
|
||||
- [ ] 只有当每个新增示例都能讲清一种独立的公开 Ebox 责任时才继续扩展示例,避免 fixture 膨胀。
|
||||
- [ ] 只有当每个新增 `.ebox` 示例都能讲清一种独立的公开 Ebox 责任时才继续扩展,避免 fixture 膨胀。
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# ebox-playground
|
||||
|
||||
`ebox-playground` is the independent developer example package for Ebox. It uses only public Ebox constructors and presents a polished three-part gallery for fixed and fractional tracks, explicit Grid placement, and public Column/Flex/Grid composition. Its restrained terracotta, sage, blue, and violet palette follows the visual standard of the original Flex reference without depending on theme-specific faces.
|
||||
`ebox-playground` is the independent, generic file runner for Ebox DSL examples. It uses only public Ebox APIs; concrete layouts live in readable `.ebox` fixtures under `examples/`. The maintained gallery demonstrates fixed and fractional tracks, explicit Grid placement, and public Column/Flex/Grid composition with a restrained terracotta, sage, blue, and violet palette.
|
||||
|
||||
The gallery owns one definite 720 px canvas so its nested Grid examples cannot each reinterpret the surrounding viewport width. It fits a compact GUI Emacs window with at least 760 px of body width. `etaf-playground` remains the separate higher-level Component and Runtime showcase.
|
||||
|
||||
@ -9,4 +9,10 @@ The gallery owns one definite 720 px canvas so its nested Grid examples cannot e
|
||||
(ebox-playground-open)
|
||||
```
|
||||
|
||||
The package also owns the `.ebox` file boundary. Visiting an Ebox DSL file selects `ebox-dsl-mode`; press `C-c C-c` to build the single DSL form and render a preview through the public Ebox API.
|
||||
|
||||
```elisp
|
||||
(add-to-list 'auto-mode-alist '("\\.ebox\\'" . ebox-dsl-mode))
|
||||
```
|
||||
|
||||
Run `make check EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs` from this directory.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# ebox-playground
|
||||
|
||||
`ebox-playground` 是 Ebox 的独立开发示例包,只使用 Ebox 公共构造函数,并通过一套精心设计的三段式画廊展示固定与分数轨道、显式 Grid 放置,以及公开的 Column/Flex/Grid 组合能力。克制的陶土色、鼠尾草绿、蓝色与紫色配色延续了原 Flex 参考示例的视觉标准,同时不依赖特定主题 face。
|
||||
`ebox-playground` 是 Ebox DSL 的独立通用文件运行器,只使用 Ebox 公共 API;具体布局都放在 `examples/` 下易读的 `.ebox` fixture 中。维护中的画廊通过这些源文件展示固定与分数轨道、显式 Grid 放置,以及公开的 Column/Flex/Grid 组合能力,并使用克制的陶土色、鼠尾草绿、蓝色与紫色配色。
|
||||
|
||||
画廊统一拥有一个明确的 720 px 画布,因此嵌套 Grid 不会各自重新解释外层视口宽度。只要 GUI Emacs 的正文区域不小于 760 px,它就能完整显示。高层 Component/Runtime 展示仍由独立的 `etaf-playground` 提供。
|
||||
|
||||
@ -9,4 +9,10 @@
|
||||
(ebox-playground-open)
|
||||
```
|
||||
|
||||
这个包也拥有 `.ebox` 文件入口。访问 Ebox DSL 文件时会自动进入 `ebox-dsl-mode`;按 `C-c C-c` 会通过 Ebox 公开 API 构建单个 DSL form 并渲染预览。
|
||||
|
||||
```elisp
|
||||
(add-to-list 'auto-mode-alist '("\\.ebox\\'" . ebox-dsl-mode))
|
||||
```
|
||||
|
||||
在该目录运行 `make check EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs`。
|
||||
|
||||
@ -9,150 +9,115 @@
|
||||
;;; Commentary:
|
||||
|
||||
;; This package is intentionally small and public-only. It demonstrates the
|
||||
;; Ebox contract without reaching into ebox-- internals. ETAF's application
|
||||
;; examples live in the sibling `etaf-playground' package.
|
||||
;; Ebox contract without reaching into internal implementation details. ETAF's
|
||||
;; application examples live in the sibling `etaf-playground' package.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'ebox)
|
||||
(require 'elisp-mode)
|
||||
(require 'subr-x)
|
||||
(defvar read-eval)
|
||||
|
||||
(defconst ebox-playground-buffer-name "*Ebox Playground*"
|
||||
"Default buffer name used by `ebox-playground-open'.")
|
||||
|
||||
(defun ebox-playground--header ()
|
||||
"Return the gallery header."
|
||||
(ebox-create
|
||||
: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))
|
||||
(defvar ebox-dsl-mode-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(set-keymap-parent map emacs-lisp-mode-map)
|
||||
(define-key map (kbd "C-c C-c") #'ebox-dsl-render)
|
||||
map)
|
||||
"Keymap used by `ebox-dsl-mode'.")
|
||||
|
||||
(defun ebox-playground--section-heading
|
||||
(number title copy border background)
|
||||
"Return a section heading for NUMBER, TITLE, COPY, BORDER, and BACKGROUND."
|
||||
(ebox-create
|
||||
:content (format "%s %s\n%s" number title copy)
|
||||
:width '(720)
|
||||
:padding '(0 (16))
|
||||
:border border
|
||||
:border-bottom-p nil
|
||||
:color "#252A2E"
|
||||
:bgcolor background
|
||||
:wrap-mode 'word))
|
||||
|
||||
(defun ebox-playground--track-grid ()
|
||||
"Return the fixed and fractional track example."
|
||||
(ebox-grid
|
||||
:width '(718)
|
||||
:grid-template-columns '((220) 1fr)
|
||||
:gap '(1 (12))
|
||||
:border "#C97252"
|
||||
:bgcolor "#FFF9F5"
|
||||
(ebox-create :content "FIXED TRACK\n220 px stays exact"
|
||||
:width '(220) :padding '(1 0) :text-align 'center
|
||||
:color "#252A2E" :bgcolor "#F1D4C9")
|
||||
(ebox-create :content "FRACTIONAL TRACK\n1fr receives the remaining width"
|
||||
:width '(486) :padding '(1 0) :text-align 'center
|
||||
:color "#252A2E" :bgcolor "#F9E8E0")
|
||||
(ebox-create :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)))
|
||||
|
||||
(defun ebox-playground--placement-grid ()
|
||||
"Return the explicit Grid placement example."
|
||||
(ebox-grid
|
||||
:width '(718)
|
||||
:grid-template-columns '((210) (210) 1fr)
|
||||
:gap '(1 (10))
|
||||
:border "#6D8A73"
|
||||
:bgcolor "#F7FBF7"
|
||||
(ebox-create :content "SPAN 1 → 3" :grid-column '(1 :span 2)
|
||||
:width '(430) :padding '(1 0) :text-align 'center
|
||||
:color "#24422D" :bgcolor "#DCEBDD")
|
||||
(ebox-create :content "COLUMN 3" :grid-column 3 :grid-row 1
|
||||
:width '(278) :padding '(1 0) :text-align 'center
|
||||
:color "#24422D" :bgcolor "#C8DDCB")
|
||||
(ebox-create :content "ROW 2 / COL 1" :grid-column 1 :grid-row 2
|
||||
:width '(210) :padding '(1 0) :text-align 'center
|
||||
:color "#24422D" :bgcolor "#EDF5EE")
|
||||
(ebox-create :content "AUTO PLACED" :width '(210) :padding '(1 0)
|
||||
:text-align 'center
|
||||
:color "#24422D" :bgcolor "#E3F0E5")
|
||||
(ebox-create :content "STABLE CELLS" :width '(278) :padding '(1 0)
|
||||
:text-align 'center
|
||||
:color "#24422D" :bgcolor "#D4E6D7")))
|
||||
|
||||
(defun ebox-playground--composition-flex ()
|
||||
"Return the public node composition example."
|
||||
(ebox-flex
|
||||
:width '(720)
|
||||
:flex-flow '(row wrap)
|
||||
:gap '(1 (12))
|
||||
:padding '(1 (12))
|
||||
:border "#4E7890"
|
||||
:bgcolor "#F7FAFC"
|
||||
(ebox-create :content "COLUMN\nvertical composition"
|
||||
:flex-grow 1 :flex-shrink 1 :flex-basis '(200)
|
||||
:min-width '(180) :padding '(1 (12))
|
||||
:color "#193846" :bgcolor "#D9EAF2")
|
||||
(ebox-create :content "FLEX\nwrap and distribute"
|
||||
:flex-grow 1 :flex-shrink 1 :flex-basis '(200)
|
||||
:min-width '(180) :padding '(1 (12))
|
||||
:color "#3F3655" :bgcolor "#E7E2F1")
|
||||
(ebox-create :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")))
|
||||
|
||||
(defun ebox-playground--footer ()
|
||||
"Return the public-contract footer."
|
||||
(ebox-create
|
||||
: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))
|
||||
(defun ebox-playground--source-form ()
|
||||
"Read the single Ebox DSL form from the current buffer."
|
||||
(ebox-playground--read-form
|
||||
(buffer-substring-no-properties (point-min) (point-max))))
|
||||
|
||||
;;;###autoload
|
||||
(defun ebox-playground-view ()
|
||||
"Return a public Ebox example layout node without buffer side effects."
|
||||
(ebox-column
|
||||
(ebox-playground--header)
|
||||
(ebox-spacer :height 1)
|
||||
(ebox-playground--section-heading
|
||||
"01" "FIXED + FRACTIONAL"
|
||||
"A definite Grid width divides into one exact track and one flexible track."
|
||||
"#C97252" "#F1D4C9")
|
||||
(ebox-playground--track-grid)
|
||||
(ebox-spacer :height 1)
|
||||
(ebox-playground--section-heading
|
||||
"02" "EXPLICIT PLACEMENT"
|
||||
"Span columns, target cells, and leave the remaining nodes to auto placement."
|
||||
"#6D8A73" "#DCEBDD")
|
||||
(ebox-playground--placement-grid)
|
||||
(ebox-spacer :height 1)
|
||||
(ebox-playground--section-heading
|
||||
"03" "PUBLIC COMPOSITION"
|
||||
"Column, Flex, and Grid share the same public node contract."
|
||||
"#4E7890" "#D9EAF2")
|
||||
(ebox-playground--composition-flex)
|
||||
(ebox-spacer :height 1)
|
||||
(ebox-playground--footer)))
|
||||
(define-derived-mode ebox-dsl-mode emacs-lisp-mode "EboxDSL"
|
||||
"Major mode for Ebox DSL source files."
|
||||
(setq-local truncate-lines nil)
|
||||
(setq-local bidi-display-reordering nil)
|
||||
(setq-local bidi-paragraph-direction 'left-to-right))
|
||||
|
||||
;;;###autoload
|
||||
(defun ebox-dsl-render ()
|
||||
"Render the current Ebox DSL buffer into a preview buffer."
|
||||
(interactive)
|
||||
(let* ((source (ebox-playground--source-form))
|
||||
(name (format "*Ebox Preview: %s*"
|
||||
(or (buffer-file-name) (buffer-name))))
|
||||
(node (ebox-build source)))
|
||||
(ebox-render-to-buffer name node)
|
||||
(message "Rendered Ebox DSL into %s" name)
|
||||
(get-buffer name)))
|
||||
|
||||
;;;###autoload
|
||||
(add-to-list 'auto-mode-alist '("\\.ebox\\'" . ebox-dsl-mode))
|
||||
|
||||
(defgroup ebox-playground nil
|
||||
"Run Ebox DSL examples from source files."
|
||||
:group 'ebox)
|
||||
|
||||
(defconst ebox-playground-directory
|
||||
(file-name-directory (or load-file-name buffer-file-name))
|
||||
"Directory containing the Ebox Playground package.")
|
||||
|
||||
(defcustom ebox-playground-default-file
|
||||
(expand-file-name "examples/public-layout-gallery.ebox"
|
||||
ebox-playground-directory)
|
||||
"Ebox DSL file rendered by `ebox-playground-open'."
|
||||
:type 'file
|
||||
:group 'ebox-playground)
|
||||
|
||||
(defun ebox-playground--read-form (source)
|
||||
"Read one Ebox DSL form from SOURCE."
|
||||
(when (string-empty-p (string-trim source))
|
||||
(user-error "The Ebox DSL source is empty"))
|
||||
(with-temp-buffer
|
||||
(insert source)
|
||||
(goto-char (point-min))
|
||||
(let ((read-eval nil)
|
||||
(form (read (current-buffer))))
|
||||
(condition-case nil
|
||||
(progn
|
||||
(read (current-buffer))
|
||||
(user-error "The Ebox DSL source must contain one form"))
|
||||
(end-of-file form)))))
|
||||
|
||||
(defun ebox-playground--read-file (file)
|
||||
"Read one Ebox DSL form from FILE."
|
||||
(unless (file-readable-p file)
|
||||
(user-error "Ebox DSL file is not readable: %s" file))
|
||||
(with-temp-buffer
|
||||
(insert-file-contents file)
|
||||
(ebox-playground--read-form
|
||||
(buffer-substring-no-properties (point-min) (point-max)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun ebox-playground-view (&optional file)
|
||||
"Build the Ebox DSL form in FILE without buffer side effects."
|
||||
(ebox-build
|
||||
(ebox-playground--read-file
|
||||
(expand-file-name (or file ebox-playground-default-file)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun ebox-playground-open (&optional buffer-name)
|
||||
"Render the public Ebox example into BUFFER-NAME and return its buffer."
|
||||
"Render the default Ebox DSL example into BUFFER-NAME and return its buffer."
|
||||
(interactive)
|
||||
(ebox-render-to-buffer (or buffer-name ebox-playground-buffer-name)
|
||||
(ebox-playground-view)))
|
||||
|
||||
;;;###autoload
|
||||
(defun ebox-playground-open-file (file &optional buffer-name)
|
||||
"Render Ebox DSL FILE into BUFFER-NAME and return its buffer."
|
||||
(interactive "fEbox DSL file: ")
|
||||
(ebox-render-to-buffer
|
||||
(or buffer-name
|
||||
(format "*Ebox Preview: %s*" (file-name-nondirectory file)))
|
||||
(ebox-playground-view file)))
|
||||
|
||||
;;;###autoload
|
||||
(defun ebox-playground-close (&optional buffer-name)
|
||||
"Kill the playground BUFFER-NAME and return its former buffer."
|
||||
|
||||
5
examples/README.md
Normal file
5
examples/README.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Ebox Playground examples
|
||||
|
||||
The `.ebox` files in this directory are the concrete layouts consumed by the generic `ebox-playground` runner. They are intentionally ordinary, reader-valid Ebox DSL forms so authors can copy, edit, and open them directly.
|
||||
|
||||
`public-layout-gallery.ebox` is the default fixture used by `M-x ebox-playground-open`. To render another fixture, visit it and press `C-c C-c`, or call `ebox-playground-open-file`.
|
||||
5
examples/README.zh-CN.md
Normal file
5
examples/README.zh-CN.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Ebox Playground 示例
|
||||
|
||||
此目录下的 `.ebox` 文件是通用 `ebox-playground` 运行器读取的具体布局。它们保持为普通、可读、可被 reader 读取的 Ebox DSL form,便于直接复制、编辑和打开。
|
||||
|
||||
`public-layout-gallery.ebox` 是 `M-x ebox-playground-open` 使用的默认 fixture。要渲染其他 fixture,可以访问该文件后按 `C-c C-c`,或调用 `ebox-playground-open-file`。
|
||||
98
examples/public-layout-gallery.ebox
Normal file
98
examples/public-layout-gallery.ebox
Normal file
@ -0,0 +1,98 @@
|
||||
(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)
|
||||
(spacer :height 1)
|
||||
(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-p nil
|
||||
:color "#252A2E"
|
||||
:bgcolor "#F1D4C9"
|
||||
:wrap-mode word)
|
||||
(grid
|
||||
:width (718)
|
||||
: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))
|
||||
(spacer :height 1)
|
||||
(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-p nil
|
||||
:color "#252A2E"
|
||||
:bgcolor "#DCEBDD"
|
||||
:wrap-mode word)
|
||||
(grid
|
||||
:width (718)
|
||||
: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"))
|
||||
(spacer :height 1)
|
||||
(box :content "03 PUBLIC COMPOSITION\nColumn, Flex, and Grid share the same public node contract."
|
||||
:width (720)
|
||||
:padding (0 (16))
|
||||
:border "#4E7890"
|
||||
:border-bottom-p nil
|
||||
:color "#252A2E"
|
||||
:bgcolor "#D9EAF2"
|
||||
:wrap-mode word)
|
||||
(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"))
|
||||
(spacer :height 1)
|
||||
(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))
|
||||
@ -12,6 +12,18 @@
|
||||
"EXPLICIT PLACEMENT" "PUBLIC COMPOSITION"))
|
||||
(should (string-match-p (regexp-quote label) rendered)))))
|
||||
|
||||
(ert-deftest ebox-playground-keeps-layout-in-ebox-source ()
|
||||
"Keep concrete gallery content out of the generic Elisp runner."
|
||||
(let ((runner (with-temp-buffer
|
||||
(insert-file-contents
|
||||
(expand-file-name "ebox-playground.el"
|
||||
ebox-playground-directory))
|
||||
(buffer-string))))
|
||||
(should (file-readable-p ebox-playground-default-file))
|
||||
(should (string-suffix-p ".ebox" ebox-playground-default-file))
|
||||
(should-not (string-match-p "FIXED TRACK" runner))
|
||||
(should-not (string-match-p "PUBLIC COMPOSITION" runner))))
|
||||
|
||||
(ert-deftest ebox-playground-opens-and-closes-buffer ()
|
||||
"The public open and close commands should own their buffer lifecycle."
|
||||
(let ((name " *ebox-playground-test*"))
|
||||
@ -34,6 +46,27 @@
|
||||
(should (= maximum gallery-width))
|
||||
(should (<= gallery-width 760))))
|
||||
|
||||
(ert-deftest ebox-playground-registers-ebox-file-mode ()
|
||||
"Open Ebox DSL files in the package-owned major mode."
|
||||
(with-temp-buffer
|
||||
(setq buffer-file-name "/tmp/ebox-playground-mode-test.ebox")
|
||||
(set-auto-mode)
|
||||
(should (eq major-mode 'ebox-dsl-mode))))
|
||||
|
||||
(ert-deftest ebox-playground-renders-ebox-file-mode-source ()
|
||||
"Render a file-mode buffer through the public Ebox build path."
|
||||
(let ((preview "*Ebox Preview: /tmp/ebox-playground-render-test.ebox*"))
|
||||
(unwind-protect
|
||||
(with-temp-buffer
|
||||
(setq buffer-file-name "/tmp/ebox-playground-render-test.ebox")
|
||||
(insert "(box :content \"Rendered from .ebox\" :width (240))")
|
||||
(ebox-dsl-mode)
|
||||
(ebox-dsl-render)
|
||||
(with-current-buffer preview
|
||||
(should (string-match-p "Rendered from .ebox" (buffer-string)))))
|
||||
(when (get-buffer preview)
|
||||
(kill-buffer preview)))))
|
||||
|
||||
(provide 'ebox-playground-tests)
|
||||
|
||||
;;; ebox-playground-tests.el ends here
|
||||
|
||||
Loading…
Reference in New Issue
Block a user