Open History to see the last commit
1interface MarkdownAstNode {
2 type?: string;
3 value?: unknown;
4 data?: {
5 hProperties?: Record<string, unknown>;
6 };
7 children?: MarkdownAstNode[];
8}
9
10const GITHUB_ALERT_MARKER = /^\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\](?:\r?\n|$)/i;
11
12function readGithubAlert(node: MarkdownAstNode): void {
13 if (node.type !== "blockquote") return;
14 const paragraph = node.children?.[0];
15 const text = paragraph?.children?.[0];
16 if (paragraph?.type !== "paragraph" || text?.type !== "text" || typeof text.value !== "string") {
17 return;
18 }
19 const match = GITHUB_ALERT_MARKER.exec(text.value);
20 if (!match?.[1]) return;
21
22 const remainder = text.value.slice(match[0].length);
23 // An empty remainder may have next-line sibling content; preserve whether the marker ended its line.
24 const markerEndsItsLine = match[0].endsWith("\n");
25 if (remainder.length > 0) {
26 text.value = remainder;
27 } else if (markerEndsItsLine || paragraph.children?.length === 1) {
28 paragraph.children?.shift();
29 if (paragraph.children?.length === 0) {
30 node.children?.shift();
31 }
32 } else {
33 return;
34 }
35
36 node.data = {
37 ...node.data,
38 hProperties: {
39 ...node.data?.hProperties,
40 dataAlert: match[1].toLowerCase(),
41 },
42 };
43}
44
45export function remarkGithubAlerts() {
46 return (tree: MarkdownAstNode) => {
47 const visit = (node: MarkdownAstNode) => {
48 node.children?.forEach(visit);
49 readGithubAlert(node);
50 };
51 visit(tree);
52 };
53}