Migrating from TinyMCE 7 to TinyMCE 8

Introduction

This guide provides a comprehensive overview of the breaking changes introduced in TinyMCE 8.0, along with the necessary steps to migrate from TinyMCE 7.x. It covers key updates to APIs, plugins, and service configurations, including deprecated methods, renamed components, and removed features. These changes are designed to enhance performance, simplify configuration, and align with modern web standards, ensuring a smoother transition and continued compatibility for your integrations.

Migrating from older versions?

If you’re migrating from TinyMCE 4, 5, or 6, you may find it helpful to review the legacy migration guides that target version 7, then follow this guide to complete your migration to version 8:

These guides provide comprehensive coverage of changes from older versions to version 7, which can be combined with this guide for a complete migration path to version 8.

Breaking Changes Quick Reference

The following table summarizes all breaking changes in TinyMCE 8.0. Each item links to detailed information further in the guide.

Any items marked "High" level require immediate attention during migration.

Breaking Change Impact Level

License Key System

Self-hosted deployments now require a new license key format and license key manager. Old keys are not compatible.

High

DOMPurify Update

Sanitization is now stricter; content previously allowed may be stripped or altered.

High

editor.selection.setContent

Method deprecated. Use editor.insertContent instead.

Medium

remove_trailing_brs

Property removed from DomParser API.

Low

Autocompleter Configuration

ch property replaced by trigger.

Low

table_responsive_width

Option replaced by table_sizing_mode. See Table Sizing Mode for details.

Low

Text Pattern Changes

Default trigger changed from Enter to Space key.

Low

addButton, addMenuItem, windowManager.open

Methods deprecated. Use editor.ui.registry.* API instead.

Medium

editor.documentBaseUrl

Undocumented property removed. Use editor.editorManager.documentBaseURI instead.

Low

skipFocus and skip_focus

Options consolidated to skipFocus in ToggleToolbarDrawer.

Low

Split buttons

Split button CSS classes and structure have changed.

Low

Transition from Version 7 License Keys to Version 8.0 License Keys

This section applies to self-hosted installations only. For cloud deployments, license key management is handled automatically.

TinyMCE 8.0 introduces an enhanced license key system that requires specific attention during migration.

The complete licensing documentation License Key Management covers:

  • Detailed explanations of all license types (GPL, Commercial, GPL with Premium Features)

  • Time-based vs Version-locked license key differences

  • License states (Active, Grace Period, Expired, Invalid)

  • Deployment options (Cloud-only, Self-hosted, Hybrid)

  • Step-by-step configuration examples for each setup

  • Commercial License Key Manager setup and requirements

  • Troubleshooting and FAQ

Impact: The new license key system introduces breaking changes that require updates to your configuration and code.

Key Migration Considerations:

  • License Key Format Change:

    • Version 7 keys are: Not compatible with TinyMCE 8.0.

    • New keys use the prefix T8LK: for commercial licenses or GPL+T8LK: for GPL with Premium Features.

  • Mandatory Key Requirement: Self-hosted deployments now require a valid license key; without one, the editor will be set to readonly.

  • Commercial License Manager: Self-hosted commercial deployments require the new License Key Manager addon.

Migration Steps:

  1. Obtain New License Key:

  2. Update Configuration:

    // Old TinyMCE 7 configuration
    tinymce.init({
      selector: '#editor',
      // No license key required
    });
    
    // New TinyMCE 8 configuration
    tinymce.init({
      selector: '#editor',
      license_key: 'T8LK:...'  // New format required
    });

License Key Manager Setup

When migrating to TinyMCE 8.0 with a commercial license, the License Key Manager addon is required for the editor to operate. The setup varies based on your deployment method:

CDN/Static Hosting:

  • Ensure the supplied licensekeymanager folder is in your TinyMCE plugins directory:

