Skip to content

Editor-API ​

Der Haupteinstiegspunkt ist die init()-Funktion aus @templatical/editor.

init(config) ​

Erstellt und hängt den Editor in ein Container-Element ein. Gibt ein Promise zurück, das aufgelöst wird, sobald der Editor bereit ist.

Ein Container enthält einen Editor. Ein späteres init() auf demselben Container ersetzt den Editor dort und behält den Container auch dann, wenn das Promise eines früheren Aufrufs noch aussteht: Dieser frühere Aufruf liefert dann einen Editor, der nie gemountet wird. Ein Aufruf mit ungültigem layout oder content lehnt ab, bevor er den Container berührt: Der Editor dort und ein noch ausstehender früherer Aufruf bleiben unverändert.

ts
import { init } from "@templatical/editor";
import "@templatical/editor/style.css";

const editor = await init({
  container: "#editor",
  content: savedTemplate,
  onChange(content) {
    // Auto-save or update state
  },
});

Rückgabewert: TemplaticalEditor

unmount() ​

Zerstört den zuletzt gemounteten Editor und räumt Event-Listener auf. Um einen bestimmten Editor abzubauen, rufen Sie unmount() an der von init() zurückgegebenen Instanz auf.

ts
import { unmount } from "@templatical/editor";

unmount();

TemplaticalEditorConfig ​

