Blöcke erstellen
Ein Blocktyp ist eine YAML-Datei (der Inhaltsvertrag) plus ein Default-Partial (die Präsentation).
Anatomie des Block-YAML
# teaser.yaml
handle: teaser # required; a plain slug (a vendor:name handle never renders)
name: Teaser # text or lang key; defaults to the handle
icon: icon-star
group: components # inserter group
partial: teaser # partial file name; defaults to the handle
container: false # true = holds child blocks (section, grid)
allowChildren: null # containers: handle whitelist for children (null = any)
childOnly: false # true = only insertable inside a container
fullBleed: false # true = spans the viewport; a host's rootWidth never boxes it in
defaultChildren: null # containers: starter children, e.g. [{ type: heading, data: { text: Hi } }]
defaultSettings: # generic settings preset on insert (scalars)
spacing_top: lg
fields: # content fields, October form field syntax
image:
label: Image
type: mediafinder
mode: image
title:
label: Title
type: text
link:
label: Link
type: pagefinder
translatable: false # opt out of AI translationfields darf keinen verschachtelten contenteditor enthalten. allowChildren wird im Editor und beim Speichern durchgesetzt, childOnly im Editor. KI-Übersetzen sendet jeden nicht leeren String eines text, textarea, richeditor, richtext- oder markdown-Felds, auch in Repeater-Einträgen; ein Feld ohne type zählt als text. Setze translatable: false an ein Textfeld ohne Fließtext, etwa eine CSS-Klasse, einen Formularfeldnamen, Koordinaten oder einen Preis. Andere Feldtypen (Dropdowns, Schalter, Farben, Icons, Medien, Seitenlinks, Zahlen) werden nie übersetzt, ebenso wenig ein Textfeld namens url, href, link, src, id, anchor, class, css, icon, color, email, phone, lat, lng, slug, embed oder mit einem dieser Namen nach einem Unterstrich am Ende (button_url). Blöcke ohne Definition greifen auf die Feldnamen text, html, caption, alt, title, author und label zurück.
Das Default-Partial
Jeder Block liefert <sourcePath>/<partial>.htm. Eine Definition, deren Partial fehlt oder deren YAML nicht parst, wird mit einer Warnung im Log übersprungen. Das Partial rendert in einer eigenständigen Twig-Umgebung mit:
| Name | Inhalt |
|---|---|
data | die Inhaltsfelder des Blocks |
settings | die generischen Einstellungen des Blocks |
children | vorgerendertes Kind-HTML; Container geben {{ children|raw }} aus |
attributes | fertiger class="…" id="…"-String aus den Einstellungen |
blockId | stabile Dokument-ID ('' in alten Dokumenten), für deterministische Element-IDs |
preview | true in der Editor-Vorschau |
locale | Locale-Code der gerenderten Site |
media Filter | Media-Pfad → URL |
rc_resize(w, h, options) Filter | URL des skalierten Bildes; ohne Resizer die einfache Media-URL |
rc_embed Filter | YouTube-/Vimeo-URL → datenschutzfreundliche Embed-URL, '' wenn nicht erkannt |
rc_url Filter | lässt http, https, mailto, tel und relative Links durch; löst october:// zur URL der aktiven Site auf |
rc_css_url Filter | maskiert eine URL für CSS-url() |
rc_icon(name, size, class) | Lucide-Icon als Inline-SVG, leer bei unbekannten Namen |
rc_t(key, replace, locale) | ein String aus renick.content::lang |
rc_image_size(path) | [width, height] eines Media-Bildes oder null |
rc_filesize(path) | lesbare Größe einer Media-Datei |
rc_map_csv(path) | Marker-Zeilen aus einer Media-CSV |
rc_entries(section, options) | veröffentlichte Tailor-Einträge; Optionen limit (1–24, Standard 6), order, direction, with |
rc_page_url(page, params) | URL einer CMS-Seite |
rc_tailor_submission_form(data) | Formularmodell des Blocks Einsendeformular |
{# teaser.htm #}
<a {{ attributes|raw }} href="{{ data.link|rc_url }}">
<img src="{{ data.image|rc_resize(600, 400) }}" alt="">
<h3>{{ data.title }}</h3>
</a>Registrierungsquellen
Bei gleichem Handle gewinnt das Plugin, dann das Theme, dann der erste Event-Listener. Themes gestalten Blöcke über Partial-Overrides um, nicht durch Neudefinition.
- Plugin:
plugins/renick/content/blocks/<handle>/<handle>.yaml+.htm. - Theme:
themes/<theme>/content-blocks/<handle>/<handle>.yaml+.htm. Ein Child-Theme erbt Blöcke und Partial-Overrides seines Parents, das nächste Theme zuerst, sodass ein Marketplace-<theme>-childsie behält. - Event: Andere Plugins geben Konfigurationen mit
sourcePath(dem Verzeichnis des Partials) zurück. Eine Konfiguration ohnesourcePathwird mit einer Warnung übersprungen.
Event::listen('renick.content.registerBlocks', fn () => [[
'handle' => 'pricing-table',
'name' => 'Pricing table',
'group' => 'components',
'fields' => ['plans' => ['label' => 'Plans', 'type' => 'textarea']],
'sourcePath' => plugins_path('acme/shop/blocks/pricing-table'),
]]);Feldtypen
Werte werden als Strings gespeichert, außer repeater und tailorfields (Arrays von Zeilen) sowie checkbox und switch (Booleans). Der default eines Feldes landet beim Einfügen in data. row: <name> auf aufeinanderfolgenden Feldern zeigt sie nebeneinander. Ein trigger am Feld (wie in October: action: show|hide, field, condition: value[a][b]|checked|unchecked) blendet es im Inspector abhängig von einem Nachbarfeld ein oder aus. Blöcke eines nicht registrierten Typs behalten ihre Daten und rendern einen Platzhalter.
| Typ | Hinweise |
|---|---|
text | einzeilig; auch für unbekannte Typen |
textarea, richeditor | mehrzeiliger Text |
number | min, max, step |
dropdown | options |
checkbox, switch | Boolean |
colorpicker | Hex-Farbe, leerbar |
mediafinder | Pfad in der Media Library |
pagefinder | october://-Referenz oder eingetippte URL; singleMode, allowCustomUrl (Standard true), allowedTypes, excludedTypes. Mit rc_url rendern |
iconpicker | Name eines Lucide-Icons für rc_icon() |
taglist | Tags, als ein String gespeichert |
repeater | sortierbare Zeilen mit Unter-fields |
tailorcolumn | eine Spalte des Tailor-Blueprints, der im Feld aus dependsOn gewählt ist; kind: sortable (Standard), image, text |
tailorfields | Felder des Einsende-Blueprints aus dependsOn, gespeichert als Zeilen aus name/label |
Labels lokalisieren
name sowie label, comment, commentAbove, emptyOption und Optionslabels jedes Feldes (auch in Repeater-Unterfeldern) dürfen Sprachschlüssel sein. Sie werden serverseitig in die Backend-Sprache aufgelöst: ein ::-Schlüssel über trans(), ein Schlüssel mit Punkten und ohne Leerzeichen über die JSON-Übersetzungen des Themes, sofern vorhanden. Andere Strings bleiben unverändert. ::-Schlüssel funktionieren auch in den data von defaultChildren.