From 748a578c310ab035f5ff857ee443208c737ef679 Mon Sep 17 00:00:00 2001 From: Kinneyzhang Date: Wed, 5 Aug 2026 19:46:45 +0800 Subject: [PATCH] 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. --- DESIGN.md | 10 +- DESIGN.zh-CN.md | 10 +- README.md | 8 +- README.zh-CN.md | 8 +- ebox-playground.el | 217 ++++++++++++---------------- examples/README.md | 5 + examples/README.zh-CN.md | 5 + examples/public-layout-gallery.ebox | 98 +++++++++++++ tests/ebox-playground-tests.el | 33 +++++ 9 files changed, 256 insertions(+), 138 deletions(-) create mode 100644 examples/README.md create mode 100644 examples/README.zh-CN.md create mode 100644 examples/public-layout-gallery.ebox diff --git a/DESIGN.md b/DESIGN.md index 5be1895..db922fe 100644 --- a/DESIGN.md +++ b/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. diff --git a/DESIGN.zh-CN.md b/DESIGN.zh-CN.md index e78001a..f01db3a 100644 --- a/DESIGN.zh-CN.md +++ b/DESIGN.zh-CN.md @@ -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 膨胀。 diff --git a/README.md b/README.md index 4260989..436b301 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/README.zh-CN.md b/README.zh-CN.md index d9fc795..977b9a2 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -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`。 diff --git a/ebox-playground.el b/ebox-playground.el index 992b1e9..a2fa86c 100644 --- a/ebox-playground.el +++ b/ebox-playground.el @@ -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." diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..6c43cb4 --- /dev/null +++ b/examples/README.md @@ -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`. diff --git a/examples/README.zh-CN.md b/examples/README.zh-CN.md new file mode 100644 index 0000000..b56f404 --- /dev/null +++ b/examples/README.zh-CN.md @@ -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`。 diff --git a/examples/public-layout-gallery.ebox b/examples/public-layout-gallery.ebox new file mode 100644 index 0000000..b3d9fa0 --- /dev/null +++ b/examples/public-layout-gallery.ebox @@ -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)) diff --git a/tests/ebox-playground-tests.el b/tests/ebox-playground-tests.el index 5b7fe27..8ffe9c7 100644 --- a/tests/ebox-playground-tests.el +++ b/tests/ebox-playground-tests.el @@ -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