PropertyTypeRequiredBeschreibung
containerstring | HTMLElementJaCSS-Selektor oder DOM-Element, in das der Editor eingehängt wird. Im Standardmodus (Shadow DOM) muss es ein Element sein, das einen Shadow Root aufnehmen kann — <div> wird empfohlen. Siehe Anforderungen an das Container-Element unten
shadowDombooleanNeinMountet innerhalb eines Shadow DOM zur CSS-Isolation von der Host-Seite. Standardwert true. Auf false setzen, um stattdessen im Light DOM zu mounten (z. B. für document.querySelector-Zugriff auf Editor-Interna oder Firefox-<101 / Safari-<16.4-Unterstützung). Siehe Shadow DOM für Kompromisse
contentTemplateContentNeinAnfänglicher Template-Inhalt. Standardmäßig ein leeres Template. Der Editor arbeitet auf einer Kopie, Änderungen erreichen das übergebene Objekt also nie
layoutTemplateContentNeinHülle des Hosts, angewendet in Vorschau und toMjml() / toHtml(). Nie in getContent(), Speichern, Verlauf oder die Bearbeitungsleinwand geschrieben. Ein TemplateContent mit genau einem slot. Darf eigene settings.locales, Block-l10n und settings.l10n enthalten, auch in Wrapper-Kindern; wird mit missing: "default" für die angefragte Sprache projiziert, mit Fallback auf die Standardsprache des Layouts. Wirft, wenn der Slot in einem Wrapper sitzt und die Vorlage mj-wrapper erzeugt. Siehe Layout
sectionWrapperbooleanNeinOb die Sektions-Symbolleiste Wrapper hinzufügen anbietet. Weggelassen / true ist an. false blendet das Steuerelement aus, auch dort, wo ein Wrapper zulässig ist. Bereits eingeschaltete Wrapper bleiben erreichbar. Nur Darstellung: Ausblenden entfernt section.wrapper nie. Unabhängig von layout. Siehe Layout
onChange(content: TemplateContent) => voidNeinWird aufgerufen, wenn sich der Template-Inhalt ändert (entprellt)
onError(error: Error) => voidNeinWird aufgerufen, wenn ein Fehler auftritt
onDirtyChange(isDirty: boolean) => voidNeinWird aufgerufen, wenn der Zustand „ungespeicherte Änderungen" umschlägt. Funktioniert mit und ohne templates-Provider — damit sichern Sie einen clientseitigen Router ab, den beforeunload nicht abdecken kann. Siehe Speichern & Laden
templatesTemplatesProviderNeinSpeicher-Backend für die Vorlage selbst — der Speicher-/Ladezyklus. Dasselbe Objekt trägt auch die Konfiguration autoSave, unsavedChangesGuard und nameField sowie die Events onSaved / onCreated / onLoaded — nichts davon bedeutet etwas ohne ein Ziel zum Speichern. Der Editor liefert Namensfeld, Speichern-Schaltfläche, Statusanzeige und Cmd+S; Sie liefern die Persistenz. Lassen Sie templates weg, ist die Funktion vollständig deaktiviert: kein Namensfeld, keine Speichern-Schaltfläche, keine Statusanzeige. Siehe Speichern & Laden
renderRenderProviderNeinRendering-Backend für toMjml() / toHtml(). Jede Methode (toMjml, toHtml, compileMjml) ist unabhängig optional und wird separat aufgelöst. Weglassen: toMjml() rendert lokal, toHtml() lehnt ab — das SDK bündelt keinen MJML-Compiler. Siehe Rendering & Export
aiAiProviderNeinKI über Ihr eigenes Backend: KI-Assistent mit Rückgängig und Anhängen, Aus Screenshot oder PDF importieren, Umformulieren und statische, lokalisierte Einstiegsanfragen. chat, fixFinding, rewrite und altText sind Funktionen oder false. chatAttachments ist ein boolesches Flag, das nur wirkt, wenn chat eine Funktion ist; die Einstiegspunkte erscheinen erst nach create() oder load(). Weglassen deaktiviert die Funktion einschließlich ihrer UI-Chunks. Siehe KI.
versionHistoryVersionHistoryProviderNeinSpeicher-Backend für den Versionsverlauf der Vorlage — die früheren Stände, die Nutzende durchsehen, in der Vorschau ansehen und wiederherstellen können. Der Editor liefert das Header-Steuerelement, das Vorschaubanner und den Wiederherstellungsablauf; Sie liefern den Speicher. Dasselbe Objekt trägt auch die Events onCreated und onRestored. Er zeichnet nie selbst eine Version auf: Das entscheidet Ihr templates.save. Weglassen, um die Funktion vollständig zu deaktivieren. Siehe Versionsverlauf
commentsCommentsProviderNeinSpeicher-Backend für Review-Kommentare — Threads, die an einem Block oder der Vorlage hängen. Dasselbe Objekt trägt auch die Events onCreated, onUpdated, onDeleted, onResolved und onUnresolved. Der Editor liefert die Seitenleiste, den Editor, Auflösen/Antworten und die Block-Marker; Sie liefern die Persistenz. Erfordert user: ohne Identität meldet sich die Funktion als nicht verfügbar, statt anonyme Kommentare zu schreiben. Ein optionales subscribe schiebt entfernte Änderungen herein. Siehe Kommentare
collaborationCollaborationProviderNeinEchtzeit-Zusammenarbeit über Ihr Backend: Jede Änderung geht als Batch von Operationen über submit hinaus, Batches anderer Sitzungen werden in Revisionsreihenfolge angewendet, die Auswahl eines Blocks nimmt seine Sperre, die Kopfzeile zeigt, wer sonst da ist, und Rückgängig schickt umgekehrte Operationen, die Ihr Backend ablehnen kann. Benötigt templates, dessen load die revision des Templates liefert; templates.save erhält dann nur noch Umbenennungen. Die drei Sperr-Methoden sind nur gemeinsam optional. Siehe Zusammenarbeit
onRemoteChange(change: CollaborationRemoteChange) => voidNeinWird mit { actor, ops } aufgerufen, nachdem der Batch einer anderen Sitzung auf dem Canvas angewendet wurde. Nicht für die eigenen Änderungen dieses Editors und nicht für einen Resync, der das Template neu lädt
userEditorUserNeinWer den Editor benutzt — { id, name }. Wird von jeder Funktion benötigt, die Arbeit einer Person zuordnet: comments und collaboration, deren Leiste in der Kopfzeile die eigenen Sitzungen dieses Nutzers auslässt. Keine Sicherheitsgrenze: Die Angabe identifiziert die Person gegenüber der Oberfläche, im Browser dieser Person. Ordnen Sie Schreibvorgänge serverseitig der Sitzung zu, der Ihr Backend ohnehin vertraut
changeDebouncenumberNeinWie lange der Editor nach der letzten Änderung wartet, bevor onChange auslöst und, sofern templates.autoSave aktiv ist, bevor gespeichert wird. Ein Timer treibt beides, sodass er onChange auch ohne konfigurierten templates-Provider taktet. Standardwert 2000. Siehe Speichern & Laden
onRequestMedia(context?: MediaRequestContext) => Promise<MediaResult | null>NeinUI-Überschreibung für die Medienauswahl (Bynder, Cloudinary-Widget, ein Host-Modal). Hat Vorrang vor media, wenn beide gesetzt sind. Gibt { url, alt?, width?, height? } oder null zurück. Siehe Bilder und Medien
resolveImageUrl(src: string) => string | null | Promise<string | null>NeinReiner Anzeige-Resolver für Bild-src-Werte sowie für die Hintergrundbild-URLs von Sektionen, Sektions-Wrappern und Layout-Wrapper-Bändern (nie für eine Merge-Tag-URL): bildet einen kanonischen src auf eine Vorschau-URL für die Leinwand ab. Inhalt und toMjml()-Ausgabe behalten den kanonischen Wert. null zurückgeben, um den src unverändert zu verwenden. Wird einmal pro bestätigtem src aufgerufen (entprellt), pro src zwischengespeichert. Siehe Bilder
mergeTagsMergeTagsConfigNeinMerge-Tag-Konfiguration. Jedes Tag kann ein optionales sample tragen — einen Beispielwert, den Vorschauen an seiner Stelle anzeigen. showRawValue: false hält den rohen Token aus der Autoren-Oberfläche heraus. Siehe Merge-Tags
resolvePreviewResolvePreviewNeinLöst die Vorlage für Vorschauflächen auf — typischerweise durch Auswerten von Logik-Tags mit echten Daten in Ihrem Backend. Nur zur Anzeige: nie in getContent(), im Versand oder im Export. Siehe Vorschau-Rendering
displayConditionsDisplayConditionsConfigNeinKonfiguration für Anzeigebedingungen. Siehe Anzeigebedingungen
logicTagsLogicTagsConfigNeinKonfiguration für Logik-Tags — Kontrollfluss Ihrer Template-Sprache (Bedingungen, Schleifen), inline im Rich Text und in Textfeldern eingefügt. Siehe Logik-Tags
customBlocksCustomBlockDefinition[]NeinDefinitionen für benutzerdefinierte Blocktypen. Siehe Benutzerdefinierte Blöcke
savedBlocksSavedBlocksProviderNeinSpeicher-Backend für gespeicherte Blöcke — wiederverwendbare Blockgruppen, die Nutzer speichern und erneut einfügen. Der Editor stellt die Oberfläche, Sie die Persistenz. Dasselbe Objekt trägt auch die Events onCreated, onUpdated und onDeleted. Weglassen deaktiviert die Funktion vollständig. createLocalStorageSavedBlocksProvider() bietet eine Variante ohne Backend. Siehe Gespeicherte Blöcke
mediaMediaProviderNeinSpeicher-Backend für die Medienbibliothek — die Auswahl hinter Durchsuchen an Bildfeldern, Video-Thumbnails und Bildfeldern benutzerdefinierter Blöcke. Der Editor stellt Modal, Raster, Zuschnitt und Einfügen; Sie stellen die Persistenz. list ist erforderlich; jede andere Methode ist false | fn. Dasselbe Objekt trägt auch onCreated / onUpdated / onDeleted. Weglassen lässt Bildfelder URL-only, sofern onRequestMedia nicht gesetzt ist. createLocalStorageMediaProvider() bietet eine Variante ohne Backend. Siehe Medien
testEmailTestEmailProviderNeinVersand-Backend für Test-E-Mails — Nutzer senden sich die Vorlage zu, die sie bearbeiten. Der Editor stellt Auslöser, Dialog, Prüfung und Zustände; Sie stellen den Versand. Dasselbe Objekt trägt auch das Event onSent. Weglassen deaktiviert die Funktion vollständig. allowedRecipients schränkt nur die Auswahl ein und ist keine Sicherheitsgrenze — serverseitig prüfen. Siehe Test-E-Mails
paletteBlocksstring[]NeinAllowlist + Reihenfolge für die Block-Palette. Nur die aufgeführten Typen erscheinen, in dieser Reihenfolge; nicht aufgeführte integrierte Blöcke werden ausgeblendet. Integrierte Blöcke über ihren reinen Typ ('image'), benutzerdefinierte über den custom:-präfixierten Typ ('custom:qrcode'). Siehe Block-Palette anpassen
htmlBlockPreviewboolean | { enabled: boolean }NeinRendert den Inhalt jedes HTML-Blocks als Live-Vorschau in der Leinwand — in einem sandboxed <iframe> ohne Skriptausführung — statt des statischen Platzhalters. Standardmäßig false. Nur Vorschau; der MJML-/HTML-Export rendert HTML-Blöcke unabhängig davon. Siehe HTML-Blöcke in der Vorschau
blockDefaultsBlockDefaultsNeinStandard-Property-Überschreibungen für neue Blöcke. Siehe Standardwerte
templateDefaultsTemplateDefaultsNeinStandardeinstellungen für leere Templates. Siehe Standardwerte
fontsFontsConfigNeinSchriftart-Konfiguration. Siehe Benutzerdefinierte Schriftarten
socialIconsBaseUrlstringNeinBasis-URL für die Social-Icon-PNGs im exportierten MJML, weitergereicht an socialIconsBaseUrl des Renderers. Setzen Sie sie, um die Icons selbst zu hosten, und spiegeln Sie dabei alle Ordner, auch die {style}-{tone}-Ordner für einen iconTone von dark oder light; ohne Angabe gilt der versionsgebundene jsDelivr-Standard. Betrifft nur den lokalen toMjml() / toHtml()-Pfad (über compileMjml) — eine render.toMjml-Implementierung übergibt die URL an ihr eigenes renderToMjml
colorsColorsConfigNeinFarbwähler-Palette. presets werden als anklickbares Raster in jedem Farbwähler gerendert; allowCustom: false beschränkt Autoren darauf. Siehe Vordefinierte Farben
templateSettingsTemplateSettingsConfigNeinWelche Template-Einstellungen das Einstellungs-Panel anbietet. fields ist eine Positivliste über Exclude<keyof TemplateSettings, "locales" | "l10n"> oder false für keine (dann entfällt der Tab). Ohne Angabe sind alle Einstellungen bearbeitbar. Siehe Einstellungs-Panel einschränken
themeThemeOverridesNeinÜberschreibungen für Farb-Tokens. Unterstützt einen dark-Schlüssel für Dark-Mode-Überschreibungen. Siehe Theming
uiTheme'light' | 'dark' | 'auto'NeinUI-Farbschema. 'auto' folgt den Systemeinstellungen. Standardwert ist 'auto'
localization{ locales: string[]; doNotTranslate?: string[] }NeinAktiviert Template-Sprachversionen. Ohne Angabe keine Sprachen-UI; vorhandene Ebenen bleiben erhalten. Renderer, Validator und Kollaborationsbackend zuerst aktualisieren. Siehe Lokalisierte Templates. doNotTranslate akzeptiert höchstens 500 Begriffe mit jeweils 1–100 Zeichen nach dem Trimmen; passende Begriffe bleiben beim Übersetzen Byte für Byte erhalten. Ungültige Listen werden mit SdkError abgelehnt: localization.doNotTranslate must be an array of at most 500 terms, each 1–100 characters. Siehe Maskierung.
translationTranslationProviderNeinÜbersetzt geeignete Felder in einer aktivierten Nicht-Standardsprachansicht; benötigt localization. Ohne Provider fehlt Übersetzen. Unabhängig von ai. Ist der Wert kein Objekt mit einer translate-Funktion, lehnt init() mit SdkError ab: translation must be an object with a translate function. Siehe Übersetzung.
onLocaleChange(locale: string) => voidNeinMeldet die Sprache, die der Canvas zeigt (getLocale()), bei jedem Wechsel: Auswahl einer Version, Rückkehr zum Standard und ein neuer Standard, während der Standard angezeigt wird (Als Standard festlegen, dessen Rückgängig oder Wiederholen, setDefaultLocale einer anderen Sitzung oder ein geladenes oder wiederhergestelltes Template mit anderer Standardsprache). Wird die angezeigte Version zum Standard, meldet es nichts. Die aktive Sprache ist ungespeicherter Ansichtsstatus.
localestringNeinLocale-Code (z. B. 'en', 'de', 'pt-BR', 'es', 'ca', 'fr', 'nl', 'ja'). Standardwert ist 'en'
brandingbooleanNeinZeigt den "Powered by Templatical"-Footer. Standardwert true. Auf false setzen, um ihn auszublenden
smallScreenNoticebooleanNeinZeigt auf Viewports schmaler als ~768px einen Hinweis „Bitte größeren Bildschirm verwenden" anstelle des Editors. Standardwert true. Der Drag-and-Drop-Editor ist ein Desktop-Werkzeug und lässt sich auf einem Smartphone nicht sinnvoll darstellen. Auf false setzen, um den Editor bei jeder Breite zu rendern, wenn Sie kleine Bildschirme selbst behandeln
lintLintOptionsNeinKonfiguration des Template-Linters. @templatical/quality ist eine optionale Abhängigkeit des Editors und wird standardmäßig mitinstalliert. Sie können es weglassen: Der Editor funktioniert ohne das Paket und blendet den Tab „Probleme“ aus. Ohne Angabe startet Linting beim Mounten des Editors. disabled: true überspringt den Import vollständig und blendet den Sidebar-Tab sowie die Inline-Marker aus. Siehe Quality-Optionen

