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-10-06 04:53:19 +03:00
|
|
|
import { FormattedString, tl } from '@mtcute/client'
|
2022-06-30 16:32:56 +03:00
|
|
|
|
2023-10-16 19:23:53 +03:00
|
|
|
import { html, HtmlMessageEntityParser } from '../src/index.js'
|
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
|
2021-04-08 12:19:38 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
describe('HtmlMessageEntityParser', () => {
|
|
|
|
const parser = new HtmlMessageEntityParser()
|
|
|
|
|
|
|
|
describe('unparse', () => {
|
2023-09-24 01:32:22 +03:00
|
|
|
const test = (text: string, entities: tl.TypeMessageEntity[], expected: string, _parser = parser): void => {
|
2023-10-06 04:53:19 +03:00
|
|
|
expect(_parser.unparse(text, entities)).eq(expected)
|
2021-04-08 12:19:38 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
it('should return the same text if there are no entities or text', () => {
|
|
|
|
test('', [], '')
|
|
|
|
test('some text', [], 'some text')
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should handle <b>, <i>, <u>, <s> tags', () => {
|
|
|
|
test(
|
|
|
|
'plain bold italic underline strikethrough plain',
|
|
|
|
[
|
|
|
|
createEntity('messageEntityBold', 6, 4),
|
|
|
|
createEntity('messageEntityItalic', 11, 6),
|
|
|
|
createEntity('messageEntityUnderline', 18, 9),
|
|
|
|
createEntity('messageEntityStrike', 28, 13),
|
|
|
|
],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain <b>bold</b> <i>italic</i> <u>underline</u> <s>strikethrough</s> plain',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
2022-05-06 00:40:47 +03:00
|
|
|
it('should handle <code>, <pre>, <blockquote>, <spoiler> tags', () => {
|
2021-04-08 12:19:38 +03:00
|
|
|
test(
|
2022-05-06 00:40:47 +03:00
|
|
|
'plain code pre blockquote spoiler plain',
|
2021-04-08 12:19:38 +03:00
|
|
|
[
|
|
|
|
createEntity('messageEntityCode', 6, 4),
|
|
|
|
createEntity('messageEntityPre', 11, 3),
|
|
|
|
createEntity('messageEntityBlockquote', 15, 10),
|
2022-05-06 00:40:47 +03:00
|
|
|
createEntity('messageEntitySpoiler', 26, 7),
|
2021-04-08 12:19:38 +03:00
|
|
|
],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain <code>code</code> <pre>pre</pre> <blockquote>blockquote</blockquote> <spoiler>spoiler</spoiler> 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('messageEntityUrl', 6, 18),
|
|
|
|
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 <a href="https://google.com">https://google.com</a> <a href="https://google.com">google</a> @durov <a href="tg://user?id=36265675">Pavel Durov</a> <a href="mailto:mail@mail.ru">mail@mail.ru</a> 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 <pre language="javascript">console.log("Hello, world!")</pre> <pre>some code</pre> 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
|
|
|
'<b>Hello</b>, <b>world</b>',
|
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
|
|
|
'<b>Hello</b>, <b>world</b>',
|
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)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain <b>Hello,</b><i> world</i> 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('messageEntityItalic', 0, 24), createEntity('messageEntityBold', 15, 8)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'<i>Welcome to the <b>gym zone</b>!</i>',
|
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)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'<i>Welcome to the <b>gym zone!</b></i>',
|
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
|
|
|
'<b>Welcome to the <i>gym zone!</i></b>',
|
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)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'<i><b>Welcome</b> to the gym zone!</i>',
|
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)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'<i><b>Welcome to the gym zone!</b></i>',
|
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
|
|
|
'<i>Welcome <b>to the</b></i><b> gym</b> 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),
|
|
|
|
],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain <b>bold <i>bold-italic <u>bold-italic-underline</u></i></b><u> underline</u> 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),
|
|
|
|
],
|
|
|
|
// not the most efficient way (in the second part we could do <u><i>...</i>...</u>), but whatever
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain <b>bold <i>bold-italic <u>bold-italic-underline</u></i></b><i><u> italic-underline</u></i><u> underline</u> 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
|
|
|
"<i>best flower</i>: <b>🌸</b>. <i>don't</i> you even doubt it.",
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should escape special symbols', () => {
|
|
|
|
test(
|
|
|
|
'<&> < & > <&>',
|
|
|
|
[createEntity('messageEntityBold', 4, 5)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'<&> <b>< & ></b> <&>',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should work with custom syntax highlighter', () => {
|
|
|
|
const parser = new HtmlMessageEntityParser({
|
2023-09-24 01:32:22 +03:00
|
|
|
syntaxHighlighter: (code, lang) => `lang: <b>${lang}</b><br>${code}`,
|
2021-04-08 12:19:38 +03:00
|
|
|
})
|
|
|
|
|
|
|
|
test(
|
|
|
|
'plain console.log("Hello, world!") some code plain',
|
|
|
|
[
|
|
|
|
createEntity('messageEntityPre', 6, 28, {
|
|
|
|
language: 'javascript',
|
|
|
|
}),
|
|
|
|
createEntity('messageEntityPre', 35, 9, { language: '' }),
|
|
|
|
],
|
2022-05-06 00:36:54 +03:00
|
|
|
'plain <pre language="javascript">lang: <b>javascript</b><br>console.log("Hello, world!")</pre> <pre>some code</pre> plain',
|
2023-06-05 03:30:48 +03:00
|
|
|
parser,
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
2022-05-06 00:05:21 +03:00
|
|
|
|
2022-05-06 00:36:54 +03:00
|
|
|
it('should replace newlines with <br> outside pre', () => {
|
2022-06-30 16:32:56 +03:00
|
|
|
test('plain\n\nplain', [], 'plain<br><br>plain')
|
2023-09-24 01:32:22 +03:00
|
|
|
test('plain\n\nplain', [createEntity('messageEntityBold', 0, 12)], '<b>plain<br><br>plain</b>')
|
|
|
|
test('plain\n\nplain', [createEntity('messageEntityPre', 0, 12)], '<pre>plain\n\nplain</pre>')
|
2022-05-06 00:05:21 +03:00
|
|
|
})
|
|
|
|
|
|
|
|
it('should replace multiple spaces with ', () => {
|
2022-06-30 16:32:56 +03:00
|
|
|
test('plain plain', [], 'plain plain')
|
2022-05-06 00:05:21 +03:00
|
|
|
})
|
2021-04-08 12:19:38 +03:00
|
|
|
})
|
|
|
|
|
|
|
|
describe('parse', () => {
|
2023-09-24 01:32:22 +03:00
|
|
|
const test = (text: string, expectedEntities: tl.TypeMessageEntity[], expectedText: string): void => {
|
2021-04-08 12:19:38 +03:00
|
|
|
const [_text, entities] = parser.parse(text)
|
|
|
|
expect(_text).eql(expectedText)
|
|
|
|
expect(entities).eql(expectedEntities)
|
|
|
|
}
|
|
|
|
|
|
|
|
it('should handle <b>, <i>, <u>, <s> tags', () => {
|
|
|
|
test(
|
|
|
|
'plain <b>bold</b> <i>italic</i> <u>underline</u> <s>strikethrough</s> plain',
|
|
|
|
[
|
|
|
|
createEntity('messageEntityBold', 6, 4),
|
|
|
|
createEntity('messageEntityItalic', 11, 6),
|
|
|
|
createEntity('messageEntityUnderline', 18, 9),
|
|
|
|
createEntity('messageEntityStrike', 28, 13),
|
|
|
|
],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain bold italic underline strikethrough plain',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
2022-05-06 00:40:47 +03:00
|
|
|
it('should handle <code>, <pre>, <blockquote>, <spoiler> tags', () => {
|
2021-04-08 12:19:38 +03:00
|
|
|
test(
|
2022-05-06 00:40:47 +03:00
|
|
|
'plain <code>code</code> <pre>pre</pre> <blockquote>blockquote</blockquote> <spoiler>spoiler</spoiler> plain',
|
2021-04-08 12:19:38 +03:00
|
|
|
[
|
|
|
|
createEntity('messageEntityCode', 6, 4),
|
|
|
|
createEntity('messageEntityPre', 11, 3, { language: '' }),
|
|
|
|
createEntity('messageEntityBlockquote', 15, 10),
|
2022-05-06 00:40:47 +03:00
|
|
|
createEntity('messageEntitySpoiler', 26, 7),
|
2021-04-08 12:19:38 +03:00
|
|
|
],
|
2023-06-05 03:30:48 +03:00
|
|
|
'plain code pre blockquote spoiler plain',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should handle links and text mentions', () => {
|
|
|
|
test(
|
|
|
|
'plain https://google.com <a href="https://google.com">google</a> @durov <a href="tg://user?id=36265675">Pavel Durov</a> 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(
|
|
|
|
'<a href="tg://user?id=1234567&hash=aabbccddaabbccdd">user</a>',
|
|
|
|
[
|
|
|
|
createEntity('inputMessageEntityMentionName', 0, 4, {
|
|
|
|
userId: {
|
|
|
|
_: 'inputUser',
|
|
|
|
userId: 1234567,
|
2022-05-06 00:05:21 +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 <pre language="javascript">console.log("Hello, world!")</pre> <pre>some code</pre> 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
|
|
|
)
|
|
|
|
})
|
|
|
|
|
2022-05-06 00:05:21 +03:00
|
|
|
it('should ignore other tags inside <pre>', () => {
|
|
|
|
test(
|
|
|
|
'<pre><b>bold</b> and not bold</pre>',
|
|
|
|
[createEntity('messageEntityPre', 0, 17, { language: '' })],
|
2023-06-05 03:30:48 +03:00
|
|
|
'bold and not bold',
|
2022-05-06 00:05:21 +03:00
|
|
|
)
|
|
|
|
test(
|
|
|
|
'<pre><pre>pre inside pre</pre> so cool</pre>',
|
|
|
|
[createEntity('messageEntityPre', 0, 22, { language: '' })],
|
2023-06-05 03:30:48 +03:00
|
|
|
'pre inside pre so cool',
|
2022-05-06 00:05:21 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should ignore newlines and indentation', () => {
|
2023-09-24 01:32:22 +03:00
|
|
|
test('this is some text\n\nwith newlines', [], 'this is some text with newlines')
|
2022-05-06 00:05:21 +03:00
|
|
|
test(
|
|
|
|
'<b>this is some text\n\nwith</b> newlines',
|
|
|
|
[createEntity('messageEntityBold', 0, 22)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'this is some text with newlines',
|
2022-05-06 00:05:21 +03:00
|
|
|
)
|
|
|
|
test(
|
|
|
|
'<b>this is some text ending with\n\n</b> newlines',
|
|
|
|
[createEntity('messageEntityBold', 0, 29)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'this is some text ending with newlines',
|
2022-05-06 00:05:21 +03:00
|
|
|
)
|
|
|
|
test(
|
|
|
|
`
|
|
|
|
this is some indented text
|
|
|
|
with newlines and
|
|
|
|
<b>
|
|
|
|
indented tags
|
|
|
|
</b> yeah <i>so cool
|
|
|
|
</i>
|
|
|
|
`,
|
2023-09-24 01:32:22 +03:00
|
|
|
[createEntity('messageEntityBold', 45, 13), createEntity('messageEntityItalic', 64, 7)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'this is some indented text with newlines and indented tags yeah so cool',
|
2022-05-06 00:05:21 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should not ignore newlines and indentation in pre', () => {
|
|
|
|
test(
|
|
|
|
'<pre>this is some text\n\nwith newlines</pre>',
|
|
|
|
[createEntity('messageEntityPre', 0, 32, { language: '' })],
|
2023-06-05 03:30:48 +03:00
|
|
|
'this is some text\n\nwith newlines',
|
2022-05-06 00:05:21 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
// fuck my life
|
|
|
|
const indent = ' '
|
|
|
|
test(
|
|
|
|
`<pre>
|
|
|
|
this is some indented text
|
|
|
|
with newlines and
|
|
|
|
<b>
|
|
|
|
indented tags
|
|
|
|
</b> yeah <i>so cool
|
|
|
|
</i>
|
|
|
|
</pre>`,
|
|
|
|
[createEntity('messageEntityPre', 0, 203, { language: '' })],
|
|
|
|
'\n' +
|
|
|
|
indent +
|
|
|
|
'this is some indented text\n' +
|
|
|
|
indent +
|
|
|
|
'with newlines and\n' +
|
|
|
|
indent +
|
|
|
|
'\n' +
|
|
|
|
indent +
|
|
|
|
' indented tags\n' +
|
|
|
|
indent +
|
|
|
|
' yeah so cool\n' +
|
|
|
|
indent +
|
|
|
|
'\n' +
|
2023-06-05 03:30:48 +03:00
|
|
|
indent,
|
2022-05-06 00:05:21 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should handle <br>', () => {
|
2023-09-24 01:32:22 +03:00
|
|
|
test('this is some text<br><br>with actual newlines', [], 'this is some text\n\nwith actual newlines')
|
2022-05-06 00:05:21 +03:00
|
|
|
test(
|
|
|
|
'<b>this is some text<br><br></b>with actual newlines',
|
|
|
|
// note that the <br> (i.e. \n) is not included in the entity
|
|
|
|
// this is expected, and the result is the same
|
|
|
|
[createEntity('messageEntityBold', 0, 17)],
|
2023-06-05 03:30:48 +03:00
|
|
|
'this is some text\n\nwith actual newlines',
|
2022-05-06 00:05:21 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should handle ', () => {
|
|
|
|
test(
|
|
|
|
'one space, many spaces, and<br>a newline',
|
|
|
|
[],
|
2023-06-05 03:30:48 +03:00
|
|
|
'one space, many spaces, and\na newline',
|
2022-05-06 00:05:21 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
2021-04-08 12:19:38 +03:00
|
|
|
it('should support entities on the edges', () => {
|
|
|
|
test(
|
|
|
|
'<b>Hello</b>, <b>world</b>',
|
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 entities followed by each other', () => {
|
|
|
|
test(
|
|
|
|
'plain <b>Hello,</b><i> world</i> plain',
|
2023-09-24 01:32:22 +03:00
|
|
|
[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(
|
|
|
|
'<i>Welcome to the <b>gym zone</b>!</i>',
|
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
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should support nested entities with the same edges', () => {
|
|
|
|
test(
|
|
|
|
'<i>Welcome to the <b>gym zone!</b></i>',
|
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(
|
|
|
|
'<b>Welcome to the <i>gym zone!</i></b>',
|
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(
|
|
|
|
'<i><b>Welcome</b> to the gym zone!</i>',
|
2023-09-24 01:32:22 +03:00
|
|
|
[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(
|
|
|
|
'<i><b>Welcome to the gym zone!</b></i>',
|
2023-09-24 01:32:22 +03:00
|
|
|
[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
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should properly handle emojis', () => {
|
|
|
|
test(
|
|
|
|
"<i>best flower</i>: <b>🌸</b>. <i>don't</i> 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 non-escaped special symbols', () => {
|
2023-09-24 01:32:22 +03:00
|
|
|
test('<&> <b>< & ></b> <&>', [createEntity('messageEntityBold', 4, 5)], '<&> < & > <&>')
|
2021-04-08 12:19:38 +03:00
|
|
|
})
|
|
|
|
|
|
|
|
it('should unescape special symbols', () => {
|
|
|
|
test(
|
|
|
|
'<&> <b>< & ></b> <&> <a href="/?a="hello"&b">link</a>',
|
|
|
|
[
|
|
|
|
createEntity('messageEntityBold', 4, 5),
|
|
|
|
createEntity('messageEntityTextUrl', 14, 4, {
|
|
|
|
url: '/?a="hello"&b',
|
|
|
|
}),
|
|
|
|
],
|
2023-06-05 03:30:48 +03:00
|
|
|
'<&> < & > <&> link',
|
2021-04-08 12:19:38 +03:00
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should ignore other tags', () => {
|
|
|
|
test('<script>alert(1)</script>', [], 'alert(1)')
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should ignore empty urls', () => {
|
|
|
|
test('<a href="">link</a> <a>link</a>', [], 'link link')
|
|
|
|
})
|
|
|
|
})
|
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(html`${unsafeString}`.value).eq('<&>')
|
2023-09-24 01:32:22 +03:00
|
|
|
expect(html`${unsafeString} <b>text</b>`.value).eq('<&> <b>text</b>')
|
|
|
|
expect(html`<b>text</b> ${unsafeString}`.value).eq('<b>text</b> <&>')
|
|
|
|
expect(html`<b>${unsafeString}</b>`.value).eq('<b><&></b>')
|
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('<&>')
|
|
|
|
|
|
|
|
expect(html`${unsafeString}`.value).eq('<&>')
|
2023-09-24 01:32:22 +03:00
|
|
|
expect(html`${unsafeString} ${unsafeString2}`.value).eq('<&> <&>')
|
|
|
|
expect(html`${unsafeString} <b>text</b>`.value).eq('<&> <b>text</b>')
|
|
|
|
expect(html`<b>text</b> ${unsafeString}`.value).eq('<b>text</b> <&>')
|
2021-07-09 16:39:45 +03:00
|
|
|
expect(html`<b>${unsafeString}</b>`.value).eq('<b><&></b>')
|
2023-09-24 01:32:22 +03:00
|
|
|
expect(html`<b>${unsafeString} ${unsafeString2}</b>`.value).eq('<b><&> <&></b>')
|
2021-07-09 16:39:45 +03:00
|
|
|
})
|
|
|
|
|
|
|
|
it('should error with incompatible FormattedString', () => {
|
|
|
|
const unsafeString = new FormattedString('<&>', 'html')
|
|
|
|
const unsafeString2 = new FormattedString('<&>', 'some-other-mode')
|
|
|
|
|
|
|
|
expect(() => html`${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(() => html`${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
|
|
|
})
|