Zum Inhalt springen
Dokumentation

First Steps

Erste Schritte mit deinem Plugin

Einen Webserver bauen

Jedes Plugin in Neleto ist einfach ein normaler Webserver mit einigen JSON-REST-Endpunkten. Diese Endpunkte können verschiedene Zwecke erfüllen. Sie können verwendet werden, um gerendertes HTML zu manipulieren, bevor es an den Client gesendet oder gecached wird, oder sie können Funktionen oder Helfer für den Renderer selbst definieren. Hier sind die Typen (wir verwenden TypeScript als Beispiel, aber du kannst dein Plugin in jeder Sprache bauen):

Rewriter-Endpunkt

Dieser Endpunkt kann unter rewriter in deiner plugin.json angegeben werden.

// Der Body der Anfrage, die dieser Endpunkt erhält, sieht so aus:
type Body = string;
// Und die Antwort muss so aussehen:
type Response = string;

Helper-Endpunkt

Dieser Endpunkt kann im Array unter helpers in deiner plugin.json verwendet werden.

// Der Body der Anfrage, die dieser Endpunkt erhält, sieht so aus:
type Body = {
    // der Name des aufgerufenen Helpers
    name: string;
    args: JsonValue[]; // jeder Wert, der gültiges JSON ist
};
// Und die Antwort muss so aussehen:
type Response = {
    // jeder Wert, der gültiges JSON ist, dies muss mit dem VariableType im
    // `type`-Abschnitt dieses Helper-Endpunkts in deiner `plugin.json` übereinstimmen
    data: JsonValue;
};

Seiten-Endpunkt

Dieser Endpunkt kann im Array unter pages in deiner plugin.json verwendet werden.

Seiten-Endpunkte sind normale Endpunkte, die die Anfrage direkt vom Client weitergeleitet bekommen. Sie können auch alles zurückgeben, da sie auch als API-Endpunkt fungieren können.

Admins und Entwickler können im CMS für jeden von Plugins definierten Seiten-Endpunkt ein Layout auswählen. Wenn ein Seiten-Endpunkt ein Layout zugewiesen hat, wird die Anfrage an diesen Endpunkt in eine POST-Anfrage umgewandelt und das gerenderte Layout wird im Body der Anfrage enthalten sein. Die Antwort wird nicht verändert.

Das gerenderte Layout enthält ein einzelnes <slot></slot>-Element, das die Stelle markiert, an der der Seiteninhalt eingefügt wird. Ersetze es durch deinen Inhalt und gib das vollständige HTML-Dokument zurück:

const layout = await request.text();
const page = layout.replace(/<slot[^>]*><\/slot>/g, yourContent);
return new Response(page, { headers: { "Content-Type": "text/html" } });

Das Layout rendert die aktuelle Seitensprache als <html lang="…"> – lies sie aus, um deinen Inhalt zu lokalisieren – und liefert einen leeren <title></title>. Setze den Titel sowie Meta-/Open-Graph-Tags selbst, indem du das Layout vor der Rückgabe anpasst.

Ein Layout wird erst angewendet, wenn im CMS eines für die Seite ausgewählt wurde. Bis dahin (oder wenn keines ausgewählt ist) erhält der Endpunkt eine normale GET-Anfrage und sollte eine eigenständige Antwort rendern.

Mehrere Sprachen

Neleto liefert nicht-Standard-Sprachen unter einem Pfad-Präfix aus (zum Beispiel /en/deine-seite). Damit der Sprachumschalter des Layouts funktioniert, definiere sowohl die einfache als auch die sprach-präfixierte Route, sodass beide dein Plugin erreichen, und lies die aktive Sprache aus dem <html lang> des Layouts:

"pages": [
    { "route": "/deine-seite/:slug", "allow_select_layout": true },
    { "route": "/:lang/deine-seite/:slug", "allow_select_layout": true }
]
Seiten-Endpunkte sind immer öffentlich. Wenn du einen authentifizierten Endpunkt benötigst, verwende einen Api-Endpunkt.

Api-Endpunkt

Dieser Endpunkt kann im Array unter api in deiner plugin.json verwendet werden.

