From ba1e38c9fa39c717601f59ef0abe12d816646ef6 Mon Sep 17 00:00:00 2001
From: Der_Googler <54764558+DerGoogler@users.noreply.github.com>
Date: Tue, 2 Jul 2024 16:08:30 +0200
Subject: [PATCH] part. support gfm alerts
---
Website/src/components/Markdown/index.tsx | 125 +++++++++++++++++++++-
1 file changed, 123 insertions(+), 2 deletions(-)
diff --git a/Website/src/components/Markdown/index.tsx b/Website/src/components/Markdown/index.tsx
index 899ed44b..917ce81e 100644
--- a/Website/src/components/Markdown/index.tsx
+++ b/Website/src/components/Markdown/index.tsx
@@ -1,7 +1,7 @@
-import Markdown, { MarkdownToJSX, compiler } from "markdown-to-jsx";
+import Markdown, { MarkdownToJSX, RuleType, compiler } from "markdown-to-jsx";
import { Video } from "@Components/dapi/Video";
import React from "react";
-import { Alert, Divider, Paper, Stack, SxProps, Theme } from "@mui/material";
+import { Alert, AlertTitle, Divider, Paper, Stack, SxProps, Theme } from "@mui/material";
import styled from "@emotion/styled";
import hljs from "highlight.js";
import { Image } from "@Components/dapi/Image";
@@ -12,6 +12,61 @@ import { Code } from "@Components/dapi/Code";
import { Pre } from "@Components/dapi/Pre";
import { Anchor } from "@Components/dapi/Anchor";
+export type AlertType = {
+ title: string;
+ render: (content: React.ReactNode) => JSX.Element;
+};
+const sx = {
+ mb: 2,
+};
+export const admonitionTypes = {
+ "[!NOTE]": {
+ title: "Note",
+ render: (content: string) => (
+
+ Note
+ {content}
+
+ ),
+ },
+ "[!TIP]": {
+ title: "Tip",
+ render: (content: string) => (
+
+ Tip
+ {content}
+
+ ),
+ },
+ "[!IMPORTANT]": {
+ title: "Important",
+ render: (content: string) => (
+
+ Important
+ {content}
+
+ ),
+ },
+ "[!WARNING]": {
+ title: "Warning",
+ render: (content: string) => (
+
+ Warning
+ {content}
+
+ ),
+ },
+ "[!CAUTION]": {
+ title: "Caution",
+ render: (content: string) => (
+
+ Caution
+ {content}
+
+ ),
+ },
+};
+
type Props = {
fetch?: string;
children?: string;
@@ -117,6 +172,72 @@ export const Markup = (props: Props) => {
return React.createElement(type, props, ...children);
}
},
+ renderRule(next, node, renderChildren, state) {
+ if (node.type != RuleType.blockQuote) return next();
+
+ const blockquote = node as MarkdownToJSX.BlockQuoteNode;
+ if (blockquote.children[0].type != RuleType.paragraph) return next();
+ const paragraph = blockquote.children[0];
+ if (paragraph.children[0].type != RuleType.text) return next();
+ let text = paragraph.children.flatMap((p: any) => p.text).join("");
+
+ console.log(text);
+
+ let title: string;
+ let admonitionType: AlertType | null = null;
+ // A link break after the title is explicitly required by GitHub
+ const titleEnd = text.indexOf("\n");
+ if (titleEnd < 0) {
+ // But if the following one is a block, the newline would be trimmed by the upstream.
+ // To start a new block, a newline is required.
+ // So we just need to addtionally check if the following one is a block.
+ // The legacy title variant is not affected since it checks an inline and does not care about the newline.
+
+ // Considering the reason why the paragraph ends here, the following one should be a children of the blockquote, which means it is always a block.
+ // So no more check is required.
+ title = text;
+ admonitionType = admonitionTypes[title];
+
+ console.log(admonitionType);
+
+ if (!admonitionType) {
+ return next();
+ }
+
+ // No addtional inlines can exist in this paragraph for the title...
+ if (paragraph.children.length > 1) {
+ // Unless it is an inline break, which can be transformed to from 2 spaces with a newline.
+ if (paragraph.children.at(1)?.type == RuleType.breakLine) {
+ // When it is, we actually have already found the line break required by GitHub.
+ // So we just strip the additional `
` element.
+ // The title element will be removed later.
+ paragraph.children.splice(1, 1);
+ } else {
+ return next();
+ }
+ }
+ // strip the title
+ paragraph.children.shift();
+ } else {
+ const textBody = text.substring(titleEnd + 1);
+ title = text.substring(0, titleEnd);
+ // Handle whitespaces after the title.
+ // Whitespace characters are defined by GFM.
+ const m = /[ \t\v\f\r]+$/.exec(title);
+ if (m) {
+ title = title.substring(0, title.length - m[0].length);
+ }
+
+ console.log(admonitionType);
+
+ admonitionType = admonitionTypes[title];
+ if (!admonitionType) return next();
+ // Update the text body to remove the title
+ text = textBody;
+ }
+
+ return admonitionType.render(text);
+ },
}}
children={text}
/>