your-site/
โ”œโ”€โ”€ tinymce/
โ”‚ โ””โ”€โ”€ plugins/
โ”‚   โ”œโ”€โ”€ licensekeymanager/     # Add this folder
โ”‚   โ”‚   โ”œโ”€โ”€ plugin.min.js
โ”‚   โ”‚   โ””โ”€โ”€ index.js
โ”‚   โ””โ”€โ”€ ... other plugins

NPM/Module Bundler:

Install TinyMCE and ensure the license key manager is imported:

// Import TinyMCE
import tinymce from 'tinymce';

// Import the license key manager
import 'tinymce/plugins/licensekeymanager';

tinymce.init({
  selector: '#editor',
  license_key: 'T8LK:...'  // New format required
});

React/Next.js:

When using the @tinymce/tinymce-react package:

import { Editor } from '@tinymce/tinymce-react';
import 'tinymce/plugins/licensekeymanager';

export default function MyEditor() {
  return (
    <Editor
      init={{
        license_key: 'T8LK:...'
      }}
    />
  );
}

PHP/Laravel:

Ensure the license key manager is included when publishing TinyMCE assets:

<script src="{{ asset('path/to/tinymce/tinymce.min.js') }}"></script>
<script src="{{ asset('path/to/tinymce/plugins/licensekeymanager/plugin.min.js') }}"></script>
<script>
  tinymce.init({
    selector: '#editor',
    license_key: 'T8LK:...'
  });
</script>
  • The license key manager is automatically included when using Tiny Cloud.

  • The plugin does not need to be added to the plugins configuration option.

  • For bundled applications, the license key manager must be loaded before TinyMCE initialization.

  • For bundled applications, ensure the license key manager is not excluded during build optimization.

For complete details on license key manager setup and troubleshooting, see Setting up the Commercial License Key Manager.

License Migration checklist:

  • Contact support for new TinyMCE 8.0 license key or use GPL for the open source version

  • Install license key manager addon for commercial licenses

  • Update configuration with new license key format

  • Test editor functionality with new license

  • Verify all premium features are working

DOMPurify Update and Stricter Sanitization (Breaking Change)

TinyMCE 8.0 updates the DOMPurify dependency to version 3.2.6 and enables the SAFE_FOR_XML flag by default. This is a breaking change: content that previously passed sanitization in TinyMCE 7 may now be stripped or altered during the sanitization process.

This change improves security and aligns with DOMPurify’s recommended defaults. However, existing content and integrations that relied on the previous, less strict sanitization behavior may be impacted.

Key Changes:

  • DOMPurify upgraded to 3.2.6

  • SAFE_FOR_XML enabled โ€” This setting enforces stricter handling of comments and attribute values, preventing certain XSS vectors.

  • Content Impact โ€” HTML comments containing tags, Internet Explorer conditional comments, and attributes with HTML-like values may now be removed during sanitization. Content that was previously allowed may be stripped.

Impact: This change improves security by preventing potential XSS attacks through comments and attributes that were previously allowed. However, it may also result in content being stripped or altered unexpectedly.

Migration Steps:

  • Review workflows and test content that previously relied on relaxed sanitization.

  • TinyMCE now provides the Content Filtering: allow_html_in_comments option option. Enabling this option allows HTML tags in comments with sanitization still enabled.

Using allow_html_in_comments increases the risk of XSS vulnerabilities. allow_html_in_comments is not recommended for production use unless you fully understand the implications and have appropriate security measures in place.
Table 1. Example: Content Differences
Content TinyMCE 7 Output TinyMCE 8.0 Output

<div><!-- <p>Hello World</p> -→</div>

<div><!-- <p>Hello World</p> -→</div>

<div></div>

<iframe><!-- Hello World -→</iframe>

<p><iframe sandbox=""><!-- Hello World -→</iframe></p>

``

<script><!-- Hello World -→</script>

<script><!-- Hello World -→</script>

``

For information on disabling DOMPurify sanitization (not recommended), see xss_sanitization option.

Core Changes

Split Button Styling Update for Custom Skins

TinyMCE 8, split toolbar buttons now render as two distinct components: one for the primary action and one for the dropdown chevron.

