@instructure/canvas-rce
Version:
A component wrapping Canvas's usage of Tinymce
74 lines (70 loc) • 3.31 kB
JavaScript
/*
* Copyright (C) 2023 - present Instructure, Inc.
*
* This file is part of Canvas.
*
* Canvas is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, version 3 of the License.
*
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import PropTypes, { bool, shape } from 'prop-types';
/**
* Interface for content item's 'custom' field, specifically for what is expected to come from Studio
*
* Used to determine whether or not Studio embedded media should be resizable, and whether or not we
* present controls for the user to modify the embedded media.
*/
export const parsedStudioOptionsPropType = shape({
resizable: bool.isRequired,
convertibleToLink: bool.isRequired
});
export function isStudioContentItemCustomJson(input) {
return typeof input === 'object' && input.source === 'studio';
}
export function studioAttributesFrom(customJson) {
var _customJson$resizable, _customJson$enableMed;
return {
'data-studio-resizable': (_customJson$resizable = customJson.resizable) !== null && _customJson$resizable !== void 0 ? _customJson$resizable : false,
'data-studio-tray-enabled': (_customJson$enableMed = customJson.enableMediaOptions) !== null && _customJson$enableMed !== void 0 ? _customJson$enableMed : false,
'data-studio-convertible-to-link': true
};
}
export function displayStyleFrom(studioAttributes) {
if (!studioAttributes) return '';
return studioAttributes['data-studio-resizable'] || studioAttributes['data-studio-tray-enabled'] ? 'inline-block' : '';
}
export function isStudioEmbeddedMedia(element) {
// Borrowing this structure from isMediaElement in ContentSelection.js
const tinymceIframeShim = element?.tagName === 'IFRAME' ? element?.parentElement : element;
if (tinymceIframeShim?.firstElementChild?.tagName !== 'IFRAME') {
return false;
}
return tinymceIframeShim.getAttribute('data-mce-p-data-studio-tray-enabled') === 'true';
}
export function parseStudioOptions(element) {
const tinymceIframeShim = element?.tagName === 'IFRAME' ? element?.parentElement : element;
return {
resizable: tinymceIframeShim?.getAttribute('data-mce-p-data-studio-resizable') === 'true',
convertibleToLink: tinymceIframeShim?.getAttribute('data-mce-p-data-studio-convertible-to-link') === 'true'
};
}
/**
* Tinymce adds an overlay when you click on an iframe inside the editor. It will by default
* add resize handles to the corners of the overlay. The code that adds these handles won't
* if the overlay has `data-mce-resize='false'` on it. Here, we force that behavior when the
* underlying iframe has a `data-studio-resizable='false'`
*/
export function handleBeforeObjectSelected(e) {
const targetElement = e.target;
if (targetElement.getAttribute('data-mce-p-data-studio-resizable') === 'false') {
targetElement.setAttribute('data-mce-resize', 'false');
}
}