From d611f91f1920e8921ad283abb4bc40436f484814 Mon Sep 17 00:00:00 2001 From: teidesu <86301490+teidesu@users.noreply.github.com> Date: Fri, 9 Jul 2021 16:39:45 +0300 Subject: [PATCH] feat: parse mode template literals override default/passed parse mode --- packages/client/src/client.ts | 16 ++++----- packages/client/src/methods/_imports.ts | 3 +- .../methods/messages/edit-inline-message.ts | 4 +-- .../src/methods/messages/edit-message.ts | 4 +-- .../src/methods/messages/forward-messages.ts | 5 +-- .../src/methods/messages/parse-entities.ts | 13 ++++++- .../client/src/methods/messages/send-copy.ts | 4 +-- .../client/src/methods/messages/send-media.ts | 4 +-- .../client/src/methods/messages/send-text.ts | 4 +-- .../src/methods/parse-modes/parse-modes.ts | 6 ++-- .../types/bots/input/input-inline-message.ts | 5 +-- .../client/src/types/media/input-media.ts | 5 +-- packages/client/src/types/messages/message.ts | 9 ++--- packages/client/src/types/parser.ts | 20 +++++------ packages/client/src/types/peers/chat.ts | 8 ++--- packages/client/src/types/peers/user.ts | 8 ++--- packages/html-parser/src/index.ts | 11 ++++-- .../html-parser/tests/html-parser.spec.ts | 34 ++++++++++++------- packages/markdown-parser/src/index.ts | 11 ++++-- .../tests/markdown-parser.spec.ts | 32 ++++++++++------- 20 files changed, 123 insertions(+), 83 deletions(-) diff --git a/packages/client/src/client.ts b/packages/client/src/client.ts index 68a57be8..75343d45 100644 --- a/packages/client/src/client.ts +++ b/packages/client/src/client.ts @@ -171,6 +171,7 @@ import { ChatsIndex, Dialog, FileDownloadParameters, + FormattedString, GameHighScore, IMessageEntityParser, InputFileLike, @@ -1829,7 +1830,7 @@ export interface TelegramClient extends BaseTelegramClient { * * When `media` is passed, `media.caption` is used instead */ - text?: string + text?: string | FormattedString /** * Parse mode to use to parse entities before sending @@ -1890,7 +1891,7 @@ export interface TelegramClient extends BaseTelegramClient { * * When `media` is passed, `media.caption` is used instead */ - text?: string + text?: string | FormattedString /** * Parse mode to use to parse entities before sending @@ -1998,7 +1999,7 @@ export interface TelegramClient extends BaseTelegramClient { * You can either pass `caption` or `captionMedia`, passing both will * result in an error */ - caption?: string + caption?: string | FormattedString /** * Optionally, a media caption for your forwarded message(s). @@ -2384,7 +2385,7 @@ export interface TelegramClient extends BaseTelegramClient { /** * New message caption (only used for media) */ - caption?: string + caption?: string | FormattedString /** * Parse mode to use to parse `text` entities before sending @@ -2546,7 +2547,7 @@ export interface TelegramClient extends BaseTelegramClient { * Can be used, for example. when using File IDs * or when using existing InputMedia objects. */ - caption?: string + caption?: string | FormattedString /** * Override entities for `media`. @@ -2636,7 +2637,7 @@ export interface TelegramClient extends BaseTelegramClient { */ sendText( chatId: InputPeerLike, - text: string, + text: string | FormattedString, params?: { /** * Message to reply to. Either a message object or message ID. @@ -2785,10 +2786,9 @@ export interface TelegramClient extends BaseTelegramClient { * mode is also set as default. * * @param parseMode Parse mode to register - * @param name (default: `parseMode.name`) Parse mode name. By default is taken from the object. * @throws MtCuteError When the parse mode with a given name is already registered. */ - registerParseMode(parseMode: IMessageEntityParser, name?: string): void + registerParseMode(parseMode: IMessageEntityParser): void /** * Unregister a parse mode by its name. * Will silently fail if given parse mode does not exist. diff --git a/packages/client/src/methods/_imports.ts b/packages/client/src/methods/_imports.ts index 163f24b0..168819cc 100644 --- a/packages/client/src/methods/_imports.ts +++ b/packages/client/src/methods/_imports.ts @@ -39,7 +39,8 @@ import { BotCommands, MessageMedia, RawDocument, - IMessageEntityParser + IMessageEntityParser, + FormattedString } from '../types' // @copy diff --git a/packages/client/src/methods/messages/edit-inline-message.ts b/packages/client/src/methods/messages/edit-inline-message.ts index 266e5fa5..8c8d10ba 100644 --- a/packages/client/src/methods/messages/edit-inline-message.ts +++ b/packages/client/src/methods/messages/edit-inline-message.ts @@ -1,5 +1,5 @@ import { TelegramClient } from '../../client' -import { BotKeyboard, InputMediaLike, ReplyMarkup } from '../../types' +import { BotKeyboard, FormattedString, InputMediaLike, ReplyMarkup } from '../../types' import { tl } from '@mtcute/tl' /** @@ -20,7 +20,7 @@ export async function editInlineMessage( * * When `media` is passed, `media.caption` is used instead */ - text?: string + text?: string | FormattedString /** * Parse mode to use to parse entities before sending diff --git a/packages/client/src/methods/messages/edit-message.ts b/packages/client/src/methods/messages/edit-message.ts index 614151c9..1ffb7567 100644 --- a/packages/client/src/methods/messages/edit-message.ts +++ b/packages/client/src/methods/messages/edit-message.ts @@ -1,6 +1,6 @@ import { TelegramClient } from '../../client' import { - BotKeyboard, + BotKeyboard, FormattedString, InputMediaLike, InputPeerLike, Message, @@ -26,7 +26,7 @@ export async function editMessage( * * When `media` is passed, `media.caption` is used instead */ - text?: string + text?: string | FormattedString /** * Parse mode to use to parse entities before sending diff --git a/packages/client/src/methods/messages/forward-messages.ts b/packages/client/src/methods/messages/forward-messages.ts index b9c795f8..7c83b463 100644 --- a/packages/client/src/methods/messages/forward-messages.ts +++ b/packages/client/src/methods/messages/forward-messages.ts @@ -1,5 +1,6 @@ import { TelegramClient } from '../../client' import { + FormattedString, InputMediaLike, InputPeerLike, Message, @@ -74,7 +75,7 @@ export async function forwardMessages( * You can either pass `caption` or `captionMedia`, passing both will * result in an error */ - caption?: string + caption?: string | FormattedString /** * Optionally, a media caption for your forwarded message(s). @@ -139,7 +140,7 @@ export async function forwardMessages( * You can either pass `caption` or `captionMedia`, passing both will * result in an error */ - caption?: string + caption?: string | FormattedString /** * Optionally, a media caption for your forwarded message(s). diff --git a/packages/client/src/methods/messages/parse-entities.ts b/packages/client/src/methods/messages/parse-entities.ts index 29ea1e25..92fade32 100644 --- a/packages/client/src/methods/messages/parse-entities.ts +++ b/packages/client/src/methods/messages/parse-entities.ts @@ -1,13 +1,14 @@ import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' import { normalizeToInputUser } from '../../utils/peer-utils' +import { FormattedString, MtCuteError } from '../../types' const empty: [string, undefined] = ['', undefined] /** @internal */ export async function _parseEntities( this: TelegramClient, - text?: string, + text?: string | FormattedString, mode?: string | null, entities?: tl.TypeMessageEntity[] ): Promise<[string, tl.TypeMessageEntity[] | undefined]> { @@ -15,12 +16,22 @@ export async function _parseEntities( return empty } + if (typeof text === 'object') { + mode = text.mode + text = text.value + } + if (!entities) { if (mode === undefined) { mode = this._defaultParseMode } // either explicitly disabled or no available parser if (!mode) return [text, []] + + if (!(mode in this._parseModes)) { + throw new MtCuteError(`Parse mode ${mode} is not registered.`) + } + ;[text, entities] = await this._parseModes[mode].parse(text) } diff --git a/packages/client/src/methods/messages/send-copy.ts b/packages/client/src/methods/messages/send-copy.ts index 42fd2668..a687317e 100644 --- a/packages/client/src/methods/messages/send-copy.ts +++ b/packages/client/src/methods/messages/send-copy.ts @@ -1,5 +1,5 @@ import { TelegramClient } from '../../client' -import { InputPeerLike, Message, ReplyMarkup } from '../../types' +import { InputPeerLike, Message, FormattedString, ReplyMarkup } from '../../types' import { tl } from '@mtcute/tl' import { MessageNotFoundError } from '@mtcute/tl/errors' @@ -45,7 +45,7 @@ export async function sendCopy( /** * New message caption (only used for media) */ - caption?: string + caption?: string | FormattedString /** * Parse mode to use to parse `text` entities before sending diff --git a/packages/client/src/methods/messages/send-media.ts b/packages/client/src/methods/messages/send-media.ts index 76e12e06..1a872841 100644 --- a/packages/client/src/methods/messages/send-media.ts +++ b/packages/client/src/methods/messages/send-media.ts @@ -1,6 +1,6 @@ import { TelegramClient } from '../../client' import { - BotKeyboard, + BotKeyboard, FormattedString, InputMediaLike, InputPeerLike, Message, MtCuteArgumentError, @@ -37,7 +37,7 @@ export async function sendMedia( * Can be used, for example. when using File IDs * or when using existing InputMedia objects. */ - caption?: string + caption?: string | FormattedString /** * Override entities for `media`. diff --git a/packages/client/src/methods/messages/send-text.ts b/packages/client/src/methods/messages/send-text.ts index 5de45f54..2f20d9a6 100644 --- a/packages/client/src/methods/messages/send-text.ts +++ b/packages/client/src/methods/messages/send-text.ts @@ -14,7 +14,7 @@ import { UsersIndex, MtCuteTypeAssertionError, ChatsIndex, - MtCuteArgumentError, + MtCuteArgumentError, FormattedString, } from '../../types' import { getMarkedPeerId, MessageNotFoundError } from '@mtcute/core' import { createDummyUpdate } from '../../utils/updates-utils' @@ -30,7 +30,7 @@ import { createDummyUpdate } from '../../utils/updates-utils' export async function sendText( this: TelegramClient, chatId: InputPeerLike, - text: string, + text: string | FormattedString, params?: { /** * Message to reply to. Either a message object or message ID. diff --git a/packages/client/src/methods/parse-modes/parse-modes.ts b/packages/client/src/methods/parse-modes/parse-modes.ts index 74c87ef2..f3d8b44b 100644 --- a/packages/client/src/methods/parse-modes/parse-modes.ts +++ b/packages/client/src/methods/parse-modes/parse-modes.ts @@ -7,15 +7,15 @@ import { MtCuteError, IMessageEntityParser } from '../../types' * mode is also set as default. * * @param parseMode Parse mode to register - * @param name Parse mode name. By default is taken from the object. * @throws MtCuteError When the parse mode with a given name is already registered. * @internal */ export function registerParseMode( this: TelegramClient, - parseMode: IMessageEntityParser, - name: string = parseMode.name + parseMode: IMessageEntityParser ): void { + const name = parseMode.name + if (name in this._parseModes) { throw new MtCuteError( `Parse mode ${name} is already registered. Unregister it first!` diff --git a/packages/client/src/types/bots/input/input-inline-message.ts b/packages/client/src/types/bots/input/input-inline-message.ts index 15c83dd3..4922f410 100644 --- a/packages/client/src/types/bots/input/input-inline-message.ts +++ b/packages/client/src/types/bots/input/input-inline-message.ts @@ -7,6 +7,7 @@ import { InputMediaGeoLive, InputMediaVenue, } from '../../media' +import { FormattedString } from '../../parser' /** * Inline message containing only text @@ -17,7 +18,7 @@ export interface InputInlineMessageText { /** * Text of the message */ - text: string + text: string | FormattedString /** * Text markup entities. @@ -46,7 +47,7 @@ export interface InputInlineMessageMedia { /** * Caption for the media */ - text?: string + text?: string | FormattedString /** * Caption markup entities. diff --git a/packages/client/src/types/media/input-media.ts b/packages/client/src/types/media/input-media.ts index 28069632..377dd504 100644 --- a/packages/client/src/types/media/input-media.ts +++ b/packages/client/src/types/media/input-media.ts @@ -2,6 +2,7 @@ import { InputFileLike } from '../files' import { tl } from '@mtcute/tl' import { Venue } from './venue' import { MaybeArray } from '@mtcute/core' +import { FormattedString } from '../parser' interface BaseInputMedia { /** @@ -12,7 +13,7 @@ interface BaseInputMedia { /** * Caption of the media */ - caption?: string + caption?: string | FormattedString /** * Caption entities of the media. @@ -517,7 +518,7 @@ export interface InputMediaQuiz extends Omit { /** * Explanation of the quiz solution */ - solution?: string + solution?: string | FormattedString /** * Format entities for `solution`. diff --git a/packages/client/src/types/messages/message.ts b/packages/client/src/types/messages/message.ts index b447f653..e56626cd 100644 --- a/packages/client/src/types/messages/message.ts +++ b/packages/client/src/types/messages/message.ts @@ -12,6 +12,7 @@ import { makeInspectable } from '../utils' import { InputMediaLike, WebPage } from '../media' import { _messageActionFromTl, MessageAction } from './message-action' import { _messageMediaFromTl, MessageMedia } from './message-media' +import { FormattedString } from '../parser' /** * A message or a service message @@ -557,7 +558,7 @@ export class Message { * @param params */ answerText( - text: string, + text: string | FormattedString, params?: Parameters[2] ): ReturnType { return this.client.sendText(this.chat.inputPeer, text, params) @@ -602,7 +603,7 @@ export class Message { * @param params */ replyText( - text: string, + text: string | FormattedString, params?: Parameters[2] ): ReturnType { if (!params) params = {} @@ -657,7 +658,7 @@ export class Message { * @param params */ commentText( - text: string, + text: string | FormattedString, params?: Parameters[2] ): ReturnType { if (this.chat.type !== 'channel') { @@ -790,7 +791,7 @@ export class Message { * @link TelegramClient.editMessage */ editText( - text: string, + text: string | FormattedString, params?: Omit[2], 'text'> ): Promise { return this.edit({ diff --git a/packages/client/src/types/parser.ts b/packages/client/src/types/parser.ts index a228231d..8bc805cf 100644 --- a/packages/client/src/types/parser.ts +++ b/packages/client/src/types/parser.ts @@ -13,9 +13,7 @@ import { MessageEntity } from '../types' */ export interface IMessageEntityParser { /** - * Default name for the parser. - * - * Used when registering the parser as a fallback value for `name` + * Parser name, which will be used when registering it. */ name: string @@ -29,9 +27,9 @@ export interface IMessageEntityParser { parse(text: string): [string, tl.TypeMessageEntity[]] /** - * Add formating to the text given the plain text and the entities. + * Add formatting to the text given the plain text and the entities. * - * **Note** that `unparse(parse(text)) === text` is not always true! + * > **Note**: `unparse(parse(text)) === text` is not always true! * * @param text Plain text * @param entities Message entities that should be added to the text @@ -43,14 +41,14 @@ export interface IMessageEntityParser { * 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) {} +export class FormattedString { + /** + * @param value Value that the string holds + * @param mode Name of the parse mode used + */ + constructor (readonly value: string, readonly mode?: string) {} toString(): string { return this.value } } - -RawString.prototype.raw = true diff --git a/packages/client/src/types/peers/chat.ts b/packages/client/src/types/peers/chat.ts index 184e043b..41c6eaca 100644 --- a/packages/client/src/types/peers/chat.ts +++ b/packages/client/src/types/peers/chat.ts @@ -8,7 +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' +import { FormattedString } from '../parser' export namespace Chat { /** @@ -552,7 +552,7 @@ export class Chat { * msg.replyText(`Hello, ${msg.chat.mention()`) * ``` */ - mention(text?: string | null, parseMode?: string | null): string | RawString { + mention(text?: string | null, parseMode?: string | null): string | FormattedString { if (this.user) return this.user.mention(text, parseMode) if (text === undefined && this.username) { @@ -564,7 +564,7 @@ export class Chat { if (!parseMode) parseMode = this.client['_defaultParseMode'] - return new RawString(this.client.getParseMode(parseMode).unparse(text, [ + return new FormattedString(this.client.getParseMode(parseMode).unparse(text, [ { raw: undefined as any, type: 'text_link', @@ -628,7 +628,7 @@ export class Chat { * @param params */ sendText( - text: string, + text: string | FormattedString, params?: Parameters[2] ): ReturnType { return this.client.sendText(this.inputPeer, text, params) diff --git a/packages/client/src/types/peers/user.ts b/packages/client/src/types/peers/user.ts index b47d959e..a7f94f02 100644 --- a/packages/client/src/types/peers/user.ts +++ b/packages/client/src/types/peers/user.ts @@ -5,7 +5,7 @@ import { MtCuteArgumentError } from '../errors' import { makeInspectable } from '../utils' import { assertTypeIs } from '../../utils/type-assertion' import { InputMediaLike } from '../media' -import { RawString } from '../parser' +import { FormattedString } from '../parser' export namespace User { /** @@ -294,7 +294,7 @@ export class User { * msg.replyText(`Hello, ${msg.sender.mention()`) * ``` */ - mention(text?: string | null, parseMode?: string | null): string | RawString { + mention(text?: string | null, parseMode?: string | null): string | FormattedString { if (text === undefined && this.username) { return `@${this.username}` } @@ -302,7 +302,7 @@ export class User { if (!text) text = this.displayName if (!parseMode) parseMode = this.client['_defaultParseMode'] - return new RawString(this.client.getParseMode(parseMode).unparse(text, [ + return new FormattedString(this.client.getParseMode(parseMode).unparse(text, [ { raw: undefined as any, type: 'text_mention', @@ -369,7 +369,7 @@ export class User { * @param params */ sendText( - text: string, + text: string | FormattedString, params?: Parameters[2] ): ReturnType { return this.client.sendText(this.inputPeer, text, params) diff --git a/packages/html-parser/src/index.ts b/packages/html-parser/src/index.ts index 374fa91e..4ab59057 100644 --- a/packages/html-parser/src/index.ts +++ b/packages/html-parser/src/index.ts @@ -1,4 +1,4 @@ -import type { IMessageEntityParser, MessageEntity, RawString } from '@mtcute/client' +import type { IMessageEntityParser, MessageEntity, FormattedString } from '@mtcute/client' import { tl } from '@mtcute/tl' import { Parser } from 'htmlparser2' import bigInt from 'big-integer' @@ -13,13 +13,18 @@ const MENTION_REGEX = /^tg:\/\/user\?id=(\d+)(?:&hash=(-?[0-9a-fA-F]+)(?:&|$)|&| * const escaped = html`${user.displayName}` * ``` */ -export function html(strings: TemplateStringsArray, ...sub: (string | RawString)[]): string { +export function html(strings: TemplateStringsArray, ...sub: (string | FormattedString)[]): FormattedString { let str = '' sub.forEach((it, idx) => { if (typeof it === 'string') it = HtmlMessageEntityParser.escape(it) + else { + if (it.mode && it.mode !== 'html') throw new Error(`Incompatible parse mode: ${it.mode}`) + it = it.value + } + str += strings[idx] + it }) - return str + strings[strings.length - 1] + return { value: str + strings[strings.length - 1], mode: 'html' } } export namespace HtmlMessageEntityParser { diff --git a/packages/html-parser/tests/html-parser.spec.ts b/packages/html-parser/tests/html-parser.spec.ts index 33a1c5b5..ebde052c 100644 --- a/packages/html-parser/tests/html-parser.spec.ts +++ b/packages/html-parser/tests/html-parser.spec.ts @@ -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, RawString } from '@mtcute/client' +import { MessageEntity, FormattedString } from '@mtcute/client' import bigInt from 'big-integer' const createEntity = ( @@ -455,22 +455,30 @@ describe('HtmlMessageEntityParser', () => { it('should work as a tagged template literal', () => { const unsafeString = '<&>' - expect(html`${unsafeString}`).eq('<&>') - expect(html`${unsafeString} text`).eq('<&> text') - expect(html`text ${unsafeString}`).eq('text <&>') - expect(html`${unsafeString}`).eq('<&>') + expect(html`${unsafeString}`.value).eq('<&>') + expect(html`${unsafeString} text`.value).eq('<&> text') + expect(html`text ${unsafeString}`.value).eq('text <&>') + expect(html`${unsafeString}`.value).eq('<&>') }) - it('should skip with RawString', () => { + it('should skip with FormattedString', () => { const unsafeString2 = '<&>' - const unsafeString = new RawString('<&>') + const unsafeString = new FormattedString('<&>') - expect(html`${unsafeString}`).eq('<&>') - expect(html`${unsafeString} ${unsafeString2}`).eq('<&> <&>') - expect(html`${unsafeString} text`).eq('<&> text') - expect(html`text ${unsafeString}`).eq('text <&>') - expect(html`${unsafeString}`).eq('<&>') - expect(html`${unsafeString} ${unsafeString2}`).eq('<&> <&>') + expect(html`${unsafeString}`.value).eq('<&>') + expect(html`${unsafeString} ${unsafeString2}`.value).eq('<&> <&>') + expect(html`${unsafeString} text`.value).eq('<&> text') + expect(html`text ${unsafeString}`.value).eq('text <&>') + expect(html`${unsafeString}`.value).eq('<&>') + expect(html`${unsafeString} ${unsafeString2}`.value).eq('<&> <&>') + }) + + 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) + expect(() => html`${unsafeString2}`.value).throw(Error) }) }) }) diff --git a/packages/markdown-parser/src/index.ts b/packages/markdown-parser/src/index.ts index a4bc927c..47fcd9df 100644 --- a/packages/markdown-parser/src/index.ts +++ b/packages/markdown-parser/src/index.ts @@ -1,7 +1,7 @@ import type { IMessageEntityParser, MessageEntity } from '@mtcute/client' import { tl } from '@mtcute/tl' import bigInt from 'big-integer' -import { RawString } from '@mtcute/client' +import { FormattedString } from '@mtcute/client' const MENTION_REGEX = /^tg:\/\/user\?id=(\d+)(?:&hash=(-?[0-9a-fA-F]+)(?:&|$)|&|$)/ @@ -22,13 +22,18 @@ const TO_BE_ESCAPED = /[*_\-~`[\\\]]/g * const escaped = md`**${user.displayName}**` * ``` */ -export function md(strings: TemplateStringsArray, ...sub: (string | RawString)[]): string { +export function md(strings: TemplateStringsArray, ...sub: (string | FormattedString)[]): FormattedString { let str = '' sub.forEach((it, idx) => { if (typeof it === 'string') it = MarkdownMessageEntityParser.escape(it as string) + else { + if (it.mode && it.mode !== 'markdown') throw new Error(`Incompatible parse mode: ${it.mode}`) + it = it.value + } + str += strings[idx] + it }) - return str + strings[strings.length - 1] + return { value: str + strings[strings.length - 1], mode: 'markdown' } } /** diff --git a/packages/markdown-parser/tests/markdown-parser.spec.ts b/packages/markdown-parser/tests/markdown-parser.spec.ts index a2fc2529..bf98387c 100644 --- a/packages/markdown-parser/tests/markdown-parser.spec.ts +++ b/packages/markdown-parser/tests/markdown-parser.spec.ts @@ -1,7 +1,7 @@ import { describe, it } from 'mocha' import { expect } from 'chai' import { tl } from '@mtcute/tl' -import { MessageEntity, RawString } from '@mtcute/client' +import { MessageEntity, FormattedString } from '@mtcute/client' import { MarkdownMessageEntityParser, md } from '../src' import bigInt from 'big-integer' @@ -652,21 +652,29 @@ describe('MarkdownMessageEntityParser', () => { it('should work as a tagged template literal', () => { const unsafeString = '__[]__' - expect(md`${unsafeString}`).eq('\\_\\_\\[\\]\\_\\_') - expect(md`${unsafeString} **text**`).eq('\\_\\_\\[\\]\\_\\_ **text**') - expect(md`**text** ${unsafeString}`).eq('**text** \\_\\_\\[\\]\\_\\_') - expect(md`**${unsafeString}**`).eq('**\\_\\_\\[\\]\\_\\_**') + expect(md`${unsafeString}`.value).eq('\\_\\_\\[\\]\\_\\_') + expect(md`${unsafeString} **text**`.value).eq('\\_\\_\\[\\]\\_\\_ **text**') + expect(md`**text** ${unsafeString}`.value).eq('**text** \\_\\_\\[\\]\\_\\_') + expect(md`**${unsafeString}**`.value).eq('**\\_\\_\\[\\]\\_\\_**') }) - it('should skip with RawString', () => { + it('should skip with FormattedString', () => { const unsafeString2 = '__[]__' - const unsafeString = new RawString('__[]__') + const unsafeString = new FormattedString('__[]__') - 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('**__[]__ \\_\\_\\[\\]\\_\\_**') + expect(md`${unsafeString}`.value).eq('__[]__') + expect(md`${unsafeString} ${unsafeString2}`.value).eq('__[]__ \\_\\_\\[\\]\\_\\_') + expect(md`${unsafeString} **text**`.value).eq('__[]__ **text**') + expect(md`**text** ${unsafeString}`.value).eq('**text** __[]__') + expect(md`**${unsafeString} ${unsafeString2}**`.value).eq('**__[]__ \\_\\_\\[\\]\\_\\_**') + }) + + 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) + expect(() => md`${unsafeString2}`.value).throw(Error) }) }) })