Skip to content

Migration von Easy Email Pro

Diese Anleitung richtet sich an Teams, die E-Mail-Templates in Easy Email Pro erstellt haben — im gehosteten Editor oder über ein Produkt, das ihn einbettet — und auf Templaticals visuellen Editor wechseln möchten. @templatical/import-easy-email-pro konvertiert eine Easy-Email-Pro-Persist-Seite in Templaticals TemplateContent-Format. Installieren Sie es, führen Sie es aus, und nutzen Sie die folgenden Abschnitte, um alles nachzuarbeiten, was es nicht automatisch abbilden kann.

Die Eingabe ist das Persist-JSON — { subject, content } mit content.type === "page", oder ein nacktes Seiten-Element. Es ist nicht EditorCore.toMJML() und nicht das kompilierte HTML.

Installation

bash
npm install @templatical/import-easy-email-pro

Ohne Build-Schritt (CDN)

Sie können es auch von einem CDN laden:

html
<script type="module">
  import { convertEasyEmailProTemplate } from 'https://cdn.jsdelivr.net/npm/@templatical/import-easy-email-pro/+esm';
  // ...dann konvertieren wie im Abschnitt „Verwendung“ unten
</script>

Verwendung

ts
import { convertEasyEmailProTemplate } from '@templatical/import-easy-email-pro';

const { content, report } = convertEasyEmailProTemplate(emailTemplate);

const editor = await init({
  container: '#editor',
  content,
});

console.log(report);

convertEasyEmailProTemplate arbeitet synchron und gibt ein ImportResult zurück mit:

  • content — das konvertierte TemplateContent, bereit für den Editor
  • report — ein Konvertierungsbericht mit dem Status jedes erzeugten Blocks (converted, approximated, html-fallback oder skipped)

Es akzeptiert:

  • den Persist-Umschlag { subject, content } mit content.type === "page"
  • ein nacktes Seiten-Element { type: "page", children, attributes, data }
  • jede der beiden Formen als serialisierten JSON-String

Zusätzliche html- / mjml- / thumbnail- / id-Schlüssel auf dem Umschlag werden ignoriert.

TIP

Übergeben Sie die Persist-Seite, nicht die Ausgabe von EditorCore.toMJML(). toMJML ist ein Compile-Pfad — MJML-Markup, das zu @templatical/import-mjml gehört, nicht zu diesem Paket. Kompiliertes HTML gehört zu @templatical/import-html. Ein Rateversuch zwischen den dreien würde Markup durch den falschen Konverter schicken.

$var(name) ist ein Design-Token, kein Merge-Tag. Werte werden gegen die nächstgelegene Tabelle aufgelöst (zuerst Widget-data.input, dann data.variables[] der Seite). Nicht aufgelöste Reste bleiben ungesetzt und werden nicht als Empfängerfelder gespeichert.

Open-Source-Easy-Email ist ein anderes JSON (type: "section" / "text" ohne das Präfix standard-). Dieses Paket wirft einen eigenen Fehler, statt es falsch zu importieren. Zalify liefert easyEmailToEasyEmailPro() für diese Richtung.

Bericht

Jeder Eintrag in report.entries beschreibt einen erzeugten Block:

StatusBedeutung
convertedAuf einen Templatical-Block abgebildet, ohne Verlust.
approximatedAuf den richtigen Block abgebildet, mit einer Begrenzung oder einem Flatten — note nennt die Änderung.
html-fallbackKeine Block-Entsprechung vorhanden; der rohe Knoten bleibt als JSON in einem HtmlBlock erhalten.
skippedLeeres logic — es gab keine Kinder zu konvertieren.
ts
console.log(report.summary);
// { total: 24, converted: 18, approximated: 5, htmlFallback: 0, skipped: 1 }

for (const entry of report.entries) {
  if (entry.status === 'approximated') {
    console.warn(`${entry.sourceTag} approximiert:`, entry.note);
  }
}

Eine note bei einem approximated-Eintrag nennt den ursprünglichen Wert. report.warnings trägt Verluste auf Dokumentebene, die an keinem einzelnen Eintrag hängen — ein nicht-leeres subject oder fonts[], Anzahlen nicht aufgelöster $var(), und mobileAttributes, wenn irgendein Knoten sie trug.

Dokumentform

