mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-17 20:13:30 +01:00
feat: add new markdown formatters (#9613)
* feat: add new markdown formatters Co-authored-by: Jaw0r3k <jaw0r3k.g@gmail.com> * Update packages/formatters/src/formatters.ts Co-authored-by: Sugden <28943913+NotSugden@users.noreply.github.com> * refactor: remove unnecessary index tracking and rename 'array' to 'items' Co-authored-by: Almeida <almeidx@pm.me> * refactor: rename 'array' to 'items' Co-authored-by: Almeida <almeidx@pm.me> * refactor(heading): consolidate heading functions into a single function Also correct param names from array to items. Co-authored-by: Jaw0r3k <jaw0r3k.g@gmail.com> * refactor: add HeadingLevel enum and use switch case * fix: export HeadingLevel enum Co-authored-by: Jaw0r3k <jaworekwiadomosci@gmail.com> * feat(heading): add missing documentation for level parameter * refactor: update list formatters * docs: correct heading formatter description * refactor: update list formatters * fix(heading): remove unnecessary space * refactor: move list callback function to outer scope * test: add tests * refactor: requested changes * refactor: suggested changes * docs: add missing documentation * style: suggested change Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com> * refactor: use math max method instead Co-authored-by: Almeida <almeidx@pm.me> --------- Co-authored-by: Jaw0r3k <jaw0r3k.g@gmail.com> Co-authored-by: Sugden <28943913+NotSugden@users.noreply.github.com> Co-authored-by: Almeida <almeidx@pm.me> Co-authored-by: Jaw0r3k <jaworekwiadomosci@gmail.com> Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com> Co-authored-by: space <spaceeec@yahoo.com>
This commit is contained in:
@@ -10,11 +10,14 @@ import {
|
|||||||
codeBlock,
|
codeBlock,
|
||||||
Faces,
|
Faces,
|
||||||
formatEmoji,
|
formatEmoji,
|
||||||
|
heading,
|
||||||
|
HeadingLevel,
|
||||||
hideLinkEmbed,
|
hideLinkEmbed,
|
||||||
hyperlink,
|
hyperlink,
|
||||||
inlineCode,
|
inlineCode,
|
||||||
italic,
|
italic,
|
||||||
messageLink,
|
messageLink,
|
||||||
|
orderedList,
|
||||||
quote,
|
quote,
|
||||||
roleMention,
|
roleMention,
|
||||||
spoiler,
|
spoiler,
|
||||||
@@ -22,6 +25,7 @@ import {
|
|||||||
time,
|
time,
|
||||||
TimestampStyles,
|
TimestampStyles,
|
||||||
underscore,
|
underscore,
|
||||||
|
unorderedList,
|
||||||
userMention,
|
userMention,
|
||||||
} from '../src/index.js';
|
} from '../src/index.js';
|
||||||
|
|
||||||
@@ -202,6 +206,42 @@ describe('Message formatters', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('heading', () => {
|
||||||
|
test('GIVEN "discord.js" THEN returns "# discord.js"', () => {
|
||||||
|
expect<'# discord.js'>(heading('discord.js')).toEqual('# discord.js');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('GIVEN "discord.js" AND a heading level 2 from number THEN returns "## discord.js"', () => {
|
||||||
|
expect<'## discord.js'>(heading('discord.js', 2)).toEqual('## discord.js');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('GIVEN "discord.js" AND a heading level 3 from enum THEN returns "### discord.js"', () => {
|
||||||
|
expect<'### discord.js'>(heading('discord.js', HeadingLevel.Three)).toEqual('### discord.js');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('orderedList', () => {
|
||||||
|
test('GIVEN ["discord.js", "discord.js 2", ["discord.js 3"]] THEN returns "1. discord.js\n1. discord.js 2\n 1. discord.js"', () => {
|
||||||
|
expect(orderedList(['discord.js', 'discord.js 2', ['discord.js 3']])).toEqual(
|
||||||
|
'1. discord.js\n1. discord.js 2\n 1. discord.js 3',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('GIVEN ["discord.js", "discord.js 2", ["discord.js 3"]] AND a startNumber THEN returns "${startNumber}. discord.js\n${startNumber}. discord.js 2\n ${startNumber}. discord.js"', () => {
|
||||||
|
expect(orderedList(['discord.js', 'discord.js 2', ['discord.js 3']], 50)).toEqual(
|
||||||
|
'50. discord.js\n50. discord.js 2\n 50. discord.js 3',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('unorderedList', () => {
|
||||||
|
test('GIVEN ["discord.js", "discord.js 2", ["discord.js 3"]] THEN returns "- discord.js\n- discord.js 2\n - discord.js"', () => {
|
||||||
|
expect(unorderedList(['discord.js', 'discord.js 2', ['discord.js 3']])).toEqual(
|
||||||
|
'- discord.js\n- discord.js 2\n - discord.js 3',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('time', () => {
|
describe('time', () => {
|
||||||
test('GIVEN no arguments THEN returns "<t:${bigint}>"', () => {
|
test('GIVEN no arguments THEN returns "<t:${bigint}>"', () => {
|
||||||
vitest.useFakeTimers();
|
vitest.useFakeTimers();
|
||||||
|
|||||||
@@ -373,6 +373,99 @@ export function messageLink<C extends Snowflake, M extends Snowflake, G extends
|
|||||||
return `${guildId === undefined ? channelLink(channelId) : channelLink(channelId, guildId)}/${messageId}`;
|
return `${guildId === undefined ? channelLink(channelId) : channelLink(channelId, guildId)}/${messageId}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The heading levels for expanded markdown.
|
||||||
|
*/
|
||||||
|
export enum HeadingLevel {
|
||||||
|
/**
|
||||||
|
* The first heading level.
|
||||||
|
*/
|
||||||
|
One = 1,
|
||||||
|
/**
|
||||||
|
* The second heading level.
|
||||||
|
*/
|
||||||
|
Two,
|
||||||
|
/**
|
||||||
|
* The third heading level.
|
||||||
|
*/
|
||||||
|
Three,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the content into a heading level.
|
||||||
|
*
|
||||||
|
* @typeParam C - This is inferred by the supplied content
|
||||||
|
* @param content - The content to wrap
|
||||||
|
* @param level - The heading level
|
||||||
|
*/
|
||||||
|
export function heading<C extends string>(content: C, level?: HeadingLevel.One): `# ${C}`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the content into a heading level.
|
||||||
|
*
|
||||||
|
* @typeParam C - This is inferred by the supplied content
|
||||||
|
* @param content - The content to wrap
|
||||||
|
* @param level - The heading level
|
||||||
|
*/
|
||||||
|
export function heading<C extends string>(content: C, level: HeadingLevel.Two): `## ${C}`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the content into a heading level.
|
||||||
|
*
|
||||||
|
* @typeParam C - This is inferred by the supplied content
|
||||||
|
* @param content - The content to wrap
|
||||||
|
* @param level - The heading level
|
||||||
|
*/
|
||||||
|
export function heading<C extends string>(content: C, level: HeadingLevel.Three): `### ${C}`;
|
||||||
|
|
||||||
|
export function heading(content: string, level?: HeadingLevel) {
|
||||||
|
switch (level) {
|
||||||
|
case HeadingLevel.Three:
|
||||||
|
return `### ${content}`;
|
||||||
|
case HeadingLevel.Two:
|
||||||
|
return `## ${content}`;
|
||||||
|
default:
|
||||||
|
return `# ${content}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A type that recursively traverses into arrays.
|
||||||
|
*/
|
||||||
|
export type RecursiveArray<T> = readonly (RecursiveArray<T> | T)[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function for list formatters.
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
function listCallback(element: RecursiveArray<string>, startNumber?: number, depth = 0): string {
|
||||||
|
if (Array.isArray(element)) {
|
||||||
|
return element.map((element) => listCallback(element, startNumber, depth + 1)).join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${' '.repeat(depth - 1)}${startNumber ? `${startNumber}.` : '-'} ${element}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the elements in the array to an ordered list.
|
||||||
|
*
|
||||||
|
* @param list - The array of elements to list
|
||||||
|
* @param startNumber - The starting number for the list
|
||||||
|
*/
|
||||||
|
export function orderedList(list: RecursiveArray<string>, startNumber = 1): string {
|
||||||
|
return listCallback(list, Math.max(startNumber, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats the elements in the array to an unordered list.
|
||||||
|
*
|
||||||
|
* @param list - The array of elements to list
|
||||||
|
*/
|
||||||
|
export function unorderedList(list: RecursiveArray<string>): string {
|
||||||
|
return listCallback(list);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats a date into a short date-time string.
|
* Formats a date into a short date-time string.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user