Skip to content

Commit

Permalink
part. support gfm alerts
Browse files Browse the repository at this point in the history
  • Loading branch information
DerGoogler committed Jul 2, 2024
1 parent b104234 commit ba1e38c
Showing 1 changed file with 123 additions and 2 deletions.
125 changes: 123 additions & 2 deletions Website/src/components/Markdown/index.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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) => (
<Alert sx={sx} severity="info">
<AlertTitle>Note</AlertTitle>
{content}
</Alert>
),
},
"[!TIP]": {
title: "Tip",
render: (content: string) => (
<Alert sx={sx} severity="success">
<AlertTitle>Tip</AlertTitle>
{content}
</Alert>
),
},
"[!IMPORTANT]": {
title: "Important",
render: (content: string) => (
<Alert sx={sx} severity="info">
<AlertTitle>Important</AlertTitle>
{content}
</Alert>
),
},
"[!WARNING]": {
title: "Warning",
render: (content: string) => (
<Alert sx={sx} severity="warning">
<AlertTitle>Warning</AlertTitle>
{content}
</Alert>
),
},
"[!CAUTION]": {
title: "Caution",
render: (content: string) => (
<Alert sx={sx} severity="error">
<AlertTitle>Caution</AlertTitle>
{content}
</Alert>
),
},
};

type Props = {
fetch?: string;
children?: string;
Expand Down Expand Up @@ -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 `<br>` 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}
/>
Expand Down

0 comments on commit ba1e38c

Please sign in to comment.