Anforderungen an das Container-Element ​

Das Standard-Mount (Shadow DOM) ruft attachShadow() auf Ihrem Container auf, und die HTML-Spezifikation erlaubt Shadow Roots nur für eine feste Menge von Elementen. Verwenden Sie eines davon:

<article>, <aside>, <blockquote>, <body>, <div> (empfohlen), <footer>, <h1>–<h6>, <header>, <main>, <nav>, <p>, <section>, <span> sowie jedes von Ihnen definierte Custom Element.

Nicht erlaubt: <table>, <tr>, <td>, <form>, <input>, <button>, <select>, Listenelemente (<ul>, <ol>, <li>), <iframe>, ersetzte Elemente (<img>, <video> usw.). Die Übergabe eines dieser Elemente wirft eine DOMException aus attachShadow().

Wenn Ihre Integration ein nicht unterstütztes Element verwenden muss (z. B. Mount in eine <form>-Zelle eines CMS-Layouts), übergeben Sie shadowDom: false — das Light-DOM-Mount akzeptiert jedes Element. Der Kompromiss ist die Host-CSS-Isolation, auf die Sie verzichten.

Block-Palette anpassen ​

Standardmäßig listet die Seitenleisten-Palette jeden integrierten Blocktyp auf. Übergeben Sie paletteBlocks, um die Palette auf eine bestimmte Menge zu beschränken und ihre Reihenfolge zu steuern — nützlich, um nicht verwendete Blocktypen (video, table, …) auszublenden oder einen häufig genutzten benutzerdefinierten Block über die integrierten Blöcke zu stellen.

