Internal links are not target=_blank by default (#1037)
* feat: internal links are not target=_blank by default * feat: use <Link> --------- Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									4633e8eb5e
								
							
						
					
					
						commit
						5be6df0266
					
				| @ -19,7 +19,7 @@ import { rehypeInlineCodeProperty } from '@/lib/md' | ||||
| import { Button } from 'react-bootstrap' | ||||
| import { useRouter } from 'next/router' | ||||
| import Link from 'next/link' | ||||
| import { UNKNOWN_LINK_REL } from '@/lib/constants' | ||||
| import { SSR, UNKNOWN_LINK_REL } from '@/lib/constants' | ||||
| import isEqual from 'lodash/isEqual' | ||||
| 
 | ||||
| export function SearchText ({ text }) { | ||||
| @ -178,6 +178,8 @@ export default memo(function Text ({ rel, imgproxyUrls, children, tab, itemId, o | ||||
|             // If [text](url) was parsed as <a> and text is not empty and not a link itself,
 | ||||
|             // we don't render it as an image since it was probably a conscious choice to include text.
 | ||||
|             const text = children[0] | ||||
|             const url = !href.startsWith('/') && new URL(href) | ||||
|             const internalURL = SSR ? 'https://stacker.news' : window.location.origin | ||||
|             if (!!text && !/^https?:\/\//.test(text)) { | ||||
|               if (props['data-footnote-ref'] || typeof props['data-footnote-backref'] !== 'undefined') { | ||||
|                 return ( | ||||
| @ -189,6 +191,16 @@ export default memo(function Text ({ rel, imgproxyUrls, children, tab, itemId, o | ||||
|                   </Link> | ||||
|                 ) | ||||
|               } | ||||
|               if (href.startsWith('/') || url.origin === internalURL) { | ||||
|                 return ( | ||||
|                   <Link | ||||
|                     id={props.id} | ||||
|                     href={href} | ||||
|                   > | ||||
|                     {text} | ||||
|                   </Link> | ||||
|                 ) | ||||
|               } | ||||
|               return ( | ||||
|                 // eslint-disable-next-line
 | ||||
|                 <a id={props.id} target='_blank' rel={rel ?? UNKNOWN_LINK_REL} href={href}>{text}</a> | ||||
| @ -198,7 +210,7 @@ export default memo(function Text ({ rel, imgproxyUrls, children, tab, itemId, o | ||||
|             try { | ||||
|               const linkText = parseInternalLinks(href) | ||||
|               if (linkText) { | ||||
|                 return <a target='_blank' href={href} rel='noreferrer'>{linkText}</a> | ||||
|                 return <Link href={href}>{linkText}</Link> | ||||
|               } | ||||
|             } catch { | ||||
|               // ignore errors like invalid URLs
 | ||||
|  | ||||
| @ -1,3 +1,5 @@ | ||||
| import { SSR } from './constants' | ||||
| 
 | ||||
| export function ensureProtocol (value) { | ||||
|   if (!value) return value | ||||
|   value = value.trim() | ||||
| @ -28,11 +30,12 @@ export function removeTracking (value) { | ||||
|  */ | ||||
| export function parseInternalLinks (href) { | ||||
|   const url = new URL(href) | ||||
|   const internalURL = SSR ? 'https://stacker.news' : window.location.origin | ||||
|   const { pathname, searchParams } = url | ||||
|   // ignore empty parts which exist due to pathname starting with '/'
 | ||||
|   const emptyPart = part => !!part | ||||
|   const parts = pathname.split('/').filter(emptyPart) | ||||
|   if (parts[0] === 'items' && /^[0-9]+$/.test(parts[1])) { | ||||
|   if (parts[0] === 'items' && /^[0-9]+$/.test(parts[1]) && url.origin === internalURL) { | ||||
|     const itemId = parts[1] | ||||
|     // check for valid item page due to referral links like /items/123456/r/ekzyis
 | ||||
|     const itemPages = ['edit', 'ots', 'related'] | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user