bold()
function src/utils/markup.ts:94function bold(text: string, options?: MarkupFilterOptions): stringFormat and escape text with Discord's markdown.
import { Utils } from 'detritus-client';
Utils.Markup;Object shapes for options, payloads and events.
Standalone helpers.
function bold(text: string, options?: MarkupFilterOptions): stringfunction codeblock(text: string, options?: CodeblockFilterOptions): stringfunction codestring(text: string, options?: MarkupFilterOptions): stringfunction headerBig(text: string, options?: HeaderFilterOptions): stringfunction headerMedium(text: string, options?: HeaderFilterOptions): stringfunction headerSmall(text: string, options?: HeaderFilterOptions): stringfunction italics(text: string, options?: MarkupFilterOptions): stringfunction list(text: string, options?: ListFilterOptions): stringfunction quote(text: string, options?: QuoteFilterOptions): stringfunction spoiler(text: string, options?: MarkupFilterOptions): stringfunction strike(text: string, options?: MarkupFilterOptions): stringfunction subtext(text: string, options?: SubtextFilterOptions): stringfunction timestamp(
timestamp: string | number | Date | null,
format?: MarkupTimestampStyles,
): stringfunction trueSlice(text: string, limit?: number): stringfunction underline(text: string, options?: MarkupFilterOptions): stringfunction url(text: string, url: string, comment?: string): stringExported values.
const escape: Readonly<{ all: (text: string, options?: MarkupFilterOptions) => string; bold: (text: string, options?: MarkupFilterOptions) => string; codeblock: (text: string, options?: CodeblockFilterOptions) => string; codestring: (text: string, options?: MarkupFilterOptions) => string; header: (text: string, options?: HeaderFilterOptions) => string; italics: (text: string, options?: MarkupFilterOptions) => string; links: (text: string, replacement?: string) => string; list: (text: string, options?: ListFilterOptions) => string; mentions: (text: string, replacement?: string) => string; quote: (text: string, options?: QuoteFilterOptions) => string; spoiler: (text: string, options?: MarkupFilterOptions) => string; strike: (text: string, options?: MarkupFilterOptions) => string; … 3 more }>export const escape = Object.freeze({
all: (text: string, options: MarkupFilterOptions = {}): string => {
const filter: MarkupFilter = Object.assign({}, defaultMarkupFilter, options);
text = text.replace(Regexes[Strings.ESCAPE], Replacements[Strings.ESCAPE]);
text = text.replace(Regexes[Strings.ITALICS], Replacements[Strings.ITALICS]);
text = text.replace(Regexes[Strings.BOLD], Replacements[Strings.BOLD]);
text = text.replace(Regexes[Strings.CODESTRING], Replacements[Strings.CODESTRING]);
text = text.replace(Regexes[Strings.SPOILER], Replacements[Strings.SPOILER]);
text = text.replace(Regexes[Strings.STRIKE], Replacements[Strings.STRIKE]);
text = text.replace(Regexes[Strings.UNDERLINE], Replacements[Strings.UNDERLINE]);
text = text.replace(Regexes[Strings.QUOTE], Replacements[Strings.QUOTE]);
text = text.replace(Regexes[Strings.SUBTEXT], Replacements[Strings.SUBTEXT]); // this includes header
// `\-`/`\*` for bullets, numbered ones escape the dot (`1\.`), a backslash before a digit isn't an escape and would show
text = text.replace(Regexes.LIST_LINE_START, (match: string, space: string, marker: string) => {
return (marker.endsWith('.')) ? `${space}${marker.slice(0, -1)}\\.` : `${space}\\${marker}`;
});
if (filter.links) {
text = escape.links(text, filter.mentionEscapeCharacter);
}
if (filter.mentions) {
text = escape.mentions(text, filter.mentionEscapeCharacter);
}
return trueSlice(text, filter.limit);
},
bold: (text: string, options: MarkupFilterOptions = {}): string => {
const filter: MarkupFilter = Object.assign({}, defaultBoldFilter, options);
// backslashes first, a trailing one would escape the closing marker
text = text.replace(Regexes[Strings.ESCAPE], Replacements[Strings.ESCAPE]);
text = text.replace(Regexes[Strings.BOLD], filter.replacement);
if (filter.mentions) {
text = escape.mentions(text, filter.mentionEscapeCharacter);
}
return trueSlice(text, filter.limit);
},
codeblock: (text: string, options: CodeblockFilterOptions = {}): string => {
const filter: CodeblockFilter = Object.assign({}, defaultCodeblockFilter, options);
while (text.includes(Strings.CODEBLOCK)) {
text = text.replace(Regexes[Strings.CODEBLOCK], filter.replacement);
}
if (options.limit === undefined) {
filter.limit -= filter.language.length;
}
return trueSlice(text, filter.limit);
},
codestring: (text: string, options: MarkupFilterOptions = {}): string => {
const filter: MarkupFilter = Object.assign({}, defaultCodestringFilter, options);
text = text.replace(Regexes[Strings.CODESTRING], filter.replacement);
if (filter.mentions) {
text = escape.mentions(text, filter.mentionEscapeCharacter);
}
return trueSlice(text, filter.limit);
},
header: (text: string, options: HeaderFilterOptions = {}): string => {
const filter: HeaderFilter = Object.assign({}, defaultHeaderFilter, options);
text = text.replace(Regexes[Strings.HEADER], filter.replacement);
if (!filter.multiline) {
text = text.replace(/\n/g, ' ');
}
if (filter.mentions) {
text = escape.mentions(text, filter.mentionEscapeCharacter);
}
return trueSlice(text, filter.limit);
},
italics: (text: string, options: MarkupFilterOptions = {}): string => {
const filter: MarkupFilter = Object.assign({}, defaultItalicsFilter, options);
// backslashes first, a trailing one would escape the closing marker
text = text.replace(Regexes[Strings.ESCAPE], Replacements[Strings.ESCAPE]);
text = text.replace(Regexes[Strings.ITALICS], filter.replacement);
if (filter.mentions) {
text = escape.mentions(text, filter.mentionEscapeCharacter);
}
return trueSlice(text, filter.limit);
},
links: (text: string, replacement: string = Replacements.MENTION): string => {
text = text.replace(Regexes.LINK, `]${replacement}(`);
return text;
},
list: (text: string, options: ListFilterOptions = {}): string => {
const filter: ListFilter = Object.assign({}, defaultListFilter, options);
text = text.replace(Regexes[Strings.LIST], filter.replacement);
if (!filter.multiline) {
text = text.replace(/\n/g, ' ');
}
if (filter.mentions) {
text = escape.mentions(text, filter.mentionEscapeCharacter);
}
return trueSlice(text, filter.limit);
},
mentions: (text: string, replacement: string = Replacements.MENTION): string => {
text = text.replace(Regexes.MENTION_HARDCORE, `@${replacement}`);
return text;
},
quote: (text: string, options: QuoteFilterOptions = {}): string => {
const filter: QuoteFilter = Object.assign({}, defaultQuoteFilter, options);
text = text.replace(Regexes[Strings.QUOTE], filter.replacement);
if (!filter.multiline) {
text = text.replace(/\n/g, ' ');
}
if (filter.mentions) {
text = escape.mentions(text, filter.mentionEscapeCharacter);
}
return trueSlice(text, filter.limit);
},
spoiler: (text: string, options: MarkupFilterOptions = {}): string => {
const filter: MarkupFilter = Object.assign({}, defaultSpoilerFilter, options);
// backslashes first, a trailing one would escape the closing marker
text = text.replace(Regexes[Strings.ESCAPE], Replacements[Strings.ESCAPE]);
text = text.replace(Regexes[Strings.SPOILER], filter.replacement);
if (filter.mentions) {
text = escape.mentions(text, filter.mentionEscapeCharacter);
}
return trueSlice(text, filter.limit);
},
strike: (text: string, options: MarkupFilterOptions = {}): string => {
const filter: MarkupFilter = Object.assign({}, defaultStrikeFilter, options);
// backslashes first, a trailing one would escape the closing marker
text = text.replace(Regexes[Strings.ESCAPE], Replacements[Strings.ESCAPE]);
text = text.replace(Regexes[Strings.STRIKE], filter.replacement);
if (filter.mentions) {
text = escape.mentions(text, filter.mentionEscapeCharacter);
}
return trueSlice(text, filter.limit);
},
subtext: (text: string, options: SubtextFilterOptions = {}): string => {
const filter: SubtextFilter = Object.assign({}, defaultSubtextFilter, options);
text = text.replace(Regexes[Strings.SUBTEXT], filter.replacement);
if (!filter.multiline) {
text = text.replace(/\n/g, ' ');
}
if (filter.mentions) {
text = escape.mentions(text, filter.mentionEscapeCharacter);
}
return trueSlice(text, filter.limit);
},
underline: (text: string, options: MarkupFilterOptions = {}): string => {
const filter: MarkupFilter = Object.assign({}, defaultUnderlineFilter, options);
// backslashes first, a trailing one would escape the closing marker
text = text.replace(Regexes[Strings.ESCAPE], Replacements[Strings.ESCAPE]);
text = text.replace(Regexes[Strings.UNDERLINE], filter.replacement);
if (filter.mentions) {
text = escape.mentions(text, filter.mentionEscapeCharacter);
}
return trueSlice(text, filter.limit);
},
url: (text: string, options: MarkupFilterOptions = {}): string => {
text = text.replace(Regexes.URL, (match: string) => {
return '%' + match.charCodeAt(0).toString(16).toUpperCase().padStart(2, '0');
});
return text;
},
});const Regexes: Readonly<{ _: RegExp; __: RegExp; -: RegExp; -#: RegExp; **: RegExp; \: RegExp; #: RegExp; `: RegExp; ```: RegExp; >: RegExp; ||: RegExp; ~~: RegExp; … 7 more }>export const Regexes = Object.freeze({
[Strings.BOLD]: /\*\*/g,
[Strings.CODEBLOCK]: new RegExp(Strings.CODEBLOCK, 'g'),
[Strings.CODESTRING]: new RegExp(Strings.CODESTRING, 'g'),
[Strings.ESCAPE]: /\\/g,
// `m` so every line's start gets escaped, not just the text's
[Strings.HEADER]: /^(\s*)#/gm,
[Strings.ITALICS]: /(_|\*)/g,
[Strings.LIST]: /(-|\*)/g,
[Strings.QUOTE]: />/g,
[Strings.SPOILER]: /\|\|/g,
[Strings.STRIKE]: new RegExp(Strings.STRIKE, 'g'),
[Strings.SUBTEXT]: /^(\s*)(-?#)/gm,
[Strings.UNDERLINE]: new RegExp(Strings.UNDERLINE, 'g'),
EVERYONE: /@(everyone|here)/g,
LINK: /\]\(/g,
LINK_TEXT: /[\[\]]/g,
// list markers at the start of a line (`- `, `* `, `1. `)
LIST_LINE_START: /^(\s*)([-*]|\d+\.)(?=\s)/gm,
MENTION: /<@([!&]?[0-9]{16,21})>/g,
MENTION_HARDCORE: /@/g,
// anything that would end the link's url early
URL: /[()\s]/g,
});const Replacements: Readonly<{ _: "\\$1"; __: "\\_\\_"; -: "\\$1"; -#: "$1\\$2"; **: "\\*\\*"; \: "\\\\"; #: "$1\\#"; `: "\\`"; ```: "```"; >: "\\>"; ||: "\\|\\|"; ~~: "\\~\\~"; … 2 more }>export const Replacements = Object.freeze({
[Strings.BOLD]: '\\*\\*',
[Strings.CODEBLOCK]: '``\u200b`',
[Strings.CODESTRING]: '\\`',
[Strings.ESCAPE]: '\\\\',
LINK_TEXT: '\\$&',
[Strings.HEADER]: '$1\\#',
[Strings.ITALICS]: '\\$1',
[Strings.LIST]: '\\$1',
[Strings.QUOTE]: '\\>',
[Strings.SPOILER]: '\\|\\|',
[Strings.STRIKE]: '\\~\\~',
[Strings.SUBTEXT]: '$1\\$2',
[Strings.UNDERLINE]: '\\_\\_',
MENTION: '\u200b',
});const Strings: Readonly<{ BOLD: "**"; CODEBLOCK: "```"; CODESTRING: "`"; CODESTRING_DOUBLE: "``"; ESCAPE: "\\"; HEADER: "#"; ITALICS: "_"; LIST: "-"; QUOTE: ">"; SPOILER: "||"; STRIKE: "~~"; SUBTEXT: "-#"; … 1 more }>export const Strings = Object.freeze({
BOLD: '**',
CODEBLOCK: '```',
CODESTRING: '`',
CODESTRING_DOUBLE: '``',
ESCAPE: '\\',
HEADER: '#',
ITALICS: '_',
LIST: '-',
QUOTE: '>',
SPOILER: '||',
STRIKE: '~~',
SUBTEXT: '-#',
UNDERLINE: '__',
});