-- allium: 1 -- bDS Template Editor View -- Scope: UI content area — template editing surface -- Distilled from: TemplateEditor.tsx -- Describes the layout and behaviour of the template editor. -- See template.allium for entity model and Liquid subset. use "./template.allium" as template use "./i18n.allium" as i18n -- ─── Template editor view ───────────────────────────────────── value TemplateEditorView { template_id: String title: String -- editable text input slug: String -- editable text input, auto-generated from title kind: String -- select: post | list | not_found | partial enabled: Boolean -- checkbox content: String -- code editor content can_publish: Boolean -- true while status = draft created_at: String -- locale-formatted date updated_at: String -- locale-formatted date } surface TemplateEditorSurface { context editor: TemplateEditorView exposes: editor.title editor.slug editor.kind editor.enabled editor.created_at editor.updated_at provides: TemplateSaveRequested(editor.template_id) TemplatePublishRequested(editor.template_id) when editor.can_publish TemplateValidateRequested(editor.template_id) TemplateDeleteRequested(editor.template_id) TemplateDeleteConfirmed(editor.template_id) TemplateForceDeleteConfirmed(editor.template_id) @guarantee HeaderLayout -- Header bar with template title tab. -- Actions (right side): Save button, Publish button (shown only when -- can_publish, i.e. status = draft), Validate button, -- Delete button (danger style). @guarantee MetadataRow -- Two rows of metadata fields above the editor. -- Row 1: Title (text input), Slug (text input, auto-generated from title). -- Row 2: Kind (select: post/list/not-found/partial), Enabled (checkbox). @guarantee EditorBody -- Code editor with HTML/Liquid syntax highlighting. -- Toolbar: "Content" label. -- Syntax errors shown inline in editor on validation. @guarantee FooterLayout -- Created date and Updated date, locale-formatted. } -- ─── Template editor actions ──────────────────────────────── rule TemplateSave { when: TemplateSaveRequested(template_id) let target = template/Template{id: template_id} let validation = ValidateLiquid(editor_content(template_id)) -- editor_content: the current code editor buffer ensures: if validation = valid: UpdateTemplateRequested(target, editor_field_changes(template_id)) -- Version bump + DB write + .liquid rewrite: -- template.allium UpdateTemplate, -- engine_side_effects.allium UpdateTemplateSideEffects else: TemplateValidationErrorsShown(template_id, validation) -- Save blocked; errors shown inline in the editor } rule TemplatePublish { when: TemplatePublishRequested(template_id) let target = template/Template{id: template_id} requires: target.status = draft -- can_publish gate on the button let validation = ValidateLiquid(editor_content(template_id)) ensures: if validation = valid: UpdateTemplateRequested(target, editor_field_changes(template_id)) PublishTemplateRequested(target) -- status -> published + .liquid file write: -- template.allium PublishTemplate else: TemplateValidationErrorsShown(template_id, validation) } rule TemplateValidate { when: TemplateValidateRequested(template_id) -- Validation only, never saves let validation = ValidateLiquid(editor_content(template_id)) ensures: if validation = valid: TemplateValidationOkShown(template_id) -- toast / status indicator else: TemplateValidationErrorsShown(template_id, validation) } rule TemplateDelete { when: TemplateDeleteRequested(template_id) let target = template/Template{id: template_id} let references = target.referencing_posts.count + target.referencing_tags.count ensures: if references > 0: TemplateForceDeleteConfirmShown(template_id) -- system confirm dialog: "This template is used by N posts -- and M tags. Force delete?" (action_patterns.allium -- confirmation_assignments: template_delete_with_references) else: ConfirmDeleteModalOpened(template_id) -- custom modal (not a native dialog): template title, no -- reference list; Cancel + Delete (destructive red style) -- — action_patterns.allium -- confirmation_assignments: template_delete } rule TemplateDeleteExecute { when: TemplateDeleteConfirmed(template_id) let target = template/Template{id: template_id} ensures: DeleteTemplateRequested(target) -- DB record + .liquid file on disk ensures: closeTab(template_id) -- sidebar removes the item reactively } rule TemplateForceDelete { when: TemplateForceDeleteConfirmed(template_id) let target = template/Template{id: template_id} -- Clear references first so template.allium DeleteTemplate's -- zero-reference precondition holds: for p in target.referencing_posts: ensures: p.template_slug = null for t in target.referencing_tags: ensures: t.post_template_slug = null ensures: DeleteTemplateRequested(target) -- DB record + .liquid file on disk ensures: closeTab(template_id) -- sidebar removes the item reactively }