This structural change modifies the DOM layout of split buttons and may break custom CSS rules that rely on the previous structure.

Impact: This change only affects integrators using custom skins.

Migration Guide:

If your implementation includes a custom skin, follow these steps to ensure compatibility:

  • Confirm whether your project uses a custom skin.

  • Rebuild your custom skin using the TinyMCE 8 codebase. See Creating a Skin for instructions.

  • Update your split button usage to align with the new structure, including support for the chevronTooltip option. Refer to Split Toolbar Buttons for updated configuration details.

  • Test the rendering and interaction of split buttons in your editor to verify expected behavior.

Summary of Changes:

  • Split buttons now render as two separate DOM elements.

  • CSS selectors and styles that depended on the old structure may no longer apply correctly.

  • The chevronTooltip API option is now supported.

Core API Changes

Breaking Changes Overview

The following sections detail important changes that require updates to your code. Please review each section carefully.

Updated Methods

skipFocus and skip_focus

The skipFocus and skip_focus options for the ToggleToolbarDrawer command have been consolidated into a single, more consistent argument. This reduces API complexity and clarifies the intended behavior.

Impact: This change simplifies focus management, reducing the risk of confusion and unexpected behavior.

Migration steps:

// Old approach (Deprecated) in TinyMCE 8
editor.execCommand('ToggleToolbarDrawer', false, { skipFocus: true })

// New approach (Recommended)
editor.execCommand('ToggleToolbarDrawer', false, null, { skip_focus: true })

Migration checklist:

  • Locate all instances of ToggleToolbarDrawer command usage

  • Replace skip_focus with skipFocus in command options

  • Update any custom plugins using this command

  • Test toolbar drawer behavior after changes


Removed Methods

editor.documentBaseUrl

The undocumented editor.documentBaseUrl property has been removed.

Example Usage
// Removed in TinyMCE 8
console.log('documentBaseUrl', editor.documentBaseUrl);

// Use this instead
console.log('documentBaseURI', editor.documentBaseURI.getURI());
Use editor.documentBaseURI.getURI() for all base URL operations.

Impact: This change improves URL handling consistency by removing an undocumented API that was not aligned with the documented documentBaseURI property.

Migration steps:

To update all references of documentBaseUrl to the new API, replace any usage of editor.documentBaseUrl (or similar) with editor.documentBaseURI.getURI(). The property documentBaseUrl has been removed, and the correct way to access the document base URL is now through the documentBaseURI property, which is a URI object. You can then call .getURI() on it to get the string value of the URL.

For example, update this:
const baseUrl = editor.documentBaseUrl;

to:

const baseUrl = tinymce.activeEditor.documentBaseURI.getURI();

This change is necessary because the undocumented editor.documentBaseUrl API has been removed to improve URL handling consistency. The new approach uses the documented documentBaseURI property, which provides a URI object with methods such as getURI() to retrieve the full URL string.

For more information see: tinymce.editor/#properties.

Migration checklist:

  • Search your codebase for all instances of editor.documentBaseUrl.

  • Replace them with tinymce.activeEditor.documentBaseURI.getURI() (or editor.documentBaseURI.getURI() if you have an editor reference).


Deprecated Methods

editor.selection.setContent

The editor.selection.setContent API has been deprecated and will be removed in TinyMCE 9.

Impact: This change simplifies content manipulation by consolidating insertion methods.

Migration steps:

To replace editor.selection.setContent, use editor.insertContent instead. The new method is more consistent with other content manipulation methods in TinyMCE.

Example Usage
// Deprecated in TinyMCE 8, will be removed in 9
editor.selection.setContent('<p>New content</p>');

// Recommended replacement
editor.insertContent('<p>New content</p>');

Migration checklist:

  • Replace all instances of editor.selection.setContent with editor.insertContent

  • Update custom plugins that use the old method

  • Test content insertion in your editor instances

remove_trailing_brs property removal from DomParser

