JavaScript Plugins API

Neben den schon von PHP bekannten Hooks (Action und Filter), gibt es in nun auch eine API um Erweiterungen für den Editor zu erstellen.

Slot / Fill

Die JS Plugins API basiert auf Slots, die mit sogenannten Fills erweitert werden können. Unter Slots versteht man erweiterbare Bereiche, denen UI Elemente hinzugefügt werden können. Beispiele für Slots im Editor sind Einträge in Menüs, Buttons in der Toolbar, Elemente in der Sidebar oder zusätzliche Sidebars.

Man kann also eigene React Komponenten erstellen und diese an den jeweiligen Slots rendern lassen. Ein Slot kann dabei mehrere Fills enthalten.

Beispiel Post Status Panel

Zuerst wird mit Hilfe der Funktion createSlotFill ein Fill und ein Slot erstellt (Zeile 3). In Zeile 5 – 11 wird der Fill definiert. Jeder Fill wird mit einem PanelRow Element umgeben und kann eine Klasse als Parameter entgegen nehmen.

import { createSlotFill, PanelRow } from '@wordpress/components';

export const { Fill, Slot } = createSlotFill( 'PluginPostStatusInfo' );

const PluginPostStatusInfo = ( { children, className } ) => (
	<Fill>
		<PanelRow className={ className }>
			{ children }
		</PanelRow>
	</Fill>
);

PluginPostStatusInfo.Slot = Slot;

export default PluginPostStatusInfo;

An der Stelle, an der dieser Slot gerendert wird, importiert man diese Komponente. PluginPostStatusInfo.Slot enthält eine Funktion, die ausgeführt wird, sobald ein Fill gerendert wird. In diesem Fall die weiteren Komponenten der Sidebar. Die registrierten Fills werden in Zeile 14 mit Hilde von { fills } ausgegeben.

import PluginPostStatusInfo from '../plugin-post-status-info';

... 

<PluginPostStatusInfo.Slot>
	{ ( fills ) => (
		<Fragment>
			<PostVisibility />
			<PostSchedule />
			<PostFormat />
			<PostSticky />
			<PostPendingStatus />
			<PostAuthor />
			{ fills }
			<PostTrash />
		</Fragment>
	) }
</PluginPostStatusInfo.Slot>

...
Position für das Slot Beispiel
An dieser Position werden die Fills gerendert.

Plugin registrieren

const { registerPlugin } = wp.plugins;
registerPlugin( name: string, settings: Object )

Um ein eigenes Plugin zu registrieren wird die Funktion registerPlugin aus dem Paket Plugins verwendet.

Als name wird ein eindeutiger Bezeichner übergeben, um das Plugin zu identifizieren. Das setting Objekt enthält ein optionales Icon für das UI (Dies ist nicht für alle Plugins nötig) und eine React Komponente mit den UI Elementen, die hinzugefügt werden sollen.

const { PluginPostStatusInfo } = wp.editPost;
const { registerPlugin } = wp.plugins;

const MyPluginPostStatusInfo = () => (
	<PluginPostStatusInfo
		className="my-plugin-post-status-info"
	>
		My post status info
	</PluginPostStatusInfo>
);

registerPlugin( 'my-plugin-post-status-info', {
	render: MyPluginPostStatusInfo,
} );

Die Render-Komponente im Settings-Objekt enthält einen oder mehrere Fills, in diesem Beispiel das PluginPostStatusInfo Element. Dieses Element enthält den Inhalt (hier: „My post status info„), der in den Slot gerendert werden soll.

Ergebnis des Beispiel Plugins
JS Plugin mit Fill/Slot

Eigene Bock-Stile erstellen

In den Block-Einstellungen kannst du im Bereich Erweitert über ein Textfeld ganz einfach einem Block weitere Klassen hinzufügen. Diese Klassen können genutzt werden, um das Aussehen per CSS zu ändern und so bsw. eine andere Button Form und Größe darzustellen. Mit der Block-Style API bekommst du eine weitere Möglichkeit, die es erlaubt Blöcken weitere Klassen zu geben. Der Vorteil dieser API ist es, dass die Klassen vordefiniert werden können, der Editor ein Interface erstellt und eine Vorschau des Stils angezeigt wird.

Stile für eigene Blöcke

Ein Beispiel für Block-Stile ist bereits im Zitat-Block vorhanden, hier gibt es die Stile „Normal“ und „Groß“, die jeweils eigene CSS Definition haben. Über das erste Icon in der Block-Toolbar kannst du ein Menü öffnen, über das du die Block-Stile auswählen oder den Block in einen andern Typ umwanden kannst. Auf der rechten Seite erhältst du gleich eine Vorschau, wie die Block mit dem Stil aussehen wird.

