Skip to content

Commit b5e100e

Browse files
fix(renderText): specify linkifyjs types to look for (email and url) (#1902)
* chore(deps): upgrade linkifyjs to v4.1.0 * fix(renderText): specify linkifyjs types to look for (email and url)
1 parent 9c979f9 commit b5e100e

File tree

3 files changed

+52
-45
lines changed

3 files changed

+52
-45
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"hast-util-find-and-replace": "^4.1.2",
3939
"i18next": "^21.6.14",
4040
"isomorphic-ws": "^4.0.1",
41-
"linkifyjs": "^2.1.9",
41+
"linkifyjs": "^4.1.0",
4242
"lodash.debounce": "^4.0.8",
4343
"lodash.throttle": "^4.1.1",
4444
"lodash.uniqby": "^4.7.0",

src/utils.tsx

Lines changed: 46 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { ComponentProps, ComponentType } from 'react';
22
import emojiRegex from 'emoji-regex';
3-
import * as linkify from 'linkifyjs';
3+
import { find } from 'linkifyjs';
44
import { nanoid } from 'nanoid';
55
import { findAndReplace, ReplaceFunction } from 'hast-util-find-and-replace';
66
import ReactMarkdown, { Options, uriTransformer } from 'react-markdown';
@@ -239,52 +239,54 @@ export const renderText = <
239239
const codeBlocks = messageCodeBlocks(newText);
240240

241241
// extract all valid links/emails within text and replace it with proper markup
242-
uniqBy(linkify.find(newText), 'value').forEach(({ href, type, value }) => {
243-
const linkIsInBlock = codeBlocks.some((block) => block?.includes(value));
244-
245-
// check if message is already markdown
246-
const noParsingNeeded =
247-
markdownLinks &&
248-
markdownLinks.filter((text) => {
249-
const strippedHref = href?.replace(detectHttp, '');
250-
const strippedText = text?.replace(detectHttp, '');
251-
252-
if (!strippedHref || !strippedText) return false;
253-
254-
return strippedHref.includes(strippedText) || strippedText.includes(strippedHref);
255-
});
256-
257-
if (noParsingNeeded.length > 0 || linkIsInBlock) return;
258-
259-
try {
260-
// special case for mentions:
261-
// it could happen that a user's name matches with an e-mail format pattern.
262-
// in that case, we check whether the found e-mail is actually a mention
263-
// by naively checking for an existence of @ sign in front of it.
264-
if (type === 'email' && mentionedUsers) {
265-
const emailMatchesWithName = mentionedUsers.some((u) => u.name === value);
266-
if (emailMatchesWithName) {
267-
newText = newText.replace(new RegExp(escapeRegExp(value), 'g'), (match, position) => {
268-
const isMention = newText.charAt(position - 1) === '@';
269-
// in case of mention, we leave the match in its original form,
270-
// and we let `mentionsMarkdownPlugin` to do its job
271-
return isMention ? match : `[${match}](${encodeDecode(href)})`;
272-
});
273-
274-
return;
242+
uniqBy([...find(newText, 'email'), ...find(newText, 'url')], 'value').forEach(
243+
({ href, type, value }) => {
244+
const linkIsInBlock = codeBlocks.some((block) => block?.includes(value));
245+
246+
// check if message is already markdown
247+
const noParsingNeeded =
248+
markdownLinks &&
249+
markdownLinks.filter((text) => {
250+
const strippedHref = href?.replace(detectHttp, '');
251+
const strippedText = text?.replace(detectHttp, '');
252+
253+
if (!strippedHref || !strippedText) return false;
254+
255+
return strippedHref.includes(strippedText) || strippedText.includes(strippedHref);
256+
});
257+
258+
if (noParsingNeeded.length > 0 || linkIsInBlock) return;
259+
260+
try {
261+
// special case for mentions:
262+
// it could happen that a user's name matches with an e-mail format pattern.
263+
// in that case, we check whether the found e-mail is actually a mention
264+
// by naively checking for an existence of @ sign in front of it.
265+
if (type === 'email' && mentionedUsers) {
266+
const emailMatchesWithName = mentionedUsers.some((u) => u.name === value);
267+
if (emailMatchesWithName) {
268+
newText = newText.replace(new RegExp(escapeRegExp(value), 'g'), (match, position) => {
269+
const isMention = newText.charAt(position - 1) === '@';
270+
// in case of mention, we leave the match in its original form,
271+
// and we let `mentionsMarkdownPlugin` to do its job
272+
return isMention ? match : `[${match}](${encodeDecode(href)})`;
273+
});
274+
275+
return;
276+
}
275277
}
276-
}
277278

278-
const displayLink = type === 'email' ? value : formatUrlForDisplay(href);
279+
const displayLink = type === 'email' ? value : formatUrlForDisplay(href);
279280

280-
newText = newText.replace(
281-
new RegExp(escapeRegExp(value), 'g'),
282-
`[${displayLink}](${encodeDecode(href)})`,
283-
);
284-
} catch (e) {
285-
void e;
286-
}
287-
});
281+
newText = newText.replace(
282+
new RegExp(escapeRegExp(value), 'g'),
283+
`[${displayLink}](${encodeDecode(href)})`,
284+
);
285+
} catch (e) {
286+
void e;
287+
}
288+
},
289+
);
288290

289291
const rehypePlugins = [emojiMarkdownPlugin];
290292

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10235,6 +10235,11 @@ linkifyjs@^2.1.9:
1023510235
resolved "https://registry.yarnpkg.com/linkifyjs/-/linkifyjs-2.1.9.tgz#af06e45a2866ff06c4766582590d098a4d584702"
1023610236
integrity sha512-74ivurkK6WHvHFozVaGtQWV38FzBwSTGNmJolEgFp7QgR2bl6ArUWlvT4GcHKbPe1z3nWYi+VUdDZk16zDOVug==
1023710237

10238+
linkifyjs@^4.1.0:
10239+
version "4.1.0"
10240+
resolved "https://registry.yarnpkg.com/linkifyjs/-/linkifyjs-4.1.0.tgz#0460bfcc37d3348fa80e078d92e7bbc82588db15"
10241+
integrity sha512-Ffv8VoY3+ixI1b3aZ3O+jM6x17cOsgwfB1Wq7pkytbo1WlyRp6ZO0YDMqiWT/gQPY/CmtiGuKfzDIVqxh1aCTA==
10242+
1023810243
load-json-file@^2.0.0:
1023910244
version "2.0.0"
1024010245
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8"

0 commit comments

Comments
 (0)