ts
const editor = await init({
  container: "#editor",
  customBlocks: [qrCodeDefinition],
  paletteBlocks: [
    "section",
    "title",
    "paragraph",
    "image",
    "custom:qrcode", // a custom block, interleaved among built-ins
    "button",
  ],
});
  • Strikte Allowlist + Reihenfolge. Es werden nur die aufgeführten Typen angezeigt, in genau dieser Reihenfolge. Jeder nicht aufgeführte integrierte Block (hier hero, divider, video, social, menu, table, spacer, html) wird aus der Palette ausgeblendet.
  • Integrierte Blöcke über ihren reinen Typ ("section", "image", …) und benutzerdefinierte Blöcke über ihren custom:-präfixierten Typ ("custom:qrcode") referenzieren, sodass beide frei vermischt werden können.
  • "hero" ist eine Verknüpfung, kein Blocktyp. Sie fügt eine einspaltige Sektion im Hero-Modus mit Titel, Absatz und Button ein (siehe Hero). Führen Sie sie wie einen integrierten Block auf.
  • Unbekannte Einträge werden übersprungen. Ein Tippfehler, ein nicht registrierter benutzerdefinierter Block oder countdown außerhalb eines Cloud-Plans wird mit einer Warnung in der Konsole protokolliert und nicht in die Palette aufgenommen.
  • Das Filtern der Palette wirkt sich nie auf das Rendering aus. Das Ausblenden eines Blocktyps entfernt ihn nur aus der Palette — vorhandener Inhalt, der diesen Typ bereits verwendet, wird weiterhin korrekt gerendert. paletteBlocks steuert, was Benutzer einfügen können, nicht, was der Editor anzeigen kann.

Lassen Sie paletteBlocks weg (oder übergeben Sie ein leeres Array), um die vollständige Standard-Palette anzuzeigen.

HTML-Blöcke in der Vorschau ​

Standardmäßig zeigt ein HTML-Block in der Leinwand eine Platzhalterkarte an, anstatt sein Markup zu rendern — der Inhalt wird erst beim Export realisiert. Setzen Sie htmlBlockPreview, um den Inhalt jedes HTML-Blocks stattdessen live in der Leinwand zu rendern:

ts
const editor = await init({
  container: "#editor",
  htmlBlockPreview: true, // shorthand for { enabled: true }
});
  • Standardmäßig aus. Lassen Sie die Option weg (oder übergeben Sie false / { enabled: false }), um den statischen Platzhalter beizubehalten.
  • In einem sandboxed <iframe> gerendert. Der Inhalt wird unverändert in einem <iframe sandbox="allow-same-origin"> ohne allow-scripts angezeigt — Skripte und Inline-Event-Handler werden nie ausgeführt, und die Styles des Fragments können nicht in den Rest des Editors gelangen. So wird verhindert, dass beliebiges oder von Mitarbeitenden erstelltes HTML im Origin Ihrer App ausgeführt wird.
  • Nur Vorschau. Diese Einstellung steuert die Editor-Leinwand, nicht die Ausgabe — renderToMjml() / editor.toMjml() rendern HTML-Blöcke unabhängig davon.