Block-Stile Menü für den Zitate Block
Block-Stile im Zitat-Block

In der Block-Definition (/block-library/src/quote/index.js) sind diese wie folgt definiert:

styles: [
	{ name: 'default', label: __( 'Regular' ), isDefault: true },
	{ name: 'large', label: __( 'Large' ) },
]

Styles ist ein Array mit den Stil-Objekten. Jedes Object hat dabei einen Namen, der für die Klasse verwendet wird. Aus name: ‚large‘ wird class=“is-style-large“. Das Label wird im Toolbar Menü angezeigt. Über den Parameter isDefault kannst du festlegen, welcher Stil vorausgewählt sein soll.

<blockquote class="wp-block-quote is-style-large">
	<p>Lorem ipsum dolor sit amet...</p>
	<cite>Das ist ein Beispiel</cite>
</blockquote>

Bestehende Blöcke erweitern

Neben der Stil Deklaration in der Block-Definition kannst du mit Hilfe eines Hooks auch Stile zu bereits bestehenden Blöcken hinzufügen. Wenn du beispielsweise einen eigenen Button-Stil hinzufügen möchtest, reichen die folgende JavaScript und CSS Anweisungen.

Mit der Funktion registerBlockStyle() registrierst du den Stil im Editor. Der erste parameter ist der registrierte Name des Blocks, bestehend aus namespace/block-name, der zweite Parameter ist ein Objekt mit mit dem Namen und dem Label.

wp.blocks.registerBlockStyle( 'core/button', { name: 'red-button', label: 'Rot' });

Der Editor erzeugt nun die Klasse is-style-red-button. Für diese Klasse kannst du eine CSS Anweisung erstellen, um so die Darstellung des Button zu definieren.

.wp-block-button.is-style-red-button .wp-block-button__link {
	background: #cf2e2e;
	text-transform: uppercase;
	border-radius: 0;
}

Im Editor sieht es dann folgendermaßen aus. Der Stil wird im Stil-Menü angezeigt und wenn du nun mit der Maus über den Stil gehst oder per Tastatur diesen auswählst, wird eine große Vorschau auf der rechten Seite dargestellt.

Block-Stil Menü für einen eigenen Button Stil
Eigener Block-Stil im Editor

Eigene Farben definieren

Einige Blöcke bieten die Möglichkeit Farben von bestimmten Elementen im Block anzupassen. Dies sind zum Beispiel die Hintergrundfarbe eines Buttons oder die Textfarbe eines Absatzes. Gutenberg liefert schon 11 vordefinierte Farben mit.

Neben den Farben gibt es auch eine Möglichkeit mit einem Farbmischer eine eigene Farbe zu mischen.

Farbwähler in Gutenberg

Mit folgenden Code lässt sich der Farbmicher deaktivieren, sodass nur die vordefinierten Farben verwendet werden können.

add_theme_support( 'disable-custom-colors' );

Vordefinierte Farben überschreiben

Themes haben die Möglichkeit die vordefinierten Farben zu überschreiben, die in der Farbwahl Palette in allen Komponenten angezeigt werden sollen.

function mytheme_add_custom_colors() {
	add_theme_support( 'editor-color-palette', array(
		// Fügt eine goldene Farbe hinzu.
		array(
			'name' => __( 'gold', 'themeLangDomain' ),
			'slug' => 'nitschmahler-gold',
			'color' => '#ae9a63',
		),
	) );
}

add_action( 'after_setup_theme', 'mytheme_add_custom_colors' );
Angepasste Farbwahl Komponente
Farbwahl Komponente

Man ruft die add_theme_support Funktion auf und übergibt als Parameter den Wert „editor-color-palette“ und ein Array mit den Farbdefinitionen. Jede Farbe ist dabei ein Array, das die Werte „name„, „slug“ und „color“ enthält.

  • Name: Der Name der angezeigt wird, dieser sollte übersetzbar sein.
  • Slug: Der Wert, der abgespeichert wird und aus dem die CSS Klasse generiert wird.
  • Color: Der Hex-Wert der Farbe um eine Vorschau zu zeigen.

Beim Auswählen einer Farbe wird bsw. im Button ein Attribut mit dem Slug „nitschmahler-gold“ abgespeichert und eine eine Klasse ‚has-nitschmahler-gold-background-color‚ zum Element hinzugefügt

<!-- wp:button {"backgroundColor":"nitschmahler-gold"} -->
<div class="wp-block-button alignnone">
<a class="wp-block-button__link has-background has-nitschmahler-gold-background-color">Mein Button</a>
</div>
<!-- /wp:button -->

Für diese Klasse muss man nun noch eine CSS Definition erstellen. Diese Definition muss im Editor und im direkt in der Seite geladen werden.

