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:
Ben Allen 2024-04-08 17:56:44 -04:00 committed by GitHub
parent 4633e8eb5e
commit 5be6df0266
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 18 additions and 3 deletions

View File

@ -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

View File

@ -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']