Vordefinierte Farben ​

Jeder Farbwähler im Editor — Block-Symbolleisten, Template-Einstellungen, Rich-Text-Farbe, Farbfelder benutzerdefinierter Blöcke — öffnet ein Popover mit einem Farbrad und einem Hex-Eingabefeld. Übergeben Sie colors, um diesem Popover eine Reihe vordefinierter Farben hinzuzufügen und optional die freien Eingabefelder zu entfernen. Die Konfiguration ist die Grundlage für jeden Farbwähler; das Farbfeld eines benutzerdefinierten Blocks kann sie für sich selbst weiter einschränken (siehe den letzten Punkt):

ts
const editor = await init({
  container: "#editor",
  colors: {
    presets: ["#0b5cff", "#111827", "#6b7280", "#ffffff"],
    allowCustom: false,
  },
});
  • presets — Hex-Zeichenketten, die als anklickbares Raster gerendert werden. Ein Klick übernimmt die Farbe; die vordefinierte Farbe, die dem aktuellen Wert entspricht, wird als ausgewählt markiert. Ergänzt das Farbrad und das Hex-Eingabefeld. Jeder Eintrag muss eine #rgb- oder #rrggbb-Hex-Zeichenkette sein — 4-/8-stellige Alpha-Hex-Werte und andere Formate werden übersprungen und mit einer Konsolenwarnung protokolliert, die die betreffenden Einträge auflistet.
  • allowCustom — standardmäßig true. Auf false gesetzt (zusammen mit presets) werden das Farbrad und das Hex-Eingabefeld ausgeblendet, sodass Autoren nur aus der Palette wählen können — nützlich beim Einbetten des Editors als White-Label- / Brand-Kit-Werkzeug. In diesem gesperrten Modus beginnt die Palette mit einem „Keine Farbe“-Feld, das den nicht gesetzten (geerbten) Zustand wiederherstellt, da die Schaltfläche zum Löschen des Hex-Eingabefelds ausgeblendet ist. Ebenfalls im gesperrten Modus protokolliert der Editor eine Entwicklungswarnung, wenn eine Farbe aus blockDefaults / templateDefaults außerhalb von presets liegt — neue Blöcke würden sonst mit einer Farbe beginnen, die kein Farbwähler erneut auswählen kann; setzen Sie diese Standardwerte daher aus derselben Palette. Wird mit einer Warnung ignoriert, wenn keine presets konfiguriert sind, da der Farbwähler sonst keine Möglichkeit hätte, eine Farbe festzulegen.
  • Einschränkung auf Feldebene. Das color-Feld eines benutzerdefinierten Blocks kann eigene presets / allowCustom mitbringen — siehe vordefinierte Farben pro Feld. Ein Feld darf eine eigene Palette vorgeben oder einzeln gesperrt werden, während der übrige Editor freie Eingaben zulässt; seine presets ersetzen dieses Raster für dieses Feld, statt eine Schnittmenge damit zu bilden, sodass ein gesperrtes Feld Farben anbieten kann, die in diesen presets überhaupt nicht vorkommen. Was ein Feld nie kann, ist den Editor entsperren — allowCustom: false sperrt hier weiterhin jeden Farbwähler.

Einstellungs-Panel einschränken ​

Der Tab „Einstellungen“ in der rechten Seitenleiste bietet Exclude<keyof TemplateSettings, "locales" | "l10n"> an. Übergeben Sie templateSettings.fields, um daraus eine Positivliste zu machen — für Einstellungen, die Ihre Anwendung besitzt und nicht der Autor:

ts
const editor = await init({
  container: "#editor",
  templateSettings: {
    fields: [
      "width",
      "backgroundColor",
      "textColor",
      "linkColor",
      "linkUnderline",
      "fontFamily",
    ],
  },
});
WertErgebnis
ohne Angabe oder fields: truealle Einstellungen sind bearbeitbar
fields: [...]nur die aufgeführten Einstellungen
fields: false oder fields: []keine — der Tab „Einstellungen“ wird nicht gerendert