Easy Email Pro speichert ein Design als Baum typisierter Knoten unter einer page:

EmailTemplate { subject, content }
  content: page
    data: { globalAttributes, blockAttributes, categoryAttributes, fonts, preheader, variables[] }
    attributes: { width, background-color, content-background-color, link-color, … }
    children: standard-section | standard-wrapper | standard-hero | *_widget | AMP_* | custom
      standard-section.children: standard-column | standard-group
        standard-group.children: standard-column
          standard-column.children: leaf | nested structure

Blätter in der dokumentierten Elementliste: standard-paragraph, standard-h1h4, standard-button, standard-image, standard-divider, standard-spacer, standard-navbar + standard-navbar-link, standard-social + standard-social-element, standard-table2, line-break, html-block-node, marketing-countdown, placeholder. uid / id / thumbnail werden verworfen — Templatical vergibt eigene IDs. placeholder ist Editor-Chrome und wird übersprungen.

  • Easy Email Pro speichert diesen Persist-Baum, plus optionale variables[] (Design-Tokens) und Seiten-data.
  • Templatical speichert Templates als JSON-Baum mit typisierten Blöcken (SectionBlock, ParagraphBlock usw.) und rendert diesen Baum beim Export zu MJML.

@templatical/import-easy-email-pro durchläuft page.children, flacht standard-group und Widgets ab und baut daraus die entsprechenden Templatical-Blöcke. Die Mapping-Tabelle unten zeigt, was er dabei umsetzt.

Visueller Neuaufbau

Bei einer Handvoll Templates ist der Neuaufbau von Hand neben einer Easy-Email-Pro-Vorschau schneller, als ein Paket zu installieren:

  1. Öffnen Sie das Easy-Email-Pro-Design — den Editor selbst oder eine Vorschau des kompilierten HTML — in einem Fenster.
  2. Öffnen Sie den Templatical-Editor (oder den Playground) daneben.
  3. Nutzen Sie diese Vorschau als visuelles Ziel. Übergeben Sie EditorCore.toMJML() nicht an diesen Konverter.
  4. Ziehen Sie die entsprechenden Templatical-Blöcke hinein (siehe Mapping-Tabelle unten).
  5. Kopieren Sie Textinhalte direkt. Hosten Sie Bilder über Ihre Medienbibliothek neu.
  6. Bilden Sie Styling über Templaticals Design-Tokens ab.

Bei größeren Mengen führen Sie zuerst @templatical/import-easy-email-pro aus und nutzen diesen Pfad nur, um nachzuarbeiten, was als approximated, skipped oder als html-fallback-Block gelandet ist.

Renderer-Prüfung

Sobald ein Template in Templatical vorliegt — importiert oder von Hand nachgebaut:

ts
import { renderToMjml } from '@templatical/renderer';

const mjml = await renderToMjml(content);

Ein visueller Vergleich mit Easy Email Pros eigener Vorschau zeigt, was der Bericht nicht zeigen kann. Mehrere der unten genannten Verluste — mobileAttributes, Hero-Overlay, Seiten-fonts[] — werden an der Stelle verworfen, an der sie gelesen werden, mit einer note, wenn der Konverter irgendwo andocken kann.

Es gibt kein Round-Trip-Orakel. Templatical rendert kein Easy-Email-Pro-JSON, und dieses Paket verarbeitet EditorCore.toMJML() nicht.

Knoten-Abbildung