The remove_trailing_brs setting was removed from the DomParser API in TinyMCE 7.0, after being deprecated in TinyMCE 6.5.

Impact:

  • DomParser no longer supports the remove_trailing_brs option

  • This affects custom DomParser configurations

  • May impact content parsing behavior

Migration Steps:

  1. Remove remove_trailing_brs from DomParser configurations

  2. Test content parsing behavior

  3. Update any custom DomParser implementations

Migration checklist:

  • Remove remove_trailing_brs from DomParser configurations

  • Test content parsing behavior

  • Update any custom DomParser implementations

Autocompleter Configuration Changes

The ch configuration property for autocompleters has been removed. Use the trigger property instead.

Migration Steps:

  1. Replace ch: '<string>' with trigger: '<string>' in autocompleter configurations

  2. Test autocompleter functionality

  3. Update any custom autocompleter implementations

Example:
// Old TinyMCE 6 configuration
editor.ui.registry.addAutocompleter('myautocompleter', {
  ch: '@',
  minChars: 0,
  fetch: function(pattern) {
    return [
      { value: 'john@example.com', text: 'John Doe' },
      { value: 'jane@example.com', text: 'Jane Smith' }
    ];
  }
});

// New TinyMCE 7+ configuration
editor.ui.registry.addAutocompleter('myautocompleter', {
  trigger: '@',
  minChars: 0,
  fetch: function(pattern) {
    return [
      { value: 'john@example.com', text: 'John Doe' },
      { value: 'jane@example.com', text: 'Jane Smith' }
    ];
  }
});

Migration checklist:

  • Replace ch: '<string>' with trigger: '<string>' in autocompleter configurations

  • Test autocompleter functionality

  • Update any custom autocompleter implementations

table_responsive_width replaced by table_sizing_mode

The table_responsive_width option has been replaced by table_sizing_mode in TinyMCE 7.0.

Migration Steps:

  1. Replace table_responsive_width with table_sizing_mode in your configuration

  2. Update the option value to match the new API

  3. Test table responsive behavior

Example:
// Old TinyMCE 6 configuration
tinymce.init({
  selector: "textarea",
  table_responsive_width: true
});

// New TinyMCE 7+ configuration
tinymce.init({
  selector: "textarea",
  table_sizing_mode: "responsive"
});

Migration checklist:

  • Replace table_responsive_width with table_sizing_mode in your configuration

  • Update the option value to match the new API

  • Test table responsive behavior

Text Pattern Changes

TinyMCE 7.0 updated the default behavior of text_patterns to apply formats when the user presses the Space key instead of Enter.

Impact:

  • Markdown-style formatting now triggers on Space key press

  • Previous Enter key behavior can be restored by configuring trigger: 'enter'

  • This affects all text patterns including headings, lists, blockquotes, and horizontal rules

Migration Steps:

  1. Test existing text pattern behavior

  2. Update configurations if Enter key triggering is required

  3. Review user experience with new Space key triggering

  4. Consider updating user documentation about text pattern behavior

Example:
// Default TinyMCE 7+ behavior (Space key trigger)
tinymce.init({
  selector: "textarea",
  text_patterns: [
    { start: '#', format: 'h1', trigger: 'space' },
    { start: '##', format: 'h2', trigger: 'space' },
    { start: '1.', cmd: 'InsertOrderedList', trigger: 'space' },
    { start: '*', cmd: 'InsertUnorderedList', trigger: 'space' },
    { start: '>', cmd: 'mceBlockQuote', trigger: 'space' }
  ]
});

// Restore previous behavior (Enter key trigger)
tinymce.init({
  selector: "textarea",
  text_patterns: [
    { start: '#', format: 'h1', trigger: 'enter' },
    { start: '##', format: 'h2', trigger: 'enter' },
    { start: '1.', cmd: 'InsertOrderedList', trigger: 'enter' },
    { start: '*', cmd: 'InsertUnorderedList', trigger: 'enter' },
    { start: '>', cmd: 'mceBlockQuote', trigger: 'enter' }
  ]
});

