diff --git a/src/components/EcosystemItem/index.tsx b/src/components/EcosystemItem/index.tsx index ff2e9738..7606a437 100644 --- a/src/components/EcosystemItem/index.tsx +++ b/src/components/EcosystemItem/index.tsx @@ -1,6 +1,7 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import type { ReactNode } from 'react'; import Layout from '@theme/Layout'; +import Admonition from '@theme/Admonition'; import Link from '@docusaurus/Link'; import { useLocation } from '@docusaurus/router'; import ReactMarkdown from 'react-markdown'; @@ -354,8 +355,57 @@ function resolveUrl(src: string, rawBaseUrl: string): string { } } +// GitHub alert markers (> [!WARNING]) mapped to Docusaurus admonition types, so a +// README renders the same callouts here as it does on GitHub. +const GITHUB_ALERT_TYPES: Record = { + NOTE: 'note', + TIP: 'tip', + IMPORTANT: 'info', + WARNING: 'warning', + CAUTION: 'danger', +}; + +// remark-gfm does not implement GitHub alerts, so they arrive as plain blockquotes +// with a literal "[!WARNING]" prefix. This rewrites those into an `admonition` node +// that createMdComponents renders with the theme's own Admonition component. +function remarkGithubAlerts() { + return (tree: any) => { + const walk = (node: any) => { + if (node.type === 'blockquote') { + const paragraph = node.children?.[0]; + const text = paragraph?.type === 'paragraph' ? paragraph.children?.[0] : undefined; + const match = + text?.type === 'text' + ? /^\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\][ \t]*\r?\n?/.exec(text.value) + : null; + if (match) { + text.value = text.value.slice(match[0].length); + if (!text.value) { + // The marker sat on its own; drop it, and the paragraph too if that + // emptied it, which is the case for the multi-paragraph alert form. + paragraph.children.shift(); + if (paragraph.children.length === 0) { + node.children.shift(); + } + } + node.data = { + ...node.data, + hName: 'admonition', + hProperties: { type: GITHUB_ALERT_TYPES[match[1]] }, + }; + } + } + node.children?.forEach(walk); + }; + walk(tree); + }; +} + function createMdComponents(rawBaseUrl: string) { return { + admonition({ type, children }: { type?: string; children?: ReactNode }) { + return {children}; + }, pre({ children }: { children?: ReactNode }) { return <>{children}; }, @@ -751,7 +801,7 @@ export default function EcosystemItem(): ReactNode { )) ) : ( {section.body} @@ -790,7 +840,10 @@ export default function EcosystemItem(): ReactNode { {parsed.intro && (
- + {parsed.intro}
@@ -898,7 +951,7 @@ export default function EcosystemItem(): ReactNode { )}
{activeSection.content}