@instructure/canvas-rce 7.2.0 → 7.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/es/enhance-user-content/doc_previews.js +1 -14
- package/es/index.d.ts +1 -0
- package/es/index.js +2 -1
- package/es/rce/AlertMessageArea.d.ts +2 -2
- package/es/rce/AlertMessageArea.js +4 -6
- package/es/rce/RCEGlobals.d.ts +2 -0
- package/es/rce/RCEGlobals.js +1 -0
- package/es/rce/RCEVariants.js +3 -3
- package/es/rce/RCEWrapper.d.ts +14 -12
- package/es/rce/RCEWrapper.js +206 -199
- package/es/rce/plugins/instructure_keyboard_shortcuts_header/clickCallback.d.ts +2 -0
- package/es/rce/plugins/instructure_keyboard_shortcuts_header/clickCallback.js +45 -0
- package/es/rce/plugins/instructure_keyboard_shortcuts_header/plugin.d.ts +1 -0
- package/es/rce/plugins/instructure_keyboard_shortcuts_header/plugin.js +43 -0
- package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolSelectionDialog/ExternalToolSelectionDialog.d.ts +1 -1
- package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolSelectionDialog/ExternalToolSelectionDialog.js +25 -25
- package/es/rce/plugins/instructure_record/AudioOptionsTray/TrayController.d.ts +1 -1
- package/es/rce/plugins/instructure_record/AudioOptionsTray/TrayController.js +2 -1
- package/es/rce/plugins/instructure_record/VideoOptionsTray/TrayController.d.ts +1 -1
- package/es/rce/plugins/instructure_record/VideoOptionsTray/TrayController.js +2 -1
- package/es/rce/plugins/instructure_record/mediaTranslations.js +1 -1
- package/es/rce/plugins/instructure_studio_media_options/plugin.js +109 -14
- package/es/rce/plugins/instructure_studio_media_options/studioToolbarIcons.d.ts +5 -0
- package/es/rce/plugins/instructure_studio_media_options/studioToolbarIcons.js +23 -0
- package/es/rce/plugins/instructure_wordcount_header/plugin.d.ts +1 -0
- package/es/rce/plugins/instructure_wordcount_header/plugin.js +75 -0
- package/es/rce/plugins/shared/ContentSelection.d.ts +1 -2
- package/es/rce/plugins/shared/ContentSelection.js +1 -18
- package/es/rce/plugins/shared/StudioLtiSupportUtils.d.ts +9 -1
- package/es/rce/plugins/shared/StudioLtiSupportUtils.js +94 -1
- package/es/rce/plugins/shared/Upload/ComputerPanel.js +1 -1
- package/es/rce/plugins/shared/Upload/UploadFileModal.js +37 -4
- package/es/rce/plugins/shared/Upload/VideoUrlPanel.d.ts +15 -0
- package/es/rce/plugins/shared/Upload/VideoUrlPanel.js +51 -0
- package/es/rce/plugins/shared/Upload/videoValidationUtils.d.ts +7 -0
- package/es/rce/plugins/shared/Upload/videoValidationUtils.js +58 -0
- package/es/rce/plugins/shared/iframeUtils.d.ts +1 -0
- package/es/rce/plugins/shared/iframeUtils.js +37 -0
- package/es/rce/tinyRCE.js +2 -0
- package/es/sidebar/actions/upload.d.ts +1 -0
- package/es/sidebar/actions/upload.js +56 -0
- package/es/sidebar/containers/sidebarHandlers.d.ts +1 -0
- package/es/sidebar/containers/sidebarHandlers.js +2 -1
- package/es/translations/locales/ar.js +15 -6
- package/es/translations/locales/ca.js +15 -6
- package/es/translations/locales/cy.js +15 -6
- package/es/translations/locales/da-x-k12.js +15 -6
- package/es/translations/locales/da.js +15 -6
- package/es/translations/locales/de.js +15 -6
- package/es/translations/locales/el.js +6 -0
- package/es/translations/locales/en-AU-x-unimelb.js +15 -6
- package/es/translations/locales/en-GB-x-ukhe.js +15 -6
- package/es/translations/locales/en.js +30 -6
- package/es/translations/locales/en_AU.js +15 -6
- package/es/translations/locales/en_CA.js +15 -6
- package/es/translations/locales/en_CY.js +15 -6
- package/es/translations/locales/en_GB.js +15 -6
- package/es/translations/locales/es.js +15 -6
- package/es/translations/locales/es_ES.js +15 -6
- package/es/translations/locales/fa_IR.js +6 -3
- package/es/translations/locales/fi.js +15 -6
- package/es/translations/locales/fr.js +15 -6
- package/es/translations/locales/fr_CA.js +19 -10
- package/es/translations/locales/ga.js +15 -6
- package/es/translations/locales/he.js +6 -0
- package/es/translations/locales/hi.js +15 -6
- package/es/translations/locales/ht.js +15 -6
- package/es/translations/locales/hu.js +6 -6
- package/es/translations/locales/hy.js +6 -0
- package/es/translations/locales/id.js +15 -6
- package/es/translations/locales/is.js +21 -6
- package/es/translations/locales/it.js +15 -6
- package/es/translations/locales/ja.js +15 -6
- package/es/translations/locales/ko.js +6 -0
- package/es/translations/locales/mi.js +15 -6
- package/es/translations/locales/ms.js +15 -6
- package/es/translations/locales/nb-x-k12.js +15 -6
- package/es/translations/locales/nb.js +15 -6
- package/es/translations/locales/nl.js +15 -6
- package/es/translations/locales/nn.js +6 -6
- package/es/translations/locales/pl.js +15 -6
- package/es/translations/locales/pt.js +15 -6
- package/es/translations/locales/pt_BR.js +15 -6
- package/es/translations/locales/ru.js +15 -6
- package/es/translations/locales/sl.js +15 -6
- package/es/translations/locales/sv-x-k12.js +15 -6
- package/es/translations/locales/sv.js +15 -6
- package/es/translations/locales/th.js +15 -6
- package/es/translations/locales/tr.js +6 -3
- package/es/translations/locales/uk_UA.js +6 -3
- package/es/translations/locales/vi.js +15 -6
- package/es/translations/locales/zh-Hans.js +15 -6
- package/es/translations/locales/zh-Hant.js +15 -6
- package/es/translations/locales/zh.js +15 -6
- package/es/translations/locales/zh_HK.js +15 -6
- package/package.json +53 -53
package/es/rce/RCEWrapper.js
CHANGED
|
@@ -17,63 +17,63 @@ import _pt from "prop-types";
|
|
|
17
17
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import React, { Suspense } from
|
|
21
|
-
import { Editor } from
|
|
22
|
-
import tinymce from
|
|
23
|
-
import _ from
|
|
24
|
-
import { StoreProvider } from
|
|
25
|
-
import { IconKeyboardShortcutsLine } from
|
|
26
|
-
import { Alert } from
|
|
27
|
-
import { Spinner } from
|
|
28
|
-
import { View } from
|
|
29
|
-
import { debounce } from
|
|
30
|
-
import { uid } from
|
|
31
|
-
import { FocusRegionManager } from
|
|
32
|
-
import getCookie from
|
|
33
|
-
import formatMessage from
|
|
34
|
-
import * as contentInsertion from
|
|
35
|
-
import indicatorRegion from
|
|
36
|
-
import { editorLanguage } from
|
|
37
|
-
import normalizeLocale from
|
|
38
|
-
import { sanitizePlugins } from
|
|
39
|
-
import RCEGlobals from
|
|
40
|
-
import defaultTinymceConfig from
|
|
41
|
-
import { FS_CHANGEEVENT, FS_ELEMENT, FS_ENABLED, FS_EXIT, FS_REQUEST, instuiPopupMountNodeFn } from
|
|
42
|
-
import indicate from
|
|
43
|
-
import bridge from
|
|
44
|
-
import CanvasContentTray from
|
|
45
|
-
import StatusBar, { PRETTY_HTML_EDITOR_VIEW, RAW_HTML_EDITOR_VIEW, WYSIWYG_VIEW } from
|
|
46
|
-
import { VIEW_CHANGE } from
|
|
47
|
-
import ShowOnFocusButton from
|
|
48
|
-
import KeyboardShortcutModal from
|
|
49
|
-
import AlertMessageArea from
|
|
50
|
-
import alertHandler from
|
|
51
|
-
import { isFileLink, isImageEmbed } from
|
|
52
|
-
import { countShouldIgnore } from
|
|
53
|
-
import launchWordcountModal from
|
|
54
|
-
import { determineOSDependentKey } from
|
|
55
|
-
import skinCSS from
|
|
56
|
-
import contentCSS from
|
|
57
|
-
import { rceWrapperPropTypes } from
|
|
58
|
-
import { insertPlaceholder, placeholderInfoFor, removePlaceholder } from
|
|
59
|
-
import { transformRceContentForEditing } from
|
|
20
|
+
import React, { Suspense } from "react";
|
|
21
|
+
import { Editor } from "@tinymce/tinymce-react";
|
|
22
|
+
import tinymce from "tinymce";
|
|
23
|
+
import _ from "lodash";
|
|
24
|
+
import { StoreProvider } from "./plugins/shared/StoreContext";
|
|
25
|
+
import { IconKeyboardShortcutsLine } from "@instructure/ui-icons";
|
|
26
|
+
import { Alert } from "@instructure/ui-alerts";
|
|
27
|
+
import { Spinner } from "@instructure/ui-spinner";
|
|
28
|
+
import { View } from "@instructure/ui-view";
|
|
29
|
+
import { debounce } from "@instructure/debounce";
|
|
30
|
+
import { uid } from "@instructure/uid";
|
|
31
|
+
import { FocusRegionManager } from "@instructure/ui-a11y-utils";
|
|
32
|
+
import getCookie from "../common/getCookie";
|
|
33
|
+
import formatMessage from "../format-message";
|
|
34
|
+
import * as contentInsertion from "./contentInsertion";
|
|
35
|
+
import indicatorRegion from "./indicatorRegion";
|
|
36
|
+
import { editorLanguage } from "./editorLanguage";
|
|
37
|
+
import normalizeLocale from "./normalizeLocale";
|
|
38
|
+
import { sanitizePlugins } from "./sanitizePlugins";
|
|
39
|
+
import RCEGlobals from "./RCEGlobals";
|
|
40
|
+
import defaultTinymceConfig from "../defaultTinymceConfig";
|
|
41
|
+
import { FS_CHANGEEVENT, FS_ELEMENT, FS_ENABLED, FS_EXIT, FS_REQUEST, instuiPopupMountNodeFn } from "../util/fullscreenHelpers";
|
|
42
|
+
import indicate from "../common/indicate";
|
|
43
|
+
import bridge from "../bridge";
|
|
44
|
+
import CanvasContentTray from "./plugins/shared/CanvasContentTray";
|
|
45
|
+
import StatusBar, { PRETTY_HTML_EDITOR_VIEW, RAW_HTML_EDITOR_VIEW, WYSIWYG_VIEW } from "./StatusBar";
|
|
46
|
+
import { VIEW_CHANGE } from "./customEvents";
|
|
47
|
+
import ShowOnFocusButton from "./ShowOnFocusButton";
|
|
48
|
+
import KeyboardShortcutModal from "./KeyboardShortcutModal";
|
|
49
|
+
import AlertMessageArea from "./AlertMessageArea";
|
|
50
|
+
import alertHandler from "./alertHandler";
|
|
51
|
+
import { isFileLink, isImageEmbed } from "./plugins/shared/ContentSelection";
|
|
52
|
+
import { countShouldIgnore } from "./plugins/instructure_wordcount/utils/countContent";
|
|
53
|
+
import launchWordcountModal from "./plugins/instructure_wordcount/clickCallback";
|
|
54
|
+
import { determineOSDependentKey } from "./userOS";
|
|
55
|
+
import skinCSS from "./tinymce.oxide.skin.min.css";
|
|
56
|
+
import contentCSS from "./tinymce.oxide.content.min.css";
|
|
57
|
+
import { rceWrapperPropTypes } from "./RCEWrapperProps";
|
|
58
|
+
import { insertPlaceholder, placeholderInfoFor, removePlaceholder } from "../util/loadingPlaceholder";
|
|
59
|
+
import { transformRceContentForEditing } from "./transformContent";
|
|
60
60
|
// @ts-expect-error
|
|
61
|
-
import { IconMoreSolid } from
|
|
62
|
-
import EncryptedStorage from
|
|
63
|
-
import buildStyle from
|
|
64
|
-
import { getMenubarForVariant, getMenuForVariant, getToolbarForVariant, getStatusBarFeaturesForVariant } from
|
|
65
|
-
import { focusFirstMenuButton, focusToolbar, isElementWithinTable, mergeMenu, mergeMenuItems, mergePlugins, mergeToolbar, parsePluginsToExclude, patchAutosavedContent } from
|
|
66
|
-
import { externalToolsForToolbar } from
|
|
67
|
-
import { initScreenreaderOnFormat } from
|
|
68
|
-
import { normalizeContainingContext } from
|
|
69
|
-
const RestoreAutoSaveModal = /*#__PURE__*/React.lazy(() => import(
|
|
70
|
-
const RceHtmlEditor = /*#__PURE__*/React.lazy(() => import(
|
|
61
|
+
import { IconMoreSolid } from "@instructure/ui-icons/es/svg";
|
|
62
|
+
import EncryptedStorage from "../util/encrypted-storage";
|
|
63
|
+
import buildStyle from "./style";
|
|
64
|
+
import { getMenubarForVariant, getMenuForVariant, getToolbarForVariant, getStatusBarFeaturesForVariant } from "./RCEVariants";
|
|
65
|
+
import { focusFirstMenuButton, focusToolbar, isElementWithinTable, mergeMenu, mergeMenuItems, mergePlugins, mergeToolbar, parsePluginsToExclude, patchAutosavedContent } from "./RCEWrapper.utils";
|
|
66
|
+
import { externalToolsForToolbar } from "./plugins/instructure_rce_external_tools/util/externalToolsForToolbar";
|
|
67
|
+
import { initScreenreaderOnFormat } from "./screenreaderOnFormat";
|
|
68
|
+
import { normalizeContainingContext } from "../util/contextHelper";
|
|
69
|
+
const RestoreAutoSaveModal = /*#__PURE__*/React.lazy(() => import("./RestoreAutoSaveModal"));
|
|
70
|
+
const RceHtmlEditor = /*#__PURE__*/React.lazy(() => import("./RceHtmlEditor"));
|
|
71
71
|
const ASYNC_FOCUS_TIMEOUT = 250;
|
|
72
|
-
const DEFAULT_RCE_HEIGHT =
|
|
72
|
+
const DEFAULT_RCE_HEIGHT = "400px";
|
|
73
73
|
function addKebabIcon(editor) {
|
|
74
74
|
// This has to be done here instead of of in plugins/instructure-ui-icons/plugin.ts
|
|
75
75
|
// presumably because the toolbar gets created before that plugin is loaded?
|
|
76
|
-
editor.ui.registry.addIcon(
|
|
76
|
+
editor.ui.registry.addIcon("more-drawer", IconMoreSolid.src);
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
// Get oxide the default skin injected into the DOM before the overrides loaded by themeable
|
|
@@ -81,8 +81,8 @@ let inserted = false;
|
|
|
81
81
|
function injectTinySkin() {
|
|
82
82
|
if (inserted) return;
|
|
83
83
|
inserted = true;
|
|
84
|
-
const style = document.createElement(
|
|
85
|
-
style.setAttribute(
|
|
84
|
+
const style = document.createElement("style");
|
|
85
|
+
style.setAttribute("data-skin", "tiny oxide skin");
|
|
86
86
|
style.appendChild(document.createTextNode(skinCSS));
|
|
87
87
|
// there's CSS from discussions that turns the instui Selectors bold
|
|
88
88
|
// and in classic quizzes that also mucks with padding
|
|
@@ -90,9 +90,9 @@ function injectTinySkin() {
|
|
|
90
90
|
#discussion-edit-view .rce-wrapper input[readonly] {font-weight: normal;}
|
|
91
91
|
#quiz_edit_wrapper .rce-wrapper input[readonly] {font-weight: normal; padding-left: .75rem;}
|
|
92
92
|
`));
|
|
93
|
-
const beforeMe = document.head.querySelector(
|
|
93
|
+
const beforeMe = document.head.querySelector("style[data-glamor]") ||
|
|
94
94
|
// find instui's themeable stylesheet
|
|
95
|
-
document.head.querySelector(
|
|
95
|
+
document.head.querySelector("style") ||
|
|
96
96
|
// find any stylesheet
|
|
97
97
|
document.head.firstElementChild;
|
|
98
98
|
document.head.insertBefore(style, beforeMe);
|
|
@@ -102,10 +102,10 @@ const editorWrappers = new WeakMap();
|
|
|
102
102
|
// determines if localStorage is available for our use.
|
|
103
103
|
// see https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API
|
|
104
104
|
export function storageAvailable() {
|
|
105
|
-
let storage;
|
|
105
|
+
let storage = null;
|
|
106
106
|
try {
|
|
107
107
|
storage = window.localStorage;
|
|
108
|
-
const x =
|
|
108
|
+
const x = "__storage_test__";
|
|
109
109
|
storage.setItem(x, x);
|
|
110
110
|
storage.removeItem(x);
|
|
111
111
|
return true;
|
|
@@ -117,15 +117,15 @@ export function storageAvailable() {
|
|
|
117
117
|
e.code === 1014 ||
|
|
118
118
|
// test name field too, because code might not be present
|
|
119
119
|
// everything except Firefox
|
|
120
|
-
e.name ===
|
|
120
|
+
e.name === "QuotaExceededError" ||
|
|
121
121
|
// Firefox
|
|
122
|
-
e.name ===
|
|
122
|
+
e.name === "NS_ERROR_DOM_QUOTA_REACHED") &&
|
|
123
123
|
// acknowledge QuotaExceededError only if there's something already stored
|
|
124
124
|
storage && storage.length !== 0;
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
127
|
function renderLoading() {
|
|
128
|
-
return formatMessage(
|
|
128
|
+
return formatMessage("Loading");
|
|
129
129
|
}
|
|
130
130
|
let alertIdValue = 0;
|
|
131
131
|
class RCEWrapper extends React.Component {
|
|
@@ -199,7 +199,7 @@ class RCEWrapper extends React.Component {
|
|
|
199
199
|
this.setState(newState);
|
|
200
200
|
this.checkAccessibility();
|
|
201
201
|
if (newView === PRETTY_HTML_EDITOR_VIEW || newView === RAW_HTML_EDITOR_VIEW) {
|
|
202
|
-
this.storage?.setItem?.(
|
|
202
|
+
this.storage?.setItem?.("rce.htmleditor", newView);
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
// Emit view change event
|
|
@@ -216,16 +216,18 @@ class RCEWrapper extends React.Component {
|
|
|
216
216
|
if (document[FS_ELEMENT]) {
|
|
217
217
|
// @ts-expect-error
|
|
218
218
|
this.resizeObserver.observe(document[FS_ELEMENT]);
|
|
219
|
-
window.visualViewport?.addEventListener(
|
|
219
|
+
window.visualViewport?.addEventListener("resize", this._handleFullscreenResize);
|
|
220
220
|
this._handleFullscreenResize();
|
|
221
221
|
// @ts-expect-error
|
|
222
|
-
this._focusRegion = FocusRegionManager.activateRegion(
|
|
222
|
+
this._focusRegion = FocusRegionManager.activateRegion(
|
|
223
|
+
// @ts-expect-error
|
|
224
|
+
document[FS_ELEMENT], {
|
|
223
225
|
shouldContainFocus: true
|
|
224
226
|
});
|
|
225
227
|
} else {
|
|
226
228
|
event.target.removeEventListener(FS_CHANGEEVENT, this._onFullscreenChange);
|
|
227
229
|
this.resizeObserver.unobserve(event.target);
|
|
228
|
-
window.visualViewport?.removeEventListener(
|
|
230
|
+
window.visualViewport?.removeEventListener("resize", this._handleFullscreenResize);
|
|
229
231
|
this._setHeight(this.state.fullscreenState.prevHeight);
|
|
230
232
|
if (this._focusRegion) {
|
|
231
233
|
FocusRegionManager.blurRegion(event.target, this._focusRegion.id);
|
|
@@ -258,35 +260,35 @@ class RCEWrapper extends React.Component {
|
|
|
258
260
|
// what we've got for now.
|
|
259
261
|
const ifr = this.iframe;
|
|
260
262
|
if (ifr?.parentElement) {
|
|
261
|
-
ifr.parentElement.classList.add(
|
|
263
|
+
ifr.parentElement.classList.add("active");
|
|
262
264
|
}
|
|
263
265
|
this.handleFocus();
|
|
264
266
|
};
|
|
265
267
|
this.handleBlurEditor = event => {
|
|
266
268
|
const ifr = this.iframe;
|
|
267
269
|
if (ifr?.parentElement) {
|
|
268
|
-
ifr.parentElement.classList.remove(
|
|
270
|
+
ifr.parentElement.classList.remove("active");
|
|
269
271
|
}
|
|
270
272
|
this.handleBlur(event);
|
|
271
273
|
};
|
|
272
274
|
this.handleKey = event => {
|
|
273
|
-
if (event.code ===
|
|
275
|
+
if (event.code === "F9" && event.altKey) {
|
|
274
276
|
event.preventDefault();
|
|
275
277
|
event.stopPropagation();
|
|
276
278
|
// @ts-expect-error
|
|
277
279
|
focusFirstMenuButton(this._elementRef.current);
|
|
278
|
-
} else if (event.code ===
|
|
280
|
+
} else if (event.code === "F10" && event.altKey) {
|
|
279
281
|
event.preventDefault();
|
|
280
282
|
event.stopPropagation();
|
|
281
283
|
// @ts-expect-error
|
|
282
284
|
focusToolbar(this._elementRef.current);
|
|
283
|
-
} else if (event.code ===
|
|
285
|
+
} else if (event.code === "F8" && event.altKey) {
|
|
284
286
|
event.preventDefault();
|
|
285
287
|
event.stopPropagation();
|
|
286
288
|
this.openKBShortcutModal();
|
|
287
|
-
} else if (event.code ===
|
|
289
|
+
} else if (event.code === "Escape") {
|
|
288
290
|
bridge.hideTrays();
|
|
289
|
-
} else if ([
|
|
291
|
+
} else if (["n", "N", "d", "D"].indexOf(event.key) !== -1) {
|
|
290
292
|
// Prevent key events from bubbling up on touch screen device
|
|
291
293
|
event.stopPropagation();
|
|
292
294
|
}
|
|
@@ -315,32 +317,32 @@ class RCEWrapper extends React.Component {
|
|
|
315
317
|
// @ts-expect-error
|
|
316
318
|
textarea.value = this.getCode();
|
|
317
319
|
textarea.style.height = this.state.height;
|
|
318
|
-
textarea.removeAttribute(
|
|
319
|
-
if (document.body.classList.contains(
|
|
320
|
+
textarea.removeAttribute("aria-hidden");
|
|
321
|
+
if (document.body.classList.contains("Underline-All-Links__enabled")) {
|
|
320
322
|
if (this.iframe?.contentDocument) {
|
|
321
|
-
this.iframe.contentDocument.body.classList.add(
|
|
323
|
+
this.iframe.contentDocument.body.classList.add("Underline-All-Links__enabled");
|
|
322
324
|
}
|
|
323
325
|
}
|
|
324
|
-
editor.on(
|
|
326
|
+
editor.on("wordCountUpdate", this.onWordCountUpdate);
|
|
325
327
|
// add an aria-label to the application div that wraps RCE
|
|
326
328
|
// and change role from "application" to "document" to ensure
|
|
327
329
|
// the editor gets properly picked up by screen readers
|
|
328
330
|
const tinyapp = document.querySelector('.tox-tinymce[role="application"]');
|
|
329
331
|
if (tinyapp) {
|
|
330
|
-
tinyapp.setAttribute(
|
|
331
|
-
tinyapp.setAttribute(
|
|
332
|
-
tinyapp.setAttribute(
|
|
332
|
+
tinyapp.setAttribute("aria-label", formatMessage("Rich Content Editor"));
|
|
333
|
+
tinyapp.setAttribute("role", "document");
|
|
334
|
+
tinyapp.setAttribute("tabIndex", "-1");
|
|
333
335
|
}
|
|
334
336
|
|
|
335
337
|
// Probably should do this in tinymce.scss, but we only want it in new rce
|
|
336
|
-
textarea.style.resize =
|
|
337
|
-
editor.on(
|
|
338
|
-
editor.on(
|
|
338
|
+
textarea.style.resize = "none";
|
|
339
|
+
editor.on("keydown", this.handleKey);
|
|
340
|
+
editor.on("FullscreenStateChanged", this._onFullscreenChange);
|
|
339
341
|
// This propagates click events on the editor out of the iframe to the parent
|
|
340
342
|
// document. We need this so that click events get captured properly by instui
|
|
341
343
|
// focus-trapping components, so they properly ignore trapping focus on click.
|
|
342
|
-
editor.on(
|
|
343
|
-
editor.on(
|
|
344
|
+
editor.on("click", () => window.document.body.click(), true);
|
|
345
|
+
editor.on("Cut Change input Undo Redo", debounce(this.handleInputChange, 1000));
|
|
344
346
|
initScreenreaderOnFormat(editor);
|
|
345
347
|
this.announceContextToolbars(editor);
|
|
346
348
|
if (this.isAutoSaving) {
|
|
@@ -352,12 +354,12 @@ class RCEWrapper extends React.Component {
|
|
|
352
354
|
|
|
353
355
|
// readonly should have been handled via the init property passed
|
|
354
356
|
// to <Editor>, but it's not.
|
|
355
|
-
editor.mode.set(this.props.readOnly ?
|
|
357
|
+
editor.mode.set(this.props.readOnly ? "readonly" : "design");
|
|
356
358
|
|
|
357
359
|
// Not using iframe_aria_text because compatibility issues.
|
|
358
360
|
// Not using iframe_attrs because library overwriting.
|
|
359
361
|
if (this.iframe) {
|
|
360
|
-
this.iframe.setAttribute(
|
|
362
|
+
this.iframe.setAttribute("title", formatMessage("Rich Text Area. Press {OSKey}+F8 for Rich Content Editor shortcuts.", {
|
|
361
363
|
OSKey: determineOSDependentKey()
|
|
362
364
|
}));
|
|
363
365
|
}
|
|
@@ -370,8 +372,8 @@ class RCEWrapper extends React.Component {
|
|
|
370
372
|
|
|
371
373
|
// cleans up highlight artifacts from findreplace plugin
|
|
372
374
|
if (this.getRequiredFeatureStatuses().rce_find_replace) {
|
|
373
|
-
editor.on(
|
|
374
|
-
if (editor?.dom?.doc?.getElementsByClassName?.(
|
|
375
|
+
editor.on("undo redo", _e => {
|
|
376
|
+
if (editor?.dom?.doc?.getElementsByClassName?.("mce-match-marker")?.length > 0) {
|
|
375
377
|
editor.plugins?.searchreplace?.done();
|
|
376
378
|
}
|
|
377
379
|
});
|
|
@@ -390,7 +392,7 @@ class RCEWrapper extends React.Component {
|
|
|
390
392
|
// This workaround removes attribute, thusly causing navigation to work correctly again.
|
|
391
393
|
// For the correct solution, Keying.config should have { selector: '.tox-toolbar__group' }
|
|
392
394
|
// in https://github.com/tinymce/tinymce/blob/develop/modules/alloy/src/main/ts/ephox/alloy/ui/schema/SplitSlidingToolbarSchema.ts
|
|
393
|
-
this._elementRef.current?.querySelectorAll(
|
|
395
|
+
this._elementRef.current?.querySelectorAll(".tox-toolbar-overlord button[data-alloy-tabstop]").forEach(it => it.removeAttribute("data-alloy-tabstop"));
|
|
394
396
|
};
|
|
395
397
|
/**
|
|
396
398
|
* Sets up selection saving and restoration logic.
|
|
@@ -417,7 +419,7 @@ class RCEWrapper extends React.Component {
|
|
|
417
419
|
selectionWasReset = false;
|
|
418
420
|
}
|
|
419
421
|
};
|
|
420
|
-
editor.on(
|
|
422
|
+
editor.on("blur", () => {
|
|
421
423
|
editorHasFocus = false;
|
|
422
424
|
selectionWasReset = false;
|
|
423
425
|
if (!this.editor) return;
|
|
@@ -426,7 +428,7 @@ class RCEWrapper extends React.Component {
|
|
|
426
428
|
isForward: this.editor.selection.isForward()
|
|
427
429
|
};
|
|
428
430
|
});
|
|
429
|
-
editor.on(
|
|
431
|
+
editor.on("focus", () => {
|
|
430
432
|
// We need to restore the selection when the editor regains focus because sometimes the editor regains
|
|
431
433
|
// focus without the user setting the selection themselves (such as when they interact with the toolbar)
|
|
432
434
|
// and if we didn't, we would end up saving the reset selection before a user managed to actually insert
|
|
@@ -435,7 +437,7 @@ class RCEWrapper extends React.Component {
|
|
|
435
437
|
editorHasFocus = true;
|
|
436
438
|
selectionWasReset = false;
|
|
437
439
|
});
|
|
438
|
-
editor.on(
|
|
440
|
+
editor.on("SelectionChange", () => {
|
|
439
441
|
if (editorHasFocus) {
|
|
440
442
|
// We don't care if a selection reset occurs when the editor has focus, the user probably intended that
|
|
441
443
|
// At least they will see the effect
|
|
@@ -445,14 +447,14 @@ class RCEWrapper extends React.Component {
|
|
|
445
447
|
const selection = this.editor.selection.normalize();
|
|
446
448
|
|
|
447
449
|
// Detect a browser-reset selection (e.g. From invoking the Find command)
|
|
448
|
-
if (selection.startContainer?.nodeName ===
|
|
450
|
+
if (selection.startContainer?.nodeName === "BODY" && selection.startContainer === selection.endContainer && selection.startOffset === 0 && selection.endOffset === 0) {
|
|
449
451
|
selectionWasReset = true;
|
|
450
452
|
}
|
|
451
453
|
});
|
|
452
|
-
editor.on(
|
|
454
|
+
editor.on("BeforeExecCommand", () => {
|
|
453
455
|
restoreSelectionIfNecessary();
|
|
454
456
|
});
|
|
455
|
-
editor.on(
|
|
457
|
+
editor.on("ExecCommand", (/* event */
|
|
456
458
|
) => {
|
|
457
459
|
if (!this.editor) return;
|
|
458
460
|
// Commands may have modified the selection, we need to recapture it
|
|
@@ -463,13 +465,14 @@ class RCEWrapper extends React.Component {
|
|
|
463
465
|
});
|
|
464
466
|
};
|
|
465
467
|
this.announcing = 0;
|
|
468
|
+
this._isMounted = false;
|
|
466
469
|
/* ********** autosave support *************** */
|
|
467
470
|
this.initAutoSave = editor => {
|
|
468
471
|
var _this$props$userCache;
|
|
469
|
-
this.storage = new EncryptedStorage((_this$props$userCache = this.props.userCacheKey) !== null && _this$props$userCache !== void 0 ? _this$props$userCache :
|
|
472
|
+
this.storage = new EncryptedStorage((_this$props$userCache = this.props.userCacheKey) !== null && _this$props$userCache !== void 0 ? _this$props$userCache : "");
|
|
470
473
|
if (this.storage) {
|
|
471
|
-
editor.on(
|
|
472
|
-
editor.on(
|
|
474
|
+
editor.on("change Undo Redo", this.doAutoSave);
|
|
475
|
+
editor.on("blur", this.doAutoSave);
|
|
473
476
|
this.cleanupAutoSave();
|
|
474
477
|
try {
|
|
475
478
|
const autosaved = this.getAutoSaved(this.autoSaveKey);
|
|
@@ -494,7 +497,7 @@ class RCEWrapper extends React.Component {
|
|
|
494
497
|
} catch (ex) {
|
|
495
498
|
// log and ignore
|
|
496
499
|
|
|
497
|
-
console.error(
|
|
500
|
+
console.error("Failed initializing rce autosave", ex);
|
|
498
501
|
}
|
|
499
502
|
}
|
|
500
503
|
};
|
|
@@ -549,7 +552,7 @@ class RCEWrapper extends React.Component {
|
|
|
549
552
|
this.cleanupAutoSave(true);
|
|
550
553
|
this.doAutoSave(e, true);
|
|
551
554
|
} else {
|
|
552
|
-
console.error(
|
|
555
|
+
console.error("Autosave failed:", ex);
|
|
553
556
|
}
|
|
554
557
|
}
|
|
555
558
|
}
|
|
@@ -557,7 +560,7 @@ class RCEWrapper extends React.Component {
|
|
|
557
560
|
/* *********** end autosave support *************** */
|
|
558
561
|
this.onWordCountUpdate = e => {
|
|
559
562
|
if (!this.editor) return;
|
|
560
|
-
const shouldIgnore = countShouldIgnore(this.editor,
|
|
563
|
+
const shouldIgnore = countShouldIgnore(this.editor, "body", "words");
|
|
561
564
|
const updatedCount = e.wordCount.words - shouldIgnore;
|
|
562
565
|
this.setState(state => {
|
|
563
566
|
if (updatedCount !== state.wordCount) {
|
|
@@ -570,7 +573,7 @@ class RCEWrapper extends React.Component {
|
|
|
570
573
|
// @ts-expect-error
|
|
571
574
|
this.onNodeChange = e => {
|
|
572
575
|
// This is basically copied out of the tinymce silver theme code for the status bar
|
|
573
|
-
const path = e.parents.filter(p => p.nodeName !==
|
|
576
|
+
const path = e.parents.filter(p => p.nodeName !== "BR" && !p.getAttribute("data-mce-bogus") && p.getAttribute("data-mce-type") !== "bookmark")
|
|
574
577
|
// @ts-expect-error
|
|
575
578
|
.map(p => p.nodeName.toLowerCase()).reverse();
|
|
576
579
|
this.setState({
|
|
@@ -581,7 +584,7 @@ class RCEWrapper extends React.Component {
|
|
|
581
584
|
this.props.onContentChange?.(content);
|
|
582
585
|
// check accessibility when clearing the editor,
|
|
583
586
|
// all other times should be checked by handleInputChange
|
|
584
|
-
if (content ===
|
|
587
|
+
if (content === "") {
|
|
585
588
|
this.checkAccessibility();
|
|
586
589
|
}
|
|
587
590
|
};
|
|
@@ -603,14 +606,14 @@ class RCEWrapper extends React.Component {
|
|
|
603
606
|
height: newHeight
|
|
604
607
|
});
|
|
605
608
|
// play nice and send the same event that the silver theme would send
|
|
606
|
-
editor.fire(
|
|
609
|
+
editor.fire("ResizeEditor", {
|
|
607
610
|
deltaY: coordinates.deltaY
|
|
608
611
|
});
|
|
609
612
|
}
|
|
610
613
|
};
|
|
611
614
|
this.onA11yChecker = triggerElementId => {
|
|
612
615
|
const editor = this.mceInstance();
|
|
613
|
-
editor.execCommand(
|
|
616
|
+
editor.execCommand("openAccessibilityChecker", false, {
|
|
614
617
|
mountNode: instuiPopupMountNodeFn,
|
|
615
618
|
triggerElementId,
|
|
616
619
|
onFixError: errors => {
|
|
@@ -624,7 +627,7 @@ class RCEWrapper extends React.Component {
|
|
|
624
627
|
};
|
|
625
628
|
this.checkAccessibility = () => {
|
|
626
629
|
const editor = this.mceInstance();
|
|
627
|
-
editor.execCommand(
|
|
630
|
+
editor.execCommand("checkAccessibility", false, {
|
|
628
631
|
// @ts-expect-error
|
|
629
632
|
done: errors => {
|
|
630
633
|
this.setState({
|
|
@@ -664,7 +667,7 @@ class RCEWrapper extends React.Component {
|
|
|
664
667
|
}
|
|
665
668
|
};
|
|
666
669
|
this.handleAIClick = () => {
|
|
667
|
-
import(
|
|
670
|
+
import("./plugins/shared/ai_tools").then(module => {
|
|
668
671
|
// @ts-expect-error
|
|
669
672
|
this.AIToolsTray = module.AIToolsTray;
|
|
670
673
|
this.setState({
|
|
@@ -672,7 +675,7 @@ class RCEWrapper extends React.Component {
|
|
|
672
675
|
AITToolsFocusReturn: document.activeElement
|
|
673
676
|
});
|
|
674
677
|
}).catch(ex => {
|
|
675
|
-
console.error(
|
|
678
|
+
console.error("Failed loading the AIToolsTray", ex);
|
|
676
679
|
});
|
|
677
680
|
};
|
|
678
681
|
this.closeAITools = () => {
|
|
@@ -714,10 +717,10 @@ class RCEWrapper extends React.Component {
|
|
|
714
717
|
this.getCurrentContentForAI = () => {
|
|
715
718
|
const selected = this.mceInstance().selection.getContent();
|
|
716
719
|
return selected ? {
|
|
717
|
-
type:
|
|
720
|
+
type: "selection",
|
|
718
721
|
content: selected
|
|
719
722
|
} : {
|
|
720
|
-
type:
|
|
723
|
+
type: "full",
|
|
721
724
|
content: this.mceInstance().getContent()
|
|
722
725
|
};
|
|
723
726
|
};
|
|
@@ -732,7 +735,7 @@ class RCEWrapper extends React.Component {
|
|
|
732
735
|
alert.id = alertIdValue++;
|
|
733
736
|
this.setState(state => {
|
|
734
737
|
let messages = state.messages.concat(alert);
|
|
735
|
-
messages = _.uniqBy(messages,
|
|
738
|
+
messages = _.uniqBy(messages, "text"); // Don't show the same message twice
|
|
736
739
|
return {
|
|
737
740
|
messages
|
|
738
741
|
};
|
|
@@ -751,7 +754,7 @@ class RCEWrapper extends React.Component {
|
|
|
751
754
|
*/
|
|
752
755
|
this.resetAlertId = () => {
|
|
753
756
|
if (this.state.messages.length > 0) {
|
|
754
|
-
throw new Error(
|
|
757
|
+
throw new Error("There are messages currently, you cannot reset when they are non-zero");
|
|
755
758
|
}
|
|
756
759
|
alertIdValue = 0;
|
|
757
760
|
};
|
|
@@ -793,7 +796,7 @@ class RCEWrapper extends React.Component {
|
|
|
793
796
|
if (!Number.isNaN(_ht)) {
|
|
794
797
|
_ht = `${_ht}px`;
|
|
795
798
|
}
|
|
796
|
-
const currentRCECount = document.querySelectorAll(
|
|
799
|
+
const currentRCECount = document.querySelectorAll(".rce-wrapper").length;
|
|
797
800
|
const maxInitRenderedRCEs = Number.isNaN(props.maxInitRenderedRCEs) ? RCEWrapper.defaultProps.maxInitRenderedRCEs : props.maxInitRenderedRCEs;
|
|
798
801
|
this.state = {
|
|
799
802
|
path: [],
|
|
@@ -804,9 +807,9 @@ class RCEWrapper extends React.Component {
|
|
|
804
807
|
messages: [],
|
|
805
808
|
announcement: null,
|
|
806
809
|
confirmAutoSave: false,
|
|
807
|
-
autoSavedContent:
|
|
810
|
+
autoSavedContent: "",
|
|
808
811
|
// @ts-expect-error
|
|
809
|
-
id: this.props.id || this.props.textareaId || `${uid(
|
|
812
|
+
id: this.props.id || this.props.textareaId || `${uid("rce", 2)}`,
|
|
810
813
|
// @ts-expect-error
|
|
811
814
|
height: _ht,
|
|
812
815
|
fullscreenState: {
|
|
@@ -814,7 +817,7 @@ class RCEWrapper extends React.Component {
|
|
|
814
817
|
prevHeight: _ht
|
|
815
818
|
},
|
|
816
819
|
a11yErrorsCount: 0,
|
|
817
|
-
shouldShowEditor: typeof IntersectionObserver ===
|
|
820
|
+
shouldShowEditor: typeof IntersectionObserver === "undefined" || maxInitRenderedRCEs <= 0 || currentRCECount < maxInitRenderedRCEs,
|
|
818
821
|
AIToolsOpen: false
|
|
819
822
|
};
|
|
820
823
|
this._statusBarId = `${this.state.id}_statusbar`;
|
|
@@ -849,11 +852,11 @@ class RCEWrapper extends React.Component {
|
|
|
849
852
|
// configure tinymce to say where that div is mounted, do this
|
|
850
853
|
// is a bit of a hack to tag the div that is this RCE's
|
|
851
854
|
_tagTinymceAuxDiv() {
|
|
852
|
-
const tinyauxlist = document.querySelectorAll(
|
|
855
|
+
const tinyauxlist = document.querySelectorAll(".tox-tinymce-aux");
|
|
853
856
|
if (tinyauxlist.length) {
|
|
854
857
|
const myaux = tinyauxlist[tinyauxlist.length - 1];
|
|
855
858
|
if (myaux.id) {
|
|
856
|
-
console.error(
|
|
859
|
+
console.error("Unexpected ID on my tox-tinymce-aux element");
|
|
857
860
|
}
|
|
858
861
|
myaux.id = `tinyaux-${this.id}`;
|
|
859
862
|
}
|
|
@@ -867,6 +870,7 @@ class RCEWrapper extends React.Component {
|
|
|
867
870
|
explicit_latex_typesetting = false,
|
|
868
871
|
rce_transform_loaded_content = false,
|
|
869
872
|
rce_find_replace = false,
|
|
873
|
+
rce_studio_embed_improvements = false,
|
|
870
874
|
file_verifiers_for_quiz_links = false,
|
|
871
875
|
consolidated_media_player = false
|
|
872
876
|
} = this.props.features;
|
|
@@ -874,6 +878,7 @@ class RCEWrapper extends React.Component {
|
|
|
874
878
|
new_math_equation_handling,
|
|
875
879
|
explicit_latex_typesetting,
|
|
876
880
|
rce_transform_loaded_content,
|
|
881
|
+
rce_studio_embed_improvements,
|
|
877
882
|
file_verifiers_for_quiz_links,
|
|
878
883
|
rce_find_replace,
|
|
879
884
|
consolidated_media_player
|
|
@@ -911,7 +916,7 @@ class RCEWrapper extends React.Component {
|
|
|
911
916
|
let status = true;
|
|
912
917
|
// Check for remaining placeholders
|
|
913
918
|
if (this.mceInstance().dom.doc.querySelector(`[data-placeholder-for]`)) {
|
|
914
|
-
status = promptFunc(formatMessage(
|
|
919
|
+
status = promptFunc(formatMessage("Content is still being uploaded, if you continue it will not be embedded properly."));
|
|
915
920
|
}
|
|
916
921
|
return status;
|
|
917
922
|
}
|
|
@@ -971,9 +976,9 @@ class RCEWrapper extends React.Component {
|
|
|
971
976
|
// @ts-expect-error
|
|
972
977
|
ifr.contentDocument.body.clientHeight -
|
|
973
978
|
// @ts-expect-error
|
|
974
|
-
parseInt(editor_body_style[
|
|
979
|
+
parseInt(editor_body_style["padding-top"], 10) -
|
|
975
980
|
// @ts-expect-error
|
|
976
|
-
parseInt(editor_body_style[
|
|
981
|
+
parseInt(editor_body_style["padding-bottom"], 10);
|
|
977
982
|
const para_margin_ht = 24;
|
|
978
983
|
const reserve_ht = Math.ceil(height + para_margin_ht);
|
|
979
984
|
if (reserve_ht > editor_ht) {
|
|
@@ -985,7 +990,7 @@ class RCEWrapper extends React.Component {
|
|
|
985
990
|
}
|
|
986
991
|
}
|
|
987
992
|
checkImageLoadError(element) {
|
|
988
|
-
if (!element || element.tagName !==
|
|
993
|
+
if (!element || element.tagName !== "IMG") {
|
|
989
994
|
return;
|
|
990
995
|
}
|
|
991
996
|
// @ts-expect-error
|
|
@@ -1000,9 +1005,9 @@ class RCEWrapper extends React.Component {
|
|
|
1000
1005
|
// @ts-expect-error
|
|
1001
1006
|
if (element.naturalWidth === 0) {
|
|
1002
1007
|
// @ts-expect-error
|
|
1003
|
-
element.style.border =
|
|
1008
|
+
element.style.border = "1px solid #000";
|
|
1004
1009
|
// @ts-expect-error
|
|
1005
|
-
element.style.padding =
|
|
1010
|
+
element.style.padding = "2px";
|
|
1006
1011
|
}
|
|
1007
1012
|
}, 0);
|
|
1008
1013
|
}
|
|
@@ -1012,7 +1017,7 @@ class RCEWrapper extends React.Component {
|
|
|
1012
1017
|
this.contentInserted(element);
|
|
1013
1018
|
}
|
|
1014
1019
|
replaceCode(code) {
|
|
1015
|
-
if (code !==
|
|
1020
|
+
if (code !== "" && window.confirm(formatMessage("Content in the editor will be changed. Press Cancel to keep the original content."))) {
|
|
1016
1021
|
this.mceInstance().setContent(code);
|
|
1017
1022
|
}
|
|
1018
1023
|
}
|
|
@@ -1029,12 +1034,12 @@ class RCEWrapper extends React.Component {
|
|
|
1029
1034
|
// that there's some embedded content helper
|
|
1030
1035
|
// From what I've read, "title" is more reliable than "aria-label" for
|
|
1031
1036
|
// elements like iframes and embeds.
|
|
1032
|
-
const temp = document.createElement(
|
|
1037
|
+
const temp = document.createElement("div");
|
|
1033
1038
|
temp.innerHTML = code;
|
|
1034
1039
|
const code_elem = temp.firstElementChild;
|
|
1035
1040
|
if (code_elem) {
|
|
1036
|
-
if (!code_elem.hasAttribute(
|
|
1037
|
-
code_elem.setAttribute(
|
|
1041
|
+
if (!code_elem.hasAttribute("title") && !code_elem.hasAttribute("aria-label")) {
|
|
1042
|
+
code_elem.setAttribute("title", formatMessage("embedded content"));
|
|
1038
1043
|
}
|
|
1039
1044
|
code = code_elem.outerHTML;
|
|
1040
1045
|
}
|
|
@@ -1044,7 +1049,7 @@ class RCEWrapper extends React.Component {
|
|
|
1044
1049
|
// and it's often inserted into a <p> on top of that. Find the
|
|
1045
1050
|
// iframe and use it to flash the indicator.
|
|
1046
1051
|
const element = contentInsertion.insertContent(editor, code);
|
|
1047
|
-
const ifr = element && element.querySelector && element.querySelector(
|
|
1052
|
+
const ifr = element && element.querySelector && element.querySelector("iframe");
|
|
1048
1053
|
if (ifr) {
|
|
1049
1054
|
this.contentInserted(ifr);
|
|
1050
1055
|
} else {
|
|
@@ -1056,7 +1061,7 @@ class RCEWrapper extends React.Component {
|
|
|
1056
1061
|
const element = contentInsertion.insertImage(editor, image, this.getCanvasUrl());
|
|
1057
1062
|
|
|
1058
1063
|
// Removes TinyMCE's caret text if exists.
|
|
1059
|
-
if (element?.nextSibling?.data?.startsWith(
|
|
1064
|
+
if (element?.nextSibling?.data?.startsWith("\xA0" /* nbsp */)) {
|
|
1060
1065
|
element.nextSibling.splitText(1);
|
|
1061
1066
|
element.nextSibling.remove();
|
|
1062
1067
|
}
|
|
@@ -1137,8 +1142,8 @@ class RCEWrapper extends React.Component {
|
|
|
1137
1142
|
onTinyMCEInstance(command, ...args) {
|
|
1138
1143
|
const editor = this.mceInstance();
|
|
1139
1144
|
if (editor) {
|
|
1140
|
-
if (command ===
|
|
1141
|
-
editor.execCommand(
|
|
1145
|
+
if (command === "mceRemoveEditor") {
|
|
1146
|
+
editor.execCommand("mceNewDocument");
|
|
1142
1147
|
} // makes sure content can't persist past removal
|
|
1143
1148
|
editor.execCommand(command, false, ...args);
|
|
1144
1149
|
}
|
|
@@ -1158,17 +1163,17 @@ class RCEWrapper extends React.Component {
|
|
|
1158
1163
|
return null;
|
|
1159
1164
|
}
|
|
1160
1165
|
textareaValue() {
|
|
1161
|
-
return this.getTextarea()?.value ||
|
|
1166
|
+
return this.getTextarea()?.value || "";
|
|
1162
1167
|
}
|
|
1163
1168
|
get id() {
|
|
1164
1169
|
return this.state.id;
|
|
1165
1170
|
}
|
|
1166
1171
|
getHtmlEditorStorage() {
|
|
1167
|
-
const cookieValue = getCookie(
|
|
1172
|
+
const cookieValue = getCookie("rce.htmleditor");
|
|
1168
1173
|
if (cookieValue) {
|
|
1169
1174
|
document.cookie = `rce.htmleditor=${cookieValue};path=/;max-age=0`;
|
|
1170
1175
|
}
|
|
1171
|
-
const value = cookieValue || this.storage?.getItem?.(
|
|
1176
|
+
const value = cookieValue || this.storage?.getItem?.("rce.htmleditor")?.content;
|
|
1172
1177
|
return value === RAW_HTML_EDITOR_VIEW || value === PRETTY_HTML_EDITOR_VIEW ? value : PRETTY_HTML_EDITOR_VIEW;
|
|
1173
1178
|
}
|
|
1174
1179
|
_isFullscreen() {
|
|
@@ -1185,7 +1190,7 @@ class RCEWrapper extends React.Component {
|
|
|
1185
1190
|
this._elementRef.current?.appendChild(tinymenuhost);
|
|
1186
1191
|
}
|
|
1187
1192
|
this._elementRef.current?.addEventListener(FS_CHANGEEVENT, this._onFullscreenChange);
|
|
1188
|
-
if (typeof this._elementRef.current?.offsetHeight ===
|
|
1193
|
+
if (typeof this._elementRef.current?.offsetHeight === "number") {
|
|
1189
1194
|
this.setState({
|
|
1190
1195
|
fullscreenState: {
|
|
1191
1196
|
prevHeight: this._elementRef.current.offsetHeight - this._getStatusBarHeight()
|
|
@@ -1217,7 +1222,7 @@ class RCEWrapper extends React.Component {
|
|
|
1217
1222
|
const container = ed.getContainer();
|
|
1218
1223
|
if (container) {
|
|
1219
1224
|
container.style.height = cssHeight;
|
|
1220
|
-
ed.fire(
|
|
1225
|
+
ed.fire("ResizeEditor");
|
|
1221
1226
|
}
|
|
1222
1227
|
const textarea = this.getTextarea();
|
|
1223
1228
|
if (textarea) {
|
|
@@ -1228,10 +1233,10 @@ class RCEWrapper extends React.Component {
|
|
|
1228
1233
|
});
|
|
1229
1234
|
}
|
|
1230
1235
|
focus() {
|
|
1231
|
-
this.onTinyMCEInstance(
|
|
1236
|
+
this.onTinyMCEInstance("mceFocus");
|
|
1232
1237
|
// tinymce doesn't always call the focus handler.
|
|
1233
1238
|
// @ts-expect-error
|
|
1234
|
-
this.handleFocusEditor(new Event(
|
|
1239
|
+
this.handleFocusEditor(new Event("focus", {
|
|
1235
1240
|
target: this.mceInstance()
|
|
1236
1241
|
}));
|
|
1237
1242
|
}
|
|
@@ -1269,7 +1274,7 @@ class RCEWrapper extends React.Component {
|
|
|
1269
1274
|
*/
|
|
1270
1275
|
get _mceSerializedInitialHtml() {
|
|
1271
1276
|
if (!this._mceSerializedInitialHtmlCached) {
|
|
1272
|
-
const el = window.document.createElement(
|
|
1277
|
+
const el = window.document.createElement("div");
|
|
1273
1278
|
// @ts-expect-error
|
|
1274
1279
|
el.innerHTML = this.initialContent;
|
|
1275
1280
|
const serializer = this.mceInstance().serializer;
|
|
@@ -1323,20 +1328,22 @@ class RCEWrapper extends React.Component {
|
|
|
1323
1328
|
// focus is still somewhere w/in me
|
|
1324
1329
|
return;
|
|
1325
1330
|
}
|
|
1326
|
-
const activeClass = document.activeElement
|
|
1331
|
+
const activeClass = document.activeElement?.getAttribute("class");
|
|
1327
1332
|
if (
|
|
1328
1333
|
// @ts-expect-error
|
|
1329
|
-
(event.focusedEditor === undefined ||
|
|
1334
|
+
(event.focusedEditor === undefined ||
|
|
1335
|
+
// @ts-expect-error
|
|
1336
|
+
event.target.id === event.focusedEditor?.id) && activeClass?.includes("tox-")) {
|
|
1330
1337
|
// if a toolbar button has focus, then the user clicks on the "more" button
|
|
1331
1338
|
// focus jumps to the body, then eventually to the popped up toolbar. This
|
|
1332
1339
|
// catches that case.
|
|
1333
1340
|
return;
|
|
1334
1341
|
}
|
|
1335
|
-
if (event?.relatedTarget?.getAttribute(
|
|
1342
|
+
if (event?.relatedTarget?.getAttribute("class")?.includes("tox-")) {
|
|
1336
1343
|
// a tinymce popup has focus
|
|
1337
1344
|
return;
|
|
1338
1345
|
}
|
|
1339
|
-
const popups = document.querySelectorAll(
|
|
1346
|
+
const popups = document.querySelectorAll("[data-mce-component]");
|
|
1340
1347
|
for (const popup of popups) {
|
|
1341
1348
|
if (popup.contains(document.activeElement)) {
|
|
1342
1349
|
// one of our popups has focus
|
|
@@ -1354,21 +1361,22 @@ class RCEWrapper extends React.Component {
|
|
|
1354
1361
|
call(methodName, ...args) {
|
|
1355
1362
|
// since exists? has a ? and cant be a regular function just return true
|
|
1356
1363
|
// rather than calling as a fn on the editor
|
|
1357
|
-
if (methodName ===
|
|
1364
|
+
if (methodName === "exists?") {
|
|
1358
1365
|
return true;
|
|
1359
1366
|
}
|
|
1360
1367
|
// @ts-expect-error
|
|
1361
1368
|
return this[methodName](...args);
|
|
1362
1369
|
}
|
|
1363
1370
|
announceContextToolbars(editor) {
|
|
1364
|
-
editor.on(
|
|
1371
|
+
editor.on("NodeChange", () => {
|
|
1372
|
+
if (!this._isMounted) return;
|
|
1365
1373
|
const node = editor.selection.getNode();
|
|
1366
1374
|
// @ts-expect-error
|
|
1367
1375
|
if (isImageEmbed(node, editor)) {
|
|
1368
1376
|
if (this.announcing !== 1) {
|
|
1369
1377
|
this.setState({
|
|
1370
|
-
announcement: formatMessage(
|
|
1371
|
-
text: node.getAttribute(
|
|
1378
|
+
announcement: formatMessage("type Control F9 to access image options. {text}", {
|
|
1379
|
+
text: node.getAttribute("alt")
|
|
1372
1380
|
})
|
|
1373
1381
|
});
|
|
1374
1382
|
this.announcing = 1;
|
|
@@ -1376,7 +1384,7 @@ class RCEWrapper extends React.Component {
|
|
|
1376
1384
|
} else if (isFileLink(node, editor)) {
|
|
1377
1385
|
if (this.announcing !== 2) {
|
|
1378
1386
|
this.setState({
|
|
1379
|
-
announcement: formatMessage(
|
|
1387
|
+
announcement: formatMessage("type Control F9 to access link options. {text}", {
|
|
1380
1388
|
text: node.textContent
|
|
1381
1389
|
})
|
|
1382
1390
|
});
|
|
@@ -1385,7 +1393,7 @@ class RCEWrapper extends React.Component {
|
|
|
1385
1393
|
} else if (isElementWithinTable(node)) {
|
|
1386
1394
|
if (this.announcing !== 3) {
|
|
1387
1395
|
this.setState({
|
|
1388
|
-
announcement: formatMessage(
|
|
1396
|
+
announcement: formatMessage("type Control F9 to access table options. {text}", {
|
|
1389
1397
|
text: node.textContent
|
|
1390
1398
|
})
|
|
1391
1399
|
});
|
|
@@ -1398,17 +1406,17 @@ class RCEWrapper extends React.Component {
|
|
|
1398
1406
|
this.announcing = 0;
|
|
1399
1407
|
}
|
|
1400
1408
|
});
|
|
1401
|
-
editor.on(
|
|
1409
|
+
editor.on("ResizeEditor", ({
|
|
1402
1410
|
deltaY
|
|
1403
1411
|
}) => {
|
|
1404
|
-
if (!deltaY) return;
|
|
1412
|
+
if (!this._isMounted || !deltaY) return;
|
|
1405
1413
|
if (deltaY < 0) {
|
|
1406
1414
|
this.setState({
|
|
1407
|
-
announcement: formatMessage(
|
|
1415
|
+
announcement: formatMessage("The height of Rich Content Area is decreased.")
|
|
1408
1416
|
});
|
|
1409
1417
|
} else {
|
|
1410
1418
|
this.setState({
|
|
1411
|
-
announcement: formatMessage(
|
|
1419
|
+
announcement: formatMessage("The height of Rich Content Area is increased.")
|
|
1412
1420
|
});
|
|
1413
1421
|
}
|
|
1414
1422
|
});
|
|
@@ -1434,20 +1442,21 @@ class RCEWrapper extends React.Component {
|
|
|
1434
1442
|
// This doesn't apply if the editor is off-screen or has visibility:hidden;
|
|
1435
1443
|
// only if it isn't rendered or has display:none;
|
|
1436
1444
|
const editorVisible = this.editor.getContainer().offsetParent;
|
|
1437
|
-
return this.props.autosave?.enabled && editorVisible && document.querySelectorAll(
|
|
1445
|
+
return this.props.autosave?.enabled && editorVisible && document.querySelectorAll(".rce-wrapper").length === 1 && storageAvailable();
|
|
1438
1446
|
}
|
|
1439
1447
|
get autoSaveKey() {
|
|
1440
|
-
const userId = this._effectiveContainingContext?.userId ||
|
|
1448
|
+
const userId = this._effectiveContainingContext?.userId || "-";
|
|
1441
1449
|
return `rceautosave:${userId}${window.location.href}:${this.props.textareaId}`;
|
|
1442
1450
|
}
|
|
1443
1451
|
componentWillUnmount() {
|
|
1452
|
+
this._isMounted = false;
|
|
1444
1453
|
if (this.state.shouldShowEditor) {
|
|
1445
1454
|
window.clearTimeout(this.blurTimer);
|
|
1446
1455
|
if (!this._destroyCalled) {
|
|
1447
1456
|
this.destroy();
|
|
1448
1457
|
}
|
|
1449
1458
|
if (this._elementRef.current) {
|
|
1450
|
-
this._elementRef.current.removeEventListener(
|
|
1459
|
+
this._elementRef.current.removeEventListener("keydown", this.handleKey, true);
|
|
1451
1460
|
}
|
|
1452
1461
|
this.mutationObserver?.disconnect();
|
|
1453
1462
|
this.intersectionObserver?.disconnect();
|
|
@@ -1459,27 +1468,27 @@ class RCEWrapper extends React.Component {
|
|
|
1459
1468
|
|
|
1460
1469
|
// @ts-expect-error
|
|
1461
1470
|
const setupCallback = options.setup;
|
|
1462
|
-
const canvasPlugins = rcsExists ? [
|
|
1471
|
+
const canvasPlugins = rcsExists ? ["instructure_image", "instructure_documents", "instructure_equation"] : [];
|
|
1463
1472
|
if (rcsExists && !this.props.instRecordDisabled) {
|
|
1464
|
-
canvasPlugins.splice(2, 0,
|
|
1473
|
+
canvasPlugins.splice(2, 0, "instructure_record");
|
|
1465
1474
|
}
|
|
1466
|
-
const pastePlugins = rcsExists ? [
|
|
1467
|
-
if (rcsExists && this.props.use_rce_icon_maker && this.props.trayProps?.contextType ===
|
|
1468
|
-
canvasPlugins.push(
|
|
1475
|
+
const pastePlugins = rcsExists ? ["instructure_paste", "paste"] : ["paste"];
|
|
1476
|
+
if (rcsExists && this.props.use_rce_icon_maker && this.props.trayProps?.contextType === "course") {
|
|
1477
|
+
canvasPlugins.push("instructure_icon_maker");
|
|
1469
1478
|
}
|
|
1470
1479
|
if (document[FS_ENABLED]) {
|
|
1471
|
-
canvasPlugins.push(
|
|
1480
|
+
canvasPlugins.push("instructure_fullscreen");
|
|
1472
1481
|
}
|
|
1473
1482
|
if (this.getRequiredFeatureStatuses().rce_find_replace) {
|
|
1474
|
-
canvasPlugins.push(
|
|
1475
|
-
canvasPlugins.push(
|
|
1483
|
+
canvasPlugins.push("searchreplace");
|
|
1484
|
+
canvasPlugins.push("instructure_search_and_replace");
|
|
1476
1485
|
}
|
|
1477
|
-
const possibleNewMenubarItems = this.props.editorOptions.menu ? Object.keys(this.props.editorOptions.menu).join(
|
|
1486
|
+
const possibleNewMenubarItems = this.props.editorOptions.menu ? Object.keys(this.props.editorOptions.menu).join(" ") : undefined;
|
|
1478
1487
|
const wrappedOpts = {
|
|
1479
1488
|
...defaultTinymceConfig,
|
|
1480
1489
|
...options,
|
|
1481
1490
|
readonly: this.props.readOnly,
|
|
1482
|
-
theme:
|
|
1491
|
+
theme: "silver",
|
|
1483
1492
|
// some older code specified 'modern', which doesn't exist any more
|
|
1484
1493
|
|
|
1485
1494
|
// @ts-expect-error
|
|
@@ -1488,7 +1497,7 @@ class RCEWrapper extends React.Component {
|
|
|
1488
1497
|
document_base_url: this.props.canvasOrigin,
|
|
1489
1498
|
block_formats:
|
|
1490
1499
|
// @ts-expect-error
|
|
1491
|
-
options.block_formats || [`${formatMessage(
|
|
1500
|
+
options.block_formats || [`${formatMessage("Heading 2")}=h2`, `${formatMessage("Heading 3")}=h3`, `${formatMessage("Heading 4")}=h4`, `${formatMessage("Preformatted")}=pre`, `${formatMessage("Paragraph")}=p`].join("; "),
|
|
1492
1501
|
setup: editor => {
|
|
1493
1502
|
addKebabIcon(editor);
|
|
1494
1503
|
editorWrappers.set(editor, this);
|
|
@@ -1501,7 +1510,7 @@ class RCEWrapper extends React.Component {
|
|
|
1501
1510
|
// @ts-expect-error
|
|
1502
1511
|
bridge.userLocale = userLocale;
|
|
1503
1512
|
bridge.canvasOrigin = this.props.canvasOrigin;
|
|
1504
|
-
if (typeof setupCallback ===
|
|
1513
|
+
if (typeof setupCallback === "function") {
|
|
1505
1514
|
setupCallback(editor);
|
|
1506
1515
|
}
|
|
1507
1516
|
},
|
|
@@ -1512,7 +1521,7 @@ class RCEWrapper extends React.Component {
|
|
|
1512
1521
|
// @ts-expect-error
|
|
1513
1522
|
content_css: options.content_css || [],
|
|
1514
1523
|
// @ts-expect-error
|
|
1515
|
-
content_style: contentCSS + (options.content_style ||
|
|
1524
|
+
content_style: contentCSS + (options.content_style || ""),
|
|
1516
1525
|
menubar: mergeMenuItems(getMenubarForVariant(this.variant), possibleNewMenubarItems),
|
|
1517
1526
|
// default menu options listed at https://www.tiny.cloud/docs/configure/editor-appearance/#menu
|
|
1518
1527
|
// tinymce's default edit and table menus are fine
|
|
@@ -1527,10 +1536,10 @@ class RCEWrapper extends React.Component {
|
|
|
1527
1536
|
getToolbarForVariant(this.variant, this.ltiToolFavorites),
|
|
1528
1537
|
// @ts-expect-error
|
|
1529
1538
|
options.toolbar),
|
|
1530
|
-
contextmenu:
|
|
1539
|
+
contextmenu: "",
|
|
1531
1540
|
// show the browser's native context menu
|
|
1532
1541
|
|
|
1533
|
-
toolbar_mode:
|
|
1542
|
+
toolbar_mode: "sliding",
|
|
1534
1543
|
toolbar_sticky: true,
|
|
1535
1544
|
// In regards to the ability to disable plugins:
|
|
1536
1545
|
// we only have to explicitly manage the removal of plugins
|
|
@@ -1539,16 +1548,16 @@ class RCEWrapper extends React.Component {
|
|
|
1539
1548
|
// handles all of that complexity. It that ever changes in the
|
|
1540
1549
|
// future in an upgraded version, we will have to update the
|
|
1541
1550
|
// logic in those other places as well.
|
|
1542
|
-
plugins: mergePlugins([
|
|
1551
|
+
plugins: mergePlugins(["autolink", "media", "table", "link", "directionality", "lists", "textpattern", "hr", "instructure_color", "instructure-ui-icons", "instructure_condensed_buttons", "instructure_links", "instructure_html_view", "instructure_media_embed", "a11y_checker", "wordcount", "instructure_wordcount", "instructure_wordcount_header", "instructure_keyboard_shortcuts_header", "instructure_studio_media_options", "instructure_rce_external_tools", ...pastePlugins, ...canvasPlugins],
|
|
1543
1552
|
// filter out the plugins designated for removal
|
|
1544
1553
|
// @ts-expect-error
|
|
1545
|
-
sanitizePlugins(options.plugins)?.filter(p => p.length > 0 && p[0] !==
|
|
1554
|
+
sanitizePlugins(options.plugins)?.filter(p => p.length > 0 && p[0] !== "-"), this.pluginsToExclude),
|
|
1546
1555
|
textpattern_patterns: [{
|
|
1547
|
-
start:
|
|
1548
|
-
cmd:
|
|
1556
|
+
start: "* ",
|
|
1557
|
+
cmd: "InsertUnorderedList"
|
|
1549
1558
|
}, {
|
|
1550
|
-
start:
|
|
1551
|
-
cmd:
|
|
1559
|
+
start: "- ",
|
|
1560
|
+
cmd: "InsertUnorderedList"
|
|
1552
1561
|
}]
|
|
1553
1562
|
};
|
|
1554
1563
|
if (this.props.trayProps) {
|
|
@@ -1570,7 +1579,7 @@ class RCEWrapper extends React.Component {
|
|
|
1570
1579
|
}
|
|
1571
1580
|
unhandleTextareaChange() {
|
|
1572
1581
|
if (this._textareaEl) {
|
|
1573
|
-
this._textareaEl.removeEventListener(
|
|
1582
|
+
this._textareaEl.removeEventListener("input", this.handleTextareaChange);
|
|
1574
1583
|
}
|
|
1575
1584
|
}
|
|
1576
1585
|
registerTextareaChange() {
|
|
@@ -1578,7 +1587,7 @@ class RCEWrapper extends React.Component {
|
|
|
1578
1587
|
if (this._textareaEl !== el) {
|
|
1579
1588
|
this.unhandleTextareaChange();
|
|
1580
1589
|
if (el) {
|
|
1581
|
-
el.addEventListener(
|
|
1590
|
+
el.addEventListener("input", this.handleTextareaChange);
|
|
1582
1591
|
if (this.props.textareaClassName) {
|
|
1583
1592
|
// split the string on whitespace because classList doesn't let you add multiple
|
|
1584
1593
|
// space seperated classes at a time but does let you add an array of them
|
|
@@ -1589,6 +1598,7 @@ class RCEWrapper extends React.Component {
|
|
|
1589
1598
|
}
|
|
1590
1599
|
}
|
|
1591
1600
|
componentDidMount() {
|
|
1601
|
+
this._isMounted = true;
|
|
1592
1602
|
if (this.state.shouldShowEditor) {
|
|
1593
1603
|
this.editorReallyDidMount();
|
|
1594
1604
|
} else {
|
|
@@ -1603,7 +1613,7 @@ class RCEWrapper extends React.Component {
|
|
|
1603
1613
|
// initialize the RCE when it gets close to entering the viewport
|
|
1604
1614
|
{
|
|
1605
1615
|
root: null,
|
|
1606
|
-
rootMargin:
|
|
1616
|
+
rootMargin: "200px 0px",
|
|
1607
1617
|
threshold: 0.0
|
|
1608
1618
|
});
|
|
1609
1619
|
// @ts-expect-error
|
|
@@ -1622,7 +1632,7 @@ class RCEWrapper extends React.Component {
|
|
|
1622
1632
|
this.focusCurrentView();
|
|
1623
1633
|
}
|
|
1624
1634
|
if (prevProps.readOnly !== this.props.readOnly) {
|
|
1625
|
-
this.mceInstance().mode.set(this.props.readOnly ?
|
|
1635
|
+
this.mceInstance().mode.set(this.props.readOnly ? "readonly" : "design");
|
|
1626
1636
|
}
|
|
1627
1637
|
}
|
|
1628
1638
|
}
|
|
@@ -1636,7 +1646,7 @@ class RCEWrapper extends React.Component {
|
|
|
1636
1646
|
this._tagTinymceAuxDiv();
|
|
1637
1647
|
this.registerTextareaChange();
|
|
1638
1648
|
// @ts-expect-error
|
|
1639
|
-
this._elementRef.current.addEventListener(
|
|
1649
|
+
this._elementRef.current.addEventListener("keydown", this.handleKey, true);
|
|
1640
1650
|
// give the textarea its initial size
|
|
1641
1651
|
this.onResize(null, {
|
|
1642
1652
|
deltaY: 0
|
|
@@ -1644,7 +1654,7 @@ class RCEWrapper extends React.Component {
|
|
|
1644
1654
|
// Preload the LTI Tools modal
|
|
1645
1655
|
// This helps with loading the favorited external tools
|
|
1646
1656
|
if (this.ltiToolFavorites.length > 0) {
|
|
1647
|
-
import(
|
|
1657
|
+
import("./plugins/instructure_rce_external_tools/components/ExternalToolSelectionDialog/ExternalToolSelectionDialog");
|
|
1648
1658
|
}
|
|
1649
1659
|
bridge.renderEditor(this);
|
|
1650
1660
|
}
|
|
@@ -1666,9 +1676,9 @@ class RCEWrapper extends React.Component {
|
|
|
1666
1676
|
fallback: /*#__PURE__*/React.createElement("div", {
|
|
1667
1677
|
style: {
|
|
1668
1678
|
height: this.state.height,
|
|
1669
|
-
display:
|
|
1670
|
-
justifyContent:
|
|
1671
|
-
alignItems:
|
|
1679
|
+
display: "flex",
|
|
1680
|
+
justifyContent: "center",
|
|
1681
|
+
alignItems: "center"
|
|
1672
1682
|
}
|
|
1673
1683
|
}, /*#__PURE__*/React.createElement(Spinner, {
|
|
1674
1684
|
renderTitle: renderLoading,
|
|
@@ -1704,7 +1714,7 @@ class RCEWrapper extends React.Component {
|
|
|
1704
1714
|
ref: this._editorPlaceholderRef,
|
|
1705
1715
|
style: {
|
|
1706
1716
|
height: `${this.props.editorOptions.height}px`,
|
|
1707
|
-
border:
|
|
1717
|
+
border: "1px solid grey"
|
|
1708
1718
|
}
|
|
1709
1719
|
});
|
|
1710
1720
|
}
|
|
@@ -1730,8 +1740,8 @@ class RCEWrapper extends React.Component {
|
|
|
1730
1740
|
// @ts-expect-error
|
|
1731
1741
|
,
|
|
1732
1742
|
ref: this._elementRef,
|
|
1733
|
-
style: this.variant ===
|
|
1734
|
-
marginBottom:
|
|
1743
|
+
style: this.variant === "full" ? {
|
|
1744
|
+
marginBottom: ".5rem"
|
|
1735
1745
|
} : undefined,
|
|
1736
1746
|
onFocus: this.handleFocusRCE,
|
|
1737
1747
|
onBlur: this.handleBlurRCE
|
|
@@ -1739,7 +1749,7 @@ class RCEWrapper extends React.Component {
|
|
|
1739
1749
|
id: `show-on-focus-btn-${this.id}`,
|
|
1740
1750
|
onClick: this.openKBShortcutModal,
|
|
1741
1751
|
margin: "xx-small",
|
|
1742
|
-
screenReaderLabel: formatMessage(
|
|
1752
|
+
screenReaderLabel: formatMessage("View keyboard shortcuts")
|
|
1743
1753
|
// @ts-expect-error
|
|
1744
1754
|
,
|
|
1745
1755
|
ref: el => this._showOnFocusButton = el
|
|
@@ -1751,7 +1761,7 @@ class RCEWrapper extends React.Component {
|
|
|
1751
1761
|
afterDismiss: this.removeAlert
|
|
1752
1762
|
}), this.state.editorView === PRETTY_HTML_EDITOR_VIEW && this.renderHtmlEditor(), /*#__PURE__*/React.createElement("div", {
|
|
1753
1763
|
style: {
|
|
1754
|
-
display: this.state.editorView === PRETTY_HTML_EDITOR_VIEW ?
|
|
1764
|
+
display: this.state.editorView === PRETTY_HTML_EDITOR_VIEW ? "none" : "block"
|
|
1755
1765
|
}
|
|
1756
1766
|
}, /*#__PURE__*/React.createElement(Editor, {
|
|
1757
1767
|
id: mceProps.textareaId,
|
|
@@ -1841,13 +1851,10 @@ class RCEWrapper extends React.Component {
|
|
|
1841
1851
|
open: this.state.confirmAutoSave,
|
|
1842
1852
|
onNo: () => this.restoreAutoSave(false),
|
|
1843
1853
|
onYes: () => this.restoreAutoSave(true)
|
|
1844
|
-
})) : null,
|
|
1845
|
-
/*#__PURE__*/
|
|
1846
|
-
// @ts-expect-error
|
|
1847
|
-
React.createElement(Alert, {
|
|
1854
|
+
})) : null, /*#__PURE__*/React.createElement(Alert, {
|
|
1848
1855
|
screenReaderOnly: true,
|
|
1849
1856
|
liveRegion: this.props.liveRegion
|
|
1850
|
-
}, this.state.announcement));
|
|
1857
|
+
}, this.state.announcement || null));
|
|
1851
1858
|
}));
|
|
1852
1859
|
}
|
|
1853
1860
|
}
|
|
@@ -1891,8 +1898,8 @@ RCEWrapper.defaultProps = {
|
|
|
1891
1898
|
maxInitRenderedRCEs: -1,
|
|
1892
1899
|
features: {},
|
|
1893
1900
|
timezone: Intl?.DateTimeFormat()?.resolvedOptions()?.timeZone,
|
|
1894
|
-
canvasOrigin:
|
|
1895
|
-
variant:
|
|
1901
|
+
canvasOrigin: "",
|
|
1902
|
+
variant: "full"
|
|
1896
1903
|
};
|
|
1897
1904
|
RCEWrapper.skinCssInjected = false;
|
|
1898
1905
|
export default RCEWrapper;
|