Skip to content

Commit

Permalink
feat(markdownv2): add general markdownv2 support
Browse files Browse the repository at this point in the history
only implements the existing interface right now
  • Loading branch information
EdJoPaTo committed Mar 3, 2020
1 parent bb885d7 commit 8642303
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 3 deletions.
6 changes: 4 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ $ npm install telegram-format
## Usage

```js
const {markdown: format} = require('telegram-format');
const {html: format} = require('telegram-format');
import {markdown as format} from 'telegram-format';
const {markdown: format} = require('telegram-format');
const {markdownv2: format} = require('telegram-format');
import {html as format} from 'telegram-format';
import {markdown as format} from 'telegram-format';
import {markdownv2 as format} from 'telegram-format';

format.bold('hey');
//=> '*hey*'
Expand Down
2 changes: 2 additions & 0 deletions source/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export * from './interface'

export * from './html'
export * from './markdown'
export * from './markdownv2'
2 changes: 1 addition & 1 deletion source/interface.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export interface Formatter {
parse_mode: 'HTML' | 'Markdown';
parse_mode: 'HTML' | 'Markdown' | 'MarkdownV2';
bold: (text: string) => string;
escape: (text: string) => string;
italic: (text: string) => string;
Expand Down
57 changes: 57 additions & 0 deletions source/markdownv2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// https://core.telegram.org/bots/api#markdownv2-style

import {Formatter} from './interface'

function escapeInteral(text: string, escapeChars: string): string {
return text.replace(new RegExp(`[${escapeChars}\\\\]`, 'g'), '\\$&')
}

function escape(text: string): string {
return text.replace(/[_*[\]()~`>#+-=|{}.!]/g, '\\$&')
}

function bold(text: string): string {
return `*${escape(text)}*`
}

function italic(text: string): string {
return `_${escape(text)}_`
}

function monospace(text: string): string {
return '`' + escapeInteral(text, '`') + '`'
}

function monospaceBlock(text: string, programmingLanguage?: string): string {
let result = ''
result += '```'

if (programmingLanguage) {
result += programmingLanguage
}

result += '\n'
result += escapeInteral(text, '`')
result += '\n'
result += '```'
return result
}

function url(label: string, url: string): string {
return `[${escapeInteral(label, '\\]')}](${escapeInteral(url, ')')})`
}

function userMention(label: string, userId: number): string {
return url(label, `tg://user?id=${userId}`)
}

export const markdownv2: Formatter = {
parse_mode: 'MarkdownV2',
escape,
bold,
italic,
monospace,
monospaceBlock,
url,
userMention
}
43 changes: 43 additions & 0 deletions test/markdownv2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import test from 'ava'

import {markdownv2 as format} from '../source'

test('bold', t => {
t.is(format.bold('bold'), '*bold*')
})

test('italic', t => {
t.is(format.italic('italic'), '_italic_')
})

test('url', t => {
t.is(format.url('me', 'https://edjopato.de'), '[me](https://edjopato.de)')
})

test('escape', t => {
t.is(format.escape('[h_]e(*y)`'), '\\[h\\_\\]e\\(\\*y\\)\\`')
})

test('bold malicious', t => {
t.is(format.bold('bo*ld'), '*bo\\*ld*')
})

test('italic malicious', t => {
t.is(format.italic('ita_lic'), '_ita\\_lic_')
})

test('user mention', t => {
t.is(format.userMention('inline mention of a user', 123456789), '[inline mention of a user](tg://user?id=123456789)')
})

test('monospace', t => {
t.is(format.monospace('inline fixed-width code'), '`inline fixed-width code`')
})

test('monospaceBlock w/o language', t => {
t.is(format.monospaceBlock('pre-formatted fixed-width code block'), '```\npre-formatted fixed-width code block\n```')
})

test('monospaceBlock w/ language', t => {
t.is(format.monospaceBlock('pre-formatted fixed-width code block written in the Python programming language', 'python'), '```python\npre-formatted fixed-width code block written in the Python programming language\n```')
})

0 comments on commit 8642303

Please sign in to comment.