move RCE's makeAllExternalLinksExternalLinks

Change-Id: I4471750caf9f13220471f3a5af7f983eaf5c3b08
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/339255
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Samuel Lee <samuel.lee@instructure.com>
QA-Review: Aaron Shafovaloff <ashafovaloff@instructure.com>
Product-Review: Aaron Shafovaloff <ashafovaloff@instructure.com>
This commit is contained in:
Aaron Shafovaloff 2024-01-30 11:34:13 -07:00
parent 3135c83e1f
commit 863eed6c6f
3 changed files with 86 additions and 62 deletions

View File

@ -16,17 +16,17 @@
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import {IconDownloadLine, IconExternalLinkLine} from '@instructure/ui-icons/es/svg' import {IconDownloadLine} from '@instructure/ui-icons/es/svg'
import formatMessage from '../format-message' import formatMessage from '../format-message'
import {closest, getData, hide, insertAfter, setData, show} from './jqueryish_funcs' import {closest, getData, hide, insertAfter, setData, show} from './jqueryish_funcs'
import {getTld, isExternalLink, showFilePreview, youTubeID} from './instructure_helper' import {isExternalLink, showFilePreview, youTubeID} from './instructure_helper'
import mediaCommentThumbnail from './media_comment_thumbnail' import mediaCommentThumbnail from './media_comment_thumbnail'
import {addParentFrameContextToUrl} from '../rce/plugins/instructure_rce_external_tools/util/addParentFrameContextToUrl' import {addParentFrameContextToUrl} from '../rce/plugins/instructure_rce_external_tools/util/addParentFrameContextToUrl'
import {MathJaxDirective, Mathml} from './mathml' import {MathJaxDirective, Mathml} from './mathml'
import {makeExternalLinkIcon} from './external_links'
// in jest the es directory doesn't exist so stub the undefined svg // in jest the es directory doesn't exist so stub the undefined svg
const IconDownloadSVG = IconDownloadLine?.src || '<svg></svg>' const IconDownloadSVG = IconDownloadLine?.src || '<svg></svg>'
const IconExternalLinkSVG = IconExternalLinkLine?.src || '<svg></svg>'
function makeDownloadButton(download_url, filename) { function makeDownloadButton(download_url, filename) {
const a = document.createElement('a') const a = document.createElement('a')
@ -53,28 +53,6 @@ function makeDownloadButton(download_url, filename) {
return a return a
} }
function makeExternalLinkIcon(forLink) {
const dir = (forLink && window.getComputedStyle(forLink).direction) || 'ltr'
const $icon = document.createElement('span')
$icon.setAttribute('class', 'external_link_icon')
const style = `margin-inline-start: 5px; display: inline-block; text-indent: initial; ${
dir === 'rtl' ? 'transform:scale(-1, 1)' : ''
}`
$icon.setAttribute('style', style)
$icon.setAttribute('role', 'presentation')
$icon.innerHTML = IconExternalLinkSVG
$icon.firstChild.setAttribute(
'style',
'width:1em; height:1em; vertical-align:middle; fill:currentColor'
)
const srspan = document.createElement('span')
srspan.setAttribute('class', 'screenreader-only')
srspan.textContent = formatMessage('Links to an external site.')
$icon.appendChild(srspan)
return $icon
}
function handleYoutubeLink($link) { function handleYoutubeLink($link) {
const href = $link.getAttribute('href') const href = $link.getAttribute('href')
const id = youTubeID(href || '') const id = youTubeID(href || '')
@ -400,39 +378,3 @@ export function enhanceUserContent(container = document, opts = {}) {
frame.src = src frame.src = src
}) })
} }
export function makeAllExternalLinksExternalLinks() {
// in 100ms (to give time for everything else to load), find all the external links and add give them
// the external link look and behavior (force them to open in a new tab)
setTimeout(function () {
const content = document.getElementById('content')
if (!content) return
const tld = getTld(window.location.hostname)
const links = content.querySelectorAll(`a[href*="//"]:not([href*="${tld}"])`) // technique for finding "external" links copied from https://davidwalsh.name/external-links-css
for (let i = 0; i < links.length; i++) {
const $link = links[i]
// don't mess with the ones that were already processed in enhanceUserContent
if ($link.classList.contains('external')) continue
if ($link.matches('.open_in_a_new_tab')) continue
if ($link.querySelectorAll('img').length > 0) continue
if ($link.matches('.not_external')) continue
if ($link.matches('.exclude_external_icon')) continue
// we have some pre-instui buttons that are styled links
if ($link.classList.contains('btn')) continue
const $linkToReplace = $link
if ($linkToReplace) {
const $linkIndicator = makeExternalLinkIcon()
$linkToReplace.classList.add('external')
$linkToReplace.querySelectorAll('span.ui-icon-extlink').forEach(c => c.remove)
$linkToReplace.setAttribute('target', '_blank')
$linkToReplace.setAttribute('rel', 'noreferrer noopener')
const $linkSpan = document.createElement('span')
const $linkText = $linkToReplace.innerHTML
$linkSpan.innerHTML = $linkText
while ($linkToReplace.firstChild) $linkToReplace.removeChild($linkToReplace.firstChild)
$linkToReplace.appendChild($linkSpan)
$linkToReplace.appendChild($linkIndicator)
}
}
}, 100)
}

