feat(core): joinTextWithEntities
method in utils
This commit is contained in:
parent
869d5987c7
commit
3f0e95ef31
3 changed files with 124 additions and 0 deletions
61
packages/core/src/highlevel/utils/entities.test.ts
Normal file
61
packages/core/src/highlevel/utils/entities.test.ts
Normal 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),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
62
packages/core/src/highlevel/utils/entities.ts
Normal file
62
packages/core/src/highlevel/utils/entities.ts
Normal 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,
|
||||||
|
}
|
||||||
|
}
|
|
@ -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'
|
||||||
|
|
Loading…
Reference in a new issue