From fa26ea0b423cdc08c61fca912d146c0627818e20 Mon Sep 17 00:00:00 2001 From: Niklas Fiekas Date: Sun, 4 Oct 2020 17:10:03 +0200 Subject: [PATCH] review client side _target=blank (closes #7411) --- ui/analyse/src/actionMenu.ts | 11 ++++++++--- ui/analyse/src/explorer/explorerView.ts | 2 +- .../src/study/relay/relayManagerView.ts | 3 ++- ui/analyse/src/study/studyShare.ts | 1 + ui/analyse/src/view.ts | 1 + ui/dasher/src/links.ts | 19 ++++++++----------- ui/insight/src/info.js | 3 ++- ui/msg/src/view/enhance.ts | 2 +- ui/round/src/view/user.ts | 2 +- ui/swiss/src/view/playerInfo.ts | 2 +- ui/tournament/src/view/playerInfo.ts | 2 +- 11 files changed, 27 insertions(+), 21 deletions(-) diff --git a/ui/analyse/src/actionMenu.ts b/ui/analyse/src/actionMenu.ts index 0ad9cd91e4..c4a9f11ab3 100644 --- a/ui/analyse/src/actionMenu.ts +++ b/ui/analyse/src/actionMenu.ts @@ -96,6 +96,7 @@ function studyButton(ctrl: AnalyseCtrl) { attrs: { href: '/study/' + ctrl.study.data.id + '#' + ctrl.study.currentChapter().id, target: '_blank', + rel: 'noopener', 'data-icon': '4' } }, ctrl.trans.noarg('openStudy')); @@ -144,9 +145,13 @@ export function view(ctrl: AnalyseCtrl): VNode { ctrl.ongoing ? null : h('a.button.button-empty', { attrs: { href: d.userAnalysis ? '/editor?fen=' + ctrl.node.fen : '/' + d.game.id + '/edit?fen=' + ctrl.node.fen, - rel: 'nofollow', - target: ctrl.embed ? '_blank' : '', - 'data-icon': 'm' + 'data-icon': 'm', + ...(ctrl.embed ? { + target: '_blank', + rel: 'noopener nofollow', + } : { + rel: 'nofollow', + }), } }, noarg('boardEditor')), canContinue ? h('a.button.button-empty', { diff --git a/ui/analyse/src/explorer/explorerView.ts b/ui/analyse/src/explorer/explorerView.ts index e1ac775234..8de091de4a 100644 --- a/ui/analyse/src/explorer/explorerView.ts +++ b/ui/analyse/src/explorer/explorerView.ts @@ -118,7 +118,7 @@ function openGame(ctrl: AnalyseCtrl, gameId: string) { fenParam = ctrl.node.ply > 0 ? ('?fen=' + ctrl.node.fen) : ''; let url = '/' + gameId + '/' + orientation + fenParam; if (ctrl.explorer.config.data.db.selected() === 'masters') url = '/import/master' + url; - window.open(url, '_blank'); + window.open(url, '_blank', 'noopener'); } function gameActions(ctrl: AnalyseCtrl, game: OpeningGame): VNode { diff --git a/ui/analyse/src/study/relay/relayManagerView.ts b/ui/analyse/src/study/relay/relayManagerView.ts index 267cf5faf7..046d0050fe 100644 --- a/ui/analyse/src/study/relay/relayManagerView.ts +++ b/ui/analyse/src/study/relay/relayManagerView.ts @@ -36,7 +36,8 @@ function renderLog(ctrl: RelayCtrl) { const err = e.error && h('a', { attrs: { href: ctrl.data.sync.url, - target: '_blank' + target: '_blank', + rel: 'noopener nofollow', } }, e.error); return h('div' + (err ? '.err' : ''), { diff --git a/ui/analyse/src/study/studyShare.ts b/ui/analyse/src/study/studyShare.ts index 96eedcc8f7..bf70f10984 100644 --- a/ui/analyse/src/study/studyShare.ts +++ b/ui/analyse/src/study/studyShare.ts @@ -130,6 +130,7 @@ export function view(ctrl: StudyShareCtrl): VNode { attrs: { href: '/developers#embed-study', target: '_blank', + rel: 'noopener', 'data-icon': '' } }, ctrl.trans.noarg('readMoreAboutEmbedding')) diff --git a/ui/analyse/src/view.ts b/ui/analyse/src/view.ts index 6a35388617..1889ab5c4a 100644 --- a/ui/analyse/src/view.ts +++ b/ui/analyse/src/view.ts @@ -202,6 +202,7 @@ function controls(ctrl: AnalyseCtrl) { attrs: { title: noarg('analysis'), target: '_blank', + rel: 'noopener', href: ctrl.studyPractice.analysisUrl(), 'data-icon': 'A' } diff --git a/ui/dasher/src/links.ts b/ui/dasher/src/links.ts index 4531f20ec6..679fae647c 100644 --- a/ui/dasher/src/links.ts +++ b/ui/dasher/src/links.ts @@ -23,7 +23,7 @@ export default function(ctrl: DasherCtrl): VNode { h( 'a.text', - linkCfg('/account/preferences/game-display', '%', ctrl.opts.playing ? {target: '_blank'} : undefined), + linkCfg('/account/preferences/game-display', '%', ctrl.opts.playing ? {target: '_blank', rel: 'noopener'} : undefined), noarg('preferences')), !d.coach ? null : h( @@ -104,16 +104,13 @@ export default function(ctrl: DasherCtrl): VNode { ]); } -function linkCfg(href: string, icon: string, more: any = undefined): any { - const cfg: any = { - attrs: { - href, - 'data-icon': icon - } - }; - if (more) for(let i in more) cfg.attrs[i] = more[i]; - return cfg; -} +const linkCfg = (href: string, icon: string, more?: Record) => ({ + attrs: { + href, + 'data-icon': icon, + ...(more || {}), + } +}); function modeCfg(ctrl: DasherCtrl, m: Mode): any { return { diff --git a/ui/insight/src/info.js b/ui/insight/src/info.js index 0d03e5ed46..71e501991d 100644 --- a/ui/insight/src/info.js +++ b/ui/insight/src/info.js @@ -18,7 +18,8 @@ module.exports = function(ctrl) { ]), m('p.share', ctrl.own ? m('a', { href: '/account/preferences/privacy', - target: '_blank' + target: '_blank', + rel: 'noopener', }, shareText) : shareText) ]), m('div.refresh', { diff --git a/ui/msg/src/view/enhance.ts b/ui/msg/src/view/enhance.ts index 2be0050dc5..d9e57423c1 100644 --- a/ui/msg/src/view/enhance.ts +++ b/ui/msg/src/view/enhance.ts @@ -34,7 +34,7 @@ const expandImage = (url: string) => /\.(jpg|jpeg|png|gif)$/.test(url) ? aImg(ur const expandLink = (url: string) => a(url, url.replace(/^https?:\/\//, '')); const a = (href: string, body: string) => -`${body}`; +`${body}`; const img = (src: string) => ``; diff --git a/ui/round/src/view/user.ts b/ui/round/src/view/user.ts index c5e4f1f9e0..003029269a 100644 --- a/ui/round/src/view/user.ts +++ b/ui/round/src/view/user.ts @@ -37,7 +37,7 @@ export function userHtml(ctrl: RoundController, player: Player, position: Positi attrs: { 'data-pt-pos': 's', href: '/@/' + user.username, - target: ctrl.isPlaying() ? '_blank' : '_self' + ...(ctrl.isPlaying() ? {target: '_blank', rel: 'noopener'} : {}), } }, user.title ? [ h( diff --git a/ui/swiss/src/view/playerInfo.ts b/ui/swiss/src/view/playerInfo.ts index b7dba16ed7..4081457f4f 100644 --- a/ui/swiss/src/view/playerInfo.ts +++ b/ui/swiss/src/view/playerInfo.ts @@ -53,7 +53,7 @@ export default function(ctrl: SwissCtrl): VNode | undefined { h('table.pairings.sublist', { hook: bind('click', e => { const href = ((e.target as HTMLElement).parentNode as HTMLElement).getAttribute('data-href'); - if (href) window.open(href, '_blank'); + if (href) window.open(href, '_blank', 'noopener'); }) }, data.sheet.map((p, i) => { const round = ctrl.data.round - i; diff --git a/ui/tournament/src/view/playerInfo.ts b/ui/tournament/src/view/playerInfo.ts index fbe299541f..aebcba0978 100644 --- a/ui/tournament/src/view/playerInfo.ts +++ b/ui/tournament/src/view/playerInfo.ts @@ -76,7 +76,7 @@ export default function(ctrl: TournamentController): VNode { h('table.pairings.sublist', { hook: bind('click', e => { const href = ((e.target as HTMLElement).parentNode as HTMLElement).getAttribute('data-href'); - if (href) window.open(href, '_blank'); + if (href) window.open(href, '_blank', 'noopener'); }) }, data.pairings.map(function(p, i) { const res = result(p.win, p.status);