UNPKG

@instructure/canvas-rce

Version:

A component wrapping Canvas's usage of Tinymce

142 lines (140 loc) 5.26 kB
/* * Copyright (C) 2018 - 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 React from 'react'; import { renderToStaticMarkup } from 'react-dom/server'; import { cleanUrl } from './contentInsertionUtils'; import formatMessage from '../format-message'; import { videoDefaultSize, AUDIO_PLAYER_SIZE } from './plugins/instructure_record/VideoOptionsTray/TrayController'; import { mediaPlayerURLFromFile } from './plugins/shared/fileTypeUtils'; import { prepEmbedSrc, prepLinkedSrc, absoluteToRelativeUrl } from '../common/fileUrl'; export function renderLink(data, contents, canvasOrigin) { const linkAttrs = { ...data }; linkAttrs.href = prepLinkedSrc(linkAttrs.href || linkAttrs.url); delete linkAttrs.url; if (linkAttrs.href) { linkAttrs.href = absoluteToRelativeUrl(cleanUrl(linkAttrs.href), canvasOrigin); } linkAttrs.title = linkAttrs.title || formatMessage('Link'); const children = contents || linkAttrs.text || linkAttrs.title; delete linkAttrs.selectionDetails; delete linkAttrs.text; linkAttrs.className = linkAttrs.class; delete linkAttrs.class; // renderToStaticMarkup isn't happy with bool attributes Object.keys(linkAttrs).forEach(attr => { if (typeof linkAttrs[attr] === 'boolean') linkAttrs[attr] = linkAttrs[attr].toString(); }); return renderToStaticMarkup(/*#__PURE__*/React.createElement("a", linkAttrs, children)); } export function renderLinkedImage(linkElem, image, canvasOrigin) { const linkHref = linkElem.getAttribute('href'); image.href = prepEmbedSrc(image.href, canvasOrigin); return renderToStaticMarkup(/*#__PURE__*/React.createElement("a", { href: absoluteToRelativeUrl(linkHref, canvasOrigin), "data-mce-href": linkHref }, constructJSXImageElement(image, canvasOrigin, { doNotLink: true }))); } export function constructJSXImageElement(image, canvasOrigin, opts = {}) { const { href, url, src, title, display_name, alt_text, isDecorativeImage, link, ...otherAttributes } = image; const imageSrc = absoluteToRelativeUrl(href || url || src, canvasOrigin); let altText = alt_text || title || display_name || ''; if (isDecorativeImage) { altText = ''; otherAttributes.role = 'presentation'; } delete otherAttributes.contextType; // react doesn't like these delete otherAttributes.contextId; const ret = /*#__PURE__*/React.createElement("img", Object.assign({ alt: altText, src: imageSrc, width: image.width, height: image.height, loading: "lazy" }, otherAttributes)); if (link && !opts.doNotLink) { return /*#__PURE__*/React.createElement("a", { href: absoluteToRelativeUrl(link, canvasOrigin), target: "_blank", rel: "noopener noreferrer" }, ret); } return ret; } export function renderImage(image, canvasOrigin, opts) { image.href = prepEmbedSrc(image.href, canvasOrigin); return renderToStaticMarkup(constructJSXImageElement(image, canvasOrigin, opts)); } export function renderVideo(video, canvasOrigin) { const src = mediaPlayerURLFromFile(video, canvasOrigin); const videoSize = videoDefaultSize(); return ` <iframe allow="fullscreen" allowfullscreen data-media-id="${getMediaId(video)}" data-media-type="video" loading="lazy" src="${src}" style="width:${videoSize.width};height:${videoSize.height};display:inline-block;" title="${formatMessage('Video player for {title}', { title: video.title || video.name || video.text })}"></iframe> `.trim().replace(/\s+/g, ' '); } export function renderAudio(audio, canvasOrigin) { const src = mediaPlayerURLFromFile(audio, canvasOrigin); return ` <iframe data-media-id="${getMediaId(audio)}" data-media-type="audio" loading="lazy" src="${src}" style="width:${AUDIO_PLAYER_SIZE.width};height:${AUDIO_PLAYER_SIZE.height};display:inline-block;" title="${formatMessage('Audio player for {title}', { title: audio.title || audio.name || audio.text })}"></iframe> `.trim().replace(/\s+/g, ' '); } export function getMediaId(media) { if (!media) return; return media.media_id || media.media_entry_id || media.id || media.file_id; } export function updateImage(editor, img, attrs) { // Workaround: When passing empty string to editor.dom.setAttribs it removes the attribute img.setAttribute('alt', attrs.altText); editor.dom.setAttribs(img, { src: absoluteToRelativeUrl(attrs.url, editor.rceWrapper?.getCanvasUrl()), role: attrs.isDecorativeImage ? 'presentation' : null, width: attrs.appliedWidth, height: attrs.appliedHeight }); }