// Für die Hintergrudnfarbe
.has-nitschmahler-gold-background-color {
	color: #ae9a63;
}
// Für die Textfarbe
.has-nitschmahler-gold-color {
	color: #ae9a63;
}

Fertig ist der Button:

Fertiger Button

Block Templates

Noch ist das Feature nicht in Gutenberg integriert, seit heute gibt es aber ein Proposal Ticket auf GitHub, das die Funktionen von Block Templates beschreibt und einige Beispiele aufzeigt.

Definition

Ein Block Template ist einfach gesagt eine Liste von Blöcken. Die Blöcke können vordefinierte Attribute und Platzhalter enthalten, sie können statisch oder dynamisch sein.

Nutzung

Block Templates sollten nicht mit globalen oder verschachtelten Blöcken verwechselt werden. Die Liste der Blöcke können aber globale Blöcke und auch verschachtelte Blöcke beinhalten. Hierbei geht es nicht darum ein Konfigurierte Gruppe von Blöcken auf verschiedenen Seiten wiederzuverwenden, dafür sind globale Blöcke, mit ineinander geschachtelten Blöcken die bessere Lösung.

Bei Block Template  geht es darum eine Vorlage zu liefern, die vom Nutzer an verschiedenen Stellen ausgefüllt werden kann.

Hier ein Beispiel wie Templates in Custom Post Types bereitgestellt werden können:

function register_book_type() {
	$args = array(
		'public' => true,
		'label'  => 'Books',
		'show_in_rest' => true,
		'template' => array(
			array( 'core/image' ),
			array( 'core/heading', array(
				'placeholder' => 'Author...',
			) ),
			array( 'core/paragraph', array(
				'placeholder' => 'Add book description...',
			) ),
		),
	);
	register_post_type( 'book', $args );
}
add_action( 'init', 'register_book_type' );

Details

Template können:

  • In JS (state tree) und PHP definiert werden
  • Blöcke mit Unterblöcken enthalten
  • Gesperrt sein (Es ist nicht möglich die Blöcke zu bewegen oder zu löschen)
  • Als Standard für einen Post Type gesetzt werden
  • Vom Benutzer gespeichert und bearbeitet werden
  • Als Inhalt eines page-template.php genutzt werden um den Editor von einem Theme aus zu initialisieren

Wie werden Blöcke gespeichert?

Bisher wurde der Inhalt eines Beitrags oder einer Seite in die Tabelle wp_posts in der Spalte post_content gespeichert. Doch wie wird das nun gelöst, ist jeder Block ein eigener Datenbank Eintrag?

Der Inhalt von Beiträgen und Seiten wird auch weiterhin komplett in der Spalte post_content in der wp_posts Tabelle abgespeichert. Dies verhindert zum einen das Zusätzliche Abfragen von Datenbankeinträgen, was Performance Einbusen bedeuten würde, zum anderen bietet diese Lösung die beste Abwärtskompatibilität mit den schon bestehenden Inhalten.

Gutenberg Block edit flow
Edit Flow

Laden

Wenn ein, aus mehreren Blöcken bestehender, Inhalt im Editor geladen wird, wird mit Hilfe eines Parsers der Text in die jeweiligen Blöcke aufgeteilt. In der Informatik nennt man diesen Schritt Serialisierung. Strukturierte Daten werden in eine Sequenzielle Darstellungsform abgebildet. Für die Strukturierung der Blöcke im Inhalt werden HTML Kommentare verwendet. Diese werden vom Parser interpretiert und und so eine geordnete Liste von Blöcken erstellt um den sogenannten Post State zu erzeugen.

<!– wp:heading –>
<h2>Eine Überschrift</h2>
<!– /wp:heading –>

<!– wp:paragraph –>
<p>Hier steht Text</p>
<!– /wp:paragraph –>

Block API und Rendern

Mit Hilfe der Block API werden die einzelnen Blöcke nun interpretiert und visuell dargestellt. Blöcke haben jeweils eine edit() Funktion, die beschreibt wie der Inhalt im Editor interpretiert werden soll. 

Wenn sich Block Attribute oder Inhalte ändern, wird die Darstellung neu gerendert und die rechte Schlaufe des Diagrams einmal durchlaufen. Dies geschieht auch, wenn ein neuer Block hinzugefügt oder entfernt wird.

Serialisieren und Speichern

Wenn der Inhalt nun gespeichert wird, wird jeweils die save() Funktion eines jeden Blocks ausgeführt und eine HTML Darstellung erzeugt. Zusätzlich wird der HTML Kommentar um den Block gesetzt, um ihn beim nächsten Laden wieder interpretieren zu können. Im nächsten Schritt werden die Blöcke der Seite oder des Beitrags zusammengesetzt und wieder in die Spalte abgespeichert.