Migration checklist:

  • Test existing text pattern behavior with Space key triggering

  • Update configurations if Enter key triggering is required

  • Review user experience with new Space key triggering

  • Update user documentation about text pattern behavior

addButton, addMenuItem, and windowManager.open

The addButton, addMenuItem, and windowManager.open methods have been replaced by the editor.ui.registry.* API.

// Deprecated in TinyMCE 8, will be removed in 9
// Old approach for adding buttons
editor.addButton('myButton', {
  text: 'My Button',
  onclick: function() {
    editor.insertContent('Hello World!');
  }
});

// New approach for adding buttons
editor.ui.registry.addButton('myButton', {
  text: 'My Button',
  onAction: function() {
    editor.insertContent('Hello World!');
  }
});

Migration checklist:

  • Replace all instances of editor.addButton with editor.ui.registry.addButton

  • Replace all instances of editor.addMenuItem with editor.ui.registry.addMenuItem

  • Replace all instances of editor.windowManager.open with editor.windowManager.open

  • Update custom plugins that use the old methods

  • Test button and menu functionality in your editor instances

fire()

The fire() method has been replaced by dispatch() for event handling. The fire() method will be removed in TinyMCE 9 to avoid confusion with its name.

// Deprecated in TinyMCE 8, will be removed in 9
// Old approach for dispatching custom events
editor.fire('someEvent');

// New approach for dispatching custom events
editor.dispatch('someEvent');

Impact: This change aligns TinyMCE with modern event handling conventions, making the API more intuitive for developers.

Migration checklist:

  • Search codebase for all uses of the fire() method

  • Replace each instance with dispatch()

  • Review and update third-party plugins

  • Test all custom event handling


Plugin Updates

Language Pack Filename Changes

Language pack filenames have been standardized to follow the RFC5646 format. This update ensures consistent language handling across platforms and improves internationalization support. While both the legacy underscore format (e.g., en_GB.js) and the new hyphenated format (e.g., en-GB.js) are supported in TinyMCE 8.0, the underscore format is deprecated and will be removed in TinyMCE 9. Migrating to the RFC5646 format now will ensure future compatibility and reduce maintenance overhead during upcoming upgrades.

Impact: Custom language packs and configurations using the underscore-based format should update before upgrading to TinyMCE 9 to avoid loading failures.

Migration checklist:

  • Identify all language pack files in your deployment

  • Rename files to RFC5646 format (e.g., en_GB.js โ†’ en-GB.js)

  • Update configuration references to language files

  • Update build scripts that handle language files

  • Test language switching in your application

  • Update custom translation files to use the new format

// Deprecated format (supported only in versions 8.x)
language_url: '/langs/en_GB.js'

// Recommended format
language_url: '/langs/en-GB.js'
Support for the underscore format will be removed in TinyMCE 9. Early migration is recommended.

Update to Image and Accessibility Checker Plugins

The Image and Accessibility Checker plugins now follow the latest W3C standards for decorative images, requiring an empty alt attribute rather than a role="presentation" attribute. This change helps improve accessibility support.

Impact: Customers using these plugins will need to update their configurations to ensure continued compliance with accessibility standards.

Migration checklist:

  • Identify images previously using role="presentation" for decorative purposes in your content

  • Replace those with empty alt attributes alt=""

  • Update image plugin configuration if customized

  • Test accessibility checker with updated content

For more information on the changes, see: Accessibility Checker: Image rules.

Cross-Origin Resource Loading Configuration

When upgrading to TinyMCE 8, you will need to review and possibly update how your integration handles cross-origin resource loading. TinyMCE 8 provides a new configuration option for controlling the crossorigin attribute on loaded resources.

