TinyMCE is one of the most popular rich-text editors for web apps. It offers an open-source community edition as well as a premium cloud-based version.
The TinyMCE team has a dedicated package for Svelte applications but unfortunately, it doesn’t work with the latest version of Svelte and uses a deprecated starter template for setting up the project.
Here are the steps to set up TinyMCE in a Sveltekit project using the core component.
1- Install the package
npm install tinymce
2- Create a Svelte component that is going to house the rich-text editor and add a textarea.
<textarea id="myTextarea" />
3- Import TinyMCE into the Svelte component along with the required plugins
import tinymce from 'tinymce';
import 'tinymce/themes/silver';
import 'tinymce/icons/default';
import 'tinymce/plugins/link';
import 'tinymce/plugins/table';
import 'tinymce/plugins/advlist';
import 'tinymce/models/dom';
import 'tinymce/plugins/autolink';
import 'tinymce/plugins/lists';
import 'tinymce/plugins/charmap';
import 'tinymce/plugins/preview';
import 'tinymce/plugins/anchor';
import 'tinymce/plugins/pagebreak';
import 'tinymce/plugins/template';
import 'tinymce/plugins/wordcount';
import 'tinymce/plugins/visualblocks';
import 'tinymce/plugins/visualchars';
import 'tinymce/plugins/code';
import 'tinymce/plugins/fullscreen';
import 'tinymce/plugins/insertdatetime';
import 'tinymce/plugins/media';
import 'tinymce/plugins/emoticons';
import 'tinymce/plugins/emoticons/js/emojis.js';
import 'tinymce/plugins/help';
import 'tinymce/plugins/image';
import 'tinymce/plugins/searchreplace';
import 'tinymce/plugins/help/js/i18n/keynav/en.js';
4- Initialise TinyMCE inside the Svelte’s onMount lifecycle function
onMount(() => {
console.log('Init TinyMCE');
tinymce.init({
selector: '#myTextarea',
width: 700,
height: 600,
plugins: [
'advlist',
'autolink',
'link',
'image',
'lists',
'charmap',
'preview',
'anchor',
'pagebreak',
'searchreplace',
'wordcount',
'visualblocks',
'visualchars',
'code',
'fullscreen',
'insertdatetime',
'media',
'table',
'emoticons',
'template',
'help'
],
toolbar:
'undo redo | styles | bold italic | alignleft aligncenter alignright alignjustify | ' +
'bullist numlist outdent indent | link image | print preview media fullscreen | ' +
'forecolor backcolor emoticons | help',
menu: {
favs: {
title: 'My Favorites',
items: 'code visualaid | searchreplace | emoticons'
}
},
menubar: 'favs file edit view insert format tools table help',
content_css: 'skins/content/default/content.css',
skin_url: 'skins/ui/oxide'
});
}
4- The above Initialization code specifies the paths to static files related to styling (content_css
and skin_url
). Copy the skins folder from node_modules/tinymce/
to static
folder so that the static files are available on the given URL.
5- That’s all. Run the application to verify the set-up.
Extra: Convert images as base64 blob
You may want to convert URLs for pasted images into base64 encoded blobs so that they are contained within the editor (rather than loaded from an external server). Include the following in the init method to achieve this:
images_upload_handler: (blobInfo) => {
const base64str = 'data:' + blobInfo.blob().type + ';base64,' + blobInfo.base64();
return Promise.resolve(base64str);
}
Extra: setup function to add custom the editor and perform actions on events
You can provide a setup function to the init method to configure the editor as per your needs and handle relevant events
setup: function (editor) {
editor.ui.registry.addMenuItem('savefile', {
text: 'Save as file',
onAction: function () {
// get the content of the TinyMCE editor and download it as a file
const content = editor.getContent();
const blob = new Blob([content], { type: 'text/plain;charset=utf-8' });
//saveAs(blob, 'long_description.txt');
}
});
editor.on('change', () => {
console.log(editor.getContent());
});
editor.on('init', () => {
editor.setContent('<p>Hello World!</p>');
});
},
The new ‘saveAs’ menu item can be added to the menubar:
menu: {
favs: {
title: 'My Favorites',
items: 'code visualaid | searchreplace | emoticons | saveAs'
}
},
Extra: Show/Hide editor
If the editor is only shown conditionally, for instance, inside a dialog that can opened and closed by the user as desired, remember to properly clean up the editor by including the following in the onDestroy
Svelte function.
tinymce.activeEditor?.remove();
Svelte Lexical
If you want a rich-text editor component for your Svelte application, I would recommend svelte-lexical which is a more modern component with a much smaller footprint.
disclaimer: I am the author of svelte-lexical project.