Studio Developer Manual / Version 2406.0
Table Of ContentsWhile in Section 10.3.6, “Adapting Existing Configurations” you only got a rough sketch of how to make adjustments to existing configurations, you will now go step-by-step through a possible use case as an example: You will add the Highlight plugin available for CKEditor 5 to the default configuration that ships with CoreMedia Blueprint. To do so, you need to:
For older releases of CoreMedia CKEditor 5 Plugins you will find a section at the end called Compatibility.
See Also
In Section 10.3.12, “Providing New CKEditor 5 Configuration By Example” you will see, how to apply this customization only to one single dedicated content property.
Add the Plugin's Dependencies
The Highlight plugin available for CKEditor 5
is part of the @ckeditor/ckeditor5-highlight
package.
Thus, within @coremedia-blueprint/studio-client.ckeditor5
we add the corresponding
dependency:
pnpm add --save-dev "@ckeditor/ckeditor5-highlight@41.1.0"
Use Fixed Versions for CKEditor 5
In contrast to other dependencies, it is important always only using
fixed versions like @41.1.0
for CKEditor 5
dependencies. CKEditor 5 blocks any use of mixed package versions at
runtime.
You will notice that when opening a content form in CoreMedia Studio by a
missing CKEditor 5 instance and a console error of an uncaught
CKEditorError
with error code
ckeditor-duplicated-modules.
TypeScript Typings
Starting from v35.0.0 first CKEditor 5 packages were developed in
TypeScript. Prior to that, typings were only available via
DefinitelyTyped. As long as corresponding packages are not
migrated to TypeScript, you may want to install the corresponding
typings from DefinitelyTyped as
@types/ckeditor__ckeditor5-highlight
in this case.
Note, that typings at DefinitelyTyped are not always up-to-date. In
these cases one possible option is ignoring these errors with
TypeScript @ts-expect-error
annotation. This will also
automatically tell you at compile time, when typings got updated
accordingly.
Add the Plugin
Next, you add the plugin to ckeditorDefault.ts
in package
@coremedia-blueprint/studio-client.ckeditor5
and extend the toolbar accordingly:
import { Highlight } from "@ckeditor/ckeditor5-highlight"; /* ... */ const defaultToolbarItems = [ /* ... */ "superscript", "highlight", "removeFormat", /* ... */ ]; return ClassicEditor.create(domElement, { /* ... */ plugins: [ /* ... */ Highlight, /* ... */ ], }); /* ... */
Of course, you may also adapt the configuration of the plugin within
ckeditorDefault.ts
. For this example we stick to the default configuration
(which is applying no extra configuration).
Configure Data-Processing
As documented for the Highlight plugin, it uses
inline <mark>
element. As described in
Section 10.1.2, “Design Principle: HTML First” you
will not change that, neither for editing view nor for data view
(see
Section 10.1.1, “Glance at CKEditor 5 Architecture” to get to know
about the various layers). Instead, you have to adapt your data-processing,
as CoreMedia Rich Text 1.0 does not support the <mark>
element.
Extend the data-processing as follows:
import { replaceElementByElementAndClass } from "@coremedia/ckeditor5-coremedia-richtext"; /* ... */ return ClassicEditor.create(domElement, { /* ... */ plugins: [ /* ... */ Highlight, /* ... */ ], "coremedia:richtext": { rules: [ // Highlight plugin support. replaceElementByElementAndClass({ viewLocalName: "mark", dataLocalName: "span", // "mark" is the default here, derived from `viewLocalName`. Thus, // we may skip it here. dataReservedClass: "mark", }), ], }, }); /* ... */
As you see it uses a method
replaceElementByElementAndClass
available from
@coremedia/ckeditor5-coremedia-richtext
.
This method covers a typical use case when it comes to identifying a
representation of an HTML element in CoreMedia Rich Text 1.0: It maps the
<mark>
element to a corresponding representation as
<span>
with identifying class attribute value and vice versa.
Thus, if you highlighted some text with green background:
<mark class="marker-green">Highlight me</mark>
It will be transformed in CoreMedia Rich Text 1.0 data via data-processing to:
<span class="mark marker-green">Highlight me</span>
Note, that replaceElementByElementAndClass
is only
a shorthand function for a slightly more complex, but also more versatile,
mapping you could apply. To get to know more about possible configuration
options of the data-processing for CoreMedia Rich Text 1.0, have a look at
Section 10.2.10, “Rich Text Plugin”.
Adapt CSS Styling
Luckily CSS styles provided by CKEditor 5 and its plugins also directly
apply to CKEditor 5 instances in CoreMedia Studio. Thus, to support, for
example, the class marker-green
as sketched in the
previous step, there is nothing which needs to be done, to make the
default style work in CoreMedia Studio. But perhaps, the Green is not Green
enough? Just apply this SCSS snippet to your CoreMedia Studio styling:
.ck-content { .marker-green { background-color: #00ff00; } /* ... */ }
For details, have a look at Section 9.16.1, “Blueprint Studio Theme”.
Adapt Delivery
Of course, adapting CoreMedia Studio and the CKEditor 5 configuration is only half of the way to take. Depending on the technology you use for delivery, you now have to apply most likely the same mapping from:
<span class="mark marker-green">Highlight me</span>
to:
<mark class="marker-green">Highlight me</mark>
unless you are satisfied applying just some additional CSS-rules for the
<span>
element.
Thus, you may want to have a look at one of these manuals:
Section 4.3.4.1, “Rendering Markup” in Content Application Developer Manual
More specifically, in CoreMedia Blueprint, you may want to adapt
BlueprintRichtextFiltersConfiguration
providing a corresponding instance ofXMLFilter
. For this use-case you may extend the configuration of beanreservedClassToElementFilter
as shown in Example 10.19, “Adapting Bean reservedClassToElementFilter”.@Bean ReservedClassToElementFilter reservedClassToElementFilter() { return new ReservedClassToElementFilter(List.of( // <span class="mark"> -> <mark> ReservedClassToElementConfig.of("span", "mark", "mark"), /* … */ )); }
Example 10.19. Adapting Bean reservedClassToElementFilter
More specifically, in CoreMedia Blueprint, you may want to adapt
variables/_coremedia-richtext-1.0.scss
andpartials/_coremedia-richtext-1.0.scss
in@coremedia/brick-utils
as shown in Example 10.20, “Adapting variables/_coremedia-richtext-1.0.scss” and Example 10.21, “Adapting partials/_coremedia-richtext-1.0.scss”./* Same Colors as CKEditor 5 Highlight Plugin by default */ $cm-richtext-mark-marker-yellow: hsl(60, 97%, 73%) !default; $cm-richtext-mark-marker-green: hsl(120, 93%, 68%) !default; $cm-richtext-mark-marker-pink: hsl(345, 96%, 73%) !default; $cm-richtext-mark-marker-blue: hsl(201, 97%, 72%) !default; $cm-richtext-mark-pen-red: hsl(0, 85%, 49%) !default; $cm-richtext-mark-pen-green: hsl(112, 100%, 27%) !default;
Example 10.20. Adapting variables/_coremedia-richtext-1.0.scss
mark { &.marker-yellow { background-color: $cm-richtext-mark-marker-yellow; color: inherit; } &.marker-green { background-color: $cm-richtext-mark-marker-green; color: inherit; } &.marker-pink { background-color: $cm-richtext-mark-marker-pink; color: inherit; } &.marker-blue { background-color: $cm-richtext-mark-marker-blue; color: inherit; } &.pen-red { background-color: transparent; color: $cm-richtext-mark-pen-red; } &.pen-green { background-color: transparent; color: $cm-richtext-mark-pen-green; } }
Example 10.21. Adapting partials/_coremedia-richtext-1.0.scss
Chapter 5, Rich Text in Headless Server Manual
More specifically, in CoreMedia Blueprint, you may want to adapt the existing default view configuration in
headless-server-base
, first by declaring the reserved classmark
as shown in Example 10.22, “Adapting richtext/includes/classes.yml” and then by defining the mapping as shown in Example 10.23, “Adapting richtext/default.yml”.classes: - &inline_styles !!java.util.ArrayList # ... - &mark_style mark
Example 10.22. Adapting richtext/includes/classes.yml
handlerSets: text: &text_handlers - !Handler eventMatcher: !Matcher {qname: *span, classes: *inline_styles} outputHandler: !ElementWriter # ... elementTransformer: !ElementFromClass mapping: # ... *mark_style: mark
Example 10.23. Adapting richtext/default.yml
Compatibility
Configuration of coremedia:richtext
provides compatibility
modes for rule parsing. The default compatibility mode is
latest
. Find below enumerated compatibility modes and
the corresponding configuration.
- v10
Version 11 of CoreMedia CKEditor 5 Plugins introduced a new way to configure data-processing. While originally using object-style definitions in version 10, with rather limited DOM manipulation support, version 11 comes with array-style definition and rich DOM manipulation support.
You may switch back to the old behavior by setting
compatibility
tov10
in configuration. The example shown in Section “Configure Data-Processing” will look like given in the following example then:import { replaceByElementAndClassBackAndForth } from "@coremedia/ckeditor5-coremedia-richtext/src/compatibility/v10/rules/ReplaceBy"; /* ... */ return ClassicEditor.create(domElement, { /* ... */ plugins: [ /* ... */ Highlight, /* ... */ ], "coremedia:richtext": { compatibility: "v10", rules: { elements: { // Highlight Plugin Support mark: replaceByElementAndClassBackAndForth("mark", "span", "mark"), }, }, }, }); /* ... */