What to check:

  1. If you’re using Tiny Cloud:

    • Ensure your script tag includes both required attributes:

      <script src="https://cdn.tiny.cloud/1/no-api-key/tinymce/8/tinymce.min.js" referrerpolicy="origin" crossorigin="anonymous"></script>
  2. If your application loads resources (scripts or stylesheets) from different domains:

    • Configure the new crossorigin function to control the crossorigin attribute for all resources.

      Example: Configuring the crossorigin function
      const crossOriginFunction = (url, resourceType) => {
          // Returning 'anonymous' or 'use-credentials' here would explicitly set the attribute
          return 'anonymous';
          // return 'use-credentials';
          // return undefined; // Omits the 'crossorigin' attribute for all resources by returning undefined
      };
      
      tinymce.init({
        selector: "textarea",
        crossorigin: crossOriginFunction
      });
  3. If you’re using content_css from a different domain:

    • The content_css_cors option takes precedence for stylesheets.

    • Review your content_css configuration if you use cross-origin stylesheets.

Migration checklist:

  • Verify script tag attributes for Cloud deployments.

  • Configure crossorigin function if using cross-origin resources.

  • Test resource loading in your deployment environment.

  • Review content_css configuration if using cross-origin stylesheets.

For complete details on the new crossorigin function API, see: crossorigin configuration option.

Technical Cleanup

Removed Empty Files

Several empty files have been removed from the codebase to reduce clutter and improve maintenance:

  • Empty CSS file from the Comments plugin

  • Empty LESS file from the Mentions plugin

Impact: These changes have no functional impact but may affect custom build processes that explicitly reference these files.

Migration checklist:

  • Check build processes for references to Comments plugin CSS

  • Check build processes for references to Mentions plugin LESS

  • Remove any imports of these empty files

  • Test Comments and Mentions plugins after removal

Service and Configuration Changes

Java Swing Integration Deprecation

TinyMCE’s Java Swing integration has been deprecated in TinyMCE 8.0 and will reach end-of-life as of December 31, 2025.

Impact: Customers using the Java Swing integration need to plan for migration to alternative solutions before the end-of-life date.

Migration checklist:

  • Evaluate alternative integration options

  • Plan migration timeline to complete before December 31, 2025

For information about the Java Swing integration, see: TinyMCE for Java Swing integration

Discontinuation of Medical English (UK)

The "Medical English (UK)" dictionary has been removed due to licensing constraints. Customers using this feature must update their configurations accordingly.

Impact: Users relying on this dictionary will need to make alternative arrangements for medical-specific spell checking.

Migration checklist:

  • Remove "Medical English (UK)" from spellchecker configurations

  • Remove any custom dictionary integrations related to Medical English

  • Test spellchecker functionality with remaining dictionaries

  • Configure alternative medical dictionary if required

Decoupling of Service Versions from TinyMCE Editor

Services previously bundled with the editor, such as Java Servlet services, are no longer included in TinyMCE 8.0 packages. Customers should migrate to Containerized service deployments or consider alternative hosting options.

Impact: This reduces the dependency between the editor and backend services, simplifying updates and maintenance.

Migration steps:

Transition from Java WAR Files to Containerized Services

TinyMCE 8.0 no longer includes Java WAR files for backend services like the spell checker. Customers are required to migrate to modern Docker/OCI containers for self-hosted deployments.

Impact: This reduces infrastructure complexity and aligns with modern DevOps practices.

Migration checklist:

  • Inventory current WAR file deployments

  • Review containerization requirements for your environment

  • Plan transition timeline to containerized services

  • Set up container infrastructure (Docker/Kubernetes)

  • Deploy and test containerized services

  • Update service connection configurations

  • Contact Tiny Support if legacy WAR files are still needed

For more information on deploying the server-side components using Docker, see: Containerized service deployments.

Conclusion

Upgrading to TinyMCE 8.0 requires integrators to update their API calls, plugin configurations, and service integrations to accommodate the breaking changes introduced in this release. While some adjustments may involve significant code updates, these enhancements are intended to simplify development, and improve the overall editor experience.

For more guidance, refer to the:

Ask AI Widget

Additional Resources

For additional details on TinyMCE 8.0 changes, see TinyMCE 8.0 release notes.