import React, { useContext, useMemo, useState } from 'react' import { MDXProvider } from '@mdx-js/react' import { Link } from 'react-router-dom' import type { MDXComponents } from 'mdx/types' import CodeBlock from './CodeBlock' import { themePropsCtx } from '../../ctx' import { Demo } from '../Demo' import { TsInfo } from '../TsInfo' import { FileText } from '../FileText' import AnchorLink from '../../components/AnchorLink' /** * use isInsidePreContext to let the `code` Component * know that it is rendered from triple backquote blocks: * ```language * code content * ``` * syntax, instead of single backquote: `code content` */ const isInsidePreContext = React.createContext(false) const components: MDXComponents = { pre: (props: any) => { // `pre` tag will be rendered by the nested `code` Component return ( {props.children} ) }, code: withMdClassName((props: any) => { const isInsidePre = useContext(isInsidePreContext) if (isInsidePre) { // this is rendered from triple backquote blocks return } // this is rendered from single backquote return }), CodeBlock, Demo, TsInfo, FileText: withMdClassName(FileText), a: (props: React.HTMLProps) => { const { href, ...rest } = props if (href?.startsWith('/')) { return } if (href?.startsWith('#')) { return ( { AnchorLink.scrollToAnchor(href.substring(1)) }} /> ) } return }, table: withMdClassName('table'), p: withMdClassName('p'), hr: withMdClassName('hr'), ul: withMdClassName('ul'), ol: withMdClassName('ol'), blockquote: withMdClassName('blockquote'), section: withMdClassName('section'), } const MDX: React.FC> = ({ children }) => { const themeProps = useContext(themePropsCtx) const mdxComponents = useMemo(() => { return { ...components, h1: heading(1), h2: heading(2), h3: heading(3), h4: heading(4), h5: heading(5), h6: heading(6), } function heading(level: number) { const Tag = 'h' + level return withMdClassName(Heading) function Heading( props: React.DetailedHTMLProps< React.HTMLAttributes, HTMLDivElement > ) { const { id } = props if (id && typeof id === 'string') { return ( {props.children} ) } return } } }, [themeProps.loadState.routePath]) return (
{children}
) } export default MDX /** * We only need to add ".markdown-el" className to top-level block elements under the markdown root. * our github-markdown-light.css will add markdown style to markdown-el and all its descendants * * Ref: "FlowContent" are the top-level block elements in mdast * https://github.com/syntax-tree/mdast#flowcontent */ export function withMdClassName(Component: React.FC | string) { return function (props: any) { const { className } = props const newClassName = className ? `${className} markdown-el` : 'markdown-el' return } }