Disclosure: I work on the team behind SynapEditor.
๐งฉ TL;DR: Moving from CKEditor 5 to SynapEditor is a one-to-one swap in three steps: installation, toolbar config, and content/event APIs. The main reason to consider it is Office document fidelity (Word, PowerPoint, Excel import/export). Full runnable example at the end.
Switching rich text editors sounds like a big job, but most of the work is a straightforward, one-to-one swap. This guide walks through moving an existing CKEditor 5 integration over to SynapEditor: loading the library, wiring up the toolbar and content APIs, and a complete working example you can copy and run.
โ๏ธ Which is better: CKEditor or SynapEditor?
Both CKEditor and SynapEditor are mature, capable editors. If you already have CKEditor running, it clearly does a lot right. So the question isn’t really “which is better” in the abstract, it’s which one fits where your product is heading.
Two things tend to drive the decision:
๐ Licensing and support. CKEditor 4 reached end of life in 2023, and security fixes now sit behind a paid Extended Support agreement. If you’re revisiting the integration anyway, it’s a natural moment to reconsider the editor itself.
๐ Office documents. This is where SynapEditor differs most. It imports a broad range of office formats: MS Word (.doc, .docx), PowerPoint (.ppt, .pptx), Excel (.xls, .xlsx, ODT, and HTML, and exports back to Word (.docx) with formatting preserved. If your users upload real documents and expect the layout to survive, that’s worth weighing.
CKEditor 5 SynapEditor Core editing โ โ CKEditor 4 still supported Paid ESM only n/a Word / PPT / Excel import-export Limited โ NativeWith that out of the way, let’s migrate.
๐ What you’ll need
- [ ] An existing CKEditor 5 integration
- [ ] A SynapEditor license and API key (free at Get Started)
- [ ] About 15 minutes for a basic swap
โ๏ธ 1. Installation
CKEditor 5 loads from a single script. SynapEditor loads from a script and a stylesheet: the UI is styled by that CSS, so both tags are required.
CKEditor
<div id="editor"></div>
<script src="https://cdn.ckeditor.com/ckeditor5/xx.x.x/classic/ckeditor.js"></script>
<script>
ClassicEditor.create(document.querySelector('#editor'));
</script>
Enter fullscreen mode Exit fullscreen mode
SynapEditor
<div style="width: 100%; height: 700px; margin: 0 auto;">
<div id="synapEditor"></div>
</div>
<script src="https://cdn.synapeditor.com/latest/synapeditor.min.js"></script>
<link rel="stylesheet" href="https://cdn.synapeditor.com/latest/synapeditor.min.css">
<script>
var config = {
'editor.license': {
company: 'YOUR_COMPANY',
key: ['YOUR_LICENSE_KEY']
},
'editor.license.load.api': {
url: 'https://www.synapeditor.com/api/v1/load-check',
apiKey: 'YOUR_API_KEY'
}
};
var editor = new SynapEditor('synapEditor', config);
</script>
Enter fullscreen mode Exit fullscreen mode
Two things worth flagging:
-
Construction is synchronous.
new SynapEditor(...)returns the instance immediately, there’s no Promise to.then()like CKEditor 5’screate(). - The license is an object, not a string: a company name and a key array. Every other config key is optional; leave it out and the editor falls back to a sensible default.
Most SynapEditor licenses also require a server-side validation call, so you’ll set editor.license.load.api alongside editor.license.
๐๏ธ 2. Toolbar options
Both editors build the toolbar from a list of button names, so this step is mostly translating names. In SynapEditor, the toolbar is set through editor.toolbar.
CKEditor
ClassicEditor.create(document.querySelector('#editor'), {
toolbar: ['bold', 'italic', 'underline', '|', 'numberedList', 'bulletedList']
});
Enter fullscreen mode Exit fullscreen mode
SynapEditor
// The license can be defined separately and managed apart from your feature config
var synapEditorLicense = {
'editor.license': {
company: 'YOUR_COMPANY',
key: ['YOUR_LICENSE_KEY']
},
'editor.license.load.api': {
url: 'https://www.synapeditor.com/api/v1/load-check',
apiKey: 'YOUR_API_KEY'
}
};
var config = {
'editor.toolbar': [
'bold', 'italic', 'underline', '|',
'numberedList', 'bulletList'
]
};
// Merge the two when you create the editor
var editor = new SynapEditor('synapEditor', Object.assign({}, synapEditorLicense, config));
Enter fullscreen mode Exit fullscreen mode
Keeping the license in its own object and merging it with Object.assign at creation time keeps the key in one place: out of your page-level config, and easy to share across pages or swap per environment.
In the editor.toolbar array, '|' inserts a separator within a row and '-' forces a line break onto a new row. There’s also a separate 'editor.mobile.toolbar' config for touch devices, grouped into main, text, table, div, image, and video sections.
๐ 3. Content and events
The last piece is reading and writing content and reacting to edits. The method names differ from CKEditor, so this is the part to search-and-replace carefully.
CKEditor
// Read and write
var html = editor.getData();
editor.setData('<p>New content</p>');
// React to edits
editor.model.document.on('change:data', function () {
console.log('Content changed');
});
Enter fullscreen mode Exit fullscreen mode
SynapEditor
// Read and write
var html = editor.getPublishingHtml();
editor.openHTML('<p>New content</p>');
// React to edits
editor.setEventListener('afterEdit', function () {
console.log('Content changed');
});
Enter fullscreen mode Exit fullscreen mode
You can also register listeners up front by passing them as the fourth constructor argument, see the complete example below.
A quick reference for the calls you’re most likely to port:
Task CKEditor 5 SynapEditor Read contenteditor.getData()
editor.getPublishingHtml()
Write content
editor.setData(html)
editor.openHTML(html)
Insert at cursor
editor.model.insertContent(...)
editor.insertHTML(html)
Content changed
change:data
afterEdit
Run a built-in command
editor.execute('bold')
editor.execCommand('bold')
Read-only on / off
enableReadOnlyMode(id) / disableโฆ
editor.setMode('readonly') / setMode('edit')
Destroy
editor.destroy()
editor.destroy()
๐ป Complete example
Here’s a full, runnable page: the CKEditor equivalent ported to SynapEditor.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="https://cdn.synapeditor.com/latest/synapeditor.min.js"></script>
<link rel="stylesheet" href="https://cdn.synapeditor.com/latest/synapeditor.min.css">
</head>
<body>
<div style="width: 100%; height: 700px; margin: 0 auto;">
<div id="synapEditor"></div>
</div>
<script>
var config = {
'editor.license': {
company: 'YOUR_COMPANY',
key: ['YOUR_LICENSE_KEY']
},
'editor.license.load.api': {
url: 'https://www.synapeditor.com/api/v1/load-check',
apiKey: 'YOUR_API_KEY'
}
};
var html = '<p>Initial content</p>';
var eventListeners = {
'initialized': function () {
console.log('Editor is ready');
},
'afterEdit': function () {
console.log('Content changed');
}
};
var editor = new SynapEditor('synapEditor', config, html, eventListeners);
</script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode
โ Recap
- [x] Swap the script/stylesheet tags and pass your license object
- [x] Translate your toolbar button names into
editor.toolbar - [x] Swap
getData/setData/change:dataforgetPublishingHtml/openHTML/afterEdit - [ ] If your users work with real Office files, test a round-trip import/export before shipping
Want to see it running before you wire it up? There’s a live demo on the SynapEditor demo page. License and API keys are available at Get Started.
๋ต๊ธ ๋จ๊ธฐ๊ธฐ