Api-Endpunkte ähneln Seiten-Endpunkten, außer dass ihr Zugriff so kontrolliert werden kann, dass er nur für eingeloggte Benutzer mit einer bestimmten Berechtigung zugänglich ist (siehe Zugriffskontrolle unten). Api-Endpunkte werden durch das CMS-Backend mit dem Routen-Präfix /api/rest/plugins/<plugin-name>/api weitergeleitet. Das bedeutet, dass eine Route, die dein Plugin als /foo definiert, unter /api/rest/plugins/<dein-plugin-name>/api/foo verfügbar sein wird. Query, Body und die Anfrage-Methode werden beim Weiterleiten nicht verändert, es wird nur auf gültige Authentifizierung und die erforderliche Berechtigung geprüft.

Zugriffskontrolle

Beschränke eine Api-Route mit allowed_permissions in der plugin.json – ein Array von CMS-Berechtigungs-IDs (z. B. page.update) mit ODER-Semantik (der Benutzer benötigt eine davon):

"api": [
    { "route": "/settings", "allowed_permissions": ["page.update"] }
]

Wenn allowed_permissions fehlt oder leer ist, ist die Route für jeden eingeloggten Benutzer zugänglich (es wird nur die Authentifizierung geprüft).

allowed_roles ist veraltet und wird ignoriert – es ist nicht Teil des Manifest-Schemas und das Backend liest es nie. Eine Route, die nur allowed_roles deklariert, hat keine Autorisierungsprüfung und ist für jeden eingeloggten Benutzer zugänglich, unabhängig von den aufgeführten Rollen. Verwende stattdessen allowed_permissions.
Der Teil /api/rest/plugins/<dein-plugin-name>/api/ ist ein fester Gateway-Präfix. Alles, was du anhängst, wird wortwörtlich gegen die Routen abgeglichen, die du unter api in deiner plugin.json deklariert hast. Dadurch kann /apizweimal in der Client-URL auftauchen: Eine Plugin-Route /settings ist unter /api/rest/plugins/<name>/api/settings erreichbar, eine Plugin-Route /api/settings jedoch unter /api/rest/plugins/<name>/api/api/settings. Halte die Manifest-Route, die Route deines Servers und den Fetch-Pfad im Client konsistent.Ein 404 bei einem Plugin-API-Aufruf ist immer ein Pfad-Fehler – niemals die HTTP-Methode. Methode und Body werden unverändert weitergeleitet; eine Methode, die dein Server nicht behandelt, ergibt 405, nicht 404. Zähle bei einem 404 zuerst die /api-Segmente.

Die Admin-UI leitet den Präfix üblicherweise aus ihrem eigenen Pfad ab, damit die Pfade korrekt bleiben. Beachte, wie die eigene Route des Plugins (inklusive /api-Namespace, falls vorhanden) an den Helper übergeben wird:

// base = Einhängepunkt dieses Plugins, z. B. /api/rest/plugins/<name>
const base = location.pathname.replace(/\/ui\/?(index\.html)?$/, "");
const api = (p) => base + "/api" + p; // ergänzt den festen /api-Präfix des Gateways

fetch(api("/settings")); // Plugin-Route "/settings"      -> .../api/settings
fetch(api("/api/settings")); // Plugin-Route "/api/settings" -> .../api/api/settings

Ui-Endpunkt

Der Ui-Endpunkt ähnelt Api-Endpunkten, da er nur für eingeloggte Benutzer zugänglich ist. Der einzige Unterschied ist, dass die Benutzerrolle für diesen Endpunkt nicht geprüft wird und dass er verwendet wird, um eine benutzerdefinierte Admin-Oberfläche für dein Plugin bereitzustellen. Du kannst nur einen Ui-Endpunkt in deiner plugin.json definieren, da dieser eine Endpunkt als Einstiegspunkt für die Benutzeroberfläche deines Plugins in einem Iframe verwendet wird.

Dein Plugin-Server kann auf mehr als einem Endpunkt lauschen, und du kannst Links verwenden, um zwischen ihnen zu navigieren, aber diese Links müssen das Präfix /api/rest/plugins/<dein-plugin-name>/ui haben.