
January 15, 2026 4 min read
CKEditor 5 in TYPO3 v14 erweitern: Code-Blöcke im RTE
Was sich beim Erweitern des RTE mit CKEditor 5 in TYPO3 v14 geändert hat, am Beispiel von Code-Blöcken mit Syntax-Highlighting.
Wiederaufnahme: Dieser Beitrag setzt meinen Artikel Den CkEditor erweitern aus dem Jahr 2020 fort. Damals ging es um CKEditor 4 und TYPO3 8 bis 11. Inzwischen hat TYPO3 den Editor gewechselt, und mit TYPO3 v14 ist es Zeit, das Thema neu aufzurollen. Der alte Beitrag bleibt online, gilt aber nur für diese älteren TYPO3-Versionen.
Das Beispiel ist geblieben: Ich möchte in meinen Beiträgen Code bequem darstellen, mit Syntax-Highlighting im Frontend. Dafür gibt es im RTE einen Button für Code-Blöcke, der die Sprachen kennt, die ich brauche.
Was sich seit CKEditor 4 geändert hat
Seit TYPO3 v12 arbeitet das Backend mit CKEditor 5. Das ist kein Update, sondern ein anderer Editor, und das merkt man bei jeder Erweiterung: Die Add-Ons von ckeditor.com aus dem alten Beitrag laufen nicht mehr, und extraPlugins gibt es nicht mehr. Plugins sind jetzt JavaScript-Module, die in der RTE-Konfiguration importiert werden. Auch die Konfigurationsschlüssel heißen anders:
| CKEditor 4 (TYPO3 8 bis 11) | CKEditor 5 (TYPO3 v12 bis v14) |
|---|---|
extraPlugins | importModules |
codeSnippet_languages | codeBlock.languages |
toolbarGroups, removeButtons | toolbar.items |
stylesSet | style.definitions |
format_tags | heading.options |
justifyClasses | alignment.options |
Das Code-Block-Plugin aktivieren
Das Paket @ckeditor/ckeditor5-code-block bringt TYPO3 bereits mit. Es muss nur importiert werden. In meinem SitePackage liegt dazu die Datei Configuration/Yaml/Rte/Plugins/code-block.yaml:
editor:
config:
importModules:
- { module: '@ckeditor/ckeditor5-code-block', exports: [ 'CodeBlock' ] }
codeBlock:
languages:
- { language: 'plaintext', label: 'Plain text' }
- { language: 'bash', label: 'Bash' }
- { language: 'apacheconf', label: 'Apache' }
- { language: 'yaml', label: 'YAML' }
- { language: 'typoscript', label: 'TypoScript' }
- { language: 'php', label: 'PHP' }
- { language: 'html', label: 'HTML / Fluid' }
- { language: 'json', label: 'JSON' }
- { language: 'diff', label: 'Diff' }Der Schlüssel language landet später als CSS-Klasse im HTML, das label sieht die Redaktion im Dropdown. Die Datei wird dann in der Konfiguration des RTE eingebunden, bei mir Configuration/Yaml/Rte/text.yaml. Neu gegenüber CKEditor 4 ist, dass der Button in der Toolbar explizit auftauchen muss:
imports:
- { resource: 'EXT:rte_ckeditor/Configuration/RTE/Processing.yaml' }
- { resource: 'EXT:rte_ckeditor/Configuration/RTE/Editor/Base.yaml' }
- { resource: 'EXT:rte_ckeditor/Configuration/RTE/Editor/Plugins.yaml' }
- { resource: 'EXT:sitepackage/Configuration/Yaml/Rte/Plugins/code-block.yaml' }
editor:
config:
contentsCss: 'EXT:sitepackage/Resources/Public/Frontend/Css/Backend/rte-styles.css'
style:
definitions:
- { name: 'Button', element: 'a', classes: [ 'btn' ] }
- { name: 'Small paragraph', element: 'p', classes: [ 'small' ] }
heading:
options:
- { model: 'paragraph', title: 'Paragraph' }
- { model: 'heading2', view: 'h2', title: 'Heading 2' }
- { model: 'heading3', view: 'h3', title: 'Heading 3' }
toolbar:
items:
- undo
- redo
- '|'
- bold
- italic
- '|'
- Link
- '|'
- codeBlock
- sourceEditing
- '-'
- heading
- styleAktiviert wird das Preset über die Page TSconfig:
RTE {
default.preset = sitepackage
}Mehr ist backend-seitig nicht zu tun. Im RTE gibt es nun einen Code-Block-Button mit Sprachauswahl. Welche Konfiguration sinnvoll ist, hängt wie damals vom Projekt und vom persönlichen Geschmack ab.
Das Frontend: Syntax-Highlighting mit PrismJS
CKEditor 5 speichert einen Code-Block als pre mit eingebettetem code-Element. Die Sprache steckt in der CSS-Klasse, das Label im Attribut data-language:
<pre data-language="YAML"><code class="language-yaml">editor:
config:
...</code></pre>Genau diese Klassen versteht PrismJS, der Syntax-Highlighter, den ich schon im alten Beitrag empfohlen habe. Ich binde ihn über npm ein und lade nur die Sprachen, die ich auch im RTE anbiete:
import Prism from 'prismjs';
import 'prismjs/components/prism-markup-templating';
import 'prismjs/components/prism-php';
import 'prismjs/components/prism-bash';
import 'prismjs/components/prism-apacheconf';
import 'prismjs/components/prism-yaml';
import 'prismjs/components/prism-typoscript';
import 'prismjs/components/prism-json';
import 'prismjs/components/prism-diff';
// Prism would otherwise highlight a second time on its own DOMContentLoaded hook.
Prism.manual = true;
document.querySelectorAll('pre code[class*="language-"]').forEach((el) => {
Prism.highlightElement(el);
});Zwei Details haben mir Zeit gekostet:
- Doppeltes Highlighting: Prism hängt sich standardmäßig selbst an
DOMContentLoaded. MitPrism.manual = truebestimme ich selbst, wann und wo gefärbt wird. - Sprachen mit Abhängigkeiten: PHP braucht
markup-templating, sonst fehlt die Komponente beim Laden. Deshalb steht der Import ganz oben.
Wer einen HTML-Cleaner oder Sanitizer im Einsatz hat, sollte außerdem prüfen, dass pre, code und die Attribute class und data-language den Weg ins Frontend überstehen. Bei mir behandelt der RTE-Cleaner Code-Blöcke getrennt, damit Einrückungen und Zeilenumbrüche erhalten bleiben.
Fazit
Die Idee ist dieselbe wie 2020, die Umsetzung ist es nicht: Statt eines Add-Ons von ckeditor.com gibt es jetzt ein ES-Modul, das über importModules geladen wird, und die gesamte Konfiguration folgt den Schlüsseln von CKEditor 5. Dafür ist das Ergebnis sauberer: Das HTML ist schlank, die Sprachauswahl steckt in einer einzigen YAML-Datei, und das Frontend braucht nur ein paar Zeilen JavaScript.




Comments (0)
No comments found!