Zum Inhalt springen

Kurz vor Weihnachten habe ich diesen Blog endgültig auf TYPO3 v12 aktualisiert. Gerade rechtzeitig, um den Rechner bis zum neuen Jahr einmal komplett links liegen zu lassen.

Heute beschreibe ich ein paar ausgewählte Arbeiten, die für das Upgrade notwendig waren.

Einleitung

Beim Upgrade auf TYPO3 v12 gab es zwei größere Baustellen, die auf jede TYPO3-Installation zukommen werden:

  1. Die strukturelle Umstellung der Composer-Installation (Changelog #98484), bei der das altbekannte Verzeichnis typo3/ext/ entfällt.
  2. Der neue CKEditor 5 (Changelog #96874), der eine veränderte Konfiguration erfordert und mit alten Plugins inkompatibel ist.

Umstellung auf typo3/cms-composer-installers v4+

In einer Composer-Installation werden der TYPO3-Core sowie alle TYPO3-Extensions zukünftig im vendor-Verzeichnis abgelegt, so wie schon zuvor alle anderen PHP-Packages.

Das Thema ist nicht neu, sondern wurde bereits im Februar 2022 kommuniziert. Die Hintergründe findet ihr auf diesen beiden Seiten detailliert beschrieben:

Um das eigentliche Upgrade auf TYPO3 v12 zu erleichtern, könnt ihr die Verzeichnisstruktur bereits in TYPO3 v11 umstellen. Diese Vorgehensweise habe ich gewählt und kann sie euch nur ans Herz legen.

Diese beiden Befehle sind notwendig:

composer req typo3/cms-composer-installers:^4.0@rc
composer install

4.0@rc ist die einzige verfügbare Version, die in TYPO3 v11 für die neue Struktur sorgt. Nach Ausführung werden TYPO3 und alle TYPO3-Extensions in vendor/ installiert und Symlinks für öffentliche Extension-Dateien in public/_assets/ erstellt.
Die alten Verzeichnisse im public-Verzeichnis (typo3/sysext/ und typo3conf/ext/) müsst ihr manuell entfernen.

Äußerst hilfreich ist der Blogbeitrag von Chris Müller, in dem er die notwendigen Migrationen in TypoScript, CSS, Fluid & Co. beschrieben hat: https://brot.krue.ml/migration-typo3-composer-cms-installers-version-4/

Middleware für das Web App Manifest

Auch in meinem Blog gab es einige Pfade, die adaptiert werden mussten. Mit Chris' Anleitung ließen sie sich einfach migrieren.

Etwas aufwändiger war nur das Webmanifest: in dieser Datei sind Pfade zu Favicons definiert. Den gehashten Teil der Dateipfade wollte ich dort aber nicht hartkodiert hinterlegen.

{
  "background_color": "#ffffff",
  "display": "browser",
  "icons": [
    {
      "src": "/_assets/6c1b7cf48a271482dd95e90ed93afd24/Images/Favicons/android-chrome-192x192.png",
      "type": "image/png",
      "sizes": "192x192"
    },
    {
      "src": "/_assets/6c1b7cf48a271482dd95e90ed93afd24/Images/Favicons/android-chrome-512x512.png",
      "type": "image/png",
      "sizes": "512x512"
    }
  ],
  "name": "sebkln.de - Sebastian Klein",
  "short_name": "sebkln.de",
  "theme_color": "#eb4a47"
}

Kevin Appelt hat in TYPO3 Slack netterweise eine Middleware-Lösung geteilt, mit der sich ein Webmanifest in TYPO3 v12 bereitstellen lässt. Die dynamischen Werte (Theme Color, Favicon-Pfade, …) werden per Site Configuration gesetzt, so dass auch Multi-Domain-Installationen unterstützt werden.

Für meinen Einsatzzweck habe ich die Middleware etwas adaptiert:
https://gist.github.com/sebkln/bfc36c0a3fea5d13c3ae8ff710b4c136
Ihr könnt sie einfach im Sitepackage eures Projekts ergänzen.

Upgrade auf CKEditor 5

Der CKEditor 4 hatte sein EOL im Juni 2023, dementsprechend setzt TYPO3 v12 auf den aktuellen Nachfolger CKEditor 5.

Problematisch bei Upgrades ist, dass sich die Software-Architektur in diesem RTE grundlegend geändert hat. Die alten Plugins sind alle nicht mehr kompatibel und müssen teils mit großem Aufwand neu geschrieben werden.

Stolpersteine und Kinderkrankheiten

Zuweisung multipler CSS-Klassen

Im RTE lassen sich Textinhalten Gestaltungsstile zuweisen. Manchmal soll ein HTML-Element dabei mehrere CSS-Klassen erhalten. Im CKEditor 4 war dies wie folgt möglich:

editor:
  config:
    stylesSet:
      - { name: 'Large button', element: 'a', attributes: { 'class': 'c-btn c-btn--large c-btn--primary' } }

In TYPO3 v12 hat sich auch die YAML-Konfiguration geändert; im Changelog ist dies dokumentiert. Was dabei nicht offensichtlich ist: mehrere Klassen müssen jetzt kommasepariert notiert werden.

editor:
  config:
    style:
      definitions:
        - { name: 'Large button', element: 'a', classes: ['c-btn', 'c-btn--large', 'c-btn--primary'] }

Listen-Styles

Mit CKEditor 5 war es in TYPO3 v12 nicht mehr möglich, CSS-Klassen bei Listen (<ul>, <ol>) zu setzen – eine oft genutzte Lösung, um Auflistungen im Text besonders zu stylen.

Tatsächlich gibt es für den CKEditor 5 zwei Listen-Plugins: List und DocumentList. Während TYPO3 v12 anfangs das List-Plugin mitlieferte, unterstützt aber nur DocumentList das Styling von Listenelementen.

Ab Version 12.4.6 wird in TYPO3 daher jetzt das DocumentList-Plugin verwendet. Das Listen-Styling ist nun möglich:

editor:
  config:
    style:
      definitions:
        - { name: 'Checkmark list', element: 'ul', classes: ['list--checkmark'] }

Das Problem betraf nicht nur TYPO3, auch in Drupal ist fehlendes Listen-Styling im CKEditor 5 ein Thema.

Im CKEditor-Projekt hat man sich der Thematik ebenfalls angenommen und gerade eine Änderung gemergt: List wird zu LegacyList umbenannt; DocumentList wird das neue List-Plugin.

Neues CKEditor-Plugin für wordbreak-Elemente

Mit dem <wbr>-Element setze ich bedingte Zeilenumbrüche in URLs und Verzeichnispfaden. Für den CKEditor 5 musste ich daher mein linebreak-Plugin durch eine neue Lösung ersetzen.

Ein einzelnes HTML-Element im CKEditor zu ergänzen, war zur Einarbeitung in dessen Architektur zumindest eine dankbare, da überschaubare Aufgabe. Daraus entwickelte sich letztlich eine neue TYPO3-Extension, die dieses Element im CKEditor 5 benutzerfreundlich bereitstellt.

Bei der Pflege dieses Artikel habe ich dann festgestellt, dass das im RTE eingesetzte <wbr>-Element die umschließenden Inline-Elemente zerteilt. Daher habe ich eine neue Version der Extension herausgebracht, die das Problem behebt.

CKEditor-Plugin für Code-Snippets

Zur Pflege meiner Code-Snippets greife ich teilweise auf die Extension "beautyofcode" zurück (Danke an Felix Nagel!), teils bislang auf das "Code Snippets"-Plugin von CKEditor 4.

Für den CKEditor 5 liefert der TYPO3-Core das Feature "Code blocks" direkt mit. Aber: es wird nicht per Default geladen! Wer in der YAML-Konfiguration einfach codeBlock in der Toolbar ergänzt, erhält in der Browserkonsole die Fehlermeldung:

toolbarview-item-unavailable {item: 'codeBlock'}

Verfügbar sind die Code Blocks (und weitere CKEditor-Features) erst, wenn man das entsprechende Modul importiert. Die Konfiguration sieht dann wie folgt aus:

editor:
  config:
    importModules:
      - { 'module': '@ckeditor/ckeditor5-code-block', 'exports': ['CodeBlock'] }

    toolbar:
      items:
        - codeBlock
        # etc.

    codeBlock:
      languages:
        - { language: 'html', label: 'HTML' }
        - { language: 'css', label: 'CSS' }
        - { language: 'yaml', label: 'YAML' }
        - { language: 'javascript', label: 'JavaScript' }
        - { language: 'json', label: 'JSON' }
        - { language: 'php', label: 'PHP' }
        - { language: 'sql', label: 'SQL' }
        # etc.

Mit den definierten Sprachen könnt ihr im Frontend dann Syntax-Highlighting einrichten, beispielsweise mit Prism.

Gefunden habe ich diese Lösung über TYPO3 Slack in einem alten Patch.

div-Wrapper in CKEditor 5

Vor allem in den Tutorials verwende ich Hinweiskästen (Alerts), um gewisse Inhalte hervorzuheben. Die Alert-Klassen werden oft einem einzelnen Absatz zugewiesen. Teilweise nutze ich aber auch einen <div>-Wrapper, etwa um im Hinweiskasten eine kurze Auflistung zu ergänzen.

Der CKEditor 5 unterstützt sowohl Absätze als auch <div>-Elemente als Block-Format. Dabei lassen sich die beiden HTML-Elemente aber nur tauschen. Eine Verschachtelung ist per Default nicht vorgesehen – Absätze lassen sich nicht innerhalb von divs positionieren.

Um das für meine Zwecke doch zu erreichen, musste ich ein weiteres Mini-Plugin schreiben. Das ist noch nicht redakteursfreundlich, erlaubt mir aber zumindest die fortgesetzte Nutzung der bisherigen Alerts und damit letztlich das Upgrade auf TYPO3 v12.

Wer den Lösungsansatz benötigt:
https://gist.github.com/sebkln/5919ef1fcf2008f3f667b0a04468e7c8

Wenn ich mal Zeit finde, versuche ich mich an einer besseren Version des Plugins, mit der ein div-Wrapper benutzerfreundlich eingefügt werden kann und bei dem die verfügbaren CSS-Klassen per YAML definiert werden können.

Weitere notwendige Arbeiten

Nutzung bestimmter ViewHelper außerhalb von Extbase

Seit TYPO3 v12 besitzen ViewHelper nicht mehr automatisch einen Extbase-Request (Changelog #98377). Das kann verschiedene Probleme in bestehenden Installationen verursachen.

In meinem Fall war das FLUIDTEMPLATE-Objekt für meine Website-Templates betroffen. Hier fehlte die Angabe des Extension-Namens im Translate- sowie Uri.Resource-ViewHelper:

<a class="c-nav-social__link" href="https://github.com/sebkln"
   title="{f:translate(key:'website.anchor.social.github')}">
    <svg class="c-nav-social__icon">
        <use xlink:href="{f:uri.resource(path: 'Images/Icons/icon-sprite.svg#icon--github')}"></use>
    </svg>
    <span class="c-nav-social__title">/sebkln</span>
</a>

Im Frontend folgt dann eine RuntimeException, in der die Lösung bereits genannt wird:

ViewHelper f:uri.resource needs an Extbase Request object to resolve
extension name for given path "Images/Icons/icon-sprite.svg#icon--github".
If not in Extbase context, either set argument "extensionName",
or (better) use the standard EXT: syntax for path attribute like
'path="EXT:indexed_search/Resources/Public/Icons/Extension.svg"'.

Dies wäre daher eine mögliche Anpassung:

<a class="c-nav-social__link" href="https://github.com/sebkln"
   title="{f:translate(key:'LLL:EXT:sitepackage/Resources/Private/Language/locallang.xlf:website.anchor.social.github')}">
    <svg class="c-nav-social__icon">
        <use xlink:href="{f:uri.resource(path: 'Images/Icons/icon-sprite.svg#icon--github', extensionName: 'sitepackage')}"></use>
    </svg>
    <span class="c-nav-social__title">/sebkln</span>
</a>

Fazit

Der Aufwand beim Wechsel zu CKEditor 5 ist nicht zu unterschätzen. Für einige Features müssen neue Lösungen gefunden werden, im Zweifel durch Eigenentwicklung. Ich freue mich, dass der neue Editor auch Dinge verbessert – beispielsweise die Trennung zwischen der Editoransicht und den in der Datenbank gespeicherten Daten. Die Einarbeitung in die Architektur und API erfordert allerdings Zeit.

Ausblick

Mit TYPO3 v12 kann ich meinen Blog wieder als Versuchsballon für neue Features nutzen. Ganz oben auf meiner Liste: das Handling der Content-Security-Policy (Changelog #99499).

Per TypoScript ist dieser HTTP Security Header seit 2019 auf meiner Website gesetzt. Zur gleichen Zeit hatte ich ein Tutorial darüber verfasst. Dass TYPO3 dies nun als prominente Core-Funktionalität bereitstellt, unterstreicht den Nutzen und die Relevanz dieses Headers.

Die bestehenden Direktiven kann ich nun in den neuen Policy Builder überführen und weitere Funktionen am praktischen Beispiel austesten.
Und am Ende springt dabei sicherlich wieder ein Tutorial heraus.

Zur News-Übersicht