Easy Email ProTemplatical-BlockHinweise
pageTemplate-settingswidthsettings.width; background-colorsettings.backgroundColor nach $var; globalAttributes["font-family"] / colorfontFamily / textColor; link-colorlinkColor, wenn gesetzt; preheadersettings.preheaderText, wenn nicht leer. content-background-color ist die Standard-Sektionsfüllung, nicht der Seitenhintergrund.
standard-sectionSectionBlockEigenes background-colorsection.styles.backgroundColor; sonst das Seiten-content-background-color. padding-* → Padding. Direkte standard-column-Kinder, oder die Spalten in einem einzelnen standard-group.
standard-columnSection-columns / children[i]Prozentbreiten ("50%", "33.33%") werden auf Templaticals fünf Layouts gematcht. Kein eigener Berichtseintrag.
standard-groupAbgeflachte Spalten; stackOnMobile: falseEine Group aus Spalten auf einer Sektion ist die Spaltenstruktur dieser Sektion. Eine verschachtelte Group in einer Spalte wird abgeflacht, approximated.
standard-wrapperInnere Sektion(en) wrapperÄußeres background-color / Padding → section.wrapper. Eine innere Sektion → converted. Mehrere Innere → Wrapper auf jede kopiert, approximated.
standard-hero1-Spalten-SectionBlockKinder werden als h1 / Paragraph / Button durchlaufen. background-color auf die Sektion; background-url stellt einen ImageBlock voran (gestapelt, nicht Overlay), approximated.
placeholderÜbersprungenEditor-Chrome. Kein Eintrag.
standard-paragraphParagraphBlockInhalt aus Slate-Kindern. Bleibt ein Paragraph, auch bei großer font-size.
standard-h1h4TitleBlocklevel 1–4 aus dem Typ.
standard-buttonButtonBlockBeschriftung aus den Kindern, nicht data.content. hrefurl. Ungesetztes Fill plus border-enabled ist outlined — Fill wird #ffffff (nicht das Factory-#333333), approximated.
standard-imageImageBlocksrc, alt; hreflinkUrl.
standard-dividerDividerBlockborder-color / border-width / border-style.
standard-spacerSpacerBlockHöhe aus height in px.
standard-navbar + standard-navbar-linkMenuBlockLinktext aus den Kindern; hrefurl; target === "_blank"openInNewTab.
standard-social + standard-social-elementSocialIconsBlockPlattform aus href-Hostname, dann src-Pfad. Benutzerdefiniertes PNG-src entfällt, approximated.
standard-table2 / tr / tdTableBlockConverted.
line-break<br>Innerhalb des Eltern-Rich-Texts. Kein Eintrag.
html-block-nodeHTML-FragmentInnerhalb des Eltern-Rich-Texts. Kein Eintrag.
marketing-countdownOverlay-Text + ImageBlock von srcDas GIF ist der Timer. Es wird kein type: "countdown" erzeugt (Cloud-only). approximated.
Kit common-videoVideoBlockConverted, wenn eine URL vorhanden ist; sonst html-fallback.
Kit shopwindow / qr-code / countdown-v2HtmlBlockJSON.stringify(node), html-fallback.
section_widget / wrapper_widgetKinder$var aus data.input; jeder erzeugte Eintrag approximated.
AMP_*HtmlBlockJSON.stringify(node), html-fallback.
logicKinder, oder SkipLeer → skipped. Nicht leer → Kinder werden konvertiert, als wäre der Wrapper nicht da; jeder erzeugte Eintrag approximated. Der Ausdruck wird nicht auf displayCondition abgebildet.
Jeder andere typeHtmlBlockDer rohe Knoten bleibt als JSON erhalten, markiert als html-fallback.

visible: "desktop" / "mobile" wird auf visibility abgebildet. Fehlt, wenn der Schlüssel fehlt.

