Skip to content

Commit 7ece520

Browse files
gabriellshfilipemarinshugocostadevdougfabris
authored
fix(message-parser): Message parser issues (#852)
* Add first test * fix: check if is emoticon to preserver colon character * fix(message-parser): Thumbs emoji becoming phone number (#858) Co-authored-by: gabriellsh <gabriel.henriques@rocket.chat> * fix(message-parser): Link/URL parser issues (#855) * feat(fuselage): Adds wordbreak in Box Component (#853) * Fixing URL/links parsing issues * restoring files from base branch * replacing backstick with single quotes Co-authored-by: Douglas Fabris <devfabris@gmail.com> * fixing domainChar accepted chars (#861) * temporarily removing emphasis support Co-authored-by: Filipe Marins <filipemarins123@gmail.com> Co-authored-by: Hugo Costa <hugocarreiracosta@gmail.com> Co-authored-by: Douglas Fabris <devfabris@gmail.com>
1 parent 50c7d94 commit 7ece520

File tree

6 files changed

+230
-62
lines changed

6 files changed

+230
-62
lines changed

packages/message-parser/src/grammar.pegjs

+28-55
Original file line numberDiff line numberDiff line change
@@ -171,19 +171,12 @@ Space
171171
/ "\t"
172172

173173
anyText
174-
= [\x20-\x27] /* ! " # $ % & ' ( ) */
174+
= [\x20-\x27] // ! " # $ % & '
175175
/ [\x2B-\x40] // + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @
176176
/ [\x41-\x5A] // A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
177177
/ [\x61-\x7A] // a b c d e f g h i j k l m n o p q r s t u v w x y z
178178
/ nonascii
179179

180-
SectionText
181-
= [-]+
182-
/ [\x20-\x40] // ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @
183-
/ [\x41-\x60] // A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ `
184-
/ [\x61-\x7A] // a b c d e f g h i j k l m n o p q r s t u v w x y z
185-
/ nonascii
186-
187180
utf8_names_validation = $[0-9a-zA-Z-_.]+
188181

189182
matrix_server_validation = ":" utf8_names_validation
@@ -203,12 +196,14 @@ ChannelMention
203196
}
204197
/ "#" channel:utf8_names_validation { return mentionChannel(channel); }
205198

199+
emoji_shortCode_name = $[0-9a-zA-Z-_+.]+
200+
206201
Emoji
207202
= Emoji_shortCode
208203
/ ch:unicodeEmoji { return emojiUnicode(ch); }
209204

210205
Emoji_shortCode
211-
= ":" shortCode:$(text:utf8_names_validation) ":" { return emoji(shortCode); }
206+
= ":" shortCode:$(text:emoji_shortCode_name) ":" { return emoji(shortCode); }
212207

213208
/* __Italic__ */
214209
/* _Italic_ */
@@ -301,27 +296,6 @@ escape
301296
= unicode
302297
/ "\\" ch:[^\r\n\f0-9a-f]i { return ch; }
303298

304-
nmstart
305-
= [_a-z]i
306-
/ nonascii
307-
/ escape
308-
309-
nmchar
310-
= [_a-z0-9-]i
311-
/ nonascii
312-
/ escape
313-
314-
string1
315-
= "\"" chars:$([^\n\r\f\\"] / "\\" nl:nl { return ''; } / escape)* "\"" {
316-
return chars;
317-
}
318-
319-
nl
320-
= "\n"
321-
/ "\r\n"
322-
/ "\r"
323-
/ "\f"
324-
325299
AutolinkedPhone = p:Phone { return link('tel:' + p.number, plain(p.text)); }
326300

327301
AutolinkedURL = u:URL { return link(u); }
@@ -375,11 +349,12 @@ hexByte = a:hexdigit b:hexdigit { return parseInt(a + b, 16); }
375349

376350
domainName
377351
= "localhost"
378-
/ $(domainNameLabel ("." domainChar domainNameLabel)+)
352+
/ $(domainNameLabel ("." (!digit domainChar) domainNameLabel)+)
379353

380354
domainNameLabel = $(domainChar+ $("-" domainChar+)*)
381355

382-
domainChar = !"\\" !"/" !"|" !">" !"<" !safe !extra !EndOfLine !Space .
356+
domainChar
357+
= !"\\" !"/" !"|" !">" !"<" !"%" !"`" !safe !extra !EndOfLine !Space .
383358

384359
/**
385360
*
@@ -409,23 +384,8 @@ phonePrefix
409384
*/
410385

411386
URL
412-
= $(
413-
s:urlScheme
414-
a:urlAuthority
415-
p:urlPath?
416-
q:urlQuery?
417-
f:urlFragment?
418-
g:urlPath?
419-
h:urlQuery?
420-
)
421-
/ $(
422-
urlAuthorityHost
423-
p:urlPath?
424-
q:urlQuery?
425-
f:urlFragment?
426-
g:urlPath?
427-
h:urlQuery?
428-
)
387+
= $(urlScheme urlAuthority urlBody)
388+
/ $(urlAuthorityHost urlBody)
429389

430390
urlScheme
431391
= $(
@@ -464,6 +424,25 @@ urlScheme
464424
":"
465425
)
466426

427+
urlBody
428+
= (
429+
!Whitespace
430+
(
431+
anyText
432+
/ "*"
433+
/ "["
434+
/ "\/"
435+
/ "]"
436+
/ "^"
437+
/ "_"
438+
/ "`"
439+
/ "{"
440+
/ "}"
441+
/ "~"
442+
/ "("
443+
)
444+
)*
445+
467446
urlAuthority = $("//" urlAuthorityUserInfo? urlAuthorityHost)
468447

469448
urlAuthorityUserInfo = $(urlAuthorityUser (":" urlAuthorityPassword)? "@")
@@ -481,12 +460,6 @@ urlAuthorityHostName
481460
urlAuthorityPort
482461
= digits // TODO: from "0" to "65535"
483462

484-
urlPath = $("/" $(!"?" !"/" !"#" !")" !">" !"|" !" " .)* urlPath*)
485-
486-
urlQuery = $("?" $(alpha_digit / safe)*)
487-
488-
urlFragment = $("#" $(alpha_digit / extra / safe)*)
489-
490463
/**
491464
*
492465
* Email

packages/message-parser/src/utils.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ const isValidLink = (link: string) => {
7575
return false;
7676
}
7777
};
78+
7879
export const link = (() => {
7980
const fn = generate('LINK');
8081

@@ -145,9 +146,17 @@ const joinEmoji = (
145146
const hasPlainAsNeighbor =
146147
(previous?.type === 'PLAIN_TEXT' && previous.value.trim() !== '') ||
147148
(next?.type === 'PLAIN_TEXT' && next.value.trim() !== '');
149+
const isEmoticon = current.shortCode !== current.value.value;
148150

149151
if (current.value && (hasEmojiAsNeighbor || hasPlainAsNeighbor)) {
150-
return current.value;
152+
if (isEmoticon) {
153+
return current.value;
154+
}
155+
156+
return {
157+
...current.value,
158+
value: `:${current.value.value}:`,
159+
};
151160
}
152161

153162
return current;

packages/message-parser/tests/emoji.test.ts

+16-6
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,22 @@ import { parse } from '../src';
22
import { emoji, bigEmoji, paragraph, plain, emojiUnicode } from '../src/utils';
33

44
test.each([
5-
[':smille: asd', [paragraph([emoji('smille'), plain(' asd')])]],
5+
[':smile: asd', [paragraph([emoji('smile'), plain(' asd')])]],
6+
['text:inner:outer', [paragraph([plain('text:inner:outer')])]],
7+
['10:20:30', [paragraph([plain('10:20:30')])]],
8+
['10:20:30:', [paragraph([plain('10:20:30:')])]],
9+
['":smile:"', [paragraph([plain('":smile:"')])]],
10+
['":smile: "', [paragraph([plain('":smile: "')])]],
11+
['" :smile: "', [paragraph([plain('" '), emoji('smile'), plain(' "')])]],
612
[
7-
`:smille:
8-
:smille:
13+
`:smile:
14+
:smile:
915
`,
10-
[bigEmoji([emoji('smille'), emoji('smille')])],
16+
[bigEmoji([emoji('smile'), emoji('smile')])],
1117
],
1218
[
13-
'asdas :smille: asd',
14-
[paragraph([plain('asdas '), emoji('smille'), plain(' asd')])],
19+
'asdas :smile: asd',
20+
[paragraph([plain('asdas '), emoji('smile'), plain(' asd')])],
1521
],
1622
[
1723
'normal emojis :smile: :smile: :smile:',
@@ -44,10 +50,13 @@ test.each([
4450
],
4551
[':smile::smile:', [bigEmoji([emoji('smile'), emoji('smile')])]],
4652
[':smile:', [bigEmoji([emoji('smile')])]],
53+
['Hi :+1:', [paragraph([plain('Hi '), emoji('+1')])]],
54+
['Hi :+1_tone4:', [paragraph([plain('Hi '), emoji('+1_tone4')])]],
4755
])('parses %p', (input, output) => {
4856
expect(parse(input)).toMatchObject(output);
4957
});
5058

59+
// Tests for unicode emojis
5160
test.each([
5261
['😀', [bigEmoji([emojiUnicode('😀')])]],
5362
['😃', [bigEmoji([emojiUnicode('😃')])]],
@@ -81,6 +90,7 @@ test.each([
8190
[bigEmoji([emojiUnicode('👆🏽'), emojiUnicode('👆🏽'), emojiUnicode('👆🏽')])],
8291
],
8392
['👆🏺', [bigEmoji([emojiUnicode('👆'), emojiUnicode('🏺')])]],
93+
['Hi 👍', [paragraph([plain('Hi '), emojiUnicode('👍')])]],
8494
])('parses %p', (input, output) => {
8595
expect(parse(input)).toMatchObject(output);
8696
});

packages/message-parser/tests/emoticons.test.ts

+4
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ test.each([
131131

132132
// Should not render Emojis or BigEmojis if they are not surrounded by spaces
133133
['normal emojis :):):)', [paragraph([plain('normal emojis :):):)')])]],
134+
[':)10:30', [paragraph([plain(':)10:30')])]],
135+
[':smile::)text', [paragraph([plain(':smile::)text')])]],
136+
['text:):smile:', [paragraph([plain('text:):smile:')])]],
137+
['text:):)', [paragraph([plain('text:):)')])]],
134138
[':):):) normal emojis', [paragraph([plain(':):):) normal emojis')])]],
135139
[':):):):)', [paragraph([plain(':):):):)')])]],
136140
['10:30', [paragraph([plain('10:30')])]],

packages/message-parser/tests/inlineCode.test.ts

+10
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@ test.each([
77
[paragraph([inlineCode(plain('[asd](https://localhost)'))])],
88
],
99
[`\`code\``, [paragraph([inlineCode(plain('code'))])]],
10+
[
11+
`File extension (\`.mov\`)`,
12+
[
13+
paragraph([
14+
plain('File extension ('),
15+
inlineCode(plain('.mov')),
16+
plain(')'),
17+
]),
18+
],
19+
],
1020
])('parses %p', (input, output) => {
1121
expect(parse(input)).toMatchObject(output);
1222
});

0 commit comments

Comments
 (0)