View File

@ -0,0 +1,81 @@
/*
* Copyright (C) 2011 - 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 {IconExternalLinkLine} from '@instructure/ui-icons/es/svg'
import {getTld} from './instructure_helper'
import formatMessage from '../format-message'
const IconExternalLinkSVG = IconExternalLinkLine?.src || '<svg></svg>'
export function makeExternalLinkIcon(forLink) {
const dir = (forLink && window.getComputedStyle(forLink).direction) || 'ltr'
const $icon = document.createElement('span')
$icon.setAttribute('class', 'external_link_icon')
const style = `margin-inline-start: 5px; display: inline-block; text-indent: initial; ${
dir === 'rtl' ? 'transform:scale(-1, 1)' : ''
}`
$icon.setAttribute('style', style)
$icon.setAttribute('role', 'presentation')
$icon.innerHTML = IconExternalLinkSVG
$icon.firstChild.setAttribute(
'style',
'width:1em; height:1em; vertical-align:middle; fill:currentColor'
)
const srspan = document.createElement('span')
srspan.setAttribute('class', 'screenreader-only')
srspan.textContent = formatMessage('Links to an external site.')
$icon.appendChild(srspan)
return $icon
}
export function makeAllExternalLinksExternalLinks() {
// in 100ms (to give time for everything else to load), find all the external links and add give them
// the external link look and behavior (force them to open in a new tab)
setTimeout(function () {
const content = document.getElementById('content')
if (!content) return
const tld = getTld(window.location.hostname)
const links = content.querySelectorAll(`a[href*="//"]:not([href*="${tld}"])`) // technique for finding "external" links copied from https://davidwalsh.name/external-links-css
for (let i = 0; i < links.length; i++) {
const $link = links[i]
// don't mess with the ones that were already processed in enhanceUserContent
if ($link.classList.contains('external')) continue
if ($link.matches('.open_in_a_new_tab')) continue
if ($link.querySelectorAll('img').length > 0) continue
if ($link.matches('.not_external')) continue
if ($link.matches('.exclude_external_icon')) continue
// we have some pre-instui buttons that are styled links
if ($link.classList.contains('btn')) continue
const $linkToReplace = $link
if ($linkToReplace) {
const $linkIndicator = makeExternalLinkIcon()
$linkToReplace.classList.add('external')
$linkToReplace.querySelectorAll('span.ui-icon-extlink').forEach(c => c.remove)
$linkToReplace.setAttribute('target', '_blank')
$linkToReplace.setAttribute('rel', 'noreferrer noopener')
const $linkSpan = document.createElement('span')
const $linkText = $linkToReplace.innerHTML
$linkSpan.innerHTML = $linkText
while ($linkToReplace.firstChild) $linkToReplace.removeChild($linkToReplace.firstChild)
$linkToReplace.appendChild($linkSpan)
$linkToReplace.appendChild($linkIndicator)
}
}
}, 100)
}

View File

@ -22,7 +22,8 @@ import {uniqueId} from 'lodash'
import htmlEscape from '@instructure/html-escape' import htmlEscape from '@instructure/html-escape'
import {showFlashAlert} from '@canvas/alerts/react/FlashAlert' import {showFlashAlert} from '@canvas/alerts/react/FlashAlert'
import RichContentEditor from '@canvas/rce/RichContentEditor' import RichContentEditor from '@canvas/rce/RichContentEditor'
import {enhanceUserContent, makeAllExternalLinksExternalLinks} from '@instructure/canvas-rce' import {enhanceUserContent} from '@instructure/canvas-rce'
import {makeAllExternalLinksExternalLinks} from '@instructure/canvas-rce/es/enhance-user-content/external_links'
import './instructure_helper' import './instructure_helper'
import 'jqueryui/draggable' import 'jqueryui/draggable'
import '@canvas/jquery/jquery.ajaxJSON' import '@canvas/jquery/jquery.ajaxJSON'