From 31c709be5caffb675177eea866dcba09ca36fb13 Mon Sep 17 00:00:00 2001 From: Nithin David Thomas <1277421+nithindavid@users.noreply.github.com> Date: Wed, 22 Nov 2023 01:57:58 +0530 Subject: [PATCH] fix: Opens foreign links from article page in new tab [cw-2725] (#8304) Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> --- app/javascript/portal/portalHelpers.js | 39 ++++++++++++++++++++++++++ app/views/layouts/portal.html.erb | 2 ++ 2 files changed, 41 insertions(+) diff --git a/app/javascript/portal/portalHelpers.js b/app/javascript/portal/portalHelpers.js index de1a36548ace..1f0f24f66142 100644 --- a/app/javascript/portal/portalHelpers.js +++ b/app/javascript/portal/portalHelpers.js @@ -68,6 +68,44 @@ export const updateThemeStyles = theme => { setPortalClass(theme); }; +export const openExternalLinksInNewTab = () => { + const { customDomain, hostURL } = window.portalConfig; + const isSameHost = + window.location.href.includes(customDomain) || + window.location.href.includes(hostURL); + + // Modify external links only on articles page + const isOnArticlePage = + isSameHost && document.querySelector('#cw-article-content') !== null; + + document.addEventListener('click', function (event) { + if (!isOnArticlePage) return; + + // Some of the links come wrapped in strong tag through prosemirror + + const isTagAnchor = event.target.tagName === 'A'; + const isParentTagAnchor = + event.target.tagName === 'STRONG' && + event.target.parentNode.tagName === 'A'; + + if (isTagAnchor || isParentTagAnchor) { + const link = isTagAnchor ? event.target : event.target.parentNode; + + const isInternalLink = + link.hostname === window.location.hostname || + link.href.includes(customDomain) || + link.href.includes(hostURL); + + if (!isInternalLink) { + link.target = '_blank'; + link.rel = 'noopener noreferrer'; // Security and performance benefits + // Prevent default if you want to stop the link from opening in the current tab + event.stopPropagation(); + } + } + }); +}; + export const toggleAppearanceDropdown = () => { const dropdown = document.getElementById('appearance-dropdown'); if (!dropdown) return; @@ -183,6 +221,7 @@ export const InitializationHelpers = { }, initialize: () => { + openExternalLinksInNewTab(); if (window.portalConfig.isPlainLayoutEnabled === 'true') { InitializationHelpers.appendPlainParamToURLs(); } else { diff --git a/app/views/layouts/portal.html.erb b/app/views/layouts/portal.html.erb index b6ec6d435d27..19295aa95c53 100644 --- a/app/views/layouts/portal.html.erb +++ b/app/views/layouts/portal.html.erb @@ -50,6 +50,8 @@ By default, it renders: window.portalConfig = { portalSlug: '<%= @portal.slug %>', portalColor: '<%= @portal.color %>', + customDomain: '<%= @portal.custom_domain %>', + hostURL: '<%= ENV.fetch('FRONTEND_URL', '') %>', theme: '<%= @theme %>', localeCode: '<%= @locale %>', searchTranslations: {