Die Felder sind width, backgroundColor, textColor, linkColor, linkUnderline, fontFamily, locale, direction und preheaderText.

  • Karten folgen ihren Feldern. Eine Karte wird gerendert, solange mindestens eine ihrer Einstellungen übrig bleibt. Ohne locale und direction entfällt die Sprach-Karte, ohne preheaderText die Preheader-Karte. width bildet die Layout-Karte, die fünf Farb- und Schrift-Einstellungen die Darstellungs-Karte.
  • Die Liste schränkt ein, sie sortiert nicht um. Einstellungen sitzen in festen Karten — anders als bei paletteBlocks gibt es keine Reihenfolge auszudrücken.
  • Ein unbekannter Eintrag wird mit einer Konsolenwarnung übersprungen. TypeScript lehnt ihn bereits beim Kompilieren ab; bei einem JavaScript-Aufruf schränkt ein Tippfehler das Panel weiter ein, statt stillschweigend alle Einstellungen wiederherzustellen.
  • Eine Einstellung auszublenden ändert ihren Wert nicht. Was der geladene Inhalt mitbringt, wird weiterhin gerendert und bleibt über getContent() und den Export erhalten. Setzen Sie die ausgeblendeten Werte über den Inhalt, den Sie dem Editor übergeben — init({ content }) oder das load Ihres eigenen templates-Providers, die Nahtstelle für „die Sprache dieses Templates kommt aus meiner Anwendung“. Für ein Template, das Sie laden, genügt templateDefaults dafür nicht: es greift nur, wenn kein Inhalt übergeben wird. Bei einem leeren Template greift es, und für locale gibt es dort eine Abkürzung — init({ locale }) setzt die Inhaltssprache, solange Sie kein templateDefaults.locale angeben, sodass auch bei ausgeblendetem Feld das richtige <html lang> entsteht.
  • Keine Sicherheitsgrenze. Die Positivliste liegt im Browser des Nutzers, wie jede andere clientseitige Einschränkung. Prüfen Sie serverseitig, was Sie speichern.
  • Ohne locale ist auch die Sprache neuer Blöcke festgelegt. Die locale eines Templates bestimmt die empfängerseitigen Standardwerte, mit denen ein neu eingefügter Block startet — das alt eines Videos, die Beschriftungen und die Ablaufmeldung eines Countdowns. Ohne das Feld folgen diese der Sprache, die der geladene Inhalt mitbringt, und der Autor kann sie nicht mehr ändern. Das ist meist genau die Absicht, bedeutet aber: der Wert, den Sie setzen, wirkt über <html lang> hinaus.
  • Ohne preheaderText bleibt eine Linter-Regel ohne Handlungsoption. a11y.missing-preheader (Schweregrad info) meldet ein Template ohne Preheader, und ohne das Feld kann der Autor darauf nicht reagieren. Setzen Sie entweder einen Preheader im geladenen Inhalt oder schalten Sie die Regel ab: lint: { accessibility: { rules: { 'a11y.missing-preheader': 'off' } } }. Keine andere Regel liest eine Template-Einstellung.

Verwandte Einschränkungen

Andere Teile der Editor-Oberfläche haben eigene Schlüssel: paletteBlocks für die Block-Palette, fonts.builtIns für die Schriftauswahl, colors.allowCustom für freie Farbeingaben und templates.nameField für das Namensfeld in der Kopfzeile.

TemplaticalEditor ​

Das von init() zurückgegebene Objekt.

getContent() ​

Gibt den aktuellen Template-Inhalt als TemplateContent-Objekt zurück.

ts
const content = editor.getContent();
// { blocks: [...], settings: { width: 600, ... } }

setContent(content) ​

Ersetzt den Editor-Inhalt durch eine Kopie von content; spätere Änderungen an Ihrem Objekt erreichen den Editor nicht.

ts
import { createDefaultTemplateContent } from "@templatical/types";

editor.setContent(createDefaultTemplateContent());

insertBlock(block) ​

Fügt einen Block dort ein, wo ein Klick auf ein Element der Block-Palette ihn platzieren würde: unter dem ausgewählten Block, in derselben Spalte, wenn die Auswahl in einer Section liegt (eine Section landet stattdessen nach dieser Section), oder am Ende, wenn nichts ausgewählt ist. Der neue Block wird ausgewählt und in den sichtbaren Bereich gescrollt, sodass der nächste Aufruf darunter einfügt. Verwenden Sie die Methode, um aus Ihrer eigenen Oberfläche einzufügen, etwa aus einer Bibliothek fertiger Sections.

ts
import type { Block } from "@templatical/types";

// A section from your own library, saved earlier as editor JSON
// (for example, a block taken from `editor.getContent().blocks`).
const footer: Block = librarySections.footer;

footerButton.addEventListener("click", () => {
  editor.insertBlock(footer);
});

Parameter: block: Block

Rückgabewert: string | null, die ID des eingefügten Blocks, oder null, wenn die Instanz mit unmount() abgebaut oder durch einen späteren init()-Aufruf auf demselben Container ersetzt wurde, im Vorschaumodus (mit einer Warnung in der Konsole) oder wenn der Block nicht platziert werden kann.

Der Block wird so eingefügt, wie er übergeben wird. Ein Block aus der Block-Palette wird mit den Standardwerten des Editors erstellt: Ihren blockDefaults, lokalisierten Platzhaltertexten und rechtsbündigen Titeln und Tabellen in RTL-Templates. Diese werden hier nicht angewendet. Für fertige Inhalte ist das richtig, ein frisch mit createTitleBlock() erstellter Block kann aber anders aussehen als einer aus der Block-Palette.

Der Editor fügt eine Kopie mit neuen IDs ein, auch für die Kinder einer Section, sodass derselbe Block beliebig oft eingefügt werden kann. Suchen Sie den Block über die zurückgegebene ID, nicht über block.id. Merge-Tags, die als reine Tokens im Text stehen, werden genauso umgewandelt wie bei setContent. Ein Slot- oder Wrapper-Block löst einen Fehler aus, wie bei setContent.

setTheme(theme) ​

Wechselt das UI-Farbschema zur Laufzeit, ohne den Editor neu zu initialisieren.

ts
editor.setTheme("dark");
editor.setTheme("light");
editor.setTheme("auto"); // follow system preference

Parameter: theme: 'light' | 'dark' | 'auto'

setMergeTags(tags) ​

Ersetzt die konfigurierten Merge-Tags zur Laufzeit. Canvas, Felder der Seitenleiste und der integrierte Picker lesen dieselbe Liste und werden gemeinsam neu gezeichnet.

ts
editor.setMergeTags([
  { label: 'First Name', value: '{{first_name}}' },
  { label: 'Plan', value: '{{plan_name}}' },
]);

Parameter: tags: MergeTag[]

