
CKEditor 5 can be installed using the npm (NodeJS Package Manager) CLI. If you don't have the npm CLI installed, check out my article FreeKB - NodeJS - Install NodeJS on Linux.
Assuming you are on a Linux system, let's create a directory.
mkdir /tmp/ckeditor5
And then move into the directory.
cd /tmp/ckeditor5
And use one of these commands to install CKEditor 5 using npm.
npm install --save @ckeditor/ckeditor5-build-classic
npm install --save @ckeditor/ckeditor5-build-inline
npm install --save @ckeditor/ckeditor5-build-balloon
npm install --save @ckeditor/ckeditor5-build-balloon-block
npm install --save @ckeditor/ckeditor5-build-decoupled-document
For example, if going with the classic editor, something like this should be displayed.
~]$ npm install --save @ckeditor/ckeditor5-build-classic
added 130 packages in 9s
npm notice
npm notice Changelog: https://github.com/npm/cli/releases/tag/v10.8.1
npm notice Run npm install -g npm@10.8.1 to update!
npm notice
Let's say you want to go with the classic edtior. Let's change to the classic editor directory.
cd node_modules/@ckeditor/ckeditor5-build-classic
And the use the npm list command to ensure no errors are returned. So far, so good.
]$ npm list
@ckeditor/ckeditor5-build-classic@41.4.2 /tmp/ckeditor5/node_modules/@ckeditor/ckeditor5-build-classic
├── @ckeditor/ckeditor5-adapter-ckfinder@41.4.2
├── @ckeditor/ckeditor5-autoformat@41.4.2
├── @ckeditor/ckeditor5-basic-styles@41.4.2
├── @ckeditor/ckeditor5-block-quote@41.4.2
├── @ckeditor/ckeditor5-ckbox@41.4.2
├── @ckeditor/ckeditor5-ckfinder@41.4.2
├── @ckeditor/ckeditor5-cloud-services@41.4.2
├── @ckeditor/ckeditor5-easy-image@41.4.2
├── @ckeditor/ckeditor5-editor-classic@41.4.2
├── @ckeditor/ckeditor5-essentials@41.4.2
├── @ckeditor/ckeditor5-heading@41.4.2
├── @ckeditor/ckeditor5-image@41.4.2
├── @ckeditor/ckeditor5-indent@41.4.2
├── @ckeditor/ckeditor5-link@41.4.2
├── @ckeditor/ckeditor5-list@41.4.2
├── @ckeditor/ckeditor5-media-embed@41.4.2
├── @ckeditor/ckeditor5-paragraph@41.4.2
├── @ckeditor/ckeditor5-paste-from-office@41.4.2
├── @ckeditor/ckeditor5-table@41.4.2
└── @ckeditor/ckeditor5-typing@41.4.2
Notice the ckeditor5-upload package is not included. Let's say you want to use ImageUpload. You can install the package in the classic editor.
npm install @ckeditor/ckeditor5-upload
And now the npm list command should include the ckeditor5-upload package.
]$ npm list
@ckeditor/ckeditor5-build-classic@41.4.2 /tmp/ckeditor5/node_modules/@ckeditor/ckeditor5-build-classic
├── @ckeditor/ckeditor5-adapter-ckfinder@41.4.2
├── @ckeditor/ckeditor5-autoformat@41.4.2
├── @ckeditor/ckeditor5-basic-styles@41.4.2
├── @ckeditor/ckeditor5-block-quote@41.4.2
├── @ckeditor/ckeditor5-ckbox@41.4.2
├── @ckeditor/ckeditor5-ckfinder@41.4.2
├── @ckeditor/ckeditor5-cloud-services@41.4.2
├── @ckeditor/ckeditor5-easy-image@41.4.2
├── @ckeditor/ckeditor5-editor-classic@41.4.2
├── @ckeditor/ckeditor5-essentials@41.4.2
├── @ckeditor/ckeditor5-heading@41.4.2
├── @ckeditor/ckeditor5-image@41.4.2
├── @ckeditor/ckeditor5-indent@41.4.2
├── @ckeditor/ckeditor5-link@41.4.2
├── @ckeditor/ckeditor5-list@41.4.2
├── @ckeditor/ckeditor5-media-embed@41.4.2
├── @ckeditor/ckeditor5-paragraph@41.4.2
├── @ckeditor/ckeditor5-paste-from-office@41.4.2
├── @ckeditor/ckeditor5-table@41.4.2
├── @ckeditor/ckeditor5-typing@41.4.2
└── @ckeditor/ckeditor5-upload@41.4.2
As well as the package.json file.
]$ cat package.json
{
"dependencies": {
"@ckeditor/ckeditor5-adapter-ckfinder": "^41.4.2",
"@ckeditor/ckeditor5-autoformat": "41.4.2",
"@ckeditor/ckeditor5-basic-styles": "41.4.2",
"@ckeditor/ckeditor5-block-quote": "41.4.2",
"@ckeditor/ckeditor5-ckbox": "41.4.2",
"@ckeditor/ckeditor5-ckfinder": "41.4.2",
"@ckeditor/ckeditor5-cloud-services": "41.4.2",
"@ckeditor/ckeditor5-easy-image": "41.4.2",
"@ckeditor/ckeditor5-editor-classic": "41.4.2",
"@ckeditor/ckeditor5-essentials": "41.4.2",
"@ckeditor/ckeditor5-heading": "41.4.2",
"@ckeditor/ckeditor5-image": "41.4.2",
"@ckeditor/ckeditor5-indent": "41.4.2",
"@ckeditor/ckeditor5-link": "41.4.2",
"@ckeditor/ckeditor5-list": "41.4.2",
"@ckeditor/ckeditor5-media-embed": "41.4.2",
"@ckeditor/ckeditor5-paragraph": "41.4.2",
"@ckeditor/ckeditor5-paste-from-office": "41.4.2",
"@ckeditor/ckeditor5-table": "41.4.2",
"@ckeditor/ckeditor5-typing": "41.4.2",
"@ckeditor/ckeditor5-upload": "^41.4.2"
}
Let's say you have a Flask application that will be using CKEditor. In this example, you could place the ckeditor5 in your Flask apps directory structure, almost always in the static folder.
├── main.py
├── my-project (directory)
│ ├── __init__.py
│ ├── views.py
│ ├── templates (directory)
│ │ ├── base.html
│ │ ├── home.html
│ └── static (directory)
│ └── ckeditor5
And then one of your HTML pages could have something like this. Of course you don't need the "before" and "after" console.log but this is super helpful to know if you are making it through the script stuff.
<script src="{{ url_for('static', filename='ckeditor5/node_modules/@ckeditor/ckeditor5-build-classic/build/ckeditor.js') }}"></script>
<textarea name="my_editor"></textarea>
<script>
console.log('before');
console.log(ClassicEditor.builtinPlugins.map( plugin => plugin.pluginName ));
ClassicEditor
.create( document.querySelector( '#my_editor' ) )
.then( editor => {
console.log( editor );
} )
.catch( error => {
console.error( error );
} );
console.log('after');
</script>
Since this is being rendered in an HTML page, you'll use your web browsers developer tools (F12) to view the console.log output. Here I can see the plugins that are available in the editor. Neat.
Often, I'll have different editors that need slightly different tools. Instead of having 2 (or more) different editors server side, I find it much easier to have the editor setup with all the plugins needed server side and to then use the toolbar option when implementing the CKEditor in code to include the desired tools.
<script src="{{ url_for('static', filename='ckeditor5/node_modules/@ckeditor/ckeditor5-build-classic/build/ckeditor.js') }}"></script>
<textarea name="my_editor"></textarea>
<script>
ClassicEditor
.create( document.querySelector( '#my_editor' ), {
toolbar: [ 'heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'blockQuote', 'imageUpload' ]
} )
.then( editor => {
console.log( editor );
} )
.catch( error => {
console.error( error );
} );
Did you find this article helpful?
If so, consider buying me a coffee over at