guidePlugin customization

The software described herein is deprecated and is no longer updated. We recommend using CKEditor 5 with collaboration features instead.

Visit the collaboration samples repository for practical solutions. Also, visit the Online builder if you would rather prepare a custom CKEditor 5 build with collaboration enabled.

Letters allows you to change the list of plugins it uses. However, it is not possible to do it using the build version of Letters from CDN. Letters and additional plugins need to use the same instances of dependencies, especially the editing engine, therefore they need to be built together with all plugins. This is why you need a custom build to add or remove a plugin to Letters.

# Custom build

This guide assumes you are familiar with npm. If not, see the npm documentation or call npm init in an empty directory.

  1. Install Letters and some dependencies:
npm install --save @ckeditor/letters @ckeditor/ckeditor5-dev-utils @ckeditor/ckeditor5-theme-lark
npm install --save-dev webpack webpack-cli postcss-loader style-loader raw-loader
  1. Write the configuration for webpack:
// webpack.config.js

'use strict';

const { getPostCssConfig } = require( '@ckeditor/ckeditor5-dev-utils' ).styles;
const path = require( 'path' );

module.exports = {
    output: {
        path: path.join( __dirname, 'build' ),
        filename: 'letters.js'
    },
    entry: './app.js',
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    {
                        loader: 'style-loader'
                    },
                    {
                        loader: 'postcss-loader',
                        options: getPostCssConfig( {
                            themeImporter: {
                                themePath: require.resolve( '@ckeditor/ckeditor5-theme-lark' )
                            },
                            minify: false,
                            sourceMap: true
                        } )
                    }
                ]
            },
            {
                test: /\.svg$/,
                loaders: [
                    'raw-loader'
                ]
            }
        ]
    },

    devtool: 'source-map'
}
  1. Add the app.js file:
// app.js

import Letters from '@ckeditor/letters/src/letters';

Letters.create( document.querySelector( '#letters' ), {
    cloudServices: {
        // PROVIDE CORRECT VALUES HERE:
        tokenUrl: 'https://example.com/cs-token-endpoint',
        uploadUrl: 'https://your-organization-id.cke-cs.com/easyimage/upload/',
        webSocketUrl: 'your-organization-id.cke-cs.com/ws/'
    },
    collaboration: {
        channelId: 'helloLetters'
    },
    title: 'Why is HBO slaying its dragon?',
    body:
        '<h3>A quick look into HBO\'s next flagship series</h3>' +
        '<p>' +
        '<strong>The reign of fantasy fiction</strong> is coming to an end since the late 90s. ' +
            'For the last 25 years we\'ve witnessed a significant technological growth and now we need ' +
            'narratives to help us understand the new reality.' +
        '</p>'
} )
.then( letters => {
    window.letters = letters;
} )
.catch( error => console.error( error ) );
  1. Fill the configuration constants in app.js based on your organization URLs.

  2. Add the index.html file:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Letters - Sample document</title>
</head>
<body>
    <div id="letters"></div>
    <script src="build/letters.js"></script>
</body>
</html>
  1. Run webpack:
./node_modules/.bin/webpack --mode development

You should see the following output:

Hash: a6f321437fc43913bd9d
Version: webpack 4.15.1
Time: 6912ms
      Asset      Size  Chunks             Chunk Names
    letters.js  4.28 MiB    main  [emitted]  main
letters.js.map  4.11 MiB    main  [emitted]  main
...
  1. Open the index.html file in the browser.

You should see the working sample 🎉!

The default balloon toolbar.

To create a minified version for a production environment, run the ./node_modules/.bin/webpack --mode production command. It adds uglify-webpack-plugin which minifies the bundle.

# Plugin customization

When you have a custom build, you can easily add plugins to it or remove them.

By default Letters comes with the default plugin setup. It contains:

  • Core plugins which are essential to make Letters work.
  • Collaboration plugins which are an integral part of Letters and should not be modified.
  • Editing plugins: Clipboard, Undo, Bold, Italic, Heading, Link, List, Autoformat, Image, ImageCaption, ImageToolbar, ImageStyle, BlockQuote.

You can change the list of editing plugins by providing the plugins and removePlugins properties to the Letters configuration object.

# Adding a plugin

To add a plugin, you need to install it:

npm install --save @ckeditor/ckeditor5-basic-styles

Then import it and pass to the plugins configuration:

// app.js

import Letters from '@ckeditor/letters/src/letters';

import Underline from '@ckeditor/ckeditor5-basic-styles/src/underline';

