diff --git a/api/resolvers/item.js b/api/resolvers/item.js index 242c003d..d2434481 100644 --- a/api/resolvers/item.js +++ b/api/resolvers/item.js @@ -1,5 +1,5 @@ import { GraphQLError } from 'graphql' -import { ensureProtocol, removeTracking, stripTrailingSlash } from '@/lib/url' +import { ensureProtocol, parseInternalLinks, removeTracking, stripTrailingSlash } from '@/lib/url' import serialize from './serial' import { decodeCursor, LIMIT, nextCursorEncoded } from '@/lib/cursor' import { getMetadata, metadataRuleSets } from 'page-metadata-parser' @@ -1185,7 +1185,7 @@ export default { } const namePattern = /\B@[\w_]+/gi -const refPattern = new RegExp(`(?:#|${process.env.NEXT_PUBLIC_URL}/items/)(?\\d+)`, 'gi') +const refPattern = new RegExp(`(#\\d+|${process.env.NEXT_PUBLIC_URL}/items/\\d+.*)`, 'gi') export const createMentions = async (item, models) => { // if we miss a mention, in the rare circumstance there's some kind of @@ -1247,8 +1247,13 @@ const createItemMentions = async (item, models) => { const refs = item.text.match(refPattern)?.map(m => { if (m.startsWith('#')) return Number(m.slice(1)) // is not # syntax but full URL - return Number(m.split('/').slice(-1)[0]) - }) + try { + const { itemId, commentId } = parseInternalLinks(m) + return Number(commentId || itemId) + } catch (err) { + return null + } + }).filter(r => !!r) if (!refs || refs.length === 0) return const referee = await models.item.findMany({ diff --git a/components/text.js b/components/text.js index 355e6434..19f02744 100644 --- a/components/text.js +++ b/components/text.js @@ -213,7 +213,7 @@ export default memo(function Text ({ rel, imgproxyUrls, children, tab, itemId, o ) } else if (href.startsWith('/') || url?.origin === internalURL) { try { - const linkText = parseInternalLinks(href) + const { linkText } = parseInternalLinks(href) if (linkText) { return ( @@ -241,7 +241,7 @@ export default memo(function Text ({ rel, imgproxyUrls, children, tab, itemId, o } try { - const linkText = parseInternalLinks(href) + const { linkText } = parseInternalLinks(href) if (linkText) { return ( diff --git a/lib/url.js b/lib/url.js index 58dcb65a..371b0275 100644 --- a/lib/url.js +++ b/lib/url.js @@ -52,12 +52,14 @@ export function parseInternalLinks (href) { // and not #2 // since commentId will be ignored anyway const linkText = `#${itemId}/${itemPage}` - return linkText + return { itemId, linkText } } const commentId = searchParams.get('commentId') const linkText = `#${commentId || itemId}` - return linkText + return { itemId, commentId, linkText } } + + return {} } export function parseEmbedUrl (href) { diff --git a/lib/url.spec.js b/lib/url.spec.js index 829cc38c..8c301364 100644 --- a/lib/url.spec.js +++ b/lib/url.spec.js @@ -24,7 +24,7 @@ describe('internal links', () => { 'parses %p as %p', (href, expected) => { process.env.NEXT_PUBLIC_URL = 'https://stacker.news' - const actual = parseInternalLinks(href) + const { linkText: actual } = parseInternalLinks(href) expect(actual).toBe(expected) } )