2021-04-08 12:19:38 +03:00
|
|
|
import { expect } from 'chai'
|
2022-06-30 16:32:56 +03:00
|
|
|
import Long from 'long'
|
2023-06-05 03:30:48 +03:00
|
|
|
import { describe, it } from 'mocha'
|
|
|
|
|
2023-09-24 03:37:34 +03:00
|
|
|
import { FormattedString, MessageEntity, tl } from '@mtcute/client'
|
2023-09-24 04:26:28 +03:00
|
|
|
import { isPresent } from '@mtcute/client/utils'
|
2022-06-30 16:32:56 +03:00
|
|
|
|
2021-07-02 20:20:29 +03:00
|
|
|
import { MarkdownMessageEntityParser, md } from '../src'
|
2021-04-08 12:19:38 +03:00
|
|
|
|
|
|
|
const createEntity = <T extends tl.TypeMessageEntity['_']>(
|
|
|
|
type: T,
|
|
|
|
offset: number,
|
|
|
|
length: number,
|
2023-09-24 01:32:22 +03:00
|
|
|
additional?: Omit<tl.FindByName<tl.TypeMessageEntity, T>, '_' | 'offset' | 'length'>,
|
2021-04-08 12:19:38 +03:00
|
|
|
): tl.TypeMessageEntity => {
|
|
|
|
return {
|
|
|
|
_: type,
|
|
|
|
offset,
|
|
|
|
length,
|
|
|
|
...(additional ?? {}),
|
2023-06-05 03:30:48 +03:00
|
|
|
} as tl.TypeMessageEntity // idc really, its not that important
|
2021-04-08 12:19:38 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
const createEntities = (entities: tl.TypeMessageEntity[]): MessageEntity[] => {
|
2023-09-24 04:26:28 +03:00
|
|
|
return entities.map((it) => MessageEntity._parse(it)).filter(isPresent)
|
2021-04-08 12:19:38 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
describe('MarkdownMessageEntityParser', () => {
|
|
|
|
const parser = new MarkdownMessageEntityParser()
|
|
|
|
|
|
|
|
describe('unparse', () => {
|
|
|
|
const test = (
|
|
|
|
text: string,
|
|
|
|
entities: tl.TypeMessageEntity[],
|
|
|
|
expected: string | string[],
|
2023-06-05 03:30:48 +03:00
|
|
|
_parser = parser,
|
2021-04-08 12:19:38 +03:00
|
|
|
): void => {
|
|
|
|
const result = _parser.unparse(text, createEntities(entities))
|
2023-06-05 03:30:48 +03:00
|
|
|
|
2021-04-08 12:19:38 +03:00
|
|
|
if (Array.isArray(expected)) {
|
|
|
|
expect(expected).to.include(result)
|
|
|
|
} else {
|
|
|
|
expect(result).eq(expected)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
it('should return the same text if there are no entities or text', () => {
|
|
|
|
test('', [], '')
|
|
|
|
test('some text', [], 'some text')
|
|
|
|
})
|
|
|
|
|
2022-05-06 00:40:47 +03:00
|
|
|
it('should handle bold, italic, underline, strikethrough and spoiler', () => {
|
2021-04-08 12:19:38 +03:00
|
|
|
test(
|
2022-05-06 00:40:47 +03:00
|
|
|
'plain bold italic underline strikethrough spoiler plain',
|
2021-04-08 12:19:38 +03:00
|
|
|
[
|
|
|
|
createEntity('messageEntityBold', 6, 4),
|
|
|
|
createEntity('messageEntityItalic', 11, 6),
|
|
|
|
createEntity('messageEntityUnderline', 18, 9),
|
|
|
|
createEntity('messageEntityStrike', 28, 13),
|
2022-05-06 00:40:47 +03:00
|
|
|
createEntity('messageEntitySpoiler', 42, 7),
|
2021-04-08 12:19:38 +03:00
|
|
|
],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain **bold** __italic__ --underline-- ~~strikethrough~~ ||spoiler|| plain',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should handle code and pre', () => {
|
|
|
|
test(
|
|
|
|
'plain code pre __ignored__ plain',
|
|
|
|
[
|
|
|
|
createEntity('messageEntityCode', 6, 4),
|
|
|
|
createEntity('messageEntityPre', 11, 3),
|
|
|
|
createEntity('messageEntityCode', 15, 11),
|
|
|
|
],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain `code` ```\npre\n``` `\\_\\_ignored\\_\\_` plain',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should handle links and text mentions', () => {
|
|
|
|
test(
|
|
|
|
'plain https://google.com google @durov Pavel Durov mail@mail.ru plain',
|
|
|
|
[
|
|
|
|
createEntity('messageEntityTextUrl', 25, 6, {
|
|
|
|
url: 'https://google.com',
|
|
|
|
}),
|
|
|
|
createEntity('messageEntityMention', 32, 6),
|
|
|
|
createEntity('messageEntityMentionName', 39, 11, {
|
|
|
|
userId: 36265675,
|
|
|
|
}),
|
|
|
|
createEntity('messageEntityEmail', 51, 12),
|
|
|
|
],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain https://google.com [google](https://google.com) @durov [Pavel Durov](tg://user?id=36265675) mail@mail.ru plain',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should handle language in pre', () => {
|
|
|
|
test(
|
|
|
|
'plain console.log("Hello, world!") some code plain',
|
|
|
|
[
|
|
|
|
createEntity('messageEntityPre', 6, 28, {
|
|
|
|
language: 'javascript',
|
|
|
|
}),
|
|
|
|
createEntity('messageEntityPre', 35, 9, { language: '' }),
|
|
|
|
],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain ```javascript\nconsole.log("Hello, world!")\n``` ```\nsome code\n``` plain',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should support entities on the edges', () => {
|
|
|
|
test(
|
|
|
|
'Hello, world',
|
2023-09-24 01:32:22 +03:00
|
|
|
[createEntity('messageEntityBold', 0, 5), createEntity('messageEntityBold', 7, 5)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'**Hello**, **world**',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should clamp out-of-range entities', () => {
|
|
|
|
test(
|
|
|
|
'Hello, world',
|
2023-09-24 01:32:22 +03:00
|
|
|
[createEntity('messageEntityBold', -2, 7), createEntity('messageEntityBold', 7, 10)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'**Hello**, **world**',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should ignore entities outside the length', () => {
|
2023-09-24 01:32:22 +03:00
|
|
|
test('Hello, world', [createEntity('messageEntityBold', 50, 5)], 'Hello, world')
|
2021-04-08 12:19:38 +03:00
|
|
|
})
|
|
|
|
|
|
|
|
it('should support entities followed by each other', () => {
|
|
|
|
test(
|
|
|
|
'plain Hello, world plain',
|
2023-09-24 01:32:22 +03:00
|
|
|
[createEntity('messageEntityBold', 6, 6), createEntity('messageEntityItalic', 12, 6)],
|
2021-04-08 12:19:38 +03:00
|
|
|
[
|
|
|
|
'plain **Hello,**__ world__ plain',
|
|
|
|
// not the most obvious order, but who cares :D
|
|
|
|
// we support this syntax in parse()
|
|
|
|
'plain **Hello,__** world__ plain',
|
2023-06-05 03:30:48 +03:00
|
|
|
],
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should support nested entities', () => {
|
|
|
|
test(
|
|
|
|
'Welcome to the gym zone!',
|
2023-09-24 01:32:22 +03:00
|
|
|
[createEntity('messageEntityItalic', 0, 24), createEntity('messageEntityBold', 15, 8)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'__Welcome to the **gym zone**!__',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should support nested entities with the same edges', () => {
|
|
|
|
test(
|
|
|
|
'Welcome to the gym zone!',
|
2023-09-24 01:32:22 +03:00
|
|
|
[createEntity('messageEntityItalic', 0, 24), createEntity('messageEntityBold', 15, 9)],
|
|
|
|
['__Welcome to the **gym zone!**__', '__Welcome to the **gym zone!__**'],
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
test(
|
|
|
|
'Welcome to the gym zone!',
|
2023-09-24 01:32:22 +03:00
|
|
|
[createEntity('messageEntityBold', 0, 24), createEntity('messageEntityItalic', 15, 9)],
|
|
|
|
['**Welcome to the __gym zone!__**', '**Welcome to the __gym zone!**__'],
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
test(
|
|
|
|
'Welcome to the gym zone!',
|
2023-09-24 01:32:22 +03:00
|
|
|
[createEntity('messageEntityItalic', 0, 24), createEntity('messageEntityBold', 0, 7)],
|
|
|
|
['__**Welcome** to the gym zone!__', '**__Welcome** to the gym zone!__'],
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
test(
|
|
|
|
'Welcome to the gym zone!',
|
2023-09-24 01:32:22 +03:00
|
|
|
[createEntity('messageEntityItalic', 0, 24), createEntity('messageEntityBold', 0, 24)],
|
2021-04-08 12:19:38 +03:00
|
|
|
[
|
|
|
|
'__**Welcome to the gym zone!**__',
|
|
|
|
'__**Welcome to the gym zone!__**',
|
|
|
|
'**__Welcome to the gym zone!**__',
|
|
|
|
'**__Welcome to the gym zone!__**',
|
2023-06-05 03:30:48 +03:00
|
|
|
],
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should support overlapping entities', () => {
|
|
|
|
test(
|
|
|
|
'Welcome to the gym zone!',
|
2023-09-24 01:32:22 +03:00
|
|
|
[createEntity('messageEntityItalic', 0, 14), createEntity('messageEntityBold', 8, 10)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'__Welcome **to the__ gym** zone!',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
test(
|
|
|
|
'plain bold bold!italic bold!italic!underline underline plain',
|
|
|
|
[
|
|
|
|
createEntity('messageEntityBold', 6, 38),
|
|
|
|
createEntity('messageEntityItalic', 11, 33),
|
|
|
|
createEntity('messageEntityUnderline', 23, 31),
|
|
|
|
],
|
|
|
|
[
|
|
|
|
'plain **bold __bold!italic --bold!italic!underline**__ underline-- plain',
|
|
|
|
'plain **bold __bold!italic --bold!italic!underline__** underline-- plain',
|
2023-06-05 03:30:48 +03:00
|
|
|
],
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
test(
|
|
|
|
'plain bold bold!italic bold!italic!underline italic!underline underline plain',
|
|
|
|
[
|
|
|
|
createEntity('messageEntityBold', 6, 38),
|
|
|
|
createEntity('messageEntityItalic', 11, 50),
|
|
|
|
createEntity('messageEntityUnderline', 23, 48),
|
|
|
|
],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain **bold __bold!italic --bold!italic!underline** italic!underline__ underline-- plain',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should properly handle emojis', () => {
|
|
|
|
test(
|
|
|
|
"best flower: 🌸. don't you even doubt it.",
|
|
|
|
[
|
|
|
|
createEntity('messageEntityItalic', 0, 11),
|
|
|
|
createEntity('messageEntityBold', 13, 2),
|
|
|
|
createEntity('messageEntityItalic', 17, 5),
|
|
|
|
],
|
2023-06-05 03:30:48 +03:00
|
|
|
"__best flower__: **🌸**. __don't__ you even doubt it.",
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should escape reserved symbols', () => {
|
|
|
|
test(
|
|
|
|
'* ** *** _ __ ___ - -- --- ~ ~~ ~~~ [ [[ ` `` ``` ```` \\ \\\\',
|
|
|
|
[createEntity('messageEntityItalic', 9, 8)],
|
|
|
|
// holy shit
|
|
|
|
'/* /*/* /*/*/* __/_ /_/_ /_/_/___ /- /-/- /-/-/- /~ /~/~ /~/~/~ /[ /[/[ /` /`/` /`/`/` /`/`/`/` // ////'
|
|
|
|
// so we don't have to escape every single backslash lol
|
2023-06-05 03:30:48 +03:00
|
|
|
.replace(/\//g, '\\'),
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
test(
|
|
|
|
'* ** *** _ __ ___ - -- ---',
|
|
|
|
[
|
|
|
|
// here we test that the order of the entities does not matter
|
|
|
|
createEntity('messageEntityItalic', 18, 4),
|
|
|
|
createEntity('messageEntityItalic', 9, 8),
|
|
|
|
],
|
2023-09-24 01:32:22 +03:00
|
|
|
'/* /*/* /*/*/* __/_ /_/_ /_/_/___ __/- /-/-__ /-/-/-'.replace(/\//g, '\\'),
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('parse', () => {
|
|
|
|
const test = (
|
|
|
|
texts: string | string[],
|
|
|
|
expectedEntities: tl.TypeMessageEntity[],
|
2023-06-05 03:30:48 +03:00
|
|
|
expectedText: string,
|
2021-04-08 12:19:38 +03:00
|
|
|
): void => {
|
|
|
|
if (!Array.isArray(texts)) texts = [texts]
|
2023-06-05 03:30:48 +03:00
|
|
|
|
2021-04-08 12:19:38 +03:00
|
|
|
for (const text of texts) {
|
|
|
|
const [_text, entities] = parser.parse(text)
|
|
|
|
expect(_text).eql(expectedText)
|
|
|
|
expect(entities).eql(expectedEntities)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-06 00:40:47 +03:00
|
|
|
it('should handle bold, italic, underline, spoiler and strikethrough', () => {
|
2021-04-08 12:19:38 +03:00
|
|
|
test(
|
2022-05-06 00:40:47 +03:00
|
|
|
'plain **bold** __italic__ --underline-- ~~strikethrough~~ ||spoiler|| plain',
|
2021-04-08 12:19:38 +03:00
|
|
|
[
|
|
|
|
createEntity('messageEntityBold', 6, 4),
|
|
|
|
createEntity('messageEntityItalic', 11, 6),
|
|
|
|
createEntity('messageEntityUnderline', 18, 9),
|
|
|
|
createEntity('messageEntityStrike', 28, 13),
|
2022-05-06 00:40:47 +03:00
|
|
|
createEntity('messageEntitySpoiler', 42, 7),
|
2021-04-08 12:19:38 +03:00
|
|
|
],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain bold italic underline strikethrough spoiler plain',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should handle code and pre', () => {
|
|
|
|
test(
|
|
|
|
[
|
|
|
|
'plain `code` ```\npre\n``` `__ignored__` plain',
|
|
|
|
'plain `code` ```\npre\n``` `\\_\\_ignored\\_\\_` plain',
|
|
|
|
'plain `code` ```\npre``` `\\_\\_ignored\\_\\_` plain',
|
|
|
|
],
|
|
|
|
[
|
|
|
|
createEntity('messageEntityCode', 6, 4),
|
|
|
|
createEntity('messageEntityPre', 11, 3, { language: '' }),
|
|
|
|
createEntity('messageEntityCode', 15, 11),
|
|
|
|
],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain code pre __ignored__ plain',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
test(
|
|
|
|
'plain ```\npre with ` and ``\n``` plain',
|
|
|
|
[createEntity('messageEntityPre', 6, 17, { language: '' })],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain pre with ` and `` plain',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
test(
|
|
|
|
'plain ```\npre with \n`\n and \n``\nend\n``` plain',
|
|
|
|
[createEntity('messageEntityPre', 6, 24, { language: '' })],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain pre with \n`\n and \n``\nend plain',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should handle links and text mentions', () => {
|
|
|
|
test(
|
|
|
|
'plain https://google.com [google](https://google.com) @durov [Pavel Durov](tg://user?id=36265675) plain',
|
|
|
|
[
|
|
|
|
createEntity('messageEntityTextUrl', 25, 6, {
|
|
|
|
url: 'https://google.com',
|
|
|
|
}),
|
|
|
|
createEntity('messageEntityMentionName', 39, 11, {
|
|
|
|
userId: 36265675,
|
|
|
|
}),
|
|
|
|
],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain https://google.com google @durov Pavel Durov plain',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
test(
|
|
|
|
'[user](tg://user?id=1234567&hash=aabbccddaabbccdd)',
|
|
|
|
[
|
|
|
|
createEntity('inputMessageEntityMentionName', 0, 4, {
|
|
|
|
userId: {
|
|
|
|
_: 'inputUser',
|
|
|
|
userId: 1234567,
|
2022-05-06 00:11:28 +03:00
|
|
|
accessHash: Long.fromString('aabbccddaabbccdd', 16),
|
2021-04-08 12:19:38 +03:00
|
|
|
},
|
|
|
|
}),
|
|
|
|
],
|
2023-06-05 03:30:48 +03:00
|
|
|
'user',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should handle language in pre', () => {
|
|
|
|
test(
|
|
|
|
'plain ```javascript\nconsole.log("Hello, world!")\n``` ```\nsome code\n``` plain',
|
|
|
|
[
|
|
|
|
createEntity('messageEntityPre', 6, 28, {
|
|
|
|
language: 'javascript',
|
|
|
|
}),
|
|
|
|
createEntity('messageEntityPre', 35, 9, { language: '' }),
|
|
|
|
],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain console.log("Hello, world!") some code plain',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should support entities on the edges', () => {
|
|
|
|
test(
|
|
|
|
'**Hello**, **world**',
|
2023-09-24 01:32:22 +03:00
|
|
|
[createEntity('messageEntityBold', 0, 5), createEntity('messageEntityBold', 7, 5)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'Hello, world',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should return empty array if there are no entities', () => {
|
|
|
|
test('Hello, world', [], 'Hello, world')
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should support overlapping entities', () => {
|
|
|
|
test(
|
|
|
|
'__Welcome **to the__ gym** zone!',
|
2023-09-24 01:32:22 +03:00
|
|
|
[createEntity('messageEntityItalic', 0, 14), createEntity('messageEntityBold', 8, 10)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'Welcome to the gym zone!',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
// resulting order will depend on the order in which the closing ** or __ are passed,
|
|
|
|
// thus we use separate tests
|
|
|
|
test(
|
|
|
|
'plain **bold __bold-italic --bold-italic-underline**__ underline-- plain',
|
|
|
|
[
|
|
|
|
createEntity('messageEntityBold', 6, 38),
|
|
|
|
createEntity('messageEntityItalic', 11, 33),
|
|
|
|
createEntity('messageEntityUnderline', 23, 31),
|
|
|
|
],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain bold bold-italic bold-italic-underline underline plain',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
test(
|
|
|
|
'plain **bold __bold-italic --bold-italic-underline__** underline-- plain',
|
|
|
|
[
|
|
|
|
createEntity('messageEntityItalic', 11, 33),
|
|
|
|
createEntity('messageEntityBold', 6, 38),
|
|
|
|
createEntity('messageEntityUnderline', 23, 31),
|
|
|
|
],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain bold bold-italic bold-italic-underline underline plain',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
test(
|
|
|
|
'plain **bold __bold-italic --bold-italic-underline** italic-underline__ underline-- plain',
|
|
|
|
[
|
|
|
|
createEntity('messageEntityBold', 6, 38),
|
|
|
|
createEntity('messageEntityItalic', 11, 50),
|
|
|
|
createEntity('messageEntityUnderline', 23, 48),
|
|
|
|
],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain bold bold-italic bold-italic-underline italic-underline underline plain',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should support entities followed by each other', () => {
|
|
|
|
test(
|
2023-09-24 01:32:22 +03:00
|
|
|
['plain **Hello,**__ world__ plain', 'plain **Hello,__** world__ plain'],
|
|
|
|
[createEntity('messageEntityBold', 6, 6), createEntity('messageEntityItalic', 12, 6)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain Hello, world plain',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should support nested entities', () => {
|
|
|
|
test(
|
|
|
|
'__Welcome to the **gym zone**!__',
|
2023-09-24 01:32:22 +03:00
|
|
|
[createEntity('messageEntityBold', 15, 8), createEntity('messageEntityItalic', 0, 24)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'Welcome to the gym zone!',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
test(
|
|
|
|
'plain [__google__](https://google.com) plain',
|
|
|
|
[
|
|
|
|
createEntity('messageEntityItalic', 6, 6),
|
|
|
|
createEntity('messageEntityTextUrl', 6, 6, {
|
|
|
|
url: 'https://google.com',
|
|
|
|
}),
|
|
|
|
],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain google plain',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
test(
|
|
|
|
'plain [plain __google__ plain](https://google.com) plain',
|
|
|
|
[
|
|
|
|
createEntity('messageEntityItalic', 12, 6),
|
|
|
|
createEntity('messageEntityTextUrl', 6, 18, {
|
|
|
|
url: 'https://google.com',
|
|
|
|
}),
|
|
|
|
],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain plain google plain plain',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should support nested entities with the same edges', () => {
|
|
|
|
// again, order of the entities depends on which closing tag goes first.
|
|
|
|
test(
|
|
|
|
'__Welcome to the **gym zone!**__',
|
2023-09-24 01:32:22 +03:00
|
|
|
[createEntity('messageEntityBold', 15, 9), createEntity('messageEntityItalic', 0, 24)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'Welcome to the gym zone!',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
test(
|
|
|
|
'__Welcome to the **gym zone!__**',
|
2023-09-24 01:32:22 +03:00
|
|
|
[createEntity('messageEntityItalic', 0, 24), createEntity('messageEntityBold', 15, 9)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'Welcome to the gym zone!',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
test(
|
|
|
|
'**Welcome to the __gym zone!__**',
|
2023-09-24 01:32:22 +03:00
|
|
|
[createEntity('messageEntityItalic', 15, 9), createEntity('messageEntityBold', 0, 24)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'Welcome to the gym zone!',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
test(
|
|
|
|
'**Welcome to the __gym zone!**__',
|
2023-09-24 01:32:22 +03:00
|
|
|
[createEntity('messageEntityBold', 0, 24), createEntity('messageEntityItalic', 15, 9)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'Welcome to the gym zone!',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
test(
|
2023-09-24 01:32:22 +03:00
|
|
|
['__**Welcome** to the gym zone!__', '**__Welcome** to the gym zone!__'],
|
|
|
|
[createEntity('messageEntityBold', 0, 7), createEntity('messageEntityItalic', 0, 24)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'Welcome to the gym zone!',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
test(
|
2023-09-24 01:32:22 +03:00
|
|
|
['__**Welcome to the gym zone!**__', '**__Welcome to the gym zone!**__'],
|
|
|
|
[createEntity('messageEntityBold', 0, 24), createEntity('messageEntityItalic', 0, 24)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'Welcome to the gym zone!',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
test(
|
2023-09-24 01:32:22 +03:00
|
|
|
['__**Welcome to the gym zone!__**', '**__Welcome to the gym zone!__**'],
|
|
|
|
[createEntity('messageEntityItalic', 0, 24), createEntity('messageEntityBold', 0, 24)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'Welcome to the gym zone!',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should properly handle emojis', () => {
|
|
|
|
test(
|
|
|
|
"__best flower__: **🌸**. __don't__ you even doubt it.",
|
|
|
|
[
|
|
|
|
createEntity('messageEntityItalic', 0, 11),
|
|
|
|
createEntity('messageEntityBold', 13, 2),
|
|
|
|
createEntity('messageEntityItalic', 17, 5),
|
|
|
|
],
|
2023-06-05 03:30:48 +03:00
|
|
|
"best flower: 🌸. don't you even doubt it.",
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should handle escaped reserved symbols', () => {
|
|
|
|
test(
|
|
|
|
'/* /*/* /*/*/* __/_ /_/_ /_/_/___ /- /-/- /-/-/- /~ /~/~ /~/~/~ /[ /[/[ /` /`/` /`/`/` /`/`/`/` // ////'.replace(
|
|
|
|
/\//g,
|
2023-06-05 03:30:48 +03:00
|
|
|
'\\',
|
2021-04-08 12:19:38 +03:00
|
|
|
),
|
|
|
|
[createEntity('messageEntityItalic', 9, 8)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'* ** *** _ __ ___ - -- --- ~ ~~ ~~~ [ [[ ` `` ``` ```` \\ \\\\',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
test(
|
2023-09-24 01:32:22 +03:00
|
|
|
'/* /*/* /*/*/* __/_ /_/_ /_/_/___ __/- /-/-__ /-/-/-'.replace(/\//g, '\\'),
|
|
|
|
[createEntity('messageEntityItalic', 9, 8), createEntity('messageEntityItalic', 18, 4)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'* ** *** _ __ ___ - -- ---',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should ignore empty urls', () => {
|
2021-06-23 17:08:23 +03:00
|
|
|
test('[link]() [link]', [], 'link [link]')
|
2021-04-08 12:19:38 +03:00
|
|
|
})
|
|
|
|
|
|
|
|
it('should ignore unclosed tags', () => {
|
2023-09-24 01:32:22 +03:00
|
|
|
test('plain ```\npre closed with single backtick`', [], 'plain pre closed with single backtick`')
|
|
|
|
test('plain ```\npre closed with single backtick\n`', [], 'plain pre closed with single backtick\n`')
|
2021-04-08 12:19:38 +03:00
|
|
|
|
2023-09-24 01:32:22 +03:00
|
|
|
test('plain ```\npre closed with double backticks`', [], 'plain pre closed with double backticks`')
|
|
|
|
test('plain ```\npre closed with double backticks\n`', [], 'plain pre closed with double backticks\n`')
|
2021-04-08 12:19:38 +03:00
|
|
|
|
|
|
|
test('plain __italic but unclosed', [], 'plain italic but unclosed')
|
2023-09-24 01:32:22 +03:00
|
|
|
test('plain __italic and **also bold but both unclosed', [], 'plain italic and also bold but both unclosed')
|
2021-04-08 12:19:38 +03:00
|
|
|
test(
|
|
|
|
'plain __italic and **also bold but italic closed__',
|
|
|
|
[createEntity('messageEntityItalic', 6, 38)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain italic and also bold but italic closed',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
test(
|
|
|
|
'plain __italic and **also bold but bold closed**',
|
|
|
|
[createEntity('messageEntityBold', 17, 25)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain italic and also bold but bold closed',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('malformed input', () => {
|
2023-09-24 01:32:22 +03:00
|
|
|
const testThrows = (input: string) => expect(() => parser.parse(input)).throws(Error)
|
2021-04-08 12:19:38 +03:00
|
|
|
|
|
|
|
it('should throw an error on malformed links', () => {
|
|
|
|
testThrows('plain [link](https://google.com but unclosed')
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should throw an error on malformed pres', () => {
|
|
|
|
testThrows('plain ```pre without linebreaks```')
|
2023-09-24 01:32:22 +03:00
|
|
|
testThrows('plain ``` pre without linebreaks but with spaces instead ```')
|
2021-04-08 12:19:38 +03:00
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
2021-07-02 20:20:29 +03:00
|
|
|
|
|
|
|
describe('template', () => {
|
|
|
|
it('should work as a tagged template literal', () => {
|
|
|
|
const unsafeString = '__[]__'
|
|
|
|
|
2021-07-09 16:39:45 +03:00
|
|
|
expect(md`${unsafeString}`.value).eq('\\_\\_\\[\\]\\_\\_')
|
2023-09-24 01:32:22 +03:00
|
|
|
expect(md`${unsafeString} **text**`.value).eq('\\_\\_\\[\\]\\_\\_ **text**')
|
|
|
|
expect(md`**text** ${unsafeString}`.value).eq('**text** \\_\\_\\[\\]\\_\\_')
|
2021-07-09 16:39:45 +03:00
|
|
|
expect(md`**${unsafeString}**`.value).eq('**\\_\\_\\[\\]\\_\\_**')
|
2021-07-02 20:20:29 +03:00
|
|
|
})
|
2021-07-02 21:28:30 +03:00
|
|
|
|
2021-07-09 16:39:45 +03:00
|
|
|
it('should skip with FormattedString', () => {
|
2021-07-02 21:28:30 +03:00
|
|
|
const unsafeString2 = '__[]__'
|
2021-07-09 16:39:45 +03:00
|
|
|
const unsafeString = new FormattedString('__[]__')
|
2021-07-02 21:28:30 +03:00
|
|
|
|
2021-07-09 16:39:45 +03:00
|
|
|
expect(md`${unsafeString}`.value).eq('__[]__')
|
2023-09-24 01:32:22 +03:00
|
|
|
expect(md`${unsafeString} ${unsafeString2}`.value).eq('__[]__ \\_\\_\\[\\]\\_\\_')
|
2021-07-09 16:39:45 +03:00
|
|
|
expect(md`${unsafeString} **text**`.value).eq('__[]__ **text**')
|
|
|
|
expect(md`**text** ${unsafeString}`.value).eq('**text** __[]__')
|
2023-09-24 01:32:22 +03:00
|
|
|
expect(md`**${unsafeString} ${unsafeString2}**`.value).eq('**__[]__ \\_\\_\\[\\]\\_\\_**')
|
2021-07-09 16:39:45 +03:00
|
|
|
})
|
|
|
|
|
|
|
|
it('should error with incompatible FormattedString', () => {
|
|
|
|
const unsafeString = new FormattedString('<&>', 'markdown')
|
|
|
|
const unsafeString2 = new FormattedString('<&>', 'some-other-mode')
|
|
|
|
|
|
|
|
expect(() => md`${unsafeString}`.value).not.throw(Error)
|
2022-05-06 00:11:28 +03:00
|
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
2023-09-03 02:37:51 +03:00
|
|
|
// @ts-expect-error
|
2021-07-09 16:39:45 +03:00
|
|
|
expect(() => md`${unsafeString2}`.value).throw(Error)
|
2021-07-02 21:28:30 +03:00
|
|
|
})
|
2021-07-02 20:20:29 +03:00
|
|
|
})
|
2021-04-08 12:19:38 +03:00
|
|
|
})
|