The extension rte_ckeditor provides a rich text editor (RTE) by integrating
CKEditor 5 into TYPO3.
This makes it possible to
use the features of CKEditor when editing rich text fields in the TYPO3
backend or frontend (if frontend editing is used). Rich text fields are
fields which may contain text with markup, for example for adding a style
such as bold, using lists or enumerations, headlines or adding links.
Editing a textfield in the backend with rte_ckeditor.
CKEditor is a WYSIWYG editor mostly written
in JavaScript, and is used in many systems due to its flexibility. There are hundreds
of free open-source plugins for CKEditor to enhance the editing experience.
History
Before TYPO3 v8, a custom fork of "HtmlArea", another open-source WYSIWYG editor
was shipped with TYPO3 Core in a separate extension rtehtmlarea. "HtmlArea"
isn't supported anymore since TYPO3 v9 LTS. You have to migrate to rte_ckeditor
when upgrading from previous TYPO3 versions (=< v8).
CKEditor 4 was officially integrated as the default rich text editor in TYPO3 v8 LTS,
within an extension called rte_ckeditor.
With TYPO3 v12, CKEditor 4 has been updated to CKEditor 5.
Features
The extension rte_ckeditor incorporates the features of CKEditor and adds
additional functionality, configuration presets and plugins.
Some examples of features:
Configurable via YAML files
Configuration presets (minimal, default, full) for TYPO3
Toolbar customization
Link functionality: integration with TYPO3 link wizard
Wordcount: plugin that counts and shows the chars/words/paragraphs in
the footer of the editor. It also supports limiting the max. amount of chars/words.
General Concepts
User interfaces
CKEditor has multiple user interfaces, of which TYPO3 uses the following:
Classic
Editing is done within a fixed container.
It is possible to customize how the editor behaves and how the content is styled.
Used in the TYPO3 Backend.
Inline
All formatting styles are reused from the surrounding HTML and CSS styles,
allowing for a seamless frontend editing.
Used by TYPO3’s frontend_editing,
which can be found on GitHub.
frontend_editing is not covered in this document.
For a demonstration of all user interfaces,
see the CKEditor demo.
Here we explain, how to modify the existing configuration in a few simple steps.
View Existing Configuration
To familiarize yourself with the configuration, look at the existing configuration
in your TYPO3 website:
To view the existing RTE presets in the "Global Configuration", go to
System > Configuration in the backend, choose
$GLOBALS['TYPO3_CONF_VARS'] (Global Configuration) and select
RTE:
Global Configuration: RTE > Presets
By default, TYPO3 is shipped with three configuration presets:
default
full
minimal
Minimal Example
Here is a very minimal example of changing the default configuration. All
configuration is done in a custom sitepackage extension, see also
Use a Sitepackage extension.
Override the configuration preset "default" by adding this in <my_extension>/ext_localconf.php
(replace my_extension with your extension key):
We explain the example Minimal.yaml from the Core:
EXT:rte_ckeditor/Configuration/RTE/Minimal.yaml
# Load default processing optionsimports:-{resource:'EXT:rte_ckeditor/Configuration/RTE/Processing.yaml'}-{resource:'EXT:rte_ckeditor/Configuration/RTE/Editor/Base.yaml'}# Minimal configuration for the editoreditor:config:toolbar:items:-bold-italic-'|'-clipboard-undo-redo
Copied!
line #2
Imports existing files to make basic parts reusable and improve structure of configuration
Just in case you are not familiar with how to configure TYPO3, we will
give you a very brief introduction. Otherwise, you can safely
skip this part and continue reading
Configuration Concepts.
We only cover configuration methods that are used to configure rte_ckeditor.
Page TSconfig
We recommend you to put all configurations for the preset in the
YAML configuration. However, it is still possible to
override these settings through the page TSconfig.
This is done directly in the file. The YAML file should be included in a
sitepackage extension, see Use a Sitepackage extension.
CKEditor related TCA configuration
The table configuration array is used to configure database fields and how they will behave in the
backend when edited. It is for example used to define that tt_content.bodytext should be edited
with a rich text editor.
This must be done in an extension in Configuration/TCA. Usually this is done within a custom sitepackage
extension, see Use a Sitepackage extension.
How to view settings
You can view TCA in the backend:
System > Configuration > $GLOBAL['TCA'] (Table configuration array).
For example, look at tt_content > columns > bodytext.
However, you will
find that neither enableRichtext, nor richtextConfiguration is set here. They
are configured in tt_content > types for various content types, for example
look at tt_content > types > text > columnsOverrides.
TCA: tt_content > types > text > columnsOverrides > bodytext
Configuration Concepts
Configuration Overview
The main principles of configuring a Rich Text Editor in TYPO3
apply to editing with any Rich Text Editor (rte_ckeditor, ...).
Some of the functionality (for example the RTE transformations) is
embedded in the TYPO3 core and not specific to rte_ckeditor.
There are three main parts relevant for rich text editing with TYPO3:
Editor configuration
This covers how the actual editor (in this case CKEditor) should behave,
what buttons should be shown, what options are available.
RTE transformations
This defines how the information is processed when saved from the Rich Text Editor to the database.
And when loaded from the database into the Rich Text Editor.
Frontend output configuration
The information fetched from the database may need to be processed for the frontend.
The configuration of the frontend output is configured via TypoScript.
This section mainly covers editor configuration and RTE transformations, as for
TypoScript the TypoScript reference handles output of HTML content and
has everything preset (see parseFunc).
TYPO3 is using a custom YAML API for handling YAML
in TYPO3 based on the Symfony YAML package. Therefore environment variables
can be used.
YAML Basics
YAML is case sensitive
Indenting level reflects hierarchy level and indenting must be used consistently
(indent with 2 spaces in rte_ckeditor configuration).
Comments begin with a #.
White space is important, use a space after :.
This is a dictionary (associative array):
key1:valuekey2:value
Copied!
A dictionary can be nested, for example:
key1:key1-2:value
Copied!
This is a list:
-listitem1-listitem2
Copied!
A dictionary can be combined with a list:
key:key2:-item1-item2
Copied!
Configuration Presets
Presets are the heart of having custom configuration per record type, or
page area. A preset consists of a name and a reference to the location
of a YAML file.
TYPO3 ships with three RTE presets, “default”, “minimal” and “full”. The
"default" configuration is active by default.
It is possible for extensions to ship their own preset like “news”, or “site_xyz”.
Registration of a preset happens within system/config.php,
system/additional.php or within
ext_localconf.php of an extension:
TYPO3 uses the “default” preset for all Rich-Text-Element fields. To use
a different preset throughout an installation or a branch of the website,
see Overriding Configuration via page TSconfig.
Selecting a specific preset for bullet lists can be done via TCA
configuration of a field. The following example shows the TCA configuration
for the sys_news database table, which can be found in
EXT:core/Configuration/TCA/sys_news.php.
Enabling Rich Text Parsing itself is done via enableRichtext,
and a specific configuration
can be set via richtextConfiguration, setting it to for example
“news”.
Overriding Configuration via page TSconfig
Instead of overriding all TCA fields to use a custom preset, it is possible
to override this information via page TSconfig.
The option
RTE.default.preset = news
can also be set on a per-field
and per-type basis:
This sets the "minimal" preset for all bodytext fields of content elements.
line #4
This sets the "bullets" preset for all bodytext fields of content elements,
with Content Type “Bullet list” (CType=bullets).
Of course, any other specific option set via YAML can be overridden via Page TSconfig as well:
Specific options set via YAML can be overridden via page TSconfig as well - but
be aware that boolean values can not be set, and arrays are not merged but
overridden.
EXT:my_sitepackage/Configuration/page.tsconfig
# Restrict format_tags to h2 in bodytext field of content elements
RTE.config.tt_content.bodytext.editor.config.format_tags = h2
Copied!
The loading order for configuration is:
preset defined for a specific field via PageTS
richtextConfiguration defined for a specific field via TCA
general preset defined via page TSconfig
default
For more examples, see RTE in "TSconfig Reference".
RTE Transformations
Transformations are directives for parsing HTML markup. They are executed by the
TYPO3 Core every time a RTE-based field is saved to the TYPO3 database or fetched
from the database for the Rich Text Editor to render. This way, there are always
two ways / two transformations applied.
There are several advantages for transformations, the most prominent reason is to
not inject bad HTML code into the database which in turn would be used for output.
Transformations from the RTE towards the database can filter out HTML tags or attributes.
Back in the very old days of TYPO3, there was an RTE which only worked inside Microsoft
Internet Explorer 4 (within the system extension “rte”). All other editors of TYPO3 had
to write HTML by hand, which was very complicated with all the table-based layouts available.
Links were not set with a
<a>
tag, but with a so-called
<typolink 23,13 _blank>
tag. Further tags were
<typolist>
and
<typohead>
, which were stored in the database
1:1. Since RTEs did not understand these special tags, they had to transform these special tags into
valid HTML tags. Additionally, TYPO3 did not store regular
<p>
or
<div>
tags but
treated every line without a surrounding HTML block element as
<p>
tag. The frontend rendering
then added <p> tags for each line when parsing (see below).
Transformations were later used to allow
<em>
/
<strong>
tags instead of
<b>
/
<i>
tags, while staying backwards-compatible.
A lot of transformation options have been dropped for TYPO3 v8, and the default configuration
for these transformations acts as a solid base. CKEditor itself includes features that work as
another security layer for disallowing injecting of certain HTML tags in the database.
For TYPO3 v8, the
<typolink>
tag was migrated to proper
<a>
tags with a special
<a href="t3://page?id=23">
syntax when linking to pages to ensure HTML valid output.
Additionally, all records that are edited and stored to the database now contain proper
<p> tags, and transformations for paragraph tags are only applied when not set yet.
Transformations for invalid links and images (still available in HtmlArea) are still in place.
Most logic related to transformations can be found within
\TYPO3\CMS\Core\Html\RteHtmlParser
.
Transformations vs. CKEditor’s Advanced Content Filter
TYPO3’s HtmlParser transformations were used to transform readable semi-HTML
code to a full-blown HTML rendering ready for the RTE and vice versa. Since
TYPO3 v8, magically adding
<p>
tags or transforming
<typolink>
tags is not necessary anymore, which leaves transformations almost obsolete.
However, they can act as an extra fallback layer of security to filter out
disallowed tags when saving. TYPO3 v8 configuration ships with a generic
transformation configuration, which is mainly based on legacy functionality
shipped with TYPO3 nowadays.
However, CKEditor comes with a separate strategy of allowing which HTML tags
and attributes are allowed, and can be configured on an editor-level.
This configuration option is called “allowedContent”, the feature itself is
named Advanced Content Filter
(ACF).
Activating CKEditor’s table plugin allows to add
<table>
,
<tr>
tags etc. Enabling the link picker enables the usage of
<a>
tags. CKEditor
cleans content right away which was e.g. copy-pasted from MS Word and does not
match the allowed tags.
Frontend Output Configuration
Mostly due to historical reasons, the frontend output added
<p>
tags to each
line which is not wrapped in HTML. Additionally the
<typolink>
tag was replaced
by
<a>
tags and checked if e.g. if a link was set to a specific page within
TYPO3 is actually accessible for this specific visitor.
The latter part is still necessary, so the
<a href="t3://page?id23">
HTML snippet
is replaced by a speaking URL which the power of typolink will still take care of.
There are, of course, more options to it, like default “target” attributes for
external links or spam-protecting links to email addresses, which all happens within the
typolink logic, the master for generating a link in the TYPO3 Frontend rendering process.
TypoScript
As with every content that is rendered via TYPO3, this processing for the frontend
output of Rich-Text-Editing fields is done via TypoScript, more specifically within
the stdWrap property parseFunc. With Fluid Styled Content and CSS Styled
Content comes
lib.parseFunc
and
lib.parseFunc_RTE
which add
support for parsing
<a>
and
<link>
tags and dumping them into the typolink
functionality. The shipped TypoScript code looks like this:
lib.parseFunc.tags {
a = TEXT
a {
current = 1
typolink {
parameter.data = parameters:href
title.data = parameters:title
ATagParams.data = parameters:allParams
target.data = parameters:target
extTarget = {$styles.content.links.extTarget}
extTarget.override.data = parameters:target
}
}
}
Copied!
If you already use Fluid Styled Content and CSS Styled Content and
you haven’t touched that area of TypoScript yet, you’re good to go
by including the TypoScript file.
Fluid
Outputting the contents of a RTE-enabled database field within Fluid can
be achieved by adding
{record.myfield -> f:format.html()}
which in turn calls
stdWrap.parseFunc
with
lib.parseFunc_RTE
thus applying the same logic. Just ensure that the
lib.parseFunc_RTE
functionality is available.
You can check if this TypoScript snippet is loaded by using
Web > TypoScript and use the TypoScript Tree (Setup)
to see if
lib.parseFunc_RTE
is filled.
Important
Take care of where you add opening and closing tags, if you don't use the fluid inline notation.
If they are on an own line, the rendered output includes empty paragraphs at beginning and end.
Configuration Best Practices
Use a Sitepackage extension
It is generally recommended to use a sitepackage extension to
customize a TYPO3 website. The sitepackage contains configuration files
for that site.
See the TYPO3 Sitepackage Tutorial on how
to create a sitepackage. We assume here your sitepackage extension has the
key my_sitepackage.
The YAML preset files should be kept in folder
EXT:my_sitepackage/Configuration/RTE/.
RTE configurations need to be registered in your sitepackages
ext_localconf.php:
It is possible but not recommended to define this setting in the projects
system/settings.php or system/additional.php
Use TYPO3’s Core Default.yaml as boilerplate
It is recommended to start by copying the file
typo3/sysext/rte_ckeditor/Configuration/RTE/Default.yaml into your
sitepackage to the file
EXT:my_sitepackage/Configuration/RTE/MyConfiguration.yaml.
Check TYPO3's Core Full.yaml to gain insight into a more extensive configuration
This preset shows more configured options and plugins. It is not intended for real use.
It acts as an example.
If you started out by copying this extensions
Default.yaml as boilerplate the imports
should already be there.
The include files are already split up so the processing transformations can
just be included or even completely disabled (by removing the line for importing).
Attention
Please be aware that removing the Processing.yaml removes
security measures. In that case you have to take care of keeping the ckeditor
safe yourself.
Configuration Examples
How do I use a different preset?
Instead of using the default "default" preset, you can change this, for example
to "full", using page TSconfig:
EXT:my_sitepackage/Configuration/page.tsconfig
RTE.default.preset = full
Copied!
Of course, the preset must already exist, or you must define it. rte_ckeditor
ships with presets "minimal", "default" and "full".
Additionally, you can set specific presets for specific types of textfields.
For example to use preset "full" for the field "bodytext" of all content elements:
EXT:my_sitepackage/Configuration/page.tsconfig
RTE.config.tt_content.bodytext.preset = full
Copied!
To use preset "minimal" for the field "bodytext" of only content elements
with ctype="text":
# Import basic configurationimports:-{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"}# Add configuration for the editor# For complete documentation see http://docs.ckeditor.com/#!/api/CKEDITOR.configeditor:config:# Include custom CSScontentsCss:-"EXT:my_extension/Resources/Public/Css/rte.css"
The toolbar can be customized individually by configuring required toolbar
items in the YAML configuration. The following configuration shows the toolbar
configuration of the minimal editor setup included in file
EXT:rte_ckeditor/Configuration/RTE/Minimal.yaml:
# Minimal configuration for the editoreditor:config:toolbar:items:-bold-italic-'|'-clipboard-undo-redo
Copied!
The
'|'
can be used as a separator between groups of toolbar items.
Additional configuration options are available in the official CKEditor 5
Toolbar documentation
Grouping toolbar items in drop-downs
To save space in the toolbar or to arrange the features thematically, it is
possible to group several items into a dropdown as shown in the following
example:
# Minimal configuration for the editoreditor:config:toolbar:items:-bold-italic-{label:'Additional',icon:'threeVerticalDots',items:['specialCharacters','horizontalLine']}
Copied!
How do I allow a specific tag?
Allowed content in CKEditor 5 is to be configured via the General HTML Support
plugin option
config.htmlSupport
.
# Allow the <iframe> tag with all attributes, all classes and all styles,# as well as demonstrating class restrictions to the <i> tageditor:config:htmlSupport:# if you want to allow that an inline tag like `<i>` can also be emptyallowEmpty:['i']allow:-{name:'iframe',attributes:true,classes:true,styles:true}# multiple definitions for the same tag name are possible-{name:'i',classes:['fa-brands','fa-typo3']}# allows any repetitive class name, that starts with `fa-`# (the regular expression has to be defined in `pattern`)-{name:'i',classes:{pattern:'^((fa-[^\h]+)(\h+|$))+'}}
Copied!
Note
config.htmlSupport
only applies to elements that are "known" to
CKEditor 5. Tags like
<svg>
or custom elements like
<my-element>
are not configurable this way as
htmlSupport.allow
can only handle
elements that are defined in the CKEditor 5 schema.
How do I configure the font plugin?
New in version 12.4.12
In order to use the font plugin, the RTE configuration needs to be adapted:
editor:config:toolbar:items:# add button to select font family-fontFamily# add button to select font size-fontSize# add button to select font color-fontColor# add button to select font background color-fontBackgroundColorfontColor:colors:-{label:'Orange',color:'#ff8700'}-{label:'Blue',color:'#0080c9'}-{label:'Green',color:'#209d44'}fontBackgroundColor:colors:-{label:'Stage orange light',color:'#fab85c'}fontFamily:options:-'default'-'Arial, sans-serif'fontSize:options:-'default'-18-21importModules:-{'module':'@ckeditor/ckeditor5-font','exports':['Font']}
editor:config:toolbar:items:# add button to enable fullscreen view-fullscreenfullscreen:menuBar:# Disable menu bar in fullscreen viewisVisible:falseimportModules:-{module:'@ckeditor/ckeditor5-fullscreen',exports:['Fullscreen']}
The TYPO3 Link Browser can be utilized in both the RTE and for FormEngine TCA fields. The latter
is configured through TCA settings, and the RTE editor itself is configured via the central
YAML file.
With CKEditor 5 the plugin architecture has changed and CKEditor 4 plugins
are not compatible with CKEditor 5. It is advised to read the
CKEditor 4 to 5 migration
to understand the conceptual changes, also related to plugins.
Writing a custom plugin for CKEditor 5 can be done in TypeScript or JavaScript,
using the CKEditor 5 plugin system.
In this example, we integrate a simple timestamp plugin to CKEditor 5.
Make sure to replace <my_extension> with your extension key.
import { Plugin } from'@ckeditor/ckeditor5-core';
import { ButtonView } from'@ckeditor/ckeditor5-ui';
exportclassTimestampextendsPlugin{
static pluginName = 'Timestamp';
init() {
const editor = this.editor;
// The button must be registered among the UI components of the editor// to be displayed in the toolbar.
editor.ui.componentFactory.add(Timestamp.pluginName, () => {
// The button will be an instance of ButtonView.const button = new ButtonView();
button.set({
label: 'Timestamp',
withText: true
});
// Execute a callback function when the button is clicked
button.on('execute', () => {
const now = newDate();
// Change the model using the model writer
editor.model.change(writer => {
// Insert the text at the user's current position
editor.model.insertContent(writer.createText(now.toString()));
});
});
return button;
});
}
}
Configuring transformations kicks in the RteHtmlParser API of TYPO3, to
only allow certain HTML tags and attributes when saving the database or
leaving the database to the RTE. However, defining transformations towards
RTE is not really necessary anymore. Defining more strict processing options
when storing content in the database also needs to be ensured that CKEditor
allows this functionality too.
This configuration option was previously built within RTE.proc and can
still be overridden via Page TSconfig. Everything defined via “processing”
is available in RTE.proc and triggers RteHtmlParser options.
editor
Editor contains all RTE-specific options. All CKEditor-specific options, which one
could imagine are available under “config” property and handed over to CKEditor’s
instance-specific config array.
All other sub-properties are usually handled via TYPO3 and then injected in the
CKEditor instance at runtime. This is useful for registering extra plugins, like
the TYPO3 core does with a custom typo3-link.js plugin, or adding
third-party plugins like handling images.
Some configuration options from the official CKEditor 5 documentation
do not apply to TYPO3, since they are related to specific plugins
(for example: CKBox, CloudServices) which are not bundled in TYPO3's
CKEditor build.
editor.config.language
defines the editor’s UI language, and is dynamically calculated (if not set otherwise) by
the backend users’ preference.
editor.config.contentsLanguage
defines the language of the data, which is fetched from the
sys_language information, but can be overridden by this option as well.
For referencing files, TYPO3's internal "EXT:" syntax can be used, for
using language labels, TYPO3's "LLL:" language functionality can be used.
editor.config.contentsCss
defines the location of one or multiple CSS file(s) of the editor, containing the style
definitions that will be applied to the backend editor RTE element.
Since the CKEditor element is rendered within the page content of the TYPO3 backend
(and not in an iframe or web-component), all CSS declarations in that file
must refer to an actual element hierarchy ending like
#data_tt_content__2687__bodytext_ckeditor5 .ck-content
. To achieve this,
TYPO3 automatically parses the contents of the CSS file with a process called
"auto-prefixing" (via JavaScript, client-side) and converts all references to
that "virtual" root hierarchy.
A CSS declaration like
:root { background-color: green }
gets turned into
#data_tt_content__2687__bodytext_ckeditor5 .ck-content { background-color: green; }
.
You can use a
:root { ... }
declaration, for example to reset
relative/absolute sizes to ensure the CKEditor area being compatible to your
usual frontend CSS. Also using body {...} is viable.
Note
Referenced CSS stylesheets need to
be downloadable via
fetch()
in order for the JavaScript-based
prefixing to work.
Note
Also note that the generated CSS file is cached by your browser. If you change
the contents of your CSS file, be sure to either reload the browser cache,
or use a directive like
editor.config.contentsCss: "EXT:my_sitepackage/Resources/Public/Css/contents.css?v=2"
where you change the ?v= URI string after any file modification to enforce
requesting an updated version of the file.
editor.config.heading
Defines headings available in the heading dropdown.
There are more configuration options that can be defined in the YAML file of an RTE preset
related to the Link Browser, when managing hyperlinks inside the CKEditor.
Note that the Link Browser can also be displayed based on FormEngine TCA definitions. These
use similar configuration, but from their TCA PHP configuration, and unrelated to the YAML
definition.
Note that the available CSS class here must also be part of the
buttons.link.properties.class.allowedClasses definition.
buttons.link
This structure defines both global options as well as Link Type-specific
options:
buttons.link.options.removeItems
Can be set to exclude certain Link Types:
MyCKPreset.yaml
buttons:link:options:removeItems:'telephone'
Copied!
buttons.link.relAttribute.enabled
If the allowedOptions string list contains rel for setting relation
attributes, this option must also be enabled:
MyCKPreset.yaml
buttons:link:relAttribute:enabled:true
Copied!
buttons.link.queryParametersSelector.enabled
If the allowedOptions string list contains params for setting URI argument
attributes, this option must also be enabled:
MyCKPreset.yaml
buttons:link:queryParametersSelector:enabled:true
Copied!
buttons.link.targetSelector.disabled
If the allowedOptions string list contains target, a dropdown is displayed by
default. If you want to hide it, you must set this option to true:
MyCKPreset.yaml
buttons:link:targetSelector:disabled:true
Copied!
buttons.link.properties.class.required
A CSS class selection can be forced, so that it may not be empty:
MyCKPreset.yaml
buttons:link:properties:class:required:true
Copied!
buttons.link.properties.class.allowedClasses
This is the most vital CSS class selection list, based on a comma-separated
string naming all CSS classes that are allowed. Default CSS classes per Link Type
can only be selected, if they are part of this list.
The names of the CSS classes can be adjusted via the classes top-level configuration
hierarchy (see below)
Note that the CSS class listed here must also be contained in
buttons.link.properties.class.allowedClasses.
classes.[CssClassName]
The list of CSS classes defined in buttons.link.properties.class.allowedClasses
can set a custom label as well as a styling the select option. Note that styling
select options does not work in every browser, and is not suggested to use.
The name of the structure key must match the CSS class name, with a sub-structure
defining name (the actual label) and value (the possible CSS styling of the option
inside the dropdown):
MyCKPreset.yaml
classes:globalCss1:name:"A Label for globalCss1"value:"color: red"customEmailCssClass:name:"An email-specific class for VIPs"
Copied!
Page TSconfig
We recommend you to put all configurations for the preset in the
YAML configuration. However, it is still possible to
override these settings through the page TSconfig.