Letters.create( document.querySelector( '#letters' ), {
    plugins: [ Underline ],
    cloudServices: {
        // PROVIDE CORRECT VALUES HERE:
        tokenUrl: 'https://example.com/cs-token-endpoint',
        uploadUrl: 'https://your-organization-id.cke-cs.com/easyimage/upload/',
        webSocketUrl: 'your-organization-id.cke-cs.com/ws/'
    },
    collaboration: {
        channelId: 'helloLettersWithAdditionalPlugin'
    },
    balloonToolbar: [ 'bold', 'italic', 'link', 'underline', 'comment' ],
    title: 'Why is HBO slaying its dragon?',
    body:
        '<h3>A quick look into HBO\'s next flagship series</h3>' +
        '<p>' +
        '<strong>The reign of fantasy fiction</strong> is coming to an end since the late 90s. ' +
            'For the last 25 years we\'ve witnessed a significant technological growth and now we need ' +
            'narratives to help us understand the new reality.' +
        '</p>'
} )
.then( letters => {
    window.letters = letters;
} )
.catch( error => console.error( error ) );

Note that all default plugins will be loaded. Letters plugins configuration option does not overwrite, but instead it extends the list of defined plugins.

All plugins introducing new elements to the editing view should also introduce the styling for the new elements. To properly use content styling inside Letters, use the .ltrs-content class.

.ltrs-editor u {
    text-decoration: underline;
}

Balloon toolbar with the underline icon.

For more information about available features refer to CKEditor 5 Features documentation.

# Creating custom plugins

You can extend Letters by writing your own CKEditor 5 Framework plugins.

// app.js

import Letters from '@ckeditor/letters/src/letters';

import Plugin from '@ckeditor/ckeditor5-core/src/plugin';

class CustomPlugin extends Plugin {
    init() {
        console.log( 'Custom plugin initialized.' );
    }
}

Letters.create( document.querySelector( '#letters' ), {
    plugins: [ CustomPlugin ],
    cloudServices: {
        // PROVIDE CORRECT VALUES HERE:
        tokenUrl: 'https://example.com/cs-token-endpoint',
        uploadUrl: 'https://your-organization-id.cke-cs.com/easyimage/upload/',
        webSocketUrl: 'your-organization-id.cke-cs.com/ws/'
    },
    collaboration: {
        channelId: 'helloLettersWithCustomPlugin'
    },
    title: 'Why is HBO slaying its dragon?',
    body:
        '<h3>A quick look into HBO\'s next flagship series</h3>' +
        '<p>' +
        '<strong>The reign of fantasy fiction</strong> is coming to an end since the late 90s. ' +
            'For the last 25 years we\'ve witnessed a significant technological growth and now we need ' +
            'narratives to help us understand the new reality.' +
        '</p>'
} )
.then( letters => {
    window.letters = letters;
} )
.catch( error => console.error( error ) );

You should see ‘Custom plugin initialized.’ in the console when you initialize Letters now.

For more information about creating custom plugins refer to CKEditor 5 Plugins guide.

# Removing a plugin

You can remove any editing plugin. For instance to disable the bold feature:

// app.js

import Letters from '@ckeditor/letters/src/letters';

Letters.create( document.querySelector( '#letters' ), {
    removePlugins: [ 'Bold' ],
    cloudServices: {
        // PROVIDE CORRECT VALUES HERE:
        tokenUrl: 'https://example.com/cs-token-endpoint',
        uploadUrl: 'https://your-organization-id.cke-cs.com/easyimage/upload/',
        webSocketUrl: 'your-organization-id.cke-cs.com/ws/',
    },
    collaboration: {
        channelId: 'helloLettersWithRemovedPlugins'
    },
    balloonToolbar: [ 'italic', 'link', 'comment' ],
    title: 'Why is HBO slaying its dragon?',
    body:
        '<h3>A quick look into HBO\'s next flagship series</h3>' +
        '<p>' +
        '<strong>The reign of fantasy fiction</strong> is coming to an end since the late 90s. ' +
            'For the last 25 years we\'ve witnessed a significant technological growth and now we need ' +
            'narratives to help us understand the new reality.' +
        '</p>'
} )
.then( letters => {
    window.letters = letters;
} )
.catch( error => console.error( error ) );

Balloon toolbar without the bold icon.

Note that “The reign of fantasy fiction” is not bold anymore and you will not be able to bold text using the keyboard shortcut.

The removePlugins option is the recommended way to remove any editing plugin. However, it is not advised to remove core or collaboration plugins.