Verwenden Sie die Methode, wenn Tags erzeugt oder umbenannt werden, während der Editor geöffnet ist. Das an init() übergebene Array zu mutieren ist kein unterstützter Ersatz — es zeichnet nichts neu, was bereits sichtbar ist. Siehe Merge-Tags für die eine Einschränkung bei der Autovervollständigung.

unmount() ​

Zerstört diese Editor-Instanz und keine andere. Hat ein späteres init() auf demselben Container sie bereits ersetzt oder ihr Mounten verhindert, bewirkt das unmount() der alten Instanz nichts.

create(input?) / load(id) / save() ​

Der Speicher-/Ladezyklus der Vorlage, über den templates-Provider.

ts
const template = await editor.create({ name: "Welcome email" });
await editor.load(template.id);
await editor.save();
  • create(input?) speichert den aktuellen Inhalt als neue Vorlage und übernimmt das Ergebnis. Übergeben Sie content, um zuvor den Inhalt des Editors zu ersetzen.
  • load(id) holt eine Vorlage und macht sie zum Inhalt des Editors; lokale Änderungen werden verworfen.
  • save() speichert Name und Inhalt der geladenen Vorlage als einen Patch.

Alle drei geben ein Promise<Template> zurück und sind stets im Typ vorhanden. Sie werden mit einer erklärenden Fehlermeldung abgelehnt, wenn kein templates-Provider konfiguriert ist, wenn der Provider die jeweilige Methode zurückhält (create: false / save: false) oder — bei save() — wenn noch nichts erstellt oder geladen wurde. Siehe Speichern & Laden.

isDirty() ​

Ob es Änderungen gibt, von denen der Editor weiß, dass sie nicht gespeichert sind. Wird durch ein erfolgreiches save(), create() oder load() zurückgesetzt.

ts
router.beforeEach((to, from, next) => {
  if (editor.isDirty() && !confirm("Discard unsaved changes?"))
    return next(false);
  next();
});

onDirtyChange ist das gegenläufige Push-Pendant.

getLocale() / setLocale(locale) ​

getLocale(): string liefert die aktive Template-Sprache, anfangs den Standard. setLocale(locale: string): void wählt bei aktivierter Lokalisierung den Standard oder eine vorhandene Version; eine unbekannte Version wirft SdkError mit Code unknown_locale. Eine gespeicherte Version außerhalb von localization.locales bleibt auswählbar, aber schreibgeschützt (Nicht aktiviert); Wert- und Strukturänderungen werden abgelehnt. Siehe Eine Sprache hinzufügen.

toMjml(options?: { locale?: string }): Promise<string> und toHtml(options?: { locale?: string }): Promise<string> rendern die ausgewählte Version, etwa editor.toMjml({ locale: "de" }). Ohne locale gilt der Standard, unabhängig von der aktiven Ansicht. Unbekannte Versionen lehnen mit unknown_locale ab. Render-Provider erhalten den projizierten Inhalt ohne Lokalisierungsfelder.

toMjml(options?) ​

Rendert den aktuellen Inhalt in MJML-Markup. Gibt ein Promise<string> zurück, da das Auflösen benutzerdefinierter Blöcke asynchrone Arbeit erfordern kann (der Liquid-Renderer des Editors wird bei Bedarf geladen).

ts
const mjml = await editor.toMjml();

Löst zuerst render.toMjml auf, wenn ein render-Provider es bereitstellt, danach den lokalen @templatical/renderer. Lehnt mit einem klaren Fehler ab, wenn keines von beiden verfügbar ist — der Renderer ist eine optionale Peer-Abhängigkeit, installieren Sie ihn also für lokalen MJML-Export. Siehe Installation.

toHtml(options?) ​

Rendert den aktuellen Inhalt in versandfertiges HTML.

ts
const html = await editor.toHtml();

Löst zuerst render.toHtml auf, danach die Ausgabe von toMjml() über render.compileMjml. Eines von beiden ist erforderlich: Das SDK bündelt keinen MJML-Compiler, ohne render-Provider lehnt dieser Aufruf also immer ab, und der Fehler nennt die zu ergänzende Methode. Siehe Rendering & Export.

Cloud-Editor

Der Cloud-Editor stellt beide Methoden bereit, aufgelöst über Clouds serverseitigen Renderer (oder Ihren eigenen render-Provider). Beachten Sie: Cloud rendert das gespeicherte Template, jeder Aufruf speichert also zuerst.

renderCustomBlock(block) ​

Rendert einen einzelnen benutzerdefinierten Block in seine HTML-Darstellung. Nützlich für Headless-Aufrufer, die @templatical/renderers renderCustomBlock-Option von außerhalb der Editor-Instanz steuern möchten – etwa beim direkten Aufruf des Renderers mit eigener Konfiguration.

ts
const html = await editor.renderCustomBlock(customBlock);

getCustomBlockStylesheet(customType) ​

Gibt das auf Definitionsebene registrierte CSS eines Custom-Block-Typs zurück — oder undefined, wenn der Typ unbekannt ist oder kein Stylesheet hat. Das Gegenstück zu renderCustomBlock() für Headless-Aufrufe, die die Option getCustomBlockStylesheet von @templatical/renderer selbst bedienen.

ts
const css = editor.getCustomBlockStylesheet("qrcode");

KI-Regellisten ​

@templatical/editor exportiert AI_FIXABLE_RULES und AI_ALT_TEXT_RULES als schreibgeschützte Tupel von Lint-Regel-IDs. AI_FIXABLE_RULES benennt die Regeln für Mit KI beheben; AI_ALT_TEXT_RULES benennt die Bildregeln für Alt-Text. Die Konstante allein aktiviert keine Alt-Text-Oberfläche. Die Qualitätsdokumentation beschreibt die Befunde.

