Von apitemplate.io migrieren
Vorlagen importieren
In der App: Vorlagen → Importieren → apitemplate.io. Es gibt zwei Wege, Vorlagen zu übernehmen.
Mit API-Schlüssel (viele Vorlagen auf einmal):
- Geben Sie den API-Schlüssel aus apitemplate.io (API Integration) und die Region ein, die Ihre Integration aufruft (
rest-de.apitemplate.ioist Europa (Frankfurt)). Der Schlüssel wird nur zum Lesen Ihrer Vorlagen verwendet und nie gespeichert. - Vorlagen auflisten zeigt alle Vorlagen des Kontos mit ihrer Gruppe. PDF-Vorlagen sind ausgewählt; filtern Sie nach Name oder Gruppe und wählen Sie mit Angezeigte auswählen oder Angezeigte abwählen eine Auswahl. Bildvorlagen sind Ebenen-Designs ohne HTML und lassen sich nicht importieren.
- Analysieren liest HTML, CSS, Einstellungen und Beispiel-JSON jeder ausgewählten Vorlage und prüft sie (siehe unten). Vorlagen, die apitemplate.io nicht liefert, stehen unter Nicht lesbar; kopieren Sie diese aus deren Editor und nutzen Sie Einfügen oder Dateien.
- Entwürfe anlegen erstellt je importierter Vorlage eine Jinja2-Vorlage, deren erste Version als Entwurf gespeichert ist (veröffentlicht wird nichts). Ihr Slug ist der Name der Vorlage in Kleinbuchstaben mit Bindestrichen (aus
Statement of costwirdstatement-of-cost);-2,-3usw. kommen nur hinzu, wenn der Workspace den Slug schon hat, archivierte Vorlagen eingeschlossen. Der Entwurf merkt sich seine apitemplate.io-ID für die Kompatibilitätsendpunkte. Im Free-Plan, der fünf Vorlagen fasst, hält ein Import an der Grenze an, und der Bericht behält den Rest.
Das JSON aus dem JSON-Tab von apitemplate.io wird zum Datensatz default des Entwurfs, die Vorschau zeigt also sofort Daten. Eine Vorlage mit leerem JSON-Tab startet ohne Daten, und der Bericht prüft dann keine fehlenden Felder. apitemplate.io kennzeichnet den Endpunkt, der die Vorlagenquelle liefert, als experimentell.
Einfügen oder Dateien (eine Vorlage): Fügen Sie ein, was deren Editor zeigt, den HTML-Body, das CSS, das Einstellungs-JSON (Papier, Ränder, Kopf- und Fußzeilenvorlagen) und das Beispiel-JSON, oder legen Sie die exportierten Dateien ab (.html, .css, .json).
Auf beiden Wegen gilt:
- Analysieren kompiliert jede Vorlage mit der Jinja2-Engine und prüft sie gegen die Beispieldaten. Der Bericht listet Fehler (unbekannte Filter, von der Engine abgelehnte Syntax), Prüfpunkte (Python-spezifische Konstrukte, Einstellungen ohne Gegenstück, fehlende Beispielschlüssel) und was der Importer abgebildet hat.
- Mit apitemplate.io vergleichen (optional): Geben Sie Ihren apitemplate.io-Schlüssel und die apitemplate.io-ID der Vorlage ein, und Original rendern rendert das Original dort mit denselben Beispieldaten, damit Sie deren PDF neben die Editor-Vorschau legen können. Der Schlüssel wird für diesen einen Aufruf verwendet und nie gespeichert.
- Entwurf anlegen erstellt eine Jinja2-Vorlage mit den abgebildeten Einstellungen und den Beispieldaten. Prüfen Sie sie im Editor und veröffentlichen Sie sie dann.
Eine so eingefügte Vorlage kennt ihre apitemplate.io-ID nicht; sie reagiert nur auf ihren Slug und ihre Formfeed-ID, auch an den Kompatibilitätsendpunkten.
Mit der CLI
In einem Vorlagenprojekt legt der Import je Vorlage einen lokalen Vorlagenordner an; prüfen Sie sie mit formfeed dev und führen Sie dann formfeed templates push aus. Mit API-Schlüssel (--key oder APITEMPLATE_API_KEY) wählen Sie die Vorlagen nach ID, nach Gruppe oder alle auf einmal und geben die Region mit --source-region oder APITEMPLATE_REGION an (default, de, us, au, alt, alt-de, alt-us; default, wenn keins von beiden gesetzt ist):
export APITEMPLATE_API_KEY=...
export APITEMPLATE_REGION=de
formfeed import apitemplate --all
formfeed import apitemplate --group Invoices
formfeed import apitemplate --template 3a677b23217dd954 69c77b2365e90a12
Vorlagen mit gleichem Namen erhalten nummerierte Ordner (overview, overview-2); Vorlagen, die apitemplate.io nicht liefert, werden gemeldet und übersprungen. --all und --group nehmen nur die PDF-Vorlagen und überspringen Bildvorlagen mit einem Hinweis. Aus exportierten Dateien (--css, --settings und --sample sind optional; --name ist ohne Angabe der Name der HTML-Datei und --slug einer, der aus dem Namen gebildet wird):
formfeed import apitemplate --name "Invoice" --html body.html --css style.css --settings settings.json --sample sample.json
Zu jeder importierten Vorlage gibt die CLI Fehler, Warnungen und Hinweise aus, denselben Bericht, den die App zeigt.
Einstellungen
Diese Einstellungen werden auf die Einstellungen der Vorlage abgebildet (Seiteneinrichtung im Editor):
| apitemplate.io | Formfeed |
|---|---|
paper_size (A3, A4, A5, Letter, Legal, Tabloid, Ledger) | paper.format; jede andere Größe wird mit einem Hinweis zu A4 |
custom_width, custom_height | paper.width, paper.height |
orientation | paper.landscape |
margin_top, margin_right, margin_bottom, margin_left | margin |
header_template, footer_template, custom_header, custom_footer, header_left … footer_right | Kopf- und Fußzeile (siehe unten) |
print_background, scale, page_ranges, prefer_css_page_size | printBackground, scale, pageRanges, preferCssPageSize |
output_image_type, viewport_width, viewport_height, device_scale | image.format, image.width, image.height, image.deviceScaleFactor |
Eine Einstellung ohne Gegenstück wird verworfen und im Bericht genannt. JPEG- und PNG-Vorlagen
werden zu Bildvorlagen. Ränder ohne Einheit ("margin_top": "40") sind Pixel, so wie der Renderer von
apitemplate.io sie liest: 40 wird zu 40px (etwa 10,6 mm), nicht zu 40 mm.
Kopf- und Fußzeilen gespeicherter Vorlagen: Markup aus custom_header und custom_footer bleibt
erhalten, wenn es etwas anzeigt. Sonst werden die Textfelder header_left, header_center,
header_right (und die footer_*-Felder) zu einer Zeile in header_font_size bzw.
footer_font_size (9px, wenn keine gesetzt ist). Die Platzhalter {{pageNumber}} oder {{page_number}},
{{totalPages}} oder {{total_pages}}, {{date}}, {{title}} und {{url}} werden wie bisher zu
Seitenzahl, Seitenanzahl, Datum, Titel und Adresse. Ein display_header_footer, das falsch ist, lässt
Kopf- und Fußzeile weg.
apitemplate.io setzt Kopf- und Fußzeilenvorlagen in 75 % der Seitenbreite und skaliert sie um 4/3
hoch, eine Länge in px fällt dort also ein Drittel größer aus. Der Importer legt das Markup in eine
Box, die genauso skaliert, damit ein importierter Logo-Kopf seine Größe behält. Markup, das den
Innenabstand der Kopf- oder Fußzeile aufhebt (#header, #footer { padding: 0 }), bekommt in den
Einstellungen padding: 0 und läuft wie bisher bis an den Rand.
Das CSS-Feld von apitemplate.io enthält oft <link>- und <script>-Tags (Google Fonts,
Icon-Fonts, Diagramm-Bibliotheken). Der Importer verschiebt sie in den Tab Head und übernimmt den
Inhalt von <style>-Blöcken als CSS, damit Schriften und Icons wie bisher laden. apitemplate.io füllt
das CSS-Feld mit den Daten, Head und CSS von Formfeed sind dagegen statisch: <script>- und
<style>-Blöcke mit Template-Syntax (ein Chart-Skript mit "data": {{ values }}) kommen deshalb ans
Ende der Vorlage, wo sie gefüllt werden. Eine Liste oder ein Dict wird wie in Python ausgegeben
([1, 2]), wie bei apitemplate.io.
Zeichenketten
Python-Formatierung von Zeichenketten mit % ("%.2f" % value) hat kein Gegenstück; nutzen Sie "{:.2f}".format(value),
number() oder money(). .upper(), .replace(), .split(), .strip() und .format() funktionieren über die
Kompatibilitätsschicht, und .format() versteht Pythons Formatangaben einschließlich Tausendertrennzeichen und
verschachtelter Felder ("{:,.{}f}".format(value, places)). truncate(length, killwords, end),
map(attribute='name') und selectattr('field', 'equalto', value) nehmen ihre Jinja2-Argumente.
Schleifen
loop.cycle() ist nicht verfügbar; nutzen Sie cycler() oder loop.index % n. Ein {% set %} in einer
Schleife, das eine vor der Schleife gesetzte Variable ändert, behält in Nunjucks den neuen Wert nach der
Schleife, während Python-Jinja2 ihn verwirft; der Bericht zeigt auf jedes solche set. namespace()
funktioniert wie in Jinja2, Zähler wie {% set ns.total = ns.total + 1 %} laufen also unverändert.
Der Import versteckt außerdem die Wrapper-Elemente, die der visuelle Editor von apitemplate.io um Schleifen-Tags
legt (Klasse apitemplate-is-content-hidden), mit einer Regel im CSS der Vorlage.
Makros, call-Blöcke, filter-Blöcke und autoescape-Blöcke laufen nach den Regeln von Nunjucks; der Bericht
bittet deshalb, ihre Ausgabe zu prüfen. {% import %} und {% from … import %} verweisen auf Dateien, die bei
apitemplate.io geblieben sind: Verschieben Sie die Makros in die Vorlage oder in ein Partial.
Tests
Jinja2-Tests nehmen in Nunjucks Klammern: is divisibleby(2) statt is divisibleby 2, das sich nicht lesen
lässt. sequence gibt es nicht; nutzen Sie is iterable. sameas vergleicht mit ===, was für Listen und
Objekte der Identitätsprüfung von Jinja2 entspricht. Der Bericht markiert jede Verwendung von divisibleby,
sameas, escaped, mapping, sequence und callable, damit Sie sie prüfen können.
Beispieldaten
Schlüssel, die die Vorlage liest, die aber im Beispiel fehlen, werden gemeldet, damit die Vorschau jeden Pfad zeigt. Der Editor leitet beim Speichern ein Datenschema aus dem Beispiel ab.
Filter
Formfeed hat Helfer gleichen Namens für qrcode und barcode von apitemplate.io;
ihre Optionen sind die von Formfeed, prüfen Sie also jeden Aufruf an der Helfer-Referenz. currency_format
ist ein Alias von money(value, currency, locale): Er rendert, und der Editor
markiert ihn mit einer Warnung und bietet an, ihn umzubenennen. Einen Filter table gibt es nicht: Eine
Vorlage, die ihn verwendet, scheitert, bis Sie die Tabelle als HTML mit einer {% for %}-Schleife schreiben.
Jeden Filter, den Formfeed nicht kennt, nennt der Bericht als Fehler.
API
Stellen Sie Basis-URL und Header um oder nutzen Sie während der Migration die Kompatibilitätsendpunkte:
| apitemplate.io | Formfeed |
|---|---|
/v2/create-pdf?template_id=… | POST /v1/renders mit template |
/v2/create-image?template_id=… | POST /v1/renders mit template und output: "png" oder "jpg" |
/v2/create-pdf-from-html | POST /v1/renders mit html und engine: "jinja2" |
/v2/create-pdf-from-url | POST /v1/renders mit url |
/v2/list-objects | GET /v1/renders |
/v2/delete-object | DELETE /v1/renders/{id}/outputs |
X-API-KEY: … | Authorization: Bearer … (oder X-API-Key) |
| Kompatibilitäts-Shim | POST /v1/compat/apitemplate/create-pdf, create-image, create-pdf-from-html und create-pdf-from-url antworten im Format von apitemplate.io |
Jede Region von apitemplate.io entspricht https://api-eu.formfeed.dev/v1: Formfeed rendert in Frankfurt
und speichert in der EU. api-us.formfeed.dev ist für eine US-Region reserviert, die noch nicht offen ist.
Mit den Kompatibilitätsendpunkten ist eine Migration drei Schritte: Vorlagen mit Ihrem API-Schlüssel importieren, veröffentlichen und die Integration auf https://api-eu.formfeed.dev/v1/compat/apitemplate/… umstellen, mit einem Formfeed-Schlüssel im selben Header X-API-KEY. So in der App importierte Vorlagen reagieren weiter auf ihre template_id von apitemplate.io, die Anfrage bleibt also unverändert; mit formfeed import importierte und aus einem Projekt hochgeladene Vorlagen reagieren nur auf ihren Slug oder ihre Formfeed-ID. Siehe die Kompatibilitätsendpunkte.
Die Post Action S3 Storage von apitemplate.io hat kein Gegenstück in der API, das sich importieren ließe, weil ihre Zugangsdaten apitemplate.io nie verlassen: Verbinden Sie Ihren Bucket stattdessen einmal in den Einstellungen des Workspace (eigener Speicher, ab dem Pro-Plan). Renderings über die Kompatibilitätsendpunkte werden dann dorthin kopiert wie jedes andere Rendering, nur schreibt eines, das aus dem Cache der Deduplizierung beantwortet wird, keine zweite Kopie, und cloud_storage wird ignoriert, weil Formfeed seine eigene Kopie immer für die Aufbewahrungsfrist des Workspace behält.