Browse Source

refactor: add rel tag when opening links in new tab using _blank

pull/6920/head
Pranav C 1 year ago
parent
commit
0ab5e2de26
  1. 1
      packages/nc-gui/components/cell/Email.vue
  2. 4
      packages/nc-gui/components/cell/GeoData.vue
  3. 8
      packages/nc-gui/components/cell/PhoneNumber.vue
  4. 32
      packages/nc-gui/components/dashboard/Sidebar/UserInfo.vue
  5. 1
      packages/nc-gui/components/dashboard/TreeView/AddNewTableNode.vue
  6. 10
      packages/nc-gui/components/dlg/AirtableImport.vue
  7. 2
      packages/nc-gui/components/general/CopyUrl.vue
  8. 2
      packages/nc-gui/components/general/JoinCloud.vue
  9. 2
      packages/nc-gui/components/general/Share.vue
  10. 2
      packages/nc-gui/components/general/ShareProject.vue
  11. 2
      packages/nc-gui/components/general/Social.vue
  12. 1
      packages/nc-gui/components/general/language/Menu.vue
  13. 1
      packages/nc-gui/components/smartsheet/ApiSnippet.vue
  14. 7
      packages/nc-gui/components/smartsheet/column/FormulaOptions.vue
  15. 8
      packages/nc-gui/components/smartsheet/toolbar/ShareView.vue
  16. 2
      packages/nc-gui/components/webhook/CallLog.vue
  17. 1
      packages/nc-gui/components/webhook/Drawer.vue
  18. 2
      packages/nc-gui/components/webhook/Editor.vue
  19. 7
      packages/nc-gui/components/workspace/Menu.vue
  20. 2
      packages/nc-gui/pages/profile/[[username]].vue
  21. 2
      packages/nc-gui/pages/signup/[[token]].vue
  22. 69
      packages/nc-gui/utils/svgToPng.ts
  23. 3
      packages/nc-gui/utils/urlUtils.ts

1
packages/nc-gui/components/cell/Email.vue