Core-Composables ​

Für fortgeschrittene Anwendungsfälle können Sie die Composables aus @templatical/core direkt verwenden.

useEditor(options) ​

Das Kern-Composable, das den gesamten Editor-Zustand verwaltet: den Block-Baum, Template-Einstellungen, Block-Auswahl, Viewport-Modus sowie alle Mutationsmethoden. Dies ist das, was init() intern verwendet. Verwenden Sie es direkt, wenn Sie eine vollständig benutzerdefinierte Editor-Oberfläche auf der Templatical-State-Engine aufbauen.

ts
import { useEditor } from "@templatical/core";

const editor = useEditor({ content: templateContent });

editor.selectBlock(blockId);
editor.updateBlock(blockId, { content: "New text" });
editor.setViewport("mobile");

useHistory(options) ​

Verfolgt Inhalts-Snapshots und stellt Undo/Redo bereit. Wird mit der Content-Ref des Editors verbunden und erfasst den Zustand nach jeder Mutation. Eine konfigurierbare maximale Verlaufsgröße verhindert unbegrenztes Speicherwachstum.

ts
import { useHistory } from "@templatical/core";

const history = useHistory({
  content: editor.content,
  setContent: editor.setContent,
  maxSize: 50,
});

history.undo();
history.redo();

useCollaboration(options) ​

Führt eine Collaboration-Sitzung über einen CollaborationProvider: Sie schickt die Änderungen des Editors als Operations-Batches, wendet die Batches anderer Sitzungen in Revisionsreihenfolge an, nimmt die Sperre des ausgewählten Blocks, verfolgt, wer da ist, und führt Rückgängig und Wiederholen als umgekehrte Batches. init({ collaboration }) erstellt sie für Sie; rufen Sie sie nur selbst auf, wenn Sie einen eigenen Editor auf useEditor bauen.

ts
import { useCollaboration, useEditor } from "@templatical/core";

const collaboration = useCollaboration({
  provider: myCollaborationProvider,
  loadTemplate: (id) => myTemplatesProvider.load(id),
  onNotice: (notice) => showNotice(notice),
});
const editor = useEditor({
  content,
  templates: myTemplatesProvider,
  lockedBlocks: collaboration.locks,
});
collaboration.attach(editor);
await editor.load("tpl_123");

collaboration.undo();
await collaboration.settle(); // resolves once every batch is confirmed

useBlockActions(options) ​

Komfortmethoden auf höherer Ebene für gängige Block-Operationen: einen Block erstellen und in einem Schritt einfügen, einen bestehenden Block duplizieren (Deep Clone mit neuer ID) und Löschen mit automatischer Auswahl-Bereinigung.

ts
import { useBlockActions } from "@templatical/core";

const actions = useBlockActions({
  addBlock: editor.addBlock,
  removeBlock: editor.removeBlock,
  updateBlock: editor.updateBlock,
  selectBlock: editor.selectBlock,
});

const newBlock = actions.createAndAddBlock("paragraph");
actions.duplicateBlock(existingBlock);
actions.deleteBlock(blockId);
actions.updateBlockProperty(blockId, "content", "<p>Updated</p>");

useAutoSave(options) ​

Überwacht den Editor-Inhalt und ruft Ihren Speicher-Callback mit konfigurierbarer Entprellung (Debounce) auf. Enthält Pause/Resume zum vorübergehenden Deaktivieren von Speichervorgängen (z. B. während Massenoperationen) sowie eine flush()-Methode für sofortiges Speichern.

ts
import { useAutoSave } from "@templatical/core";

const autoSave = useAutoSave({
  content: editor.content,
  isDirty: () => editor.state.isDirty,
  onChange: (content) => saveToServer(content),
  debounce: 2000, // the default
  enabled: true, // boolean or () => boolean
});

autoSave.flush(); // Save immediately
autoSave.cancel(); // Cancel pending debounced save
autoSave.pause(); // Pause auto-save
autoSave.resume(); // Resume
autoSave.destroy(); // Stop watching and clean up

useConditionPreview() ​

Verwaltet den Vorschauzustand für Anzeigebedingungen im Editor. Ermöglicht das Ein-/Ausschalten einzelner Blöcke, um zu simulieren, wie bedingter Inhalt aussieht, wenn unterschiedliche Bedingungen erfüllt sind.

ts
import { useConditionPreview } from "@templatical/core";

const preview = useConditionPreview(editor);

preview.isHidden(blockId); // Check if a block is hidden in preview
preview.toggleBlock(blockId); // Toggle a block's visibility
preview.reset(); // Reset all blocks to visible
preview.hasHiddenBlocks; // ComputedRef<boolean>

useDataSourceFetch(options) ​

Übernimmt das Abrufen externer Daten für benutzerdefinierte Blöcke mit Datenquellen. Verwaltet den Ladezustand und die Fehlerbehandlung für den onFetch-Callback.

ts
import { useDataSourceFetch } from "@templatical/core";

const dataFetch = useDataSourceFetch({
  definition: computed(() => customBlockDefinition),
  block: computed(() => customBlock),
  onUpdate: (fieldValues, fetched) => {
    updateBlock(block.id, { fieldValues, dataSourceFetched: fetched });
  },
});

dataFetch.isFetching; // Ref<boolean>
dataFetch.fetchError; // Ref<boolean>
dataFetch.hasDataSource; // ComputedRef<boolean>
dataFetch.needsFetch; // ComputedRef<boolean>
await dataFetch.fetch(); // Trigger the fetch