Verlustbehaftete Konvertierung

  • Nicht aufgelöste $var-Reste$var(name) wird gegen Widget-data.input, dann gegen variables[] der Seite aufgelöst. Ein Name ohne Wert bleibt ungesetzt ("" / übrig gebliebenes $var(…) werden keine Merge-Tags). Eine Warnung auf Dokumentebene nennt, wie viele Werte aufgelöst wurden und wie viele unaufgelöst blieben.
  • mobileAttributes — eine zweite Attributtasche für das mobile Viewport. Templatical hat kein Padding je Viewport. Verworfen. Eine Warnung auf Dokumentebene, wenn irgendein Knoten sie trug.
  • Hero-Overlaystandard-hero hat keine Block-Entsprechung. Kinder laufen in eine 1-Spalten-Sektion; background-url wird zu einem führenden ImageBlock, gestapelt, nicht überlagert. Overlay-auf-Bild ist der Verlust; editierbare CTAs bleiben. approximated.
  • Outlined-Buttonsborder-enabled: true plus ungesetztes Fill hat keine Templatical-Entsprechung. Nach createButtonBlock wird Fill als #ffffff geschrieben, damit das Factory-#333333 einen Ghost-Button nicht in eine dunkle Pille verwandelt. Der Outline entfällt; der Eintrag ist approximated.
  • 4+ Spalten — Templatical unterstützt fünf Spalten-Layouts (1, 2, 3, 2-1, 1-2). Eine Sektion mit 4, 5 oder 6 Spalten wird auf "3" gefaltet; überzählige Kinder hängen an den letzten Slot, approximated, Originalbreiten in der note.
  • Abflachen verschachtelter Groups — ein standard-group innerhalb einer Spalte kann kein verschachtelter SectionBlock werden. Die Kinder der inneren Spalten werden in Dokumentreihenfolge in die Elternspalte eingefügt, approximated, note "nested group flattened (N columns)". Blätter werden konvertiert; die Geometrie ist der Verlust.
  • Benutzerdefinierte Social-PNGsstandard-social-element trägt ein eigenes PNG-src. SocialIconsBlock hat kein Custom-Src — es wählt ein Icon aus platform + iconStyle. Das PNG ist der Verlust; der Eintrag ist approximated, wenn ein Custom-src vorhanden war.
  • AMPAMP_*-Knoten haben keine Templatical-Entsprechung. Als JSON in einem HtmlBlock erhalten, html-fallback.
  • logic — Pro-logic.condition / logic.iteration werden zur toMJML-Zeit nach Liquid (oder einer eigenen Engine) kompiliert. Sie sind nicht displayCondition.{ before, after }. Leere Knoten skipped. Gefüllte Knoten konvertieren ihre Kinder und verwerfen die Verzweigung.
  • Countdown als GIFmarketing-countdown ist Overlay-Text plus ein ImageBlock von attributes.src. Templaticals countdown-Block ist Cloud-only und auf OSS leer, daher erzeugt dieses Paket ihn nicht. Das GIF ist ein statisches Bild; der Timer läuft nicht.

TIP

Verschachtelte Groups werden abgeflacht, weil MJML eine Sektion innerhalb einer Spalte verbietet und addBlock das ebenfalls tut. Ein erfundener verschachtelter SectionBlock würde nicht rendern. Hero-Kinder werden durchlaufen, statt den ganzen Teilbaum als html-fallback zu legen, damit editierbare CTAs erhalten bleiben; Overlay-auf-Bild kann Templatical nicht ausdrücken. Leeres logic wird übersprungen statt zu einem undurchsichtigen HtmlBlock, sodass ein gefüllter Zweig aus Produktzeilen als konvertierte Kinder erhalten bleibt. Der Countdown bleibt ein Bild, damit ein OSS-Renderer den Block nicht leer lässt.

Nicht abgebildete Felder

  • subject — Templatical-Templates haben kein Betreff-Feld. Ein nicht-leerer Wert wird in report.warnings genannt.
  • fonts[] — keine Schrift-Datei-Tabelle auf Dokumentebene. Ein nicht-leeres Array wird in report.warnings genannt. Text, der davon abhing, wird in der Ersatzschriftart gerendert.
  • headStyles — keine Head-Style-Tabelle auf Dokumentebene. Ein nicht-leerer Wert wird in report.warnings genannt.
  • thumbnail / id — still; sie sind nicht empfängerseitig.
  • classAttributes — in v1 übersprungen. Eine Warnung, wenn das Objekt nicht leer ist.
  • breakpoint — still. Templatical-Mobil ist 375 / MJML 480; dieses Paket erfindet keine Einstellung.

Ein frisch importiertes Template scheitert bei der Ankunft häufig an den Barrierefreiheits-Regeln von @templatical/quality, und das validate.mjs des Agent Skill beendet sich dabei mit einem Exit-Code ungleich 0. Aus Easy Email Pro exportierte Bilder tragen typischerweise keinen alt-Text, und der Importer übernimmt diese Lücke originalgetreu — eine Beschreibung zu erfinden wäre selbst ein Anti-Pattern für Barrierefreiheit. Die strukturelle Validierung besteht; die Befunde betreffen den Inhalt. Fügen Sie den importierten Bildern Alt-Text hinzu, und die Befunde verschwinden.

Weitere Fälle

Eröffnen Sie eine Diskussion mit einem geschwärzten Ausschnitt Ihres Easy-Email-Pro-Persist-JSON und dem, was Sie erreichen wollen. Wir nutzen diese Rückmeldungen, um die Abdeckung von @templatical/import-easy-email-pro zu verbessern.