feat(nuxt): nuxt link add white list

This commit is contained in:
xjccc 2025-02-19 14:25:01 +08:00
parent b0729241bc
commit 123c4b395d
2 changed files with 25 additions and 1 deletions

View File

@ -100,6 +100,11 @@ export interface NuxtLinkOptions extends
* Allows controlling default setting for when to prefetch links. By default, prefetch is triggered only on visibility. * Allows controlling default setting for when to prefetch links. By default, prefetch is triggered only on visibility.
*/ */
prefetchOn?: Exclude<NuxtLinkProps['prefetchOn'], string> prefetchOn?: Exclude<NuxtLinkProps['prefetchOn'], string>
/**
* A white list of domain that should be not set noreferrer.
* @example ['nuxt.com', 'nuxtjs.org']
*/
whiteList?: string[]
} }
/* @__NO_SIDE_EFFECTS__ */ /* @__NO_SIDE_EFFECTS__ */
@ -421,6 +426,19 @@ export function defineNuxtLink (options: NuxtLinkOptions) {
// Resolves `target` value // Resolves `target` value
const target = props.target || null const target = props.target || null
function isUrlInWhitelist (url: string, whitelist: string[] = []): boolean {
try {
const urlObj = new URL(url)
return whitelist.some(domain => urlObj.hostname.endsWith(domain))
} catch (e) {
console.error(e)
return false
}
}
let defaultExternalRel = 'noopener noreferrer'
if (isUrlInWhitelist(href.value, options.whiteList)) {
defaultExternalRel = 'noopener'
}
// Resolves `rel` // Resolves `rel`
checkPropConflicts(props, 'noRel', 'rel') checkPropConflicts(props, 'noRel', 'rel')
const rel = firstNonUndefined<string | null>( const rel = firstNonUndefined<string | null>(
@ -431,7 +449,7 @@ export function defineNuxtLink (options: NuxtLinkOptions) {
* A fallback rel of `noopener noreferrer` is applied for external links or links that open in a new tab. * A fallback rel of `noopener noreferrer` is applied for external links or links that open in a new tab.
* This solves a reverse tabnapping security flaw in browsers pre-2021 as well as improving privacy. * This solves a reverse tabnapping security flaw in browsers pre-2021 as well as improving privacy.
*/ */
(isAbsoluteUrl.value || hasTarget.value) ? 'noopener noreferrer' : '', (isAbsoluteUrl.value || hasTarget.value) ? defaultExternalRel : '',
) || null ) || null
// https://router.vuejs.org/api/#custom // https://router.vuejs.org/api/#custom

View File

@ -211,6 +211,12 @@ describe('nuxt-link:propsOrAttributes', () => {
expect(nuxtLink({ to: 'https://nuxtjs.org', rel: '' }, { externalRelAttribute: 'bar' }).props.rel).toBe(null) expect(nuxtLink({ to: 'https://nuxtjs.org', rel: '' }, { externalRelAttribute: 'bar' }).props.rel).toBe(null)
}) })
it('uses set white list', () => {
expect(nuxtLink({ to: 'https://nuxtjs.org' }, { whiteList: ['nuxtjs.org'] }).props.rel).toBe('noopener')
expect(nuxtLink({ to: 'https://nuxt.com' }, { whiteList: ['nuxtjs.org', '.nuxt.com'] }).props.rel).toBe('noopener noreferrer')
expect(nuxtLink({ to: 'https://nuxters.nuxt.com' }, { whiteList: ['nuxtjs.org', '.nuxt.com'] }).props.rel).toBe('noopener')
})
it('honors `noRel` prop', () => { it('honors `noRel` prop', () => {
expect(nuxtLink({ to: 'https://nuxtjs.org', noRel: true }).props.rel).toBe(null) expect(nuxtLink({ to: 'https://nuxtjs.org', noRel: true }).props.rel).toBe(null)
expect(nuxtLink({ to: 'https://nuxtjs.org', noRel: false }).props.rel).toBe('noopener noreferrer') expect(nuxtLink({ to: 'https://nuxtjs.org', noRel: false }).props.rel).toBe('noopener noreferrer')