fix: message parser being slow to process very long messages with too many symbols (#33227)

pull/33224/head^2
Pierre Lehnen 1 year ago committed by GitHub
parent 6730a3c911
commit 79c16d315a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 6
      .changeset/short-drinks-itch.md
  2. 126
      packages/message-parser/src/grammar.pegjs
  3. 36
      packages/message-parser/src/utils.ts
  4. 268
      packages/message-parser/tests/abuse.test.ts
  5. 62
      packages/message-parser/tests/emphasis.test.ts
  6. 24
      packages/message-parser/tests/link.test.ts

@ -0,0 +1,6 @@
---
'@rocket.chat/message-parser': patch
'@rocket.chat/peggy-loader': patch
---
Improved the performance of the message parser

@ -10,6 +10,7 @@
emoji,
emojiUnicode,
emoticon,
extractFirstResult,
heading,
image,
inlineCode,
@ -33,6 +34,11 @@
unorderedList,
timestamp,
} = require('./utils');
let skipBold = false;
let skipItalic = false;
let skipStrikethrough = false;
let skipReferences = false;
}}
Start
@ -212,7 +218,7 @@ Inline = value:(InlineItem / Any)+ EndOfLine? { return reducePlainTexts(value);
InlineItem = Whitespace
/ Timestamp
/ References
/ MaybeReferences
/ AutolinkedPhone
/ AutolinkedEmail
/ AutolinkedURL
@ -240,7 +246,7 @@ References
= "[" title:LinkTitle* "](" href:LinkRef ")" { return title.length ? link(href, reducePlainTexts(title)) : link(href); }
/ "<" href:LinkRef "|" title:LinkTitle2 ">" { return link(href, [plain(title)]); }
LinkTitle = (Whitespace / EmphasisForReferences) / anyTitle:$(!("](" .) .) { return plain(anyTitle) }
LinkTitle = (Whitespace / Emphasis) / anyTitle:$(!("](" .) .) { return plain(anyTitle) }
LinkTitle2 = $([\x20-\x3B\x3D\x3F-\x60\x61-\x7B\x7D-\xFF] / NonASCII)+
@ -349,14 +355,7 @@ AutoLinkURLBody = !(Extra* (Whitespace / EndOfLine)) .
* Emphasis
*
*/
Emphasis = Bold / Italic / Strikethrough
/**
*
* Emphasis for References
*
*/
EmphasisForReferences = BoldForReferences / ItalicForReferences / StrikethroughForReferences
Emphasis = MaybeBold / MaybeItalic / MaybeStrikethrough
/**
*
@ -365,6 +364,63 @@ EmphasisForReferences = BoldForReferences / ItalicForReferences / StrikethroughF
*
*/
// This rule is used inside expressions that have a JS code ensuring they always fail,
// Without any pattern to match, peggy will think the rule may end up succedding without consuming any input, which could cause infinite loops
// So this unreachable rule is added to them to satisfy peggy's requirement.
BlockedByJavascript = 'unreachable'
MaybeBold
= result:(
& {
if (skipBold) { return false; }
skipBold = true;
return true;
}
(
(text:Bold { skipBold = false; return text; })
/ (& { skipBold = false; return false; } BlockedByJavascript)
)
) { return extractFirstResult(result); }
MaybeStrikethrough
= result:(
& {
if (skipStrikethrough) { return false; }
skipStrikethrough = true;
return true;
}
(
(text:Strikethrough { skipStrikethrough = false; return text; })
/ (& { skipStrikethrough = false; return false; } BlockedByJavascript)
)
) { return extractFirstResult(result); }
MaybeItalic
= result:(
& {
if (skipItalic) { return false; }
skipItalic = true;
return true;
}
(
(text:Italic { skipItalic = false; return text; })
/ (& { skipItalic = false; return false; } BlockedByJavascript)
)
) { return extractFirstResult(result); }
MaybeReferences
= result:(
& {
if (skipReferences) { return false; }
skipReferences = true;
return true;
}
(
(text:References { skipReferences = false; return text; })
/ (& { skipReferences = false; return false; } BlockedByJavascript)
)
) { return extractFirstResult(result); }
/* Italic */
Italic
= value:$([a-zA-Z0-9]+ [\x5F] [\x5F]?) { return plain(value); }
@ -384,11 +440,11 @@ ItalicContentItems = text:ItalicContentItem+ { return reducePlainTexts(text); }
ItalicContentItem
= Whitespace
/ InlineCode
/ References
/ MaybeReferences
/ UserMention
/ ChannelMention
/ Bold
/ Strikethrough
/ MaybeBold
/ MaybeStrikethrough
/ Emoji
/ Emoticon
/ AnyItalic
@ -399,52 +455,12 @@ Bold = [\x2A] [\x2A] @BoldContent [\x2A] [\x2A] / [\x2A] @BoldContent [\x2A]
BoldContent = text:BoldContentItem+ { return bold(reducePlainTexts(text)); }
BoldContentItem = Whitespace / InlineCode / References / UserMention / ChannelMention / Italic / Strikethrough / Emoji / Emoticon / AnyBold / Line
BoldContentItem = Whitespace / InlineCode / MaybeReferences / UserMention / ChannelMention / MaybeItalic / MaybeStrikethrough / Emoji / Emoticon / AnyBold / Line
/* Strike */
Strikethrough = [\x7E] [\x7E] @StrikethroughContent [\x7E] [\x7E] / [\x7E] @StrikethroughContent [\x7E]
StrikethroughContent = text:(Timestamp / InlineCode / Whitespace / References / UserMention / ChannelMention / Italic / Bold / Emoji / Emoticon / AnyStrike / Line)+ {
return strike(reducePlainTexts(text));
}
/* Italic for References */
ItalicForReferences
= value:$([a-zA-Z0-9]+ [\x5F] [\x5F]?) { return plain(value); }
/ [\x5F] [\x5F] i:ItalicContentItemsForReferences [\x5F] [\x5F] t:$[a-zA-Z0-9]+ {
return reducePlainTexts([plain('__'), ...i, plain('__'), plain(t)])[0];
}
/ [\x5F] i:ItalicContentItemsForReferences [\x5F] t:$[a-zA-Z]+ {
return reducePlainTexts([plain('_'), ...i, plain('_'), plain(t)])[0];
}
/ [\x5F] [\x5F] @ItalicContentForReferences [\x5F] [\x5F]
/ [\x5F] @ItalicContentForReferences [\x5F]
ItalicContentForReferences = text:ItalicContentItemsForReferences { return italic(text); }
ItalicContentItemsForReferences = text:ItalicContentItemForReferences+ { return reducePlainTexts(text); }
ItalicContentItemForReferences
= Whitespace
/ UserMention
/ ChannelMention
/ BoldForReferences
/ StrikethroughForReferences
/ Emoji
/ Emoticon
/ AnyItalic
/ Line
/ InlineCode
/* Bold for References */
BoldForReferences = [\x2A] [\x2A] @BoldContentForReferences [\x2A] [\x2A] / [\x2A] @BoldContentForReferences [\x2A]
BoldContentForReferences = text:(Whitespace / UserMention / ChannelMention / ItalicForReferences / StrikethroughForReferences / Emoji / Emoticon / AnyBold / Line / InlineCode)+ { return bold(reducePlainTexts(text)); }
/* Strike for References */
StrikethroughForReferences = [\x7E] [\x7E] @StrikethroughContentForReferences [\x7E] [\x7E] / [\x7E] @StrikethroughContentForReferences [\x7E]
StrikethroughContentForReferences = text:(Whitespace / UserMention / ChannelMention / ItalicForReferences / BoldForReferences / Emoji / Emoticon / AnyStrike / Line / InlineCode)+ {
StrikethroughContent = text:(Timestamp / Whitespace / InlineCode / MaybeReferences / UserMention / ChannelMention / MaybeItalic / MaybeBold / Emoji / Emoticon / AnyStrike / Line)+ {
return strike(reducePlainTexts(text));
}

@ -198,21 +198,19 @@ const joinEmoji = (
export const reducePlainTexts = (
values: Paragraph['value']
): Paragraph['value'] =>
values
.flatMap((item) => item)
.reduce((result, item, index, values) => {
const next = values[index + 1];
const current = joinEmoji(item, values[index - 1], next);
const previous: Inlines = result[result.length - 1];
if (previous) {
if (current.type === 'PLAIN_TEXT' && current.type === previous.type) {
previous.value += current.value;
return result;
}
values.flat().reduce((result, item, index, values) => {
const next = values[index + 1];
const current = joinEmoji(item, values[index - 1], next);
const previous: Inlines = result[result.length - 1];
if (previous) {
if (current.type === 'PLAIN_TEXT' && current.type === previous.type) {
previous.value += current.value;
return result;
}
return [...result, current];
}, [] as Paragraph['value']);
}
return [...result, current];
}, [] as Paragraph['value']);
export const lineBreak = (): LineBreak => ({
type: 'LINE_BREAK',
value: undefined,
@ -249,3 +247,13 @@ export const timestamp = (
fallback: plain(`<t:${value}:${type || 't'}>`),
};
};
export const extractFirstResult = (
value: Types[keyof Types]['value']
): Types[keyof Types]['value'] => {
if (typeof value !== 'object' || !Array.isArray(value)) {
return value;
}
return value.filter((item) => item).shift() as Types[keyof Types]['value'];
};

@ -0,0 +1,268 @@
import { parse } from '../src';
import { paragraph, plain, bold, italic, strike } from '../src/utils';
test.each([
[
`This a message designed to stress test the message parser, trying to force several rules to stack at the same time !!@#$%^&*()_+, overloading the symbols {}:"|<>?, some more text ,./;'\\[], numbers too 1234567890-= let it call s o s ok~, from now on we repeat some. , REPEATx2 This a message designed to stress test the message parser, trying to force several rules to stack at the same time !!@#$%^&*()_+, overloading the symbols {}:"|<>?, some more text ,./;'\\[], numbers too 1234567890-= let it call s o s ok~, from now on we repeat some. REPEAT x3 This a message designed to stress test the message parser, trying to force several rules to stack at the same time !!@#$%^&*()_+, overloading the symbols {}:"|<>?, some more text ,./;'\\[], numbers too 1234567890-= let it call s o s ok~, from now on we repeat some. REPEAT x4 This a message designed to stress test the message parser, trying to force several rules to stack at the same time !!@#$%^&*()_+, overloading the symbols {}:"|<>?, some more text ,./;'\\[], numbers too 1234567890-= let it call s o s ok~, from now on we repeat some. REPEATx 5 This a message designed to stress test the message parser, trying to force several rules to stack at the same time !!@#$%^&*()_+, overloading the symbols {}:"|<>?, some more text ,./;'\\[], numbers too 1234567890-= let it call s o s ok~, from now on we repeat some. , REPEAT x6 This a message designed to stress test the message parser, trying to force several rules to stack at the same time !!@#$%^&*()_+, overloading the symbols {}:"|<>?, some more text ,./;'\\[], numbers too 1234567890-= let it call s o s ok~, from now on we repeat some. this can go long for some time, repeat x7 This a message designed to stress test the message parser, trying to force several rules to stack at the same time !!@#$%^&*()_+, overloading the symbols {}:"|<>?, some more text ,./;'\\[], numbers too 1234567890-= let it call s o s ok~, from now on we repeat some. ,repeat x8 This a message designed to stress test the message parser, trying to force several rules to stack at the same time !!@#$%^&*()_+, overloading the symbols {}:"|<>?, some more text ,./;'\\[], numbers too 1234567890-= let it call s o s ok~, from now on we repeat some.`,
[
paragraph([
plain(
'This a message designed to stress test the message parser, trying to force several rules to stack at the same time !!@#$%^&'
),
bold([
plain('()'),
italic([
plain(
`+, overloading the symbols {}:"|<>?, some more text ,./;'\\[], numbers too 1234567890-= let it call s o s ok`
),
strike([
plain(
`, from now on we repeat some. , REPEATx2 This a message designed to stress test the message parser, trying to force several rules to stack at the same time !!@#$%^&*()_+, overloading the symbols {}:"|<>?, some more text ,./;'\\[], numbers too 1234567890-= let it call s o s ok`
),
]),
plain(
', from now on we repeat some. REPEAT x3 This a message designed to stress test the message parser, trying to force several rules to stack at the same time !!@#$%^&*()'
),
]),
plain(
`+, overloading the symbols {}:"|<>?, some more text ,./;'\\[], numbers too 1234567890-= let it call s o s ok`
),
strike([
plain(
', from now on we repeat some. REPEAT x4 This a message designed to stress test the message parser, trying to force several rules to stack at the same time !!@#$%^&*()'
),
italic([
plain(
`+, overloading the symbols {}:"|<>?, some more text ,./;'\\[], numbers too 1234567890-= let it call s o s ok~, from now on we repeat some. REPEATx 5 This a message designed to stress test the message parser, trying to force several rules to stack at the same time !!@#$%^&*()`
),
]),
plain(
`+, overloading the symbols {}:"|<>?, some more text ,./;'\\[], numbers too 1234567890-= let it call s o s ok`
),
]),
plain(
`, from now on we repeat some. , REPEAT x6 This a message designed to stress test the message parser, trying to force several rules to stack at the same time !!@#$%^&`
),
]),
plain(
`()_+, overloading the symbols {}:"|<>?, some more text ,./;'\\[], numbers too 1234567890-= let it call s o s ok`
),
strike([
plain(
`, from now on we repeat some. this can go long for some time, repeat x7 This a message designed to stress test the message parser, trying to force several rules to stack at the same time !!@#$%^&*()`
),
italic([
plain(
`+, overloading the symbols {}:"|<>?, some more text ,./;'\\[], numbers too 1234567890-= let it call s o s ok~, from now on we repeat some. ,repeat x8 This a message designed to stress test the message parser, trying to force several rules to stack at the same time !!@#$%^&*()`
),
]),
plain(
`+, overloading the symbols {}:"|<>?, some more text ,./;'\\[], numbers too 1234567890-= let it call s o s ok`
),
]),
plain(', from now on we repeat some.'),
]),
],
],
[
'**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__**_**__',
[
paragraph([
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
italic([bold([plain('_')])]),
bold([italic([plain('**')]), italic([plain('**')])]),
plain('__'),
]),
],
],
])('parses %p', (input, output) => {
expect(parse(input)).toMatchObject(output);
});

@ -185,6 +185,68 @@ test.each([
]),
],
],
[
'**bold ~~and strike~~** **not bold ~~but strike** ~~ not strike~~',
[
paragraph([
bold([plain('bold '), strike([plain('and strike')])]),
plain(' **not bold '),
strike([plain('but strike** ')]),
plain(' not strike~~'),
]),
],
],
[
'**bold** **another bold** ~~strike~~ ~~another strike~~ **bold ~~and strike~~** **not bold ~~but strike** ~~ not strike~~',
[
paragraph([
bold([plain('bold')]),
plain(' '),
bold([plain('another bold')]),
plain(' '),
strike([plain('strike')]),
plain(' '),
strike([plain('another strike')]),
plain(' '),
bold([plain('bold '), strike([plain('and strike')])]),
plain(' **not bold '),
strike([plain('but strike** ')]),
plain(' not strike~~'),
]),
],
],
[
'some_snake_case_text and even_more',
[paragraph([plain('some_snake_case_text and even_more')])],
],
[
'some_snake_case_text and some __italic__ text',
[
paragraph([
plain('some_snake_case_text and some '),
italic([plain('italic')]),
plain(' text'),
]),
],
],
[
'some__double__snake__case__text and even_more',
[paragraph([plain('some__double__snake__case__text and even_more')])],
],
[
'some__double__snake__case__text and some __italic__ text',
[
paragraph([
plain('some__double__snake__case__text and some '),
italic([plain('italic')]),
plain(' text'),
]),
],
],
[
'something__ __and italic__',
[paragraph([plain('something__ '), italic([plain('and italic')])])],
],
])('parses %p', (input, output) => {
expect(parse(input)).toMatchObject(output);
});

@ -584,6 +584,30 @@ Text after line break`,
]),
],
],
[
'[test **bold** and __italic__](https://rocket.chat)',
[
paragraph([
link('https://rocket.chat', [
plain('test '),
bold([plain('bold')]),
plain(' and '),
italic([plain('italic')]),
]),
]),
],
],
[
'[test **bold with __italic__**](https://rocket.chat)',
[
paragraph([
link('https://rocket.chat', [
plain('test '),
bold([plain('bold with '), italic([plain('italic')])]),
]),
]),
],
],
])('parses %p', (input, output) => {
expect(parse(input)).toMatchObject(output);
});

Loading…
Cancel
Save