@instructure/canvas-rce 5.9.0 → 5.10.1
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/.mocharc.js +7 -0
- package/CHANGELOG.md +17 -0
- package/es/enhance-user-content/enhance_user_content.js +9 -1
- package/es/enhance-user-content/mathml.js +8 -5
- package/es/rce/RCEWrapper.js +0 -40
- package/es/rce/plugins/instructure_equation/EquationEditorModal/parseLatex.js +0 -2
- package/es/rce/plugins/instructure_rce_external_tools/components/ExternalToolDialog/ExternalToolDialogModal.js +4 -5
- package/es/rce/plugins/instructure_rce_external_tools/lti13-content-items/models/ResourceLinkContentItem.js +1 -1
- package/es/rce/plugins/shared/CanvasContentTray.js +8 -8
- package/es/rce/plugins/shared/ContentSelection.js +7 -3
- package/es/rce/plugins/shared/ImageCropper/Preview.js +8 -7
- package/es/rce/plugins/shared/LinkDisplay.js +2 -2
- package/es/rce/plugins/shared/fileTypeUtils.js +14 -6
- package/es/rce/plugins/tinymce-a11y-checker/rules/large-text-contrast.js +9 -0
- package/es/rce/plugins/tinymce-a11y-checker/rules/small-text-contrast.js +9 -0
- package/es/rce/transformContent.js +8 -0
- package/es/sidebar/actions/upload.js +3 -1
- package/es/translations/locales/de.js +4 -4
- package/jest/jest-setup.js +0 -1
- package/lib/enhance-user-content/enhance_user_content.js +9 -1
- package/lib/enhance-user-content/mathml.js +8 -5
- package/lib/rce/RCEWrapper.js +0 -40
- package/lib/rce/plugins/instructure_equation/EquationEditorModal/parseLatex.js +0 -2
- package/lib/rce/plugins/instructure_rce_external_tools/components/ExternalToolDialog/ExternalToolDialogModal.js +4 -5
- package/lib/rce/plugins/instructure_rce_external_tools/lti13-content-items/models/ResourceLinkContentItem.js +1 -1
- package/lib/rce/plugins/shared/CanvasContentTray.js +8 -8
- package/lib/rce/plugins/shared/ContentSelection.js +7 -3
- package/lib/rce/plugins/shared/ImageCropper/Preview.js +8 -7
- package/lib/rce/plugins/shared/LinkDisplay.js +2 -2
- package/lib/rce/plugins/shared/fileTypeUtils.js +14 -6
- package/lib/rce/plugins/tinymce-a11y-checker/rules/large-text-contrast.js +9 -0
- package/lib/rce/plugins/tinymce-a11y-checker/rules/small-text-contrast.js +9 -0
- package/lib/rce/transformContent.js +8 -0
- package/lib/sidebar/actions/upload.js +3 -1
- package/lib/translations/locales/de.js +4 -4
- package/package.json +4 -4
- package/canvas/README.md +0 -84
- package/canvas/locales/en.json +0 -934
- package/canvas/package.json +0 -189
- package/es/rce/getBrowser.js +0 -53
- package/lib/rce/getBrowser.js +0 -53
package/.mocharc.js
CHANGED
|
@@ -15,6 +15,13 @@
|
|
|
15
15
|
* You should have received a copy of the GNU Affero General Public License along
|
|
16
16
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17
17
|
*/
|
|
18
|
+
|
|
19
|
+
global.MutationObserver = class {
|
|
20
|
+
disconnect() {}
|
|
21
|
+
|
|
22
|
+
observe() {}
|
|
23
|
+
}
|
|
24
|
+
|
|
18
25
|
module.exports = {
|
|
19
26
|
require: [
|
|
20
27
|
'@instructure/canvas-theme',
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,23 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## 5.10.1 - 2023-12-01
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- Allow more fields from Canvas media object creation
|
|
12
|
+
- Ensure postMessage works with RCE LTI launches
|
|
13
|
+
|
|
14
|
+
## 5.10.0 - 2023-09-26
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
- An issue where media controls don't respond in Safari
|
|
18
|
+
- An issue where embedded Studio videos cause unresponsiveness
|
|
19
|
+
- A potential race condition in postMessage forwarding
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
- Ignore a11y check on elements with a background image or gradient
|
|
23
|
+
- Remove math processing percentage indicator
|
|
24
|
+
|
|
8
25
|
## 5.9.0 - 2023-08-30
|
|
9
26
|
|
|
10
27
|
### Fixed
|
|
@@ -216,8 +216,16 @@ export function enhanceUserContent() {
|
|
|
216
216
|
iframeElem.setAttribute('src', addParentFrameContextToUrl(src, containingCanvasLtiToolId));
|
|
217
217
|
}
|
|
218
218
|
});
|
|
219
|
-
}
|
|
219
|
+
} // tell LTI tools that they are launching from within the active RCE
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
unenhanced_elem.querySelectorAll('iframe[src]').forEach(iframeElem => {
|
|
223
|
+
const src = iframeElem.getAttribute('src');
|
|
220
224
|
|
|
225
|
+
if (src.startsWith(canvasOrigin)) {
|
|
226
|
+
iframeElem.setAttribute('src', src.replace('display=in_rce', 'display=borderless'));
|
|
227
|
+
}
|
|
228
|
+
});
|
|
221
229
|
unenhanced_elem.querySelectorAll('a:not(.not_external, .external)').forEach(childLink => {
|
|
222
230
|
if (!isExternalLink(childLink, canvasOrigin)) return;
|
|
223
231
|
if (childLink.tagName === 'IMG' || childLink.querySelectorAll('img').length > 0) return;
|
|
@@ -45,7 +45,8 @@ const localConfig = {
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
},
|
|
48
|
-
showMathMenu: true
|
|
48
|
+
showMathMenu: true,
|
|
49
|
+
messageStyle: 'none'
|
|
49
50
|
};
|
|
50
51
|
|
|
51
52
|
class Mathml {
|
|
@@ -106,7 +107,7 @@ class Mathml {
|
|
|
106
107
|
window.MathJax.Hub.Register.MessageHook('Math Processing Error', function (message) {
|
|
107
108
|
var _elem$parentElement;
|
|
108
109
|
|
|
109
|
-
const elem = message[1]; // ".math_equation_latex" is the elem we added for MathJax to typeset the image equation
|
|
110
|
+
const elem = Array.isArray(message[1]) ? message[1][0] : message[1]; // ".math_equation_latex" is the elem we added for MathJax to typeset the image equation
|
|
110
111
|
|
|
111
112
|
if ((_elem$parentElement = elem.parentElement) !== null && _elem$parentElement !== void 0 && _elem$parentElement.classList.contains('math_equation_latex')) {
|
|
112
113
|
var _elem$parentElement$p;
|
|
@@ -123,7 +124,7 @@ class Mathml {
|
|
|
123
124
|
}
|
|
124
125
|
});
|
|
125
126
|
window.MathJax.Hub.Register.MessageHook('End Math', function (message) {
|
|
126
|
-
const elem = message[1];
|
|
127
|
+
const elem = Array.isArray(message[1]) ? message[1][0] : message[1];
|
|
127
128
|
mathImageHelper.removeStrayEquationImages(elem);
|
|
128
129
|
mathImageHelper.nearlyInfiniteStyleFix(elem);
|
|
129
130
|
elem.querySelectorAll('.math_equation_latex').forEach(m => m.classList.add('fade-in-equation'));
|
|
@@ -138,7 +139,8 @@ class Mathml {
|
|
|
138
139
|
// Since we want to ignore <math> in .hidden-readable spans, let's remove the MathJunk™
|
|
139
140
|
// right after MathJax adds it.
|
|
140
141
|
window.MathJax.Hub.Register.MessageHook('End Math', function (message) {
|
|
141
|
-
|
|
142
|
+
const elm = Array.isArray(message[1]) ? message[1][0] : message[1];
|
|
143
|
+
$(elm).find('.hidden-readable [class^="MathJax"], .hidden-readable [id^="MathJax"]').remove();
|
|
142
144
|
});
|
|
143
145
|
} // leaving this here so I don't have to keep looking up how to see all messages
|
|
144
146
|
// window.MathJax.Hub.Startup.signal.Interest(function (message) {
|
|
@@ -315,7 +317,8 @@ const mathImageHelper = {
|
|
|
315
317
|
},
|
|
316
318
|
|
|
317
319
|
catchEquationImages(refnode) {
|
|
318
|
-
// find equation images and replace with inline LaTeX
|
|
320
|
+
refnode = Array.isArray(refnode) ? refnode[0] : refnode; // find equation images and replace with inline LaTeX
|
|
321
|
+
|
|
319
322
|
const eqimgs = refnode.querySelectorAll('img.equation_image');
|
|
320
323
|
|
|
321
324
|
if (eqimgs.length > 0) {
|
package/es/rce/RCEWrapper.js
CHANGED
|
@@ -2714,48 +2714,9 @@ class RCEWrapper extends React.Component {
|
|
|
2714
2714
|
|
|
2715
2715
|
this.checkAccessibility();
|
|
2716
2716
|
this.fixToolbarKeyboardNavigation();
|
|
2717
|
-
this.forwardPostMessages();
|
|
2718
2717
|
(_this$props$onInitted = (_this$props = this.props).onInitted) === null || _this$props$onInitted === void 0 ? void 0 : _this$props$onInitted.call(_this$props, editor);
|
|
2719
2718
|
};
|
|
2720
2719
|
|
|
2721
|
-
this.forwardPostMessages = () => {
|
|
2722
|
-
const windowReferences = {};
|
|
2723
|
-
const rceWindow = this.editor.getWin(); // explicitly assign name for reference by parent window
|
|
2724
|
-
|
|
2725
|
-
rceWindow.name = `${RCEWrapper.editorFrameName}_${this.id}`;
|
|
2726
|
-
rceWindow.addEventListener('message', this.forwardPostMessagesHandler(rceWindow, windowReferences));
|
|
2727
|
-
};
|
|
2728
|
-
|
|
2729
|
-
this.forwardPostMessagesHandler = (rceWindow, windowReferences) => e => {
|
|
2730
|
-
let message;
|
|
2731
|
-
|
|
2732
|
-
try {
|
|
2733
|
-
message = typeof e.data === 'string' ? JSON.parse(e.data) : e.data;
|
|
2734
|
-
} catch (err) {
|
|
2735
|
-
// unparseable message may not be meant for our handlers
|
|
2736
|
-
return false;
|
|
2737
|
-
}
|
|
2738
|
-
|
|
2739
|
-
if (e.origin === rceWindow.origin) {
|
|
2740
|
-
// message is from Canvas window, forward to tool
|
|
2741
|
-
const targetOrigin = message.toolOrigin;
|
|
2742
|
-
|
|
2743
|
-
if (!targetOrigin) {
|
|
2744
|
-
return false;
|
|
2745
|
-
}
|
|
2746
|
-
|
|
2747
|
-
const targetWindow = windowReferences[targetOrigin];
|
|
2748
|
-
delete message.toolOrigin;
|
|
2749
|
-
targetWindow === null || targetWindow === void 0 ? void 0 : targetWindow.postMessage(message, targetOrigin);
|
|
2750
|
-
} else {
|
|
2751
|
-
// message is from tool, forward to Canvas window
|
|
2752
|
-
windowReferences[e.origin] = e.source;
|
|
2753
|
-
message.toolOrigin = e.origin;
|
|
2754
|
-
message.frameName = rceWindow.name;
|
|
2755
|
-
rceWindow.parent.postMessage(message, rceWindow.origin);
|
|
2756
|
-
}
|
|
2757
|
-
};
|
|
2758
|
-
|
|
2759
2720
|
this.fixToolbarKeyboardNavigation = () => {
|
|
2760
2721
|
var _this$_elementRef$cur2;
|
|
2761
2722
|
|
|
@@ -4238,7 +4199,6 @@ RCEWrapper.defaultProps = {
|
|
|
4238
4199
|
canvasOrigin: ''
|
|
4239
4200
|
};
|
|
4240
4201
|
RCEWrapper.skinCssInjected = false;
|
|
4241
|
-
RCEWrapper.editorFrameName = 'active_rce_frame';
|
|
4242
4202
|
|
|
4243
4203
|
function mergeMenuItems(standard, custom) {
|
|
4244
4204
|
var _custom$trim;
|
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
19
19
|
*/
|
|
20
20
|
import React from 'react';
|
|
21
|
-
import { Flex } from '@instructure/ui-flex';
|
|
22
21
|
import { Heading } from '@instructure/ui-heading';
|
|
23
22
|
import { CloseButton } from '@instructure/ui-buttons';
|
|
24
23
|
import { View } from '@instructure/ui-view';
|
|
@@ -33,12 +32,12 @@ export function ExternalToolDialogModal(props) {
|
|
|
33
32
|
onOpen: props.onOpen,
|
|
34
33
|
onClose: props.onClose,
|
|
35
34
|
mountNode: props.mountNode
|
|
36
|
-
}, /*#__PURE__*/React.createElement(Modal.Header, null, /*#__PURE__*/React.createElement(
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
}, /*#__PURE__*/React.createElement(Modal.Header, null, /*#__PURE__*/React.createElement(Heading, null, props.name), /*#__PURE__*/React.createElement(CloseButton, {
|
|
36
|
+
placement: "end",
|
|
37
|
+
offset: "medium",
|
|
39
38
|
onClick: props.onCloseButton,
|
|
40
39
|
screenReaderLabel: formatMessage('Close')
|
|
41
|
-
}))
|
|
40
|
+
})), /*#__PURE__*/React.createElement(Modal.Body, {
|
|
42
41
|
padding: "0"
|
|
43
42
|
}, /*#__PURE__*/React.createElement(View, {
|
|
44
43
|
as: "div",
|
|
@@ -35,7 +35,7 @@ export default class ResourceLinkContentItem extends BaseLinkContentItem {
|
|
|
35
35
|
|
|
36
36
|
buildUrl() {
|
|
37
37
|
return addQueryParamsToUrl(this.context.ltiEndpoint, {
|
|
38
|
-
display: '
|
|
38
|
+
display: 'in_rce',
|
|
39
39
|
resource_link_lookup_uuid: this.lookup_uuid,
|
|
40
40
|
[PARENT_FRAME_CONTEXT_PARAM]: this.context.containingCanvasLtiToolId
|
|
41
41
|
});
|
|
@@ -22,6 +22,7 @@ import { CloseButton, Button } from '@instructure/ui-buttons';
|
|
|
22
22
|
import { Heading } from '@instructure/ui-heading';
|
|
23
23
|
import { Spinner } from '@instructure/ui-spinner';
|
|
24
24
|
import { Flex } from '@instructure/ui-flex';
|
|
25
|
+
import { View } from '@instructure/ui-view';
|
|
25
26
|
import ErrorBoundary from './ErrorBoundary';
|
|
26
27
|
import Bridge from '../../../bridge/Bridge';
|
|
27
28
|
import formatMessage from '../../../format-message';
|
|
@@ -463,19 +464,18 @@ export default function CanvasContentTray(props) {
|
|
|
463
464
|
}, /*#__PURE__*/React.createElement(Flex.Item, {
|
|
464
465
|
padding: "medium",
|
|
465
466
|
shadow: "above"
|
|
466
|
-
}, /*#__PURE__*/React.createElement(
|
|
467
|
+
}, /*#__PURE__*/React.createElement(View, {
|
|
468
|
+
as: "div",
|
|
467
469
|
margin: "none none medium none"
|
|
468
|
-
}, /*#__PURE__*/React.createElement(Flex.Item, {
|
|
469
|
-
shouldgrow: true,
|
|
470
|
-
shouldshrink: true
|
|
471
470
|
}, /*#__PURE__*/React.createElement(Heading, {
|
|
472
471
|
level: "h2"
|
|
473
|
-
}, getHeader())
|
|
472
|
+
}, getHeader()), /*#__PURE__*/React.createElement(CloseButton, {
|
|
474
473
|
placement: "end",
|
|
474
|
+
offset: "medium",
|
|
475
475
|
onClick: handleDismissTray,
|
|
476
476
|
"data-testid": "CloseButton_ContentTray",
|
|
477
477
|
screenReaderLabel: formatMessage('Close')
|
|
478
|
-
}))
|
|
478
|
+
})), isEditTray && /*#__PURE__*/React.createElement(LinkDisplay, {
|
|
479
479
|
linkText: linkText,
|
|
480
480
|
placeholderText: (link === null || link === void 0 ? void 0 : link.title) || placeholderText,
|
|
481
481
|
linkFileName: (link === null || link === void 0 ? void 0 : link.title) || '',
|
|
@@ -492,8 +492,8 @@ export default function CanvasContentTray(props) {
|
|
|
492
492
|
isContentLoading: isLoading(storeProps),
|
|
493
493
|
use_rce_icon_maker: props.use_rce_icon_maker
|
|
494
494
|
}))), /*#__PURE__*/React.createElement(Flex.Item, {
|
|
495
|
-
|
|
496
|
-
|
|
495
|
+
shouldGrow: true,
|
|
496
|
+
shouldShrink: true,
|
|
497
497
|
margin: "xx-small xxx-small 0",
|
|
498
498
|
elementRef: el => scrollingAreaRef.current = el
|
|
499
499
|
}, /*#__PURE__*/React.createElement(Flex, {
|
|
@@ -32,7 +32,7 @@ export const DISPLAY_AS_EMBED = 'embed';
|
|
|
32
32
|
export const DISPLAY_AS_EMBED_DISABLED = 'embed-disabled';
|
|
33
33
|
export const DISPLAY_AS_DOWNLOAD_LINK = 'download-link';
|
|
34
34
|
export function asImageEmbed($element) {
|
|
35
|
-
const nodeName = $element.nodeName.toLowerCase();
|
|
35
|
+
const nodeName = $element === null || $element === void 0 ? void 0 : $element.nodeName.toLowerCase();
|
|
36
36
|
|
|
37
37
|
if (nodeName !== 'img') {
|
|
38
38
|
return null;
|
|
@@ -44,9 +44,11 @@ export function asImageEmbed($element) {
|
|
|
44
44
|
};
|
|
45
45
|
}
|
|
46
46
|
export function asLink($element, editor) {
|
|
47
|
+
var _$link;
|
|
48
|
+
|
|
47
49
|
let $link = $element;
|
|
48
50
|
|
|
49
|
-
if ($link.tagName !== 'A') {
|
|
51
|
+
if (((_$link = $link) === null || _$link === void 0 ? void 0 : _$link.tagName) !== 'A') {
|
|
50
52
|
// the user may have selected some text that is w/in a link
|
|
51
53
|
// but didn't include the <a>. Let's see if that's true
|
|
52
54
|
$link = editor.dom.getParent($link, 'a[href]');
|
|
@@ -213,7 +215,7 @@ function isMediaElement($element, mediaType) {
|
|
|
213
215
|
|
|
214
216
|
// the video is hosted in an iframe, but tinymce
|
|
215
217
|
// wraps it in a span with swizzled attribute names
|
|
216
|
-
if (!($element !== null && $element !== void 0 && $element.getAttribute)) {
|
|
218
|
+
if (!($element !== null && $element !== void 0 && $element.getAttribute) || !$element) {
|
|
217
219
|
return false;
|
|
218
220
|
}
|
|
219
221
|
|
|
@@ -242,6 +244,8 @@ export function isAudioElement($element) {
|
|
|
242
244
|
export function findMediaPlayerIframe(elem) {
|
|
243
245
|
var _elem$firstElementChi;
|
|
244
246
|
|
|
247
|
+
if (!elem) return null;
|
|
248
|
+
|
|
245
249
|
if (elem.tagName === 'IFRAME') {
|
|
246
250
|
// we have the iframe
|
|
247
251
|
return elem;
|
|
@@ -25,7 +25,6 @@ import { useMouseWheel } from './useMouseWheel';
|
|
|
25
25
|
import { useKeyMouseTouchEvents } from './useKeyMouseEvents';
|
|
26
26
|
import checkerboardStyle from '../CheckerboardStyling';
|
|
27
27
|
import { View } from '@instructure/ui-view';
|
|
28
|
-
import { getBrowser } from '../../../getBrowser';
|
|
29
28
|
/**
|
|
30
29
|
* Remove the node contents and append the svg element.
|
|
31
30
|
*/
|
|
@@ -86,17 +85,19 @@ export const Preview = _ref2 => {
|
|
|
86
85
|
translateY: tempTranslateY,
|
|
87
86
|
rotation,
|
|
88
87
|
scaleRatio: tempScaleRatio
|
|
89
|
-
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
function isSafariVersion15OrLesser() {
|
|
91
|
+
const match = /Version\/(\d+).+Safari/.exec(navigator.userAgent);
|
|
92
|
+
return match ? parseInt(match[1], 10) < 16 : false;
|
|
93
|
+
} // Clip is not supported in Safari until v16.
|
|
90
94
|
// It's needed here to prevent a strange screenreader
|
|
91
95
|
// behavior that makes the cropper look bad. 'hidden'
|
|
92
96
|
// suffices when clip is not available, although it's not perfect
|
|
93
97
|
// TODO: remove when Safari versions >= 16 are more commonplace
|
|
94
98
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
version
|
|
98
|
-
} = getBrowser();
|
|
99
|
-
const overflow = name === 'Safari' && parseFloat(version) < 16 ? 'hidden' : 'clip';
|
|
99
|
+
|
|
100
|
+
const overflow = isSafariVersion15OrLesser() ? 'hidden' : 'clip';
|
|
100
101
|
return /*#__PURE__*/React.createElement("div", {
|
|
101
102
|
style: {
|
|
102
103
|
justifyContent: 'center',
|
|
@@ -81,8 +81,8 @@ export const LinkDisplay = _ref => {
|
|
|
81
81
|
size: "x-small"
|
|
82
82
|
}))), /*#__PURE__*/React.createElement(Flex.Item, {
|
|
83
83
|
padding: "0 x-small 0 0",
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
shouldGrow: true,
|
|
85
|
+
shouldShrink: true,
|
|
86
86
|
textAlign: "start"
|
|
87
87
|
}, /*#__PURE__*/React.createElement(View, {
|
|
88
88
|
as: "div"
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* You should have received a copy of the GNU Affero General Public License along
|
|
16
16
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17
17
|
*/
|
|
18
|
-
import { parse } from 'url';
|
|
18
|
+
import { format, parse } from 'url';
|
|
19
19
|
import { absoluteToRelativeUrl } from '../../../common/fileUrl';
|
|
20
20
|
import { IconAudioLine, IconDocumentLine, IconMsExcelLine, IconMsPptLine, IconMsWordLine, IconPdfLine, IconVideoLine } from '@instructure/ui-icons';
|
|
21
21
|
import RCEGlobals from '../../RCEGlobals';
|
|
@@ -94,13 +94,21 @@ export function mediaPlayerURLFromFile(file, canvasOrigin) {
|
|
|
94
94
|
const type = content_type.replace(/\/.*$/, '');
|
|
95
95
|
|
|
96
96
|
if ((_RCEGlobals$getFeatur = RCEGlobals.getFeatures()) !== null && _RCEGlobals$getFeatur !== void 0 && _RCEGlobals$getFeatur.media_links_use_attachment_id && isAudioOrVideo(content_type) && file.id) {
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
const url = parse(`/media_attachments_iframe/${file.id}`, true);
|
|
98
|
+
url.query.type = type;
|
|
99
|
+
url.query.embedded = true;
|
|
100
|
+
|
|
101
|
+
if (file.uuid && file.contextType == 'User') {
|
|
102
|
+
url.query.verifier = file.uuid;
|
|
103
|
+
} else if (file.url || file.href) {
|
|
104
|
+
const parsed_url = parse(file.url || file.href, true);
|
|
105
|
+
|
|
106
|
+
if (parsed_url.query.verifier) {
|
|
107
|
+
url.query.verifier = parsed_url.query.verifier;
|
|
108
|
+
}
|
|
99
109
|
}
|
|
100
110
|
|
|
101
|
-
|
|
102
|
-
const verifier = parsed_url.query.verifier ? `&verifier=${parsed_url.query.verifier}` : '';
|
|
103
|
-
return `/media_attachments_iframe/${file.id}?type=${type}${verifier}&embedded=true`;
|
|
111
|
+
return format(url);
|
|
104
112
|
}
|
|
105
113
|
|
|
106
114
|
if (file.embedded_iframe_url) {
|
|
@@ -30,6 +30,15 @@ export default {
|
|
|
30
30
|
return true;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
for (let e = elem; e; e = e.parentElement) {
|
|
34
|
+
const bgimage = window.getComputedStyle(e).getPropertyValue('background-image');
|
|
35
|
+
|
|
36
|
+
if (bgimage !== 'none' && bgimage !== '') {
|
|
37
|
+
// ignore background images and gradients
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
33
42
|
return contrast(elem);
|
|
34
43
|
},
|
|
35
44
|
data: smallTextContrast.data,
|
|
@@ -32,6 +32,15 @@ export default {
|
|
|
32
32
|
return true;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
for (let e = elem; e; e = e.parentElement) {
|
|
36
|
+
const bgimage = window.getComputedStyle(e).getPropertyValue('background-image');
|
|
37
|
+
|
|
38
|
+
if (bgimage !== 'none' && bgimage !== '') {
|
|
39
|
+
// ignore background images and gradients
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
35
44
|
return contrast(elem);
|
|
36
45
|
},
|
|
37
46
|
data: elem => {
|
|
@@ -60,6 +60,14 @@ export function transformRceContentForEditing(inputHtml, options) {
|
|
|
60
60
|
for (const attributeName of attributeNamesToRemove) {
|
|
61
61
|
element.removeAttribute(attributeName);
|
|
62
62
|
}
|
|
63
|
+
}); // fixup LTI iframe launches to use the `in_rce` display type
|
|
64
|
+
|
|
65
|
+
container.querySelectorAll('iframe[src]').forEach(element => {
|
|
66
|
+
const src = element.getAttribute('src');
|
|
67
|
+
|
|
68
|
+
if (src !== null && src !== void 0 && src.includes('display=borderless')) {
|
|
69
|
+
element.setAttribute('src', src.replace('display=borderless', 'display=in_rce'));
|
|
70
|
+
}
|
|
63
71
|
});
|
|
64
72
|
return container.innerHTML;
|
|
65
73
|
}
|
|
@@ -272,7 +272,9 @@ export function mediaUploadComplete(error, uploadData) {
|
|
|
272
272
|
media_id: mediaObject.media_object.media_id,
|
|
273
273
|
type: uploadedFile.type,
|
|
274
274
|
title: uploadedFile.title || uploadedFile.name,
|
|
275
|
-
id: mediaObject.media_object.attachment_id
|
|
275
|
+
id: mediaObject.media_object.attachment_id,
|
|
276
|
+
uuid: mediaObject.media_object.uuid,
|
|
277
|
+
contextType: mediaObject.media_object.context_type
|
|
276
278
|
};
|
|
277
279
|
dispatch(removePlaceholdersFor(uploadedFile.name));
|
|
278
280
|
embedUploadResult(embedData, 'media');
|
|
@@ -373,7 +373,7 @@ const locale = {
|
|
|
373
373
|
"message": "{ count, plural,\n one {# Objekt geladen}\n other {# Objekte geladen}\n}"
|
|
374
374
|
},
|
|
375
375
|
"course_documents_104d76e0": {
|
|
376
|
-
"message": "
|
|
376
|
+
"message": "Kursdokumente"
|
|
377
377
|
},
|
|
378
378
|
"course_files_62deb8f8": {
|
|
379
379
|
"message": "Kursdateien"
|
|
@@ -2278,16 +2278,16 @@ const locale = {
|
|
|
2278
2278
|
"message": "Wird von Screenreadern verwendet, um das Video zu beschreiben."
|
|
2279
2279
|
},
|
|
2280
2280
|
"user_documents_c206e61f": {
|
|
2281
|
-
"message": "
|
|
2281
|
+
"message": "Meine Dokumente"
|
|
2282
2282
|
},
|
|
2283
2283
|
"user_files_78e21703": {
|
|
2284
2284
|
"message": "Benutzerdateien"
|
|
2285
2285
|
},
|
|
2286
2286
|
"user_images_b6490852": {
|
|
2287
|
-
"message": "
|
|
2287
|
+
"message": "Meine Bilder"
|
|
2288
2288
|
},
|
|
2289
2289
|
"user_media_14fbf656": {
|
|
2290
|
-
"message": "
|
|
2290
|
+
"message": "Meine Medien"
|
|
2291
2291
|
},
|
|
2292
2292
|
"vector_notation_cf6086ab": {
|
|
2293
2293
|
"message": "Vektor (Notation)"
|
package/jest/jest-setup.js
CHANGED
|
@@ -41,7 +41,6 @@ const ignoredErrors = [
|
|
|
41
41
|
/The prop `videoOptions.naturalHeight` is marked as required in `VideoOptionsTray`/,
|
|
42
42
|
/The prop `sortBy.order` is marked as required in `MediaPanel`/,
|
|
43
43
|
/Invalid prop `images.searchString` of type `string` supplied to `Images`/,
|
|
44
|
-
/Invalid URL: undefined/,
|
|
45
44
|
/failed updating video captions/,
|
|
46
45
|
/You seem to have overlapping act\(\) calls/,
|
|
47
46
|
/A theme registry has already been initialized/,
|
|
@@ -216,8 +216,16 @@ export function enhanceUserContent() {
|
|
|
216
216
|
iframeElem.setAttribute('src', addParentFrameContextToUrl(src, containingCanvasLtiToolId));
|
|
217
217
|
}
|
|
218
218
|
});
|
|
219
|
-
}
|
|
219
|
+
} // tell LTI tools that they are launching from within the active RCE
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
unenhanced_elem.querySelectorAll('iframe[src]').forEach(iframeElem => {
|
|
223
|
+
const src = iframeElem.getAttribute('src');
|
|
220
224
|
|
|
225
|
+
if (src.startsWith(canvasOrigin)) {
|
|
226
|
+
iframeElem.setAttribute('src', src.replace('display=in_rce', 'display=borderless'));
|
|
227
|
+
}
|
|
228
|
+
});
|
|
221
229
|
unenhanced_elem.querySelectorAll('a:not(.not_external, .external)').forEach(childLink => {
|
|
222
230
|
if (!isExternalLink(childLink, canvasOrigin)) return;
|
|
223
231
|
if (childLink.tagName === 'IMG' || childLink.querySelectorAll('img').length > 0) return;
|
|
@@ -45,7 +45,8 @@ const localConfig = {
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
},
|
|
48
|
-
showMathMenu: true
|
|
48
|
+
showMathMenu: true,
|
|
49
|
+
messageStyle: 'none'
|
|
49
50
|
};
|
|
50
51
|
|
|
51
52
|
class Mathml {
|
|
@@ -106,7 +107,7 @@ class Mathml {
|
|
|
106
107
|
window.MathJax.Hub.Register.MessageHook('Math Processing Error', function (message) {
|
|
107
108
|
var _elem$parentElement;
|
|
108
109
|
|
|
109
|
-
const elem = message[1]; // ".math_equation_latex" is the elem we added for MathJax to typeset the image equation
|
|
110
|
+
const elem = Array.isArray(message[1]) ? message[1][0] : message[1]; // ".math_equation_latex" is the elem we added for MathJax to typeset the image equation
|
|
110
111
|
|
|
111
112
|
if ((_elem$parentElement = elem.parentElement) !== null && _elem$parentElement !== void 0 && _elem$parentElement.classList.contains('math_equation_latex')) {
|
|
112
113
|
var _elem$parentElement$p;
|
|
@@ -123,7 +124,7 @@ class Mathml {
|
|
|
123
124
|
}
|
|
124
125
|
});
|
|
125
126
|
window.MathJax.Hub.Register.MessageHook('End Math', function (message) {
|
|
126
|
-
const elem = message[1];
|
|
127
|
+
const elem = Array.isArray(message[1]) ? message[1][0] : message[1];
|
|
127
128
|
mathImageHelper.removeStrayEquationImages(elem);
|
|
128
129
|
mathImageHelper.nearlyInfiniteStyleFix(elem);
|
|
129
130
|
elem.querySelectorAll('.math_equation_latex').forEach(m => m.classList.add('fade-in-equation'));
|
|
@@ -138,7 +139,8 @@ class Mathml {
|
|
|
138
139
|
// Since we want to ignore <math> in .hidden-readable spans, let's remove the MathJunk™
|
|
139
140
|
// right after MathJax adds it.
|
|
140
141
|
window.MathJax.Hub.Register.MessageHook('End Math', function (message) {
|
|
141
|
-
|
|
142
|
+
const elm = Array.isArray(message[1]) ? message[1][0] : message[1];
|
|
143
|
+
$(elm).find('.hidden-readable [class^="MathJax"], .hidden-readable [id^="MathJax"]').remove();
|
|
142
144
|
});
|
|
143
145
|
} // leaving this here so I don't have to keep looking up how to see all messages
|
|
144
146
|
// window.MathJax.Hub.Startup.signal.Interest(function (message) {
|
|
@@ -315,7 +317,8 @@ const mathImageHelper = {
|
|
|
315
317
|
},
|
|
316
318
|
|
|
317
319
|
catchEquationImages(refnode) {
|
|
318
|
-
// find equation images and replace with inline LaTeX
|
|
320
|
+
refnode = Array.isArray(refnode) ? refnode[0] : refnode; // find equation images and replace with inline LaTeX
|
|
321
|
+
|
|
319
322
|
const eqimgs = refnode.querySelectorAll('img.equation_image');
|
|
320
323
|
|
|
321
324
|
if (eqimgs.length > 0) {
|
package/lib/rce/RCEWrapper.js
CHANGED
|
@@ -2714,48 +2714,9 @@ class RCEWrapper extends React.Component {
|
|
|
2714
2714
|
|
|
2715
2715
|
this.checkAccessibility();
|
|
2716
2716
|
this.fixToolbarKeyboardNavigation();
|
|
2717
|
-
this.forwardPostMessages();
|
|
2718
2717
|
(_this$props$onInitted = (_this$props = this.props).onInitted) === null || _this$props$onInitted === void 0 ? void 0 : _this$props$onInitted.call(_this$props, editor);
|
|
2719
2718
|
};
|
|
2720
2719
|
|
|
2721
|
-
this.forwardPostMessages = () => {
|
|
2722
|
-
const windowReferences = {};
|
|
2723
|
-
const rceWindow = this.editor.getWin(); // explicitly assign name for reference by parent window
|
|
2724
|
-
|
|
2725
|
-
rceWindow.name = `${RCEWrapper.editorFrameName}_${this.id}`;
|
|
2726
|
-
rceWindow.addEventListener('message', this.forwardPostMessagesHandler(rceWindow, windowReferences));
|
|
2727
|
-
};
|
|
2728
|
-
|
|
2729
|
-
this.forwardPostMessagesHandler = (rceWindow, windowReferences) => e => {
|
|
2730
|
-
let message;
|
|
2731
|
-
|
|
2732
|
-
try {
|
|
2733
|
-
message = typeof e.data === 'string' ? JSON.parse(e.data) : e.data;
|
|
2734
|
-
} catch (err) {
|
|
2735
|
-
// unparseable message may not be meant for our handlers
|
|
2736
|
-
return false;
|
|
2737
|
-
}
|
|
2738
|
-
|
|
2739
|
-
if (e.origin === rceWindow.origin) {
|
|
2740
|
-
// message is from Canvas window, forward to tool
|
|
2741
|
-
const targetOrigin = message.toolOrigin;
|
|
2742
|
-
|
|
2743
|
-
if (!targetOrigin) {
|
|
2744
|
-
return false;
|
|
2745
|
-
}
|
|
2746
|
-
|
|
2747
|
-
const targetWindow = windowReferences[targetOrigin];
|
|
2748
|
-
delete message.toolOrigin;
|
|
2749
|
-
targetWindow === null || targetWindow === void 0 ? void 0 : targetWindow.postMessage(message, targetOrigin);
|
|
2750
|
-
} else {
|
|
2751
|
-
// message is from tool, forward to Canvas window
|
|
2752
|
-
windowReferences[e.origin] = e.source;
|
|
2753
|
-
message.toolOrigin = e.origin;
|
|
2754
|
-
message.frameName = rceWindow.name;
|
|
2755
|
-
rceWindow.parent.postMessage(message, rceWindow.origin);
|
|
2756
|
-
}
|
|
2757
|
-
};
|
|
2758
|
-
|
|
2759
2720
|
this.fixToolbarKeyboardNavigation = () => {
|
|
2760
2721
|
var _this$_elementRef$cur2;
|
|
2761
2722
|
|
|
@@ -4238,7 +4199,6 @@ RCEWrapper.defaultProps = {
|
|
|
4238
4199
|
canvasOrigin: ''
|
|
4239
4200
|
};
|
|
4240
4201
|
RCEWrapper.skinCssInjected = false;
|
|
4241
|
-
RCEWrapper.editorFrameName = 'active_rce_frame';
|
|
4242
4202
|
|
|
4243
4203
|
function mergeMenuItems(standard, custom) {
|
|
4244
4204
|
var _custom$trim;
|
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
19
19
|
*/
|
|
20
20
|
import React from 'react';
|
|
21
|
-
import { Flex } from '@instructure/ui-flex';
|
|
22
21
|
import { Heading } from '@instructure/ui-heading';
|
|
23
22
|
import { CloseButton } from '@instructure/ui-buttons';
|
|
24
23
|
import { View } from '@instructure/ui-view';
|
|
@@ -33,12 +32,12 @@ export function ExternalToolDialogModal(props) {
|
|
|
33
32
|
onOpen: props.onOpen,
|
|
34
33
|
onClose: props.onClose,
|
|
35
34
|
mountNode: props.mountNode
|
|
36
|
-
}, /*#__PURE__*/React.createElement(Modal.Header, null, /*#__PURE__*/React.createElement(
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
}, /*#__PURE__*/React.createElement(Modal.Header, null, /*#__PURE__*/React.createElement(Heading, null, props.name), /*#__PURE__*/React.createElement(CloseButton, {
|
|
36
|
+
placement: "end",
|
|
37
|
+
offset: "medium",
|
|
39
38
|
onClick: props.onCloseButton,
|
|
40
39
|
screenReaderLabel: formatMessage('Close')
|
|
41
|
-
}))
|
|
40
|
+
})), /*#__PURE__*/React.createElement(Modal.Body, {
|
|
42
41
|
padding: "0"
|
|
43
42
|
}, /*#__PURE__*/React.createElement(View, {
|
|
44
43
|
as: "div",
|
|
@@ -35,7 +35,7 @@ export default class ResourceLinkContentItem extends BaseLinkContentItem {
|
|
|
35
35
|
|
|
36
36
|
buildUrl() {
|
|
37
37
|
return addQueryParamsToUrl(this.context.ltiEndpoint, {
|
|
38
|
-
display: '
|
|
38
|
+
display: 'in_rce',
|
|
39
39
|
resource_link_lookup_uuid: this.lookup_uuid,
|
|
40
40
|
[PARENT_FRAME_CONTEXT_PARAM]: this.context.containingCanvasLtiToolId
|
|
41
41
|
});
|