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
}
}