Syed Umar AnisWebUse TinyMCE rich-text editor in a Svelte app
Syed Umar AnisWebUse TinyMCE rich-text editor in a Svelte app
Web

Use TinyMCE rich-text editor in a Svelte app

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.

Hi, I’m Umar

Leave a Reply

Your email address will not be published. Required fields are marked *