Skip to content

Commit

Permalink
fix(message-parser): Differ link, autoLink, and autoEmail helpe…
Browse files Browse the repository at this point in the history
…rs (#993)
  • Loading branch information
tassoevan authored Mar 1, 2023
1 parent c92cfad commit db343e0
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 101 deletions.
34 changes: 18 additions & 16 deletions packages/message-parser/src/grammar.pegjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
{
const {
autoEmail,
autoLink,
bigEmoji,
bold,
code,
Expand All @@ -21,14 +23,14 @@
mentionUser,
orderedList,
paragraph,
phoneChecker,
plain,
quote,
reducePlainTexts,
strike,
task,
tasks,
unorderedList,
phoneChecker,
} = require('./utils');
}

Expand Down Expand Up @@ -263,7 +265,7 @@ InlineCode = "`" text:$InlineCode__+ "`" { return inlineCode(plain(text)); }

InlineCode__ = $(!"`" !"\n" $:.)

FilePath = $(urlScheme urlBody+)
FilePath = $(URL_scheme URL_body+)

LinkTitle = text:(Emphasis / Line / Whitespace) { return text; }

Expand Down Expand Up @@ -307,9 +309,9 @@ unicode

AutolinkedPhone = p:Phone { return phoneChecker(p.text, p.number); }

AutolinkedURL = u:URL { return link(u); }
AutolinkedURL = u:URL { return autoLink(u); }

AutolinkedEmail = e:Email { return link('mailto:' + e, [plain(e)]); }
AutolinkedEmail = e:Email { return autoEmail(e); }

alpha = [a-zA-Z]

Expand Down Expand Up @@ -405,12 +407,12 @@ phonePrefix
*/

URL
= $(urlScheme urlAuthority urlBody*)
/ $(urlAuthorityHost urlBody*)
= $(URL_scheme URL_authority URL_body*)
/ $(URL_authorityHost URL_body*)

urlScheme
URL_scheme
= $(
[[A-Za-z0-9+-]
[A-Za-z0-9+-]
[A-Za-z0-9+-]?
[A-Za-z0-9+-]?
[A-Za-z0-9+-]?
Expand Down Expand Up @@ -445,7 +447,7 @@ urlScheme
":"
)

urlBody
URL_body
= (
!(extra+ (Whitespace / EndOfLine) / Whitespace)
(
Expand All @@ -464,21 +466,21 @@ urlBody
)
)+

urlAuthority = $("//" urlAuthorityUserInfo? urlAuthorityHost)
URL_authority = $("//" URL_authorityUserInfo? URL_authorityHost)

urlAuthorityUserInfo = $(urlAuthorityUser (":" urlAuthorityPassword)? "@")
URL_authorityUserInfo = $(URL_authorityUser (":" URL_authorityPassword)? "@")

urlAuthorityUser = $(alpha_digit / !"@" !"/" safe)+
URL_authorityUser = $(alpha_digit / !"@" !"/" safe)+

urlAuthorityPassword = $(alpha_digit / !"@" !"/" safe)+
URL_authorityPassword = $(alpha_digit / !"@" !"/" safe)+

urlAuthorityHost = t:urlAuthorityHostName (":" urlAuthorityPort)?
URL_authorityHost = t:URL_authorityHostName (":" URL_authorityPort)?

urlAuthorityHostName
URL_authorityHostName
= domainName
/ $(digits "." digits "." digits "." digits) // TODO: IPv4 and IPv6

urlAuthorityPort
URL_authorityPort
= digits // TODO: from "0" to "65535"

/**
Expand Down
49 changes: 31 additions & 18 deletions packages/message-parser/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import type {
Emoji,
KaTeX,
InlineKaTeX,
Link,
} from './definitions';

const generate =
Expand Down Expand Up @@ -78,29 +79,41 @@ const isValidLink = (link: string) => {
}
};

export const link = (() => {
const fn = generate('LINK');
export const link = (src: string, label?: Markup[]): Link => ({
type: 'LINK',
value: { src: plain(src), label: label ?? [plain(src)] },
});

return (src: string, label?: Markup[]) => {
const { isIcann, isIp, isPrivate } = tldParse(src, {
detectIp: false,
allowPrivateDomains: true,
});
export const autoLink = (src: string) => {
const { isIcann, isIp, isPrivate, domain } = tldParse(src, {
detectIp: false,
allowPrivateDomains: true,
validHosts: ['localhost'],
});

if (!(isIcann || isIp || isPrivate || label)) {
return plain(src);
}
if (!(isIcann || isIp || isPrivate || domain === 'localhost')) {
return plain(src);
}

const tldLengthChecker = src.split('.');
if (tldLengthChecker[tldLengthChecker.length - 1].length < 2) {
return plain(src.replace('mailto:', ''));
}
const href = isValidLink(src) || src.startsWith('//') ? src : `//${src}`;

const href = isValidLink(src) || src.startsWith('//') ? src : `//${src}`;
return link(href, [plain(src)]);
};

return fn({ src: plain(href), label: label || [plain(src)] });
};
})();
export const autoEmail = (src: string) => {
const href = `mailto:${src}`;

const { isIcann, isIp, isPrivate } = tldParse(href, {
detectIp: false,
allowPrivateDomains: true,
});

if (!(isIcann || isIp || isPrivate)) {
return plain(src);
}

return link(href, [plain(src)]);
};

export const image = (() => {
const fn = generate('IMAGE');
Expand Down
8 changes: 4 additions & 4 deletions packages/message-parser/tests/email.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,10 @@ test.each([
'My email is fake@gmail.c',
[paragraph([plain('My email is fake@gmail.c')])],
],
// [
// 'My email is fake@gmail.comf',
// [paragraph([plain('My email is fake@gmail.comf')])],
// ],
[
'My email is fake@gmail.comf',
[paragraph([plain('My email is fake@gmail.comf')])],
],
])('parses %p', (input, output) => {
expect(parse(input)).toMatchObject(output);
});
24 changes: 19 additions & 5 deletions packages/message-parser/tests/link.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,10 @@ test.each([
],
],
['google.com', [paragraph([link('//google.com', [plain('google.com')])])]],
['www.google.com', [paragraph([link('www.google.com')])]],
[
'www.google.com',
[paragraph([link('//www.google.com', [plain('www.google.com')])])],
],
['rocket.chat:8080', [paragraph([link('rocket.chat:8080')])]],
['ShouldNotBeALink', [paragraph([plain('ShouldNotBeALink')])]],
[
Expand Down Expand Up @@ -400,11 +403,11 @@ Text after line break`,
],
[
'[9gag](https://9gag.com/)',
[paragraph([link('https://9gag.com/', [plain(`9gag`)])])],
[paragraph([link('https://9gag.com/', [plain('9gag')])])],
],
['[9gag](9gag.com)', [paragraph([link('9gag.com', [plain(`9gag`)])])]],
['<9gag.com|9gag>', [paragraph([link('9gag.com', [plain(`9gag`)])])]],
['9gag.com', [paragraph([link('9gag.com')])]],
['[9gag](9gag.com)', [paragraph([link('9gag.com', [plain('9gag')])])]],
['<9gag.com|9gag>', [paragraph([link('9gag.com', [plain('9gag')])])]],
['9gag.com', [paragraph([link('//9gag.com', [plain('9gag.com')])])]],
[
'[notes link](notes://Server/C3257116002CAD60/0/CCAF6BE2824A1F49432588D2001FA73E)',
[
Expand Down Expand Up @@ -500,6 +503,17 @@ Text after line break`,
['77.77', [paragraph([plain('77.77')])]],
['https://77.77', [paragraph([plain('https://77.77')])]],
['test.9gag', [paragraph([plain('test.9gag')])]],
[
'[here](https://github.com/RocketChat/Rocket.Chat/releases/tag/6.0.0-rc.3)',
[
paragraph([
link(
'https://github.com/RocketChat/Rocket.Chat/releases/tag/6.0.0-rc.3',
[plain('here')]
),
]),
],
],
])('parses %p', (input, output) => {
expect(parse(input)).toMatchObject(output);
});
2 changes: 1 addition & 1 deletion packages/message-parser/tests/strikethrough.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { parse } from '../src';
import { strike, paragraph, plain, link } from '../src/utils';
import { link, paragraph, plain, strike } from '../src/utils';

test.each([
[
Expand Down
Loading

0 comments on commit db343e0

Please sign in to comment.