feat(core): joinTextWithEntities method in utils

This commit is contained in:
alina 🌸 2024-04-05 18:19:52 +03:00
parent 869d5987c7
commit 3f0e95ef31
Signed by: teidesu
SSH key fingerprint: SHA256:uNeCpw6aTSU4aIObXLvHfLkDa82HWH9EiOj9AXOIRpI
3 changed files with 124 additions and 0 deletions

View file

@ -0,0 +1,61 @@
import { describe, expect, it } from 'vitest'
import { tl } from '@mtcute/tl'
import { joinTextWithEntities } from './entities.js'
const createEntity = (offset: number, length: number): tl.TypeMessageEntity => {
return {
_: 'messageEntityBold',
offset,
length,
}
}
describe('joinTextWithEntities', () => {
it('should join text with entities using a string delimiter', () => {
expect(
joinTextWithEntities(
[
{ text: 'foo bar baz', entities: [createEntity(0, 3), createEntity(4, 3), createEntity(8, 3)] },
{ text: 'egg spam', entities: [createEntity(4, 4)] },
{ text: 'very spam', entities: [createEntity(0, 4)] },
],
' 🚀 ',
),
).toEqual({
text: 'foo bar baz 🚀 egg spam 🚀 very spam',
entities: [
createEntity(0, 3),
createEntity(4, 3),
createEntity(8, 3),
createEntity(19, 4),
createEntity(27, 4),
],
})
})
it('should join text with entities using a TextWithEntities delimiter', () => {
expect(
joinTextWithEntities(
[
{ text: 'foo bar baz', entities: [createEntity(0, 3), createEntity(4, 3), createEntity(8, 3)] },
{ text: 'egg spam', entities: [createEntity(4, 4)] },
{ text: 'very spam', entities: [createEntity(0, 4)] },
],
{ text: ' 🚀 ', entities: [createEntity(1, 2)] },
),
).toEqual({
text: 'foo bar baz 🚀 egg spam 🚀 very spam',
entities: [
createEntity(0, 3),
createEntity(4, 3),
createEntity(8, 3),
createEntity(12, 2),
createEntity(19, 4),
createEntity(24, 2),
createEntity(27, 4),
],
})
})
})

View file

@ -0,0 +1,62 @@
import { tl } from '@mtcute/tl'
import { TextWithEntities } from '../types/misc/entities.js'
/**
* Join multiple text parts with entities into a single text with entities,
* adjusting the entities' offsets accordingly.
*
* @param parts List of text parts with entities
* @param delim Delimiter to insert between parts
* @returns A single text with entities
* @example
*
* ```ts
* const scoreboardText = joinTextWithEntities(
* apiResult.scoreboard.map((entry) => html`<b>${entry.name}</b>: ${entry.score}`),
* html`<br>`
* )
* await tg.sendText(chatId, html`<b>scoreboard:</b><br><br>${scoreboardText}`)
* ```
*/
export function joinTextWithEntities(
parts: (string | TextWithEntities)[],
delim: string | TextWithEntities = '',
): TextWithEntities {
const textParts: string[] = []
const newEntities: tl.TypeMessageEntity[] = []
let position = 0
if (typeof delim === 'string') {
delim = { text: delim }
}
const pushPart = (part: TextWithEntities) => {
textParts.push(part.text)
const entitiesOffset = position
position += part.text.length
if (part.entities) {
for (const entity of part.entities) {
newEntities.push({
...entity,
offset: entity.offset + entitiesOffset,
})
}
}
}
for (const part of parts) {
if (position > 0) {
pushPart(delim)
}
pushPart(typeof part === 'string' ? { text: part } : part)
}
return {
text: textParts.join(''),
entities: newEntities,
}
}

View file

@ -1,5 +1,6 @@
// todo: merge this with the main utils dir? // todo: merge this with the main utils dir?
export * from './entities.js'
export * from './file-utils.js' export * from './file-utils.js'
export * from './inline-utils.js' export * from './inline-utils.js'
export * from './inspectable.js' export * from './inspectable.js'