@ -86,6 +86,7 @@ watch(
<nuxt-link
v-else-if="validEmail"
no-ref
class="text-sm underline hover:opacity-75 inline-block"
:href="`mailto:${vModel}`"
target="_blank"

4
packages/nc-gui/components/cell/GeoData.vue

@ -72,13 +72,13 @@ const onClickSetCurrentLocation = () => {
const openInGoogleMaps = () => {
const [latitude, longitude] = (vModel.value || '').split(';')
const url = `https://www.google.com/maps/search/?api=1&query=${latitude},${longitude}`
window.open(url, '_blank')
window.open(url, '_blank', 'noopener,noreferrer')
}
const openInOSM = () => {
const [latitude, longitude] = (vModel.value || '').split(';')
const url = `https://www.openstreetmap.org/?mlat=${latitude}&mlon=${longitude}#map=15/${latitude}/${longitude}`
window.open(url, '_blank')
window.open(url, '_blank', "'noopener,noreferrer'")
}
</script>

8
packages/nc-gui/components/cell/PhoneNumber.vue

@ -76,7 +76,13 @@ watch(
<span v-else-if="vModel === null && showNull" class="nc-null uppercase">{{ $t('general.null') }}</span>
<a v-else-if="validEmail" class="text-sm underline hover:opacity-75" :href="`tel:${vModel}`" target="_blank">
<a
v-else-if="validEmail"
class="text-sm underline hover:opacity-75"
:href="`tel:${vModel}`"
target="_blank"
rel="noopener noreferrer"
>
<LazyCellClampedText :value="vModel" :lines="rowHeight" />
</a>

32
packages/nc-gui/components/dashboard/Sidebar/UserInfo.vue

@ -107,13 +107,25 @@ onMounted(() => {
</NcMenuItem>
</template>
<NcDivider />
<a v-e="['c:nocodb:discord']" href="https://discord.gg/5RgZmkW" target="_blank" class="!underline-transparent">
<a
v-e="['c:nocodb:discord']"
href="https://discord.gg/5RgZmkW"
target="_blank"
class="!underline-transparent"
rel="noopener noreferrer"
>
<NcMenuItem class="social-icon-wrapper">
<GeneralIcon class="social-icon" icon="discord" />
<span class="menu-btn"> {{ $t('labels.community.joinDiscord') }} </span>
</NcMenuItem>
</a>
<a v-e="['c:nocodb:reddit']" href="https://www.reddit.com/r/NocoDB" target="_blank" class="!underline-transparent">
<a
v-e="['c:nocodb:reddit']"
href="https://www.reddit.com/r/NocoDB"
target="_blank"
class="!underline-transparent"
rel="noopener noreferrer"
>
<NcMenuItem class="social-icon-wrapper">
<GeneralIcon class="social-icon" icon="reddit" />
<span class="menu-btn"> {{ $t('labels.community.joinReddit') }} </span>
@ -148,14 +160,26 @@ onMounted(() => {
<template v-if="!isMobileMode">
<NcDivider />
<a v-e="['c:nocodb:forum-open']" href="https://community.nocodb.com" target="_blank" class="!underline-transparent">
<a
v-e="['c:nocodb:forum-open']"
href="https://community.nocodb.com"
target="_blank"
class="!underline-transparent"
rel="noopener"
>
<NcMenuItem>
<GeneralIcon icon="help" class="menu-icon mt-0.5" />
<span class="menu-btn"> {{ $t('title.forum') }} </span>
</NcMenuItem>
</a>
<a v-e="['c:nocodb:docs-open']" href="https://docs.nocodb.com" target="_blank" class="!underline-transparent">
<a
v-e="['c:nocodb:docs-open']"
href="https://docs.nocodb.com"
target="_blank"
class="!underline-transparent"
rel="noopener"
>
<NcMenuItem>
<GeneralIcon icon="doc" class="menu-icon mt-0.5" />
<span class="menu-btn"> {{ $t('title.docs') }} </span>

1
packages/nc-gui/components/dashboard/TreeView/AddNewTableNode.vue

@ -250,6 +250,7 @@ function openTableCreateMagicDialog(sourceId?: string) {
href="https://github.com/nocodb/nocodb/issues/2052"
target="_blank"
class="prose-sm hover:(!text-primary !opacity-100) color-transition nc-base-menu-item group after:(!rounded-b)"
rel="noopener noreferrer"
>
<GeneralIcon icon="openInNew" class="group-hover:text-accent" />
<!-- Request a data source you need? -->

10
packages/nc-gui/components/dlg/AirtableImport.vue

@ -330,6 +330,7 @@ onMounted(async () => {
href="https://docs.nocodb.com/bases/import-base-from-airtable#get-airtable-credentials"
class="prose-sm underline text-grey text-xs"
target="_blank"
rel="noopener"
>
{{ $t('msg.info.airtable.credentials') }}
</a>
@ -414,7 +415,7 @@ onMounted(async () => {
<!-- Questions / Help - Reach out here -->
<div>
<a href="https://github.com/nocodb/nocodb/issues/2052" target="_blank">
<a href="https://github.com/nocodb/nocodb/issues/2052" target="_blank" rel="noopener noreferrer">
{{ $t('general.questions') }} / {{ $t('general.help') }} - {{ $t('general.reachOut') }}</a
>
@ -422,7 +423,12 @@ onMounted(async () => {
<!-- This feature is currently in beta and more information can be found here -->
<div>
{{ $t('general.betaNote') }}
<a class="prose-sm" href="https://github.com/nocodb/nocodb/discussions/2122" target="_blank">
<a
class="prose-sm"
href="https://github.com/nocodb/nocodb/discussions/2122"
target="_blank"
rel="noopener noreferrer"
>
{{ $t('general.moreInfo') }}
</a>
.

2
packages/nc-gui/components/general/CopyUrl.vue

@ -13,7 +13,7 @@ const isCopied = ref({
})
const openUrl = async () => {
window.open(url.value, '_blank')
window.open(url.value, '_blank', 'noopener,noreferrer')
}
const embedHtml = async () => {

2
packages/nc-gui/components/general/JoinCloud.vue

@ -10,14 +10,12 @@ import { iconMap } from '#imports'
>
<div
class="flex justify-center items-center rounded-l-[3px] w-full cursor-pointer px-2 py-1 !text-current !no-underline text-primary border-1 border-[#cdd1d6] bg-[#EFF2F6] hover:bg-[#e9ebef] m-0"
target="_blank"
>
<component :is="iconMap.cloud" class="mt-[1px] text-black font-bold" />
<div class="px-1 text-xs font-bold text-gray-800">{{ $t('general.join') }}</div>
</div>
<div
class="group flex justify-center items-center rounded-r-[3px] w-full cursor-pointer px-1 py-1 text-primary border-r-1 border-b-1 border-t-1 border-[#cdd1d6] m-0"
target="_blank"
>
<div class="px-1 text-xs font-semibold group-hover:text-[#0a69da] text-gray-900">NocoDB Cloud</div>
</div>

2
packages/nc-gui/components/general/Share.vue

@ -40,7 +40,7 @@ const encodedSummary = computed(() => encodeURIComponent(summary || summaryArr[M
const fbHashTags = computed(() => hashTags && `%23${hashTags}`)
const openUrl = (url: string) => {
window.open(url, '_blank')
window.open(url, '_blank', 'noopener,noreferrer')
}
</script>

2
packages/nc-gui/components/general/ShareProject.vue

@ -40,7 +40,7 @@ useEventListener(document, 'keydown', async (e: KeyboardEvent) => {
const copySharedBase = async () => {
const baseUrl = getMainUrl()
window.open(`${baseUrl || ''}#/copy-shared-base?base=${route.params.baseId}`, '_blank')
window.open(`${baseUrl || ''}#/copy-shared-base?base=${route.params.baseId}`, '_blank', 'noopener,noreferrer')
}
</script>

2
packages/nc-gui/components/general/Social.vue

@ -4,7 +4,7 @@ import { iconMap, useI18n } from '#imports'
const { locale } = useI18n()
const open = (url: string) => {
window.open(url, '_blank')
window.open(url, '_blank', 'noopener,noreferrer')
}
const isZhLang = computed(() => locale.value.startsWith('zh'))

1
packages/nc-gui/components/general/language/Menu.vue

@ -26,6 +26,7 @@ async function changeLanguage(lang: string) {
href="https://docs.nocodb.com/engineering/translation/#how-to-contribute--for-community-members"
target="_blank"
class="caption nc-base-menu-item py-2 text-primary underline hover:opacity-75"
rel="noopener"
>
{{ $t('activity.translate') }}
</a>

1
packages/nc-gui/components/smartsheet/ApiSnippet.vue

@ -210,6 +210,7 @@ watch(activeLang, (newLang) => {
class="px-4 py-2 ! rounded shadow"
href="https://angel.co/company/nocodb"
target="_blank"
rel="noopener noreferrer"
@click.stop
>
🚀 {{ $t('labels.weAreHiring') }}! 🚀

7
packages/nc-gui/components/smartsheet/column/FormulaOptions.vue

@ -747,7 +747,12 @@ onMounted(() => {
placeholder2: '{column_name}',
})
}}
<a class="prose-sm" href="https://docs.nocodb.com/setup-and-usages/formulas#available-formula-features" target="_blank">
<a
class="prose-sm"
href="https://docs.nocodb.com/setup-and-usages/formulas#available-formula-features"
target="_blank"
rel="noopener"
>
{{ $t('msg.formula.hintEnd') }}
</a>
</div>

8
packages/nc-gui/components/smartsheet/toolbar/ShareView.vue

@ -271,7 +271,13 @@ const copyIframeCode = async () => {
<div class="share-link-box !bg-primary !bg-opacity-5 ring-1 ring-accent ring-opacity-100">
<div data-testid="nc-modal-share-view__link" class="flex-1 h-min text-xs text-gray-500">{{ sharedViewUrl }}</div>
<a v-e="['c:view:share:open-url']" :href="sharedViewUrl" target="_blank" class="flex items-center !no-underline">
<a
v-e="['c:view:share:open-url']"
:href="sharedViewUrl"
target="_blank"
rel="noopener noreferrer"
class="flex items-center !no-underline"
>
<component :is="iconMap.share" class="text-sm text-gray-500" />
</a>

2
packages/nc-gui/components/webhook/CallLog.vue

@ -88,7 +88,7 @@ onBeforeMount(async () => {
</span>
<span>
For additional configuration options, please refer the documentation
<a href="https://docs.nocodb.com/developer-resources/webhooks#call-log" target="_blank">here</a>.
<a href="https://docs.nocodb.com/developer-resources/webhooks#call-log" target="_blank" rel="noopener">here</a>.
</span>
</a-card>

1
packages/nc-gui/components/webhook/Drawer.vue

@ -50,6 +50,7 @@ async function addHook() {
href="https://angel.co/company/nocodb"
target="_blank"
size="large"
rel="noopener noreferrer"
>
🚀 {{ $t('labels.weAreHiring') }}! 🚀
</a-button>

2
packages/nc-gui/components/webhook/Editor.vue

@ -783,7 +783,7 @@ onMounted(async () => {
</div>
<div class="my-3">
<a href="https://docs.nocodb.com/developer-resources/webhooks/" target="_blank">
<a href="https://docs.nocodb.com/developer-resources/webhooks/" target="_blank" rel="noopener">
<!-- Document Reference -->
{{ $t('labels.docReference') }}
</a>

7
packages/nc-gui/components/workspace/Menu.vue

@ -7,7 +7,12 @@
data-testid="nc-workspace-menu"
class="flex items-center nc-workspace-menu overflow-hidden py-1.25 pr-0.25 justify-center w-full ml-2"
>
<a class="transition-all duration-200 transform w-24 min-w-10" href="https://github.com/nocodb/nocodb" target="_blank">
<a
class="transition-all duration-200 transform w-24 min-w-10"
href="https://github.com/nocodb/nocodb"
target="_blank"
rel="noopener noreferrer"
>
<img alt="NocoDB" src="~/assets/img/brand/nocodb.png" />
</a>
<div class="flex flex-grow"></div>

2
packages/nc-gui/pages/profile/[[username]].vue

@ -72,7 +72,7 @@ await loadProfile(route.params.username as string)
<div v-if="profile.website" class="nc-profile-website my-2">
<div class="flex items-center mr-4">
<MdiLinkVariant class="text-lg mr-2" />
<a class="!no-underline" :href="profile.website" target="_blank">{{ profile.website }}</a>
<a class="!no-underline" :href="profile.website" rel="noopener noreferrer" target="_blank">{{ profile.website }}</a>
</div>
</div>

2
packages/nc-gui/pages/signup/[[token]].vue

@ -238,7 +238,7 @@ onMounted(async () => {
<div class="prose-sm mt-4 text-gray-500">
{{ $t('msg.bySigningUp') }}
<a class="prose-sm !text-gray-500 underline" target="_blank" href="https://nocodb.com/policy-nocodb">
<a class="prose-sm !text-gray-500 underline" target="_blank" href="https://nocodb.com/policy-nocodb" rel="noopener">
{{ $t('title.termsOfService') }}</a
>
</div>

69
packages/nc-gui/utils/svgToPng.ts

@ -0,0 +1,69 @@
function copyStylesInline(destinationNode: any, sourceNode: any) {
const containerElements = ['svg', 'g']
for (let cd = 0; cd < destinationNode.childNodes.length; cd++) {
const child = destinationNode.childNodes[cd]
if (containerElements.includes(child.tagName)) {
copyStylesInline(child, sourceNode.childNodes[cd])
continue
}
const style = sourceNode.childNodes[cd].currentStyle || window.getComputedStyle(sourceNode.childNodes[cd])
if (style === 'undefined' || style == null) continue
for (let st = 0; st < style.length; st++) {
child.style.setProperty(style[st], style.getPropertyValue(style[st]))
}
}
}
function triggerDownload(imgURI: string, fileName: string) {
const evt = new MouseEvent('click', {
view: window,
bubbles: false,
cancelable: true,
})
const a = document.createElement('a')
a.setAttribute('download', fileName)
a.setAttribute('href', imgURI)
a.setAttribute('target', '_blank')
a.setAttribute('rel', 'noopener,noreferrer')
a.dispatchEvent(evt)
}
function downloadSvg(svg: SVGGraphicsElement, fileName: string) {
const copy = svg.cloneNode(true)
copyStylesInline(copy, svg)
const canvas = document.createElement('canvas')
const bbox = svg.getBBox()
canvas.width = bbox.width
canvas.height = bbox.height
const ctx = canvas.getContext('2d')!
ctx.clearRect(0, 0, bbox.width, bbox.height)
const data = new XMLSerializer().serializeToString(copy)
const DOMURL = window.URL || window.webkitURL || window
const img = new Image()
const svgBlob = new Blob([data], { type: 'image/svg+xml;charset=utf-8' })
const url = DOMURL.createObjectURL(svgBlob)
img.onload = function () {
ctx.drawImage(img, 0, 0)
DOMURL.revokeObjectURL(url)
if (typeof navigator !== 'undefined' && navigator.msSaveOrOpenBlob) {
const blob = canvas.msToBlob()
navigator.msSaveOrOpenBlob(blob, fileName)
} else {
const imgURI = canvas.toDataURL('image/png').replace('image/png', 'image/octet-stream')
triggerDownload(imgURI, fileName)
}
console.log(canvas)
// TODO: Somehow canvas dom element is getting deleted
// document.removeChild(canvas)
}
img.src = url
}
export { downloadSvg }

3
packages/nc-gui/utils/urlUtils.ts

@ -13,6 +13,7 @@ export const replaceUrlsWithLink = (text: string): boolean | string => {
a.textContent = url
a.setAttribute('href', url)
a.setAttribute('target', '_blank')
a.setAttribute('rel', 'noopener,noreferrer')
return a.outerHTML
})
@ -25,5 +26,5 @@ export const isValidURL = (str: string) => {
export const openLink = (path: string, baseURL?: string, target = '_blank') => {
const url = new URL(path, baseURL)
window.open(url.href, target)
window.open(url.href, target, 'noopener,noreferrer')
}

Loading…
Cancel
Save