fix: upgrade TinyMCE to v7 and remove the premium plugin stub package - #3245
bradenmacdonald wants to merge 3 commits into
Conversation
TinyMCE 5 -> 7 removed several APIs and plugins this app relied on: - `tinymce.editors` is gone; the problem editor now uses `tinymce.get()` to collect answer/hint/feedback content and check dirty state. - The `hr` and `imagetools` plugins were removed (the `hr` button is now core). The "Edit Image Settings" context toolbar that imagetools used to provide is re-registered as a plain context toolbar. - The `formatselect` toolbar item was renamed to `blocks`. - The `dom` model and each core plugin must now be imported explicitly. - TinyMCE 7 is GPL-2.0-or-later; `licenseKey="gpl"` silences its evaluation-mode warning. `frontend-components-tinymce-advanced-plugins` is removed as a dependency. It pinned TinyMCE 5 (pulling a second core into the bundle that clobbered `window.tinymce`) and only shipped no-op stubs for the paid a11ychecker and powerpaste plugins. Operators who have licensed those plugins can now load them via `TINYMCE_EXTERNAL_PLUGINS`, `TINYMCE_LICENSE_KEY` and `TINYMCE_PLUGIN_OPTIONS` in env.config.jsx (see README). The jest setup now stubs `tinymce/themes/silver` so the editor never finishes initializing under JSDOM, which the test suite has always implicitly relied on (previously the stubbed plugins hung initialization). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Thanks for the pull request, @bradenmacdonald! This repository is currently maintained by Once you've gone through the following steps feel free to tag them in a comment and let them know that your changes are ready for engineering review. 🔘 Get product approvalIf you haven't already, check this list to see if your contribution needs to go through the product review process.
🔘 Provide contextTo help your reviewers and other members of the community understand the purpose and larger context of your changes, feel free to add as much of the following information to the PR description as you can:
🔘 Get a green buildIf one or more checks are failing, continue working on your changes until this is no longer the case and your build turns green. DetailsWhere can I find more information?If you'd like to get more details on all aspects of the review process for open source pull requests (OSPRs), check out the following resources: When can I expect my changes to be merged?Our goal is to get community contributions seen and reviewed as efficiently as possible. However, the amount of time that it takes to review and merge a PR can vary significantly based on factors such as:
💡 As a result it may take up to several weeks or months to complete a review and merge your PR. |
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #3245 +/- ##
==========================================
- Coverage 96.03% 96.03% -0.01%
==========================================
Files 1407 1407
Lines 34287 34295 +8
Branches 7882 8148 +266
==========================================
+ Hits 32928 32935 +7
+ Misses 1318 1304 -14
- Partials 41 56 +15 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Description
Upgrades TinyMCE from 5.10 to 7.9 (supersedes #3176, renovate's security bump, which fails tests and would break the editor at runtime) and removes the
frontend-components-tinymce-advanced-pluginsdependency, replacing it with a configuration-based way to load premium plugins.This affects Course Authors and Library Authors (all rich text editors: HTML/Text, Problem, hints, feedback, expandable text areas, course updates, schedule & details) and Operators (new configuration keys, license change, dependency removal).
Why the renovate PR alone was not mergeable
tinymce.editorswas removed in v7. The problem editor used it to collect answer/hint/feedback content and to check dirty state. This was the cause of the two failing tests. It now uses the publictinymce.get()API and reads each editor'sid.frontend-components-tinymce-advanced-pluginspinstinymce ^5.10.4, so with v7 at the root npm nested a separate TinyMCE 5 copy under it. The app imported all of its standard plugins through that package, so the bundle contained two cores, and the v5 one overwrotewindow.tinymce, which is what@tinymce/tinymce-reactreads. The editor would have been broken in the browser even though the unit tests didn't catch it.hrandimagetoolsplugins no longer exist (hris now a core button). The "Edit Image Settings" context toolbar thatimagetools_toolbarused to provide is re-registered as a plain context toolbar on<img>nodes.formatselecttoolbar item was renamed toblocks.dommodel and each core plugin now have to be imported explicitly.licenseKey="gpl"on the ReactEditor).Removal of
frontend-components-tinymce-advanced-pluginsThat package only shipped no-op stubs for the paid
a11ycheckerandpowerpasteplugins, is still on TinyMCE 5 upstream (a renovate PR bumping it was closed), and re-exports plugins that no longer exist. It is removed entirely. Operators who have licensed the premium plugins can now load them throughenv.config.jsx:TINYMCE_EXTERNAL_PLUGINS:{ pluginName: 'https://.../plugin.min.js' }, passed to TinyMCE's built-inexternal_pluginsloader. Configuringa11ycheckerrestores its toolbar button; configuringpowerpasterestores the paste defaults the app previously set.TINYMCE_LICENSE_KEY: the commercial license key that premium plugins in v7 require (defaults togpl).TINYMCE_PLUGIN_OPTIONS: extra init options for those plugins.Documented in the README under "Feature: New React XBlock Editors", with a test in
pluginConfig.test.Behavior changes to be aware of
valid_elements: '*[*]'.<script>tags and inline event handlers are preserved exactly as v5 did, so existing course content is not stripped. The one change is the fix for CVE-2024-29881 itself:convert_unsafe_embedsis on by default, so<object>/<embed>are rewritten to<iframe>/<img>/<video>/<audio>(by MIME type) when content is loaded and re-saved.paste_data_imagesdefaulting totrue, so pasted screenshots now land in the content as base64 data URIs (v5 dropped them). Left at the default; easy to set tofalseif we would rather not allow it.highlight_on_focusby default, adding a blue outline around the focused editor.Test-suite note
Removing the stub plugin names exposed that the jest suite has always relied on TinyMCE never finishing initialization under JSDOM: previously the editor silently hung trying to fetch the (mocked)
a11ychecker/powerpastescripts over the network. With every plugin genuinely registered, the editor initialized for real and crashed inside the theme's sizing code, which JSDOM can't support.src/setupTest.jsnow stubstinymce/themes/silverto make that dependency explicit. Browser behavior is unaffected.Supporting information
Testing instructions
Automated: full jest suite (568 suites),
npm run types,npm run lint, andnpm run buildall pass. The production bundle contains exactly one TinyMCE core (7.9.3).Manual:
TINYMCE_EXTERNAL_PLUGINS/TINYMCE_LICENSE_KEYinenv.config.jsxand confirm the plugins load and thea11ycheckbutton appears.Other information
frontend-components-tinymce-advanced-pluginspackage no longer needs a TinyMCE 7 release for this MFE.TINYMCE_*configuration keys.Best Practices Checklist
.ts,.tsx).propTypesanddefaultPropsin any new or modified code. (No new usages; the pre-existing ones inTinyMceWidgetare untouched.)src/testUtils.tsx(specificallyinitializeMocks) (N/A: the new test is a pure config test; existing tests were adapted in place.)messages.tsfiles have adescription. (N/A)../in import paths. (No new relative imports added.)🤖 Generated with Claude Code