+9
-9
app/(home)/page.tsx
+9
-9
app/(home)/page.tsx
···
10
10
import DiscordAppBadge from "@/components/discord/app-badge";
11
11
import DiscordChannel from "@/components/discord/channel";
12
12
import DiscordChannelCategory from "@/components/discord/channel-category";
13
-
import Highlight from "@/components/discord/markdown";
13
+
import { DiscordMarkdown } from "@/components/discord/markdown";
14
14
import DiscordMessage from "@/components/discord/message";
15
15
import DiscordMessageEmbed from "@/components/discord/message-embed";
16
16
import DiscordUser from "@/components/discord/user";
···
299
299
<div className="bg-[#313338] h-0.5 w-full sm:w-0.5 sm:h-32 md:h-0.5 md:w-full lg:w-0.5 lg:h-32 rounded-full ml-2" />
300
300
301
301
<DiscordMessage {...messageProps("tts voice")}>
302
-
<Highlight mode={"DARK"} text="Now talking..." />
302
+
<DiscordMarkdown mode={"DARK"} text="Now talking..." />
303
303
</DiscordMessage>
304
304
</div>
305
305
···
366
366
style={{ backgroundColor: "rgb(43, 45, 49)" }}
367
367
>
368
368
<DiscordMessage {...messageProps()}>
369
-
<Highlight mode={"DARK"} text="Hey **@everyone**, Linus Tech Tips just posted a new video!\n[youtube.com/watch?v=74Lj5cHseI8]()" />
369
+
<DiscordMarkdown mode={"DARK"} text="Hey **@everyone**, Linus Tech Tips just posted a new video!\n[youtube.com/watch?v=74Lj5cHseI8](https://youtube.com/watch?v=74Lj5cHseI8)" />
370
370
<DiscordMessageEmbed
371
371
mode="DARK"
372
372
title="Your PC Can Look Like THIS Now!"
···
441
441
style={{ backgroundColor: "rgb(43, 45, 49)" }}
442
442
>
443
443
<DiscordMessage {...messageProps("image")}>
444
-
<Highlight mode={"DARK"} text="query: **femboy**" />
444
+
<DiscordMarkdown mode={"DARK"} text="query: **femboy**" />
445
445
<Image
446
446
alt=""
447
447
className="rounded-md shadow-md w-64 md:w-56 lg:w-72 md:w-unset max-w-md mt-2"
···
627
627
<span className="text-blue-500 hover:underline cursor-pointer">#lounge</span>
628
628
</div>
629
629
630
-
<Highlight mode={"DARK"} text="**Replied to @drijon**" />
631
-
<Highlight mode={"DARK"} text="As if someone creates a discord account being like: OH I NEED TO KNOW THE GAS PRICES. THERE IS A NICE WAY FOR IT. MEE6 PREMIUM!" />
630
+
<DiscordMarkdown mode={"DARK"} text="**Replied to @drijon**" />
631
+
<DiscordMarkdown mode={"DARK"} text="As if someone creates a discord account being like: OH I NEED TO KNOW THE GAS PRICES. THERE IS A NICE WAY FOR IT. MEE6 PREMIUM!" />
632
632
</DiscordMessageEmbed>
633
633
</DiscordMessage>
634
634
</div>
···
676
676
style={{ backgroundColor: "rgb(43, 45, 49)" }}
677
677
>
678
678
<DiscordMessage {...messageProps()}>
679
-
<Highlight mode={"DARK"} text="Welcome @mwlica to **Someone's** 👋" />
679
+
<DiscordMarkdown mode={"DARK"} text="Welcome @mwlica to **Someone's** 👋" />
680
680
<Image
681
681
alt="example welcome card"
682
682
src={WelcomePic}
···
795
795
bot: false
796
796
}}
797
797
>
798
-
<Highlight mode={"DARK"} text="wm - howto" />
798
+
<DiscordMarkdown mode={"DARK"} text="wm - howto" />
799
799
</DiscordMessage>
800
800
801
801
<DiscordMessage
···
810
810
mode={"DARK"}
811
811
color={0xbc7ed4}
812
812
>
813
-
<Highlight mode={"DARK"} text="To create a custom command, go to [your server's dashboard](/dashboard?to=custom-commands), click on `Create`, fill in the response **content**, **embed title**, **embed description**, **embed color**, **embed images**, command **permissions** and more. When you're done you can start using the command 🎉" />
813
+
<DiscordMarkdown mode={"DARK"} text="To create a custom command, go to [your server's dashboard](/dashboard?to=custom-commands), click on `Create`, fill in the response **content**, **embed title**, **embed description**, **embed color**, **embed images**, command **permissions** and more. When you're done you can start using the command 🎉" />
814
814
</DiscordMessageEmbed>
815
815
</DiscordMessage>
816
816
</div>
+2
-2
app/dashboard/[guildId]/starboard/page.tsx
+2
-2
app/dashboard/[guildId]/starboard/page.tsx
···
8
8
import { useQuery } from "react-query";
9
9
10
10
import { guildStore } from "@/common/guilds";
11
-
import Highlight from "@/components/discord/markdown";
11
+
import { DiscordMarkdown } from "@/components/discord/markdown";
12
12
import DiscordMessage from "@/components/discord/message";
13
13
import DiscordMessageEmbed from "@/components/discord/message-embed";
14
14
import MultiSelectMenu from "@/components/inputs/multi-select-menu";
···
308
308
bot: true
309
309
}}
310
310
>
311
-
<Highlight
311
+
<DiscordMarkdown
312
312
mode={"DARK"}
313
313
text={""}
314
314
/>
+8
-7
app/dashboard/[guildId]/tts.component.tsx
+8
-7
app/dashboard/[guildId]/tts.component.tsx
···
1
+
import { Accordion, AccordionItem } from "@nextui-org/react";
2
+
import Image from "next/image";
3
+
import Link from "next/link";
4
+
import { useParams } from "next/navigation";
5
+
import { useCookies } from "next-client-cookies";
6
+
1
7
import { guildStore } from "@/common/guilds";
2
8
import NumberInput from "@/components/inputs/number-input";
3
9
import SelectMenu from "@/components/inputs/select-menu";
4
10
import Switch from "@/components/inputs/switch";
5
-
import { Accordion, AccordionItem } from "@nextui-org/react";
6
-
import { useCookies } from "next-client-cookies";
7
-
import Image from "next/image";
8
-
import Link from "next/link";
9
-
import { useParams } from "next/navigation";
10
11
11
12
export function TTSSettings() {
12
13
const guild = guildStore((g) => g);
···
63
64
64
65
<Faq />
65
66
</div>
66
-
)
67
+
);
67
68
}
68
69
69
70
function Faq() {
···
111
112
</Link>
112
113
</AccordionItem>
113
114
</Accordion>
114
-
)
115
+
);
115
116
}
+5
-5
app/profile/spotify/page.tsx
+5
-5
app/profile/spotify/page.tsx
···
6
6
7
7
import { userStore } from "@/common/user";
8
8
import Box from "@/components/box";
9
-
import Highlight from "@/components/discord/markdown";
9
+
import { DiscordMarkdown } from "@/components/discord/markdown";
10
10
import DiscordMessage from "@/components/discord/message";
11
11
import { HomeButton, ScreenMessage, SupportButton } from "@/components/screen-message";
12
12
import { cacheOptions, getData } from "@/lib/api";
···
101
101
}}
102
102
>
103
103
104
-
<Highlight mode={"DARK"} text={`wm play [https://open.spotify.com/track/${data.playing?.id || "4cOdK2wGLETKBW3PvgPWqT"}](#)`} />
104
+
<DiscordMarkdown mode={"DARK"} text={`wm play [https://open.spotify.com/track/${data.playing?.id || "4cOdK2wGLETKBW3PvgPWqT"}](#)`} />
105
105
106
106
</DiscordMessage>
107
107
<DiscordMessage
···
115
115
116
116
<div className="flex items-center gap-1">
117
117
<Image src="https://cdn.discordapp.com/emojis/845043307351900183.gif?size=44&quality=lossless" height={18} width={18} alt="" />
118
-
<Highlight mode={"DARK"} text={`@${user.username} now playing [${data.playing?.name || "Never Gonna Give You Up"}](#) for **${data.playing?.duration || "3 minutes 33 seconds"}**`} />
118
+
<DiscordMarkdown mode={"DARK"} text={`@${user.username} now playing [${data.playing?.name || "Never Gonna Give You Up"}](#) for **${data.playing?.duration || "3 minutes 33 seconds"}**`} />
119
119
</div>
120
120
121
121
<div className="flex flex-row gap-1.5 h-8 mt-3">
···
141
141
}}
142
142
>
143
143
144
-
<Highlight mode={"DARK"} text="wm" />
144
+
<DiscordMarkdown mode={"DARK"} text="wm" />
145
145
146
146
</DiscordMessage>
147
147
<DiscordMessage
···
155
155
156
156
<div className="flex items-center gap-1">
157
157
<Image src="https://cdn.discordapp.com/emojis/845043307351900183.gif?size=44&quality=lossless" height={18} width={18} alt="" />
158
-
<Highlight mode={"DARK"} text={`@${user.username} is playing [${data.playing?.name || "Never Gonna Give You Up"}](#) by ${data.playing?.artists || "[Rick Astley]()"}`} />
158
+
<DiscordMarkdown mode={"DARK"} text={`@${user.username} is playing [${data.playing?.name || "Never Gonna Give You Up"}](#) by ${data.playing?.artists || "[Rick Astley]()"}`} />
159
159
</div>
160
160
161
161
<div className="flex gap-1.5 h-8 mt-3">
+39
components/discord/markdown.css
+39
components/discord/markdown.css
···
1
+
.discord-md a {
2
+
@apply text-blurple hover:underline
3
+
}
4
+
5
+
.discord-md code {
6
+
@apply bg-neutral-900 border-[1px] border-neutral-600 p-1 text-xs rounded
7
+
}
8
+
9
+
.discord-md-light code {
10
+
@apply !bg-neutral-300 !border-neutral-400
11
+
}
12
+
13
+
.discord-md .d-mention {
14
+
@apply bg-blurple/30 hover:bg-blurple/50 py-0.5 px-1 rounded-md dark:text-neutral-100 text-neutral-900 font-light duration-200 cursor-pointer
15
+
}
16
+
17
+
.discord-md .d-emoji {
18
+
@apply size-5 inline
19
+
}
20
+
21
+
.discord-md .d-spoiler {
22
+
@apply bg-neutral-500/75 px-0.5 text-sm rounded
23
+
}
24
+
25
+
.discord-md h1 {
26
+
@apply text-3xl font-semibold text-white
27
+
}
28
+
29
+
.discord-md h2 {
30
+
@apply text-2xl font-semibold text-white
31
+
}
32
+
33
+
.discord-md h3 {
34
+
@apply text-xl font-semibold text-white
35
+
}
36
+
37
+
.discord-md strong {
38
+
@apply font-semibold
39
+
}
+16
-112
components/discord/markdown.tsx
+16
-112
components/discord/markdown.tsx
···
1
-
"use client";
1
+
import "./markdown.css";
2
2
3
-
import React from "react";
4
-
import { renderToString } from "react-dom/server";
5
-
import ReactMarkdown from "react-markdown";
6
-
import rehypeRaw from "rehype-raw";
3
+
import md from "@odiffey/discord-markdown";
7
4
8
5
import cn from "@/utils/cn";
9
6
10
-
import Channel from "../markdown/channel";
11
-
import Emoji from "../markdown/emoji";
12
-
import User from "../markdown/user";
13
-
14
-
interface Props {
15
-
text: string;
16
-
mode: "DARK" | "LIGHT";
17
-
discord?: boolean;
18
-
}
19
-
20
-
export default function Highlight({
7
+
export function DiscordMarkdown({
21
8
text,
22
9
mode,
23
-
discord = true
24
-
}: Props) {
25
-
26
-
function parseDiscordMarkdown(content: string) {
27
-
return content
28
-
.replace(/<(?!(?:[@#]|a:|:))/g, "<")
29
-
.replaceAll("\\n", "\n\n")
30
-
.replace(/__(.*?)__/g, "<u>$1</u>")
31
-
.replace(/\{(\w*?)\.(\w*?)\}|{ping}/g, (match) => {
32
-
return renderToString(
33
-
<span
34
-
className={cn(
35
-
mode === "DARK" ? "bg-wamellow text-neutral-200" : "bg-wamellow-100 text-neutral-800",
36
-
"border-1 border-violet-400 px-[3px] rounded-md font-light"
37
-
)}
38
-
>
39
-
{match.slice(1, -1)}
40
-
</span>
41
-
);
42
-
})
43
-
.replace(/<a?:\w{2,32}:\d{15,21}>/g, (match) => {
44
-
const emojiId = match.match(/\d{15,21}/)?.[0]!;
45
-
46
-
return renderToString(<Emoji emojiId={emojiId} />);
47
-
})
48
-
.replace(/<(@[!&]?)\d{15,21}>/g, (match) => {
49
-
return renderToString(<User username={match.includes("&") ? "some-role" : "some-user"} />);
50
-
})
51
-
.replace(/<(#!?)\d{15,21}>/g, () => {
52
-
return renderToString(<Channel name="some-channel" />);
53
-
});
54
-
}
55
-
56
-
if (!discord) return (
57
-
<ReactMarkdown
58
-
// @ts-expect-error they broke types
59
-
rehypePlugins={[rehypeRaw]}
60
-
allowedElements={["span", "p"]}
61
-
>
62
-
{parseDiscordMarkdown(text
63
-
.replaceAll("*", "\\*")
64
-
.replaceAll("_", "\\_")
65
-
.replaceAll("~", "\\~")
66
-
.replaceAll("`", "\\`")
67
-
)}
68
-
</ReactMarkdown>
69
-
);
10
+
embed = true
11
+
}: {
12
+
text: string;
13
+
mode: "DARK" | "LIGHT";
14
+
embed?: boolean;
15
+
}) {
16
+
const sanitizedHtml = text
17
+
.replaceAll("\\n", "\n")
18
+
.trim();
70
19
71
20
return (
72
-
<ReactMarkdown
73
-
className="break-words"
74
-
// @ts-expect-error inline does exist
75
-
rehypePlugins={[rehypeRaw]}
76
-
components={{
77
-
h1: (props) => <div className="text-3xl font-semibold" {...props} />,
78
-
h2: (props) => <div className="text-2xl font-semibold" {...props} />,
79
-
h3: (props) => <div className="text-xl font-semibold" {...props} />,
80
-
strong: (props) => <span className="font-semibold" {...props} />,
81
-
i: (props) => <span className="italic" {...props} />,
82
-
a: (props) => <a className="text-blue-600 hover:underline underline-blue-500" {...props} />,
83
-
del: (props) => <span className="line-through" {...props} />,
84
-
ins: (props) => <span className="underline" {...props} />,
85
-
li: (props) => (
86
-
<div>
87
-
<span className="mr-1">•</span>
88
-
<span {...props} />
89
-
</div>
90
-
),
91
-
code: ({ inline, children, ...props }) => {
92
-
if (!inline) return (
93
-
<div
94
-
className={cn(
95
-
mode === "DARK" ? "bg-neutral-900" : "bg-neutral-200",
96
-
"px-4 py-3 text-sm rounded-md min-w-full max-w-full my-2 break-all"
97
-
)}
98
-
>
99
-
{children}
100
-
</div>
101
-
);
102
-
103
-
return (
104
-
<code
105
-
{...props}
106
-
className={cn(
107
-
mode === "DARK" ? "bg-neutral-900 text-neutral-100" : "bg-neutral-200 text-neutral-900",
108
-
"p-1 text-sm rounded"
109
-
)}
110
-
>
111
-
{children}
112
-
</code>
113
-
);
114
-
},
115
-
p: (props) => <p className="mb-4" {...props} />
116
-
}}
117
-
>
118
-
{parseDiscordMarkdown(text)}
119
-
</ReactMarkdown>
21
+
<div
22
+
className={cn("discord-md", mode === "LIGHT" && "discord-md-light")}
23
+
dangerouslySetInnerHTML={{ __html: md.toHTML(sanitizedHtml, { embed }) }}
24
+
/>
120
25
);
121
-
122
26
}
+20
-8
components/discord/message-embed.tsx
+20
-8
components/discord/message-embed.tsx
···
2
2
3
3
import cn from "@/utils/cn";
4
4
5
-
import Highlight from "./markdown";
5
+
import { DiscordMarkdown } from "./markdown";
6
6
7
7
interface Props {
8
8
children: React.ReactNode;
···
62
62
>
63
63
{/* eslint-disable-next-line @next/next/no-img-element */}
64
64
{author.icon_url && <img src={author.icon_url} alt="" className="rounded-full h-6 w-6" />}
65
-
<Highlight
65
+
<DiscordMarkdown
66
66
mode={mode}
67
67
text={author.text}
68
-
discord={false}
68
+
embed={true}
69
69
/>
70
70
</div>
71
71
}
···
76
76
"font-semibold text-lg mb-2"
77
77
)}
78
78
>
79
-
<Highlight
79
+
<DiscordMarkdown
80
80
mode={mode}
81
81
text={title}
82
-
discord={false}
82
+
embed={true}
83
83
/>
84
84
</div>
85
85
}
···
89
89
</div>
90
90
91
91
{/* eslint-disable-next-line @next/next/no-img-element */}
92
-
{thumbnail && <img src={thumbnail} alt="" className="ml-auto h-20 w-20 rounded-md" />}
92
+
{thumbnail && <img src={replaceTemplatesToUrl(thumbnail)} alt="" className="ml-auto h-20 w-20 rounded-md" />}
93
93
</div>
94
94
95
95
{/* eslint-disable-next-line @next/next/no-img-element */}
96
-
{image && <img src={image} alt="" className="ml-auto rounded-md h-full w-full mt-4" />}
96
+
{image && <img src={replaceTemplatesToUrl(image)} alt="" className="ml-auto rounded-md h-full w-full mt-4" />}
97
97
98
98
{footer?.text &&
99
99
<div className="flex gap-1 items-center mt-3">
100
100
{/* eslint-disable-next-line @next/next/no-img-element */}
101
101
{footer.icon_url && <img src={footer.icon_url} alt="" className="rounded-full h-5 w-5" />}
102
102
<span className="text-xs">
103
-
<Highlight mode={mode} text={footer.text} discord={false} />
103
+
<DiscordMarkdown
104
+
mode={mode}
105
+
text={footer.text}
106
+
embed={true}
107
+
/>
104
108
</span>
105
109
</div>
106
110
}
107
111
108
112
</div>
109
113
);
114
+
}
115
+
116
+
function replaceTemplatesToUrl(input: string) {
117
+
if (/^{(user|guild|creator)\.(icon|avatar)}$/.test(input)) return "https://cdn.discordapp.com/embed/avatars/0.png";
118
+
if (/^{video\.thumbnail}/.test(input)) return "/_next/image?url=/notifications-thumbnail-placeholder.webp&w=384&q=75";
119
+
120
+
if (!input.startsWith("http")) return;
121
+
return input;
110
122
}
+3
-3
components/embed-creator.tsx
+3
-3
components/embed-creator.tsx
···
7
7
import { GuildEmbed } from "@/typings";
8
8
import cn from "@/utils/cn";
9
9
10
-
import Highlight from "./discord/markdown";
10
+
import { DiscordMarkdown } from "./discord/markdown";
11
11
import DiscordMessage from "./discord/message";
12
12
import DiscordMessageEmbed from "./discord/message-embed";
13
13
import DumbColorInput from "./inputs/dumb-color-input";
···
238
238
bot: true
239
239
}}
240
240
>
241
-
<Highlight
241
+
<DiscordMarkdown
242
242
mode={mode}
243
243
text={content || ""}
244
244
/>
···
251
251
image={JSON.parse(embed).image}
252
252
footer={JSON.parse(embedfooter)}
253
253
>
254
-
{JSON.parse(embed).description && <Highlight mode={mode} text={JSON.parse(embed).description} />}
254
+
{JSON.parse(embed).description && <DiscordMarkdown mode={mode} text={JSON.parse(embed).description} />}
255
255
{showMessageAttachmentComponentInEmbed && messageAttachmentComponent}
256
256
</DiscordMessageEmbed>
257
257
+4
-3
components/markdown/index.tsx
+4
-3
components/markdown/index.tsx
···
40
40
return content
41
41
.replace(/__(.*?)__/g, "<u>$1</u>")
42
42
.replace(/<a?:\w{2,32}:\d{15,21}>/g, (match) => {
43
-
const emojiId = match.match(/\d{15,21}/)?.[0]!;
43
+
const emojiId = match.match(/\d{15,21}/)?.[0] as string;
44
44
45
45
return renderToString(<Emoji emojiId={emojiId} />);
46
46
})
···
57
57
return renderToString(<Channel name="some-channel" />);
58
58
})
59
59
.replace(/<t:\d{1,10}:[Rf]?>/g, (match) => {
60
-
const timestamp = match.match(/\d{1,10}/)?.[0]!;
60
+
const timestamp = match.match(/\d{1,10}/)?.[0] as string;
61
61
const format = match.match(/:\w*?>/)?.[0] || "f";
62
62
63
63
return renderToString(
···
182
182
},
183
183
184
184
ol: ({ ordered, ...props }) => <ol className="list-decimal list-inside space-y-1 marker:text-neutral-300/40 my-1" {...props} />,
185
-
ul: ({ ordered, ...props }) => <ul className="list-disc list-inside space-y-1 marker:text-neutral-300/40 my-1" {...props} />
185
+
ul: ({ ordered, ...props }) => <ul className="list-disc list-inside space-y-1 marker:text-neutral-300/40 my-1" {...props} />,
186
+
p: (props) => <span {...props} />
186
187
187
188
}}
188
189
>
+1
package.json
+1
package.json
+37
pnpm-lock.yaml
+37
pnpm-lock.yaml
···
17
17
'@nextui-org/react':
18
18
specifier: ^2.4.6
19
19
version: 2.4.6(@types/react@18.3.3)(framer-motion@11.3.20(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.7)
20
+
'@odiffey/discord-markdown':
21
+
specifier: ^3.1.2
22
+
version: 3.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
20
23
autoprefixer:
21
24
specifier: ^10.4.19
22
25
version: 10.4.19(postcss@8.4.40)
···
336
339
337
340
'@jridgewell/trace-mapping@0.3.25':
338
341
resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
342
+
343
+
'@khanacademy/perseus-core@1.5.0':
344
+
resolution: {integrity: sha512-QR9tGBr8nAUFuARSbzgzL6ZkyjDur0Cz9tgQREjC0L+Sug5aj0DHuK86lhosZAbtgAzitX3KVRAsOMbKqU2fYg==}
345
+
346
+
'@khanacademy/simple-markdown@0.12.1':
347
+
resolution: {integrity: sha512-GnrK+mxULyO58pWjPQSU1bVUd892teNIzf7stdBB9mucFDXk2TiplPD9BJDUZ10uGfliyDVKlvwV3BIjHPhL5g==}
348
+
peerDependencies:
349
+
react: 16.14.0
350
+
react-dom: 16.14.0
339
351
340
352
'@next/env@14.2.5':
341
353
resolution: {integrity: sha512-/zZGkrTOsraVfYjGP8uM0p6r0BDT6xWpkjdVbcz66PJVSpwXX3yNiRycxAuDfBKGWBrZBXRuK/YVlkNgxHGwmA==}
···
894
906
895
907
'@octokit/types@13.5.0':
896
908
resolution: {integrity: sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==}
909
+
910
+
'@odiffey/discord-markdown@3.1.2':
911
+
resolution: {integrity: sha512-V+lVkoMhiNVEyLJ4ezmvigHU91SwiACc13jcBDosfkUbcLK82YXG+L6Dkzuaw7EY34Gh4HGO6+n8ZtwEF1WZJQ==}
897
912
898
913
'@pkgjs/parseargs@0.11.0':
899
914
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
···
2480
2495
2481
2496
hastscript@8.0.0:
2482
2497
resolution: {integrity: sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==}
2498
+
2499
+
highlight.js@11.10.0:
2500
+
resolution: {integrity: sha512-SYVnVFswQER+zu1laSya563s+F8VDGt7o35d4utbamowvUNLLMovFqwCLSocpZTz3MgaSRA1IbqRWZv97dtErQ==}
2501
+
engines: {node: '>=12.0.0'}
2483
2502
2484
2503
html-void-elements@3.0.0:
2485
2504
resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
···
4090
4109
'@jridgewell/resolve-uri': 3.1.2
4091
4110
'@jridgewell/sourcemap-codec': 1.5.0
4092
4111
4112
+
'@khanacademy/perseus-core@1.5.0': {}
4113
+
4114
+
'@khanacademy/simple-markdown@0.12.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
4115
+
dependencies:
4116
+
'@khanacademy/perseus-core': 1.5.0
4117
+
react: 18.3.1
4118
+
react-dom: 18.3.1(react@18.3.1)
4119
+
4093
4120
'@next/env@14.2.5': {}
4094
4121
4095
4122
'@next/eslint-plugin-next@14.2.5':
···
5101
5128
'@octokit/types@13.5.0':
5102
5129
dependencies:
5103
5130
'@octokit/openapi-types': 22.2.0
5131
+
5132
+
'@odiffey/discord-markdown@3.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
5133
+
dependencies:
5134
+
'@khanacademy/simple-markdown': 0.12.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
5135
+
highlight.js: 11.10.0
5136
+
transitivePeerDependencies:
5137
+
- react
5138
+
- react-dom
5104
5139
5105
5140
'@pkgjs/parseargs@0.11.0':
5106
5141
optional: true
···
7314
7349
hast-util-parse-selector: 4.0.0
7315
7350
property-information: 6.5.0
7316
7351
space-separated-tokens: 2.0.2
7352
+
7353
+
highlight.js@11.10.0: {}
7317
7354
7318
7355
html-void-elements@3.0.0: {}
7319
7356
public/notifications-thumbnail-placeholder.webp
public/notifications-thumbnail-placeholder.webp
This is a binary file and will not be displayed.