discord-message-transcript-base 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,175 @@
1
+ export function markdownToHTML(text, mentions, everyone, dateFormat) {
2
+ const codeBlock = [];
3
+ const codeLine = [];
4
+ // Code Block (```)
5
+ text = text.replace(/```(?:(\S+)\n)?([\s\S]+?)```/g, (_m, lang, code) => {
6
+ const rawLang = lang?.toLowerCase();
7
+ const normalizedLang = rawLang ? (LANGUAGE_ALIAS[rawLang] ?? rawLang) : null;
8
+ const language = normalizedLang && SUPPORTED_LANGUAGES.has(rawLang) ? normalizedLang : 'plaintext';
9
+ codeBlock.push(`<pre><code class="language-${language}">${code.trimEnd()}</code></pre>`);
10
+ return `%$%CODE!BLOCK!${codeBlock.length - 1}%$%`;
11
+ });
12
+ // Code line (`)
13
+ text = text.replace(/`([^`]+)`/g, (_m, code) => {
14
+ codeLine.push(`<code>${code}</code>`);
15
+ return `%$%CODE!LINE!${codeLine.length - 1}%$%`;
16
+ });
17
+ // Citation (> | >>>)
18
+ text = text.replace(/(^> ?.*(?:(?:\n^> ?.*)+)?)/gm, (match) => {
19
+ const cleanContent = match.split('\n').map(line => {
20
+ return line.replace(/^>+ ?/, '');
21
+ }).join('\n');
22
+ return `<blockquote class="quote-multi">${cleanContent}</blockquote>`;
23
+ });
24
+ // Headers (#)
25
+ text = text.replace(/^### (.*)(?=\n|$)/gm, `<h3>$1</h3>`);
26
+ text = text.replace(/^## (.*)(?=\n|$)/gm, `<h2>$1</h2>`);
27
+ text = text.replace(/^# (.*)(?=\n|$)/gm, `<h1>$1</h1>`);
28
+ // Subtext(-#)
29
+ text = text.replace(/^-# (.*)(?=\n|$)/gm, `<p class="subtext">$1</p>`);
30
+ // List (- | *)
31
+ text = text.replace(/^(\s*)[-*] (.*)(?=\n|$)/gm, (_m, indentation, text) => {
32
+ const isSubItem = indentation.length > 0;
33
+ const bullet = isSubItem ? '◦' : '•';
34
+ return `<p class="pList">${indentation}${bullet} ${text}</p>`;
35
+ });
36
+ // Spoiler (||)
37
+ text = text.replace(/\|\|(.*?)\|\|/gs, `<span class="spoilerMsg">$1</span>`);
38
+ // Bold & Italic (***)
39
+ text = text.replace(/\*\*\*(.*?)\*\*\*/gs, `<strong><em>$1</em></strong>`);
40
+ // Bold (**)
41
+ text = text.replace(/\*\*(.*?)\*\*/gs, `<strong>$1</strong>`);
42
+ // Underline(__)
43
+ text = text.replace(/__(.*?)__/gs, `<u>$1</u>`);
44
+ // Italic (*)
45
+ text = text.replace(/\*(.*?)\*/gs, `<em>$1</em>`);
46
+ text = text.replace(/\_(.*?)\_/gs, `<em>$1</em>`);
47
+ // Strikethrough (~~)
48
+ text = text.replace(/~~(.*?)~~/gs, `<s>$1</s>`);
49
+ // Links ([]() && https)
50
+ text = text.replace(/\[([^\]]+)\]\((https?:\/\/[^\s]+)\)/g, (_m, text, link) => `<a href="${link}" target="_blank">${text}</a>`);
51
+ text = text.replace(/(?<!href=")(https?:\/\/[^\s]+)/g, (_m, link) => `<a href="${link}" target="_blank">${link}</a>`);
52
+ // Mentions (@)
53
+ if (mentions.users.length != 0) {
54
+ const users = new Map(mentions.users.map(user => [user.id, user]));
55
+ text = text.replace(/<@!?(\d+)>/g, (_m, id) => {
56
+ let user = users.get(id);
57
+ return user ? `<span class="mention" style="color: ${user.color ?? "#dbdee1"}">@${user.name}</span> ` : `<span class="mention"><@${id}></span> `;
58
+ });
59
+ }
60
+ if (mentions.roles.length != 0) {
61
+ const roles = new Map(mentions.roles.map(role => [role.id, role]));
62
+ text = text.replace(/<@&(\d+)>/g, (_m, id) => {
63
+ const role = roles.get(id);
64
+ return role ? `<span class="mention" style="color: ${role.color}">@${role.name}</span> ` : `<span class="mention"><@&${id}></span> `;
65
+ });
66
+ }
67
+ if (mentions.channels.length != 0) {
68
+ const channels = new Map(mentions.channels.map(channel => [channel.id, channel]));
69
+ text = text.replace(/<#(\d+)>/g, (_m, id) => {
70
+ const channel = channels.get(id);
71
+ return channel && channel.name ? `<span class="mention">#${channel.name}</span> ` : `<span class="mention"><#${id}></span> `;
72
+ });
73
+ }
74
+ if (everyone) {
75
+ text = text.replace("@everyone", `<span class="mention">@everyone</span> `);
76
+ text = text.replace("@here", `<span class="mention">@here</span> `);
77
+ }
78
+ // Timestamp
79
+ const { locale, timeZone } = dateFormat.resolvedOptions();
80
+ text = text.replace(/<t:(\d+)(?::([tTdDfFR]))?>/g, (_m, timestamp, format) => {
81
+ const date = new Date(parseInt(timestamp, 10) * 1000);
82
+ const style = format || 'f';
83
+ const isoString = date.toISOString();
84
+ const titleFormatter = new Intl.DateTimeFormat(locale, {
85
+ dateStyle: 'full',
86
+ timeStyle: 'full',
87
+ timeZone: timeZone,
88
+ });
89
+ const fullDateForTitle = titleFormatter.format(date);
90
+ if (style === 'R') {
91
+ const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' });
92
+ const seconds = Math.floor((date.getTime() - Date.now()) / 1000);
93
+ const minutes = Math.floor(seconds / 60);
94
+ const hours = Math.floor(minutes / 60);
95
+ const days = Math.floor(hours / 24);
96
+ let relativeString;
97
+ if (Math.abs(days) > 30)
98
+ relativeString = rtf.format(Math.floor(days / 30.44), 'month');
99
+ else if (Math.abs(days) > 0)
100
+ relativeString = rtf.format(days, 'day');
101
+ else if (Math.abs(hours) > 0)
102
+ relativeString = rtf.format(hours, 'hour');
103
+ else if (Math.abs(minutes) > 0)
104
+ relativeString = rtf.format(minutes, 'minute');
105
+ else
106
+ relativeString = rtf.format(seconds, 'second');
107
+ return `<time datetime="${isoString}" title="${fullDateForTitle}">${relativeString}</time>`;
108
+ }
109
+ else if (isStyleKey(style)) {
110
+ const formatter = new Intl.DateTimeFormat(locale, {
111
+ ...styleOptions[style],
112
+ timeZone: timeZone,
113
+ });
114
+ const formattedDate = formatter.format(date);
115
+ return `<time datetime="${isoString}" title="${fullDateForTitle}">${formattedDate}</time>`;
116
+ }
117
+ return _m;
118
+ });
119
+ // Break Line
120
+ text = text.replace(/\n/g, '<br>');
121
+ // Clear Unecessary Break Line
122
+ text = text.replace(/(<\/(?:p|h[1-3]|blockquote)>)\s*<br>/g, '$1');
123
+ // Remove Placeholders
124
+ text = text.replace(/%\$%CODE!BLOCK!(\d+)%\$%/g, (_m, number) => {
125
+ return codeBlock[number];
126
+ });
127
+ text = text.replace(/%\$%CODE!LINE!(\d+)%\$%/g, (_m, number) => {
128
+ return codeLine[number];
129
+ });
130
+ return text;
131
+ }
132
+ // Check if styleKey is valid
133
+ const styleOptions = {
134
+ 't': { timeStyle: 'short' },
135
+ 'T': { timeStyle: 'medium' },
136
+ 'd': { dateStyle: 'short' },
137
+ 'D': { dateStyle: 'long' },
138
+ 'f': { dateStyle: 'long', timeStyle: 'short' },
139
+ 'F': { dateStyle: 'full', timeStyle: 'short' },
140
+ };
141
+ function isStyleKey(key) {
142
+ return key in styleOptions;
143
+ }
144
+ // At least I hope
145
+ const SUPPORTED_LANGUAGES = new Set([
146
+ 'bash', 'sh', 'shell',
147
+ 'c',
148
+ 'cpp',
149
+ 'css',
150
+ 'javascript', 'js',
151
+ 'typescript', 'ts',
152
+ 'json',
153
+ 'xml',
154
+ 'yaml', 'yml',
155
+ 'java',
156
+ 'kotlin',
157
+ 'php',
158
+ 'python', 'py',
159
+ 'ruby', 'rb',
160
+ 'sql',
161
+ 'lua',
162
+ 'markdown', 'md',
163
+ 'plaintext', 'txt'
164
+ ]);
165
+ const LANGUAGE_ALIAS = {
166
+ sh: 'bash',
167
+ shell: 'bash',
168
+ js: 'javascript',
169
+ ts: 'typescript',
170
+ py: 'python',
171
+ rb: 'ruby',
172
+ md: 'markdown',
173
+ yml: 'yaml',
174
+ txt: 'plaintext'
175
+ };
@@ -0,0 +1,3 @@
1
+ import { JsonData, Uploadable } from "../types/types.js";
2
+ import Stream from 'stream';
3
+ export declare function output(json: JsonData): Promise<string | Stream | Buffer | Uploadable>;
@@ -0,0 +1,24 @@
1
+ import { Readable } from 'stream';
2
+ import { Html } from "../renderers/html/html.js";
3
+ export async function output(json) {
4
+ const objectHTML = new Html(json);
5
+ const stringHTML = objectHTML.toHTML();
6
+ if (json.options.returnType == "string") {
7
+ return stringHTML;
8
+ }
9
+ const buffer = Buffer.from(stringHTML, 'utf-8');
10
+ if (json.options.returnType == "buffer") {
11
+ return buffer;
12
+ }
13
+ if (json.options.returnType == "stream") {
14
+ return Readable.from([stringHTML]);
15
+ }
16
+ if (json.options.returnType == "uploadable") {
17
+ return {
18
+ content: stringHTML,
19
+ contentType: 'text/html',
20
+ fileName: json.options.fileName
21
+ };
22
+ }
23
+ throw new Error("Return format or return type invalid!");
24
+ }
@@ -0,0 +1,13 @@
1
+ import { ConvertTranscriptOptions, ReturnTypeBase, OutputTypeBase } from "./types/types.js";
2
+ export * from './types/types.js';
3
+ export { CustomError } from "./core/error.js";
4
+ export { output as outputBase } from "./core/output.js";
5
+ /**
6
+ * Converts a JSON transcript string into an HTML transcript.
7
+ * Depending on the `returnType` option, this function can return a `string`, a `Buffer`, a `Stream`, or an `Uploadable` object.
8
+ *
9
+ * @param jsonString The JSON string representing the transcript data.
10
+ * @param options Configuration options for converting the transcript. See {@link ConvertTranscriptOptions} for details.
11
+ * @returns A promise that resolves to the HTML transcript in the specified format.
12
+ */
13
+ export declare function renderHTMLFromJSON<T extends ReturnTypeBase = typeof ReturnTypeBase.String>(jsonString: string, options?: ConvertTranscriptOptions<T>): Promise<OutputTypeBase<T>>;
package/dist/index.js ADDED
@@ -0,0 +1,37 @@
1
+ import { CustomError } from "./core/error.js";
2
+ import { output } from "./core/output.js";
3
+ import { ReturnTypeBase, ReturnFormat } from "./types/types.js";
4
+ export * from './types/types.js';
5
+ export { CustomError } from "./core/error.js";
6
+ export { output as outputBase } from "./core/output.js";
7
+ /**
8
+ * Converts a JSON transcript string into an HTML transcript.
9
+ * Depending on the `returnType` option, this function can return a `string`, a `Buffer`, a `Stream`, or an `Uploadable` object.
10
+ *
11
+ * @param jsonString The JSON string representing the transcript data.
12
+ * @param options Configuration options for converting the transcript. See {@link ConvertTranscriptOptions} for details.
13
+ * @returns A promise that resolves to the HTML transcript in the specified format.
14
+ */
15
+ export async function renderHTMLFromJSON(jsonString, options = {}) {
16
+ try {
17
+ const jsonParse = JSON.parse(jsonString);
18
+ const json = {
19
+ ...jsonParse,
20
+ options: {
21
+ ...jsonParse.options,
22
+ returnFormat: ReturnFormat.HTML,
23
+ returnType: options?.returnType ?? ReturnTypeBase.String,
24
+ selfContained: options?.selfContained ?? false,
25
+ watermark: options.watermark ?? jsonParse.options.watermark
26
+ }
27
+ };
28
+ return await output(json);
29
+ }
30
+ catch (error) {
31
+ if (error instanceof Error) {
32
+ throw new CustomError(`Error converting JSON to HTML: ${error.stack}`);
33
+ }
34
+ const unknowErrorMessage = String(error);
35
+ throw new CustomError(`Unknown error: ${unknowErrorMessage}`);
36
+ }
37
+ }
@@ -0,0 +1,11 @@
1
+ export declare const DEFAULT_CSS = "\nbody {\n background-color: #3a3c43;\n color: #dbdee1;\n font-family: \"Whitney\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n margin: 0;\n padding: 0;\n width: 100%;\n}\nheader {\n height: fit-content;\n border-bottom: 2px solid black;\n margin-top: 2rem;\n padding-left: 2rem;\n padding-bottom: 1rem;\n display: flex;\n flex-direction: column;\n display: flex;\n flex-direction: row;\n}\na {\n text-decoration: none;\n color: #1E90FF;\n}\np {\n margin: 0;\n}\nh1 {\n margin: 0.5rem 0;\n}\nh2 {\n margin: 0.3rem 0;\n}\nh3 {\n margin: 0.15rem\n}\nh4 {\n margin: 0;\n}\ncode {\n border: 1px solid #202225;\n border-radius: 0.25rem;\n}\nblockquote {\n margin: 0.5rem 0;\n border-left: 0.25rem solid #4f545c;\n padding: 0.4rem 0.6rem;\n border-radius: 0.25rem;\n color: #9f9fa6;\n}\n.line {\n display: flex;\n align-items: baseline;\n gap: 0.5rem\n}\n.badge {\n background-color: #5865f2;\n color: white;\n font-weight: 600;\n font-size: 80%;\n padding: 0.1rem 0.35rem;\n border-radius: 0.25rem;\n letter-spacing: 0.03rem;\n height: fit-content;\n width: fit-content;\n align-self: flex-start;\n}\n.badgeTag {\n background-color: #747F8D50;\n color: white;\n font-weight: 600;\n font-size: 70%;\n padding: 0.1rem 0.35rem;\n border-radius: 0.25rem;\n letter-spacing: 0.03rem;\n height: fit-content;\n width: fit-content;\n align-self: center;\n}\n.mention {\n background-color: #5664fa41;\n padding: 0.2rem;\n border-radius: 0.25rem;\n transition: background-color 0.2s ease;\n}\n.mention:hover {\n background-color: #5664fa7e;\n}\n.guildInitialsIcon {\n width: 7rem;\n height: 7rem;\n border-radius: 50%;\n background-color: #4f545c;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 3rem;\n font-weight: 600;\n}\n";
2
+ export declare const MESSAGE_CSS = "\n.messageDiv {\n display: flex;\n flex-direction: column;\n gap: 0.2rem;\n padding: 0.5rem;\n border-radius: 1rem;\n}\n.messageDiv.highlight, .messageDiv:hover {\n background-color: #40434b;\n transition: background-color 0.3s ease-in-out;\n}\n.messageBotton {\n display: flex;\n flex-direction: row;\n gap: 1rem;\n padding: 0.5rem;\n border-radius: 0.25rem;\n}\n.messageImg {\n width: 3.5rem; \n height: 3.5rem; \n border-radius: 50%;\n}\n.messageDivRight {\n display: flex;\n flex-direction: column;\n gap: 0.25rem\n}\n.messageUser {\n display: flex;\n flex-direction: row;\n gap: 0.75rem;\n}\n.messageUsername {\n margin: 0;\n}\n.messageTimeStamp {\n color: #999999;\n font-size: 77.5%;\n align-self: center;\n}\n.messageContent {\n line-height: 1.5;\n}\n.pList {\n white-space: pre-wrap;\n}\n.subtext {\n font-size: 85%;\n color: #808080;\n}\n.spoilerMsg {\n display: inline-block;\n background-color: #202225;\n color: #202225;\n padding: 0 0.2rem;\n border-radius: 0.2rem;\n cursor: pointer;\n transition: background-color 0.1s ease-in-out, color 0.1s ease-in-out;\n}\n.spoilerMsg.revealed {\n background-color: transparent;\n color: inherit;\n}\n.messageReply {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.8rem;\n color: #b5bac1;\n cursor: pointer;\n margin-left: 2rem;\n}\n.messageReplySvg {\n flex-shrink: 0;\n width: 2.25rem;\n height: 2.25rem;\n color: #b5bac1;\n}\n.messageReplyImg {\n width: 1.75rem;\n height: 1.75rem;\n border-radius: 50%;\n flex-shrink: 0;\n}\n.messageReplyAuthor {\n font-weight: 600;\n color: #dbdee1;\n margin-right: 0.3rem;\n}\n.badgeReply {\n background-color: #5865f2;\n color: white;\n font-weight: 600;\n font-size: 70%;\n padding: 0.1rem 0.3rem;\n border-radius: 0.25rem;\n letter-spacing: 0.03rem;\n height: fit-content;\n align-self: center;\n flex-shrink: 0;\n}\n.messageReplyText {\n flex-grow: 1;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n color: #b5bac1;\n font-size: 0.75rem;\n}\n";
3
+ export declare const EMBED_CSS = "\n.embed {\n background-color: #2b2d31;\n border: 0.15rem solid #2b2d31;\n border-left: 0.25rem solid;\n border-radius: 0.25rem;\n padding: 0.5rem 0.75rem;\n margin-top: 0.5rem;\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n max-width: 40rem;\n min-width: 30rem;\n}\n.embed a {\n color: #00aff4;\n text-decoration: none;\n}\n.embed a:hover {\n text-decoration: underline;\n}\n.embedHeader {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 0.5rem;\n}\n.embedHeaderLeft {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n}\n.embedHeaderLeftAuthor {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.875rem;\n font-weight: 500;\n color: #ffffff;\n margin-bottom: 0.5rem;\n}\n.embedHeaderLeftAuthorImg {\n width: 1.5rem;\n height: 1.5rem;\n border-radius: 50%;\n}\n.embedHeaderLeftAuthorName {\n color: #ffffff;\n font-weight: 500;\n}\n.embedHeaderLeftTitle {\n font-size: 1rem;\n font-weight: bold;\n color: #ffffff;\n margin-bottom: 0.75rem;\n}\n.embedHeaderThumbnail {\n max-width: 80px;\n max-height: 80px;\n object-fit: contain;\n border-radius: 0.25rem;\n flex-shrink: 0;\n}\n.embedDescription {\n font-size: 0.875rem;\n color: #dcddde;\n}\n.embedFields {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n}\n.embedFieldsField {\n flex: 1;\n min-width: 150px;\n}\n.embedFieldsFieldTitle {\n font-size: 0.75rem;\n font-weight: bold;\n color: #ffffff;\n margin-bottom: 0.25rem;\n}\n.embedFieldsFieldValue {\n font-size: 0.875rem;\n color: #dcddde;\n}\n.embedImage {\n margin-top: 0.5rem;\n max-width: 100%;\n height: auto;\n}\n.embedImage img {\n max-width: 100%;\n max-height: 300px;\n object-fit: contain;\n border-radius: 0.25rem;\n}\n.embedFooter {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.75rem;\n color: #999999;\n margin-top: 0.5rem;\n}\n.embedFooterImg {\n width: 1.25rem;\n height: 1.25rem;\n border-radius: 50%;\n}\n.embedFooterText {\n color: #999999;\n}\n";
4
+ export declare const ATTACHMENT_CSS = "\n.attachmentImage, .attachmentVideo {\n max-width: 400px;\n height: auto;\n border-radius: 0.25rem;\n margin-top: 0.5rem;\n}\n.attachmentAudio {\n width: 300px;\n margin-top: 0.5rem;\n}\n.attachmentFile {\n background-color: #2b2d31;\n border: 1px solid #202225;\n border-radius: 0.75rem;\n padding: 0.75rem;\n display: flex;\n align-items: center;\n gap: 0.75rem;\n max-width: 400px;\n margin-top: 0.5rem;\n width: fit-content;\n}\n.attachmentFileIcon {\n width: 2.5rem;\n height: 2.5rem;\n fill: #b9bbbe;\n flex-shrink: 0;\n}\n.attachmentFileInfo {\n display: flex;\n flex-direction: column;\n gap: 0.1rem;\n overflow: hidden;\n flex-grow: 1;\n}\n.attachmentFileName {\n color: #ffffff;\n text-decoration: none;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.attachmentFileSize {\n font-size: 0.75rem;\n color: #72767d;\n}\n.attachmentDownload {\n display: block;\n flex-shrink: 0;\n}\n.attachmentDownloadIcon {\n width: 1.5rem;\n height: 1.5rem;\n fill: #b9bbbe;\n transition: fill 0.2s ease;\n}\n.attachmentDownload:hover .attachmentDownloadIcon {\n fill: #ffffff;\n}\n.spoilerAttachment {\n position: relative;\n display: inline-block;\n border-radius: 0.5rem;\n overflow: hidden;\n cursor: pointer;\n}\n.spoilerAttachment .spoilerAttachmentContent {\n filter: blur(64px);\n pointer-events: none;\n transition: filter 0.2s ease;\n width: 100%;\n height: 100%;\n}\n.spoilerAttachment .spoilerAttachmentOverlay {\n position: absolute;\n inset: 0;\n background: rgba(32, 34, 37, 0.85);\n color: #fff;\n font-weight: 600;\n letter-spacing: 0.05em;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 2;\n user-select: none;\n}\n.spoilerAttachment.revealed .spoilerAttachmentContent {\n filter: none;\n pointer-events: auto;\n}\n.spoilerAttachment.revealed .spoilerAttachmentOverlay {\n display: none;\n}\n";
5
+ export declare const ACTIONROW_CSS = "\n.actionRow {\n display: flex;\n gap: 0.5rem;\n margin-top: 0.5rem;\n}\n";
6
+ export declare const BUTTON_CSS = "\n.button {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0rem 0.8rem;\n height: 2.5rem;\n border-radius: 0.6rem;\n color: white;\n font-weight: 600;\n cursor: pointer;\n transition: filter 0.2s ease;\n}\n.button:hover {\n filter: brightness(1.1);\n}\n.buttonEmoji {\n font-size: 1.25rem;\n}\n.buttonLabel {\n font-size: 0.875rem;\n}\n.buttonLink {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n color: white;\n font-weight: 600;\n}\n.buttonLinkIcon {\n width: 1.25rem;\n height: 1.25rem;\n}\n";
7
+ export declare const COMPONENTS_CSS = "\n.selector {\n width: 100%;\n position: relative;\n}\n.selectorInput {\n background-color: #2b2d31;\n border: 1px solid #202225;\n border-radius: 0.75rem;\n padding: 0.75rem;\n min-width: 17.5rem;\n cursor: pointer;\n user-select: none;\n}\n.selectorInputText {\n color: #808080;\n}\n.selectorOptionMenu {\n display: none; \n position: absolute;\n top: 100%;\n left: 0;\n width: 100%;\n background-color: #2b2d31;\n border: 1px solid #202225;\n border-radius: 1rem;\n margin-top: 0.25rem;\n padding: 0.5rem;\n z-index: 10;\n box-sizing: border-box;\n}\n.selector.active .selectorOptionMenu {\n display: block;\n}\n.selectorOption {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem;\n border-radius: 0.75rem;\n cursor: pointer;\n transition: background-color 0.2s ease;\n}\n.selectorOption:hover {\n background-color: #4f545c;\n}\n.selectorOptionEmoji {\n font-size: 1.25rem;\n}\n.selectorOptionRight {\n display: flex;\n flex-direction: column;\n}\n.selectorOptionTitle {\n font-weight: 500;\n}\n.selectorOptionDesc {\n font-size: 0.75rem;\n color: #808080;\n}\n";
8
+ export declare const COMPONENTSV2_CSS = "\n.mediaGallery {\n display: flex;\n flex-wrap: wrap;\n gap: 0.25rem;\n width: 100%;\n max-width: 40rem;\n aspect-ratio: 1 / 1;\n padding: 0.35rem;\n overflow: hidden;\n}\n.mediaGalleryItem {\n flex-grow: 1;\n flex-basis: 0;\n min-width: 30%;\n display: flex;\n}\n.mediaGalleryImg {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n border-radius: 1rem;\n}\n.container {\n background-color: #2b2d31;\n border-radius: 0.5rem;\n padding: 1rem;\n max-width: 40rem;\n min-width: 30rem;\n border-left: 0.25rem solid;\n}\n.section {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n padding: 0.5rem 0;\n}\n.sectionRight {\n margin-right: 0.5rem;\n margin-left: 1rem;\n}\n.sectionThumbnail {\n width: 5rem;\n height: 5rem;\n border-radius: 0.5rem;\n}\n.textDisplay {\n padding: 0.5rem 0;\n}\n.separator {\n border: 1px solid #808080;\n}\n";
9
+ export declare const POLL_CSS = "\n.pollDiv {\n background-color: #2b2d31;\n border-radius: 0.5rem;\n padding: 1rem;\n margin-top: 0.5rem;\n max-width: 40rem;\n min-width: 25rem\n}\n.pollQuestion {\n font-size: 1.1rem;\n font-weight: bold;\n margin-bottom: 1rem;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n.pollAnswers {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n.pollAnswer {\n background-color: #3a3c42;\n border-radius: 0.3rem;\n padding: 0.75rem;\n cursor: pointer;\n border: 1px solid transparent;\n transition: border-color 0.2s ease;\n position: relative;\n overflow: hidden;\n}\n.pollAnswer:hover {\n border-color: #4d515a;\n}\n.pollAnswerBar {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n background-color: #5664fa7a;\n border-radius: 0.2rem;\n z-index: 1;\n}\n.pollAnswerContent {\n position: relative;\n z-index: 2;\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n.pollAnswerDetails {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n.pollAnswerEmoji {\n font-size: 1.25rem;\n}\n.pollAnswerText {\n font-weight: 500;\n}\n.pollAnswerVotes {\n font-size: 0.8rem;\n color: #b5bac1;\n font-weight: bold;\n}\n.pollFooter {\n margin-top: 1rem;\n font-size: 0.75rem;\n color: #949ba4;\n}\n";
10
+ export declare const POLL_RESULT_EMBED_CSS = "\n.pollResultEmbed {\n background-color: #2b2d31;\n border-radius: 0.5rem;\n padding: 1rem;\n margin-top: 0.5rem;\n border: 1px solid #3a3c42;\n min-width: 20rem;\n max-width: 40rem;\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n}\n.pollResultEmbedWinner {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 1rem;\n font-weight: 600;\n margin-bottom: 0.4rem;\n}\n.pollResultEmbedCheckmark {\n color: #57f287;\n font-size: 1.1em;\n}\n.pollResultEmbedSubtitle {\n font-size: 0.9rem;\n color: #b5bac1;\n}\n.pollResultEmbedButtonDiv {\n margin-right: 0.5rem;\n margin-left: 1rem;\n align-self: center;\n}\n.pollResultEmbedButton {\n background-color: black;\n color: white;\n padding: 0.5rem 1rem;\n border-radius: 0.3rem;\n text-decoration: none;\n font-weight: 500;\n transition: background-color 0.2s ease;\n cursor: pointer;\n}\n.pollResultEmbedButton:hover {\n filter: brightness(1.1);\n}\n";
11
+ export declare const REACTIONS_CSS = "\n.reactionsDiv {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n margin-top: 0.5rem;\n}\n.reaction {\n align-items: center;\n background-color: #2b2d31;\n border: 1px solid #3a3c42;\n border-radius: 1rem;\n padding: 0.25rem 0.6rem;\n font-size: 1rem;\n color: #dcddde;\n font-weight: bold;\n cursor: pointer;\n}\n.reaction:hover {\n filter: brightness(1.1);\n}\n";