fix: made .mention() work with tagged templates
This commit is contained in:
parent
733a1ab84f
commit
9ed51fd996
13 changed files with 63 additions and 22 deletions
|
@ -157,7 +157,6 @@ import { setProfilePhoto } from './methods/users/set-profile-photo'
|
|||
import { unblockUser } from './methods/users/unblock-user'
|
||||
import { updateProfile } from './methods/users/update-profile'
|
||||
import { updateUsername } from './methods/users/update-username'
|
||||
import { IMessageEntityParser } from './parser'
|
||||
import { Readable } from 'stream'
|
||||
import {
|
||||
ArrayWithTotal,
|
||||
|
@ -171,6 +170,7 @@ import {
|
|||
Dialog,
|
||||
FileDownloadParameters,
|
||||
GameHighScore,
|
||||
IMessageEntityParser,
|
||||
InputFileLike,
|
||||
InputInlineResult,
|
||||
InputMediaLike,
|
||||
|
|
|
@ -6,7 +6,6 @@ export {
|
|||
} from '@mtcute/core'
|
||||
export * from '@mtcute/tl/errors'
|
||||
|
||||
export * from './parser'
|
||||
export * from './types'
|
||||
export * from './client'
|
||||
export * from './utils/peer-utils'
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
|
||||
// @copy
|
||||
import { IMessageEntityParser } from '../parser'
|
||||
|
||||
// @copy
|
||||
import { Readable } from 'stream'
|
||||
|
||||
|
@ -41,7 +38,8 @@ import {
|
|||
ArrayWithTotal,
|
||||
BotCommands,
|
||||
MessageMedia,
|
||||
RawDocument
|
||||
RawDocument,
|
||||
IMessageEntityParser
|
||||
} from '../types'
|
||||
|
||||
// @copy
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { IMessageEntityParser } from '../../parser'
|
||||
import { IMessageEntityParser } from '../../types'
|
||||
import { TelegramClient } from '../../client'
|
||||
|
||||
// @extension
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { TelegramClient } from '../../client'
|
||||
import { IMessageEntityParser } from '../../parser'
|
||||
import { MtCuteError } from '../../types'
|
||||
import { MtCuteError, IMessageEntityParser } from '../../types'
|
||||
|
||||
/**
|
||||
* Register a given {@link IMessageEntityParser} as a parse mode
|
||||
|
|
|
@ -7,5 +7,6 @@ export * from './peers'
|
|||
export * from './misc'
|
||||
|
||||
export * from './errors'
|
||||
export * from './parser'
|
||||
export { MaybeDynamic, ArrayWithTotal } from './utils'
|
||||
export { MaybeAsync, PartialExcept, PartialOnly } from '@mtcute/core'
|
||||
|
|
|
@ -38,3 +38,19 @@ export interface IMessageEntityParser {
|
|||
*/
|
||||
unparse(text: string, entities: ReadonlyArray<MessageEntity>): string
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw string that will not be escaped when passing
|
||||
* to tagged template helpers (like `html` and `md`)
|
||||
*/
|
||||
export class RawString {
|
||||
raw!: true
|
||||
|
||||
constructor (readonly value: string) {}
|
||||
|
||||
toString(): string {
|
||||
return this.value
|
||||
}
|
||||
}
|
||||
|
||||
RawString.prototype.raw = true
|
|
@ -8,6 +8,7 @@ import { makeInspectable } from '../utils'
|
|||
import { ChatsIndex, InputPeerLike, User, UsersIndex } from './index'
|
||||
import { ChatLocation } from './chat-location'
|
||||
import { InputMediaLike } from '../media'
|
||||
import { RawString } from '../parser'
|
||||
|
||||
export namespace Chat {
|
||||
/**
|
||||
|
@ -548,7 +549,7 @@ export class Chat {
|
|||
* msg.replyText(`Hello, ${msg.chat.mention()`)
|
||||
* ```
|
||||
*/
|
||||
mention(text?: string | null, parseMode?: string | null): string {
|
||||
mention(text?: string | null, parseMode?: string | null): string | RawString {
|
||||
if (this.user) return this.user.mention(text, parseMode)
|
||||
|
||||
if (!text && this.username) {
|
||||
|
@ -560,7 +561,7 @@ export class Chat {
|
|||
|
||||
if (!parseMode) parseMode = this.client['_defaultParseMode']
|
||||
|
||||
return this.client.getParseMode(parseMode).unparse(text, [
|
||||
return new RawString(this.client.getParseMode(parseMode).unparse(text, [
|
||||
{
|
||||
raw: undefined as any,
|
||||
type: 'text_link',
|
||||
|
@ -568,7 +569,7 @@ export class Chat {
|
|||
length: text.length,
|
||||
url: `https://t.me/${this.username}`
|
||||
},
|
||||
])
|
||||
]))
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,6 +5,7 @@ import { MtCuteArgumentError } from '../errors'
|
|||
import { makeInspectable } from '../utils'
|
||||
import { assertTypeIs } from '../../utils/type-assertion'
|
||||
import { InputMediaLike } from '../media'
|
||||
import { RawString } from '../parser'
|
||||
|
||||
export namespace User {
|
||||
/**
|
||||
|
@ -290,7 +291,7 @@ export class User {
|
|||
* msg.replyText(`Hello, ${msg.sender.mention()`)
|
||||
* ```
|
||||
*/
|
||||
mention(text?: string | null, parseMode?: string | null): string {
|
||||
mention(text?: string | null, parseMode?: string | null): string | RawString {
|
||||
if (!text && this.username) {
|
||||
return `@${this.username}`
|
||||
}
|
||||
|
@ -298,7 +299,7 @@ export class User {
|
|||
if (!text) text = this.displayName
|
||||
if (!parseMode) parseMode = this.client['_defaultParseMode']
|
||||
|
||||
return this.client.getParseMode(parseMode).unparse(text, [
|
||||
return new RawString(this.client.getParseMode(parseMode).unparse(text, [
|
||||
{
|
||||
raw: undefined as any,
|
||||
type: 'text_mention',
|
||||
|
@ -306,7 +307,7 @@ export class User {
|
|||
length: text.length,
|
||||
userId: this.id,
|
||||
},
|
||||
])
|
||||
]))
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import type { IMessageEntityParser, MessageEntity } from '@mtcute/client'
|
||||
import type { IMessageEntityParser, MessageEntity, RawString } from '@mtcute/client'
|
||||
import { tl } from '@mtcute/tl'
|
||||
import { Parser } from 'htmlparser2'
|
||||
import bigInt from 'big-integer'
|
||||
|
@ -13,10 +13,11 @@ const MENTION_REGEX = /^tg:\/\/user\?id=(\d+)(?:&hash=(-?[0-9a-fA-F]+)(?:&|$)|&|
|
|||
* const escaped = html`<b>${user.displayName}</b>`
|
||||
* ```
|
||||
*/
|
||||
export function html(strings: TemplateStringsArray, ...sub: string[]): string {
|
||||
export function html(strings: TemplateStringsArray, ...sub: (string | RawString)[]): string {
|
||||
let str = ''
|
||||
sub.forEach((it, idx) => {
|
||||
str += strings[idx] + HtmlMessageEntityParser.escape(it)
|
||||
if (typeof it === 'string') it = HtmlMessageEntityParser.escape(it)
|
||||
str += strings[idx] + it
|
||||
})
|
||||
return str + strings[strings.length - 1]
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import { describe, it } from 'mocha'
|
|||
import { expect } from 'chai'
|
||||
import { tl } from '@mtcute/tl'
|
||||
import { HtmlMessageEntityParser, html } from '../src'
|
||||
import { MessageEntity } from '@mtcute/client'
|
||||
import { MessageEntity, RawString } from '@mtcute/client'
|
||||
import bigInt from 'big-integer'
|
||||
|
||||
const createEntity = <T extends tl.TypeMessageEntity['_']>(
|
||||
|
@ -460,5 +460,17 @@ describe('HtmlMessageEntityParser', () => {
|
|||
expect(html`<b>text</b> ${unsafeString}`).eq('<b>text</b> <&>')
|
||||
expect(html`<b>${unsafeString}</b>`).eq('<b><&></b>')
|
||||
})
|
||||
|
||||
it('should skip with RawString', () => {
|
||||
const unsafeString2 = '<&>'
|
||||
const unsafeString = new RawString('<&>')
|
||||
|
||||
expect(html`${unsafeString}`).eq('<&>')
|
||||
expect(html`${unsafeString} ${unsafeString2}`).eq('<&> <&>')
|
||||
expect(html`${unsafeString} <b>text</b>`).eq('<&> <b>text</b>')
|
||||
expect(html`<b>text</b> ${unsafeString}`).eq('<b>text</b> <&>')
|
||||
expect(html`<b>${unsafeString}</b>`).eq('<b><&></b>')
|
||||
expect(html`<b>${unsafeString} ${unsafeString2}</b>`).eq('<b><&> <&></b>')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import type { IMessageEntityParser, MessageEntity } from '@mtcute/client'
|
||||
import { tl } from '@mtcute/tl'
|
||||
import bigInt from 'big-integer'
|
||||
import { RawString } from '@mtcute/client'
|
||||
|
||||
const MENTION_REGEX = /^tg:\/\/user\?id=(\d+)(?:&hash=(-?[0-9a-fA-F]+)(?:&|$)|&|$)/
|
||||
|
||||
|
@ -21,10 +22,11 @@ const TO_BE_ESCAPED = /[*_\-~`[\\\]]/g
|
|||
* const escaped = md`**${user.displayName}**`
|
||||
* ```
|
||||
*/
|
||||
export function md(strings: TemplateStringsArray, ...sub: string[]): string {
|
||||
export function md(strings: TemplateStringsArray, ...sub: (string | RawString)[]): string {
|
||||
let str = ''
|
||||
sub.forEach((it, idx) => {
|
||||
str += strings[idx] + MarkdownMessageEntityParser.escape(it)
|
||||
if (typeof it === 'string') it = MarkdownMessageEntityParser.escape(it as string)
|
||||
str += strings[idx] + it
|
||||
})
|
||||
return str + strings[strings.length - 1]
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { describe, it } from 'mocha'
|
||||
import { expect } from 'chai'
|
||||
import { tl } from '@mtcute/tl'
|
||||
import { MessageEntity } from '@mtcute/client'
|
||||
import { MessageEntity, RawString } from '@mtcute/client'
|
||||
import { MarkdownMessageEntityParser, md } from '../src'
|
||||
import bigInt from 'big-integer'
|
||||
|
||||
|
@ -657,5 +657,16 @@ describe('MarkdownMessageEntityParser', () => {
|
|||
expect(md`**text** ${unsafeString}`).eq('**text** \\_\\_\\[\\]\\_\\_')
|
||||
expect(md`**${unsafeString}**`).eq('**\\_\\_\\[\\]\\_\\_**')
|
||||
})
|
||||
|
||||
it('should skip with RawString', () => {
|
||||
const unsafeString2 = '__[]__'
|
||||
const unsafeString = new RawString('__[]__')
|
||||
|
||||
expect(md`${unsafeString}`).eq('__[]__')
|
||||
expect(md`${unsafeString} ${unsafeString2}`).eq('__[]__ \\_\\_\\[\\]\\_\\_')
|
||||
expect(md`${unsafeString} **text**`).eq('__[]__ **text**')
|
||||
expect(md`**text** ${unsafeString}`).eq('**text** __[]__')
|
||||
expect(md`**${unsafeString} ${unsafeString2}**`).eq('**__[]__ \\_\\_\\[\\]\\_\\_**')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue