mon-entreprise/publicodes-react/source/Markdown.tsx

79 lines
1.6 KiB
TypeScript
Raw Normal View History

import React, { useContext } from 'react'
import emoji from 'react-easy-emoji'
import ReactMarkdown, { ReactMarkdownProps } from 'react-markdown'
import { HashLink as Link } from 'react-router-hash-link'
import { EngineContext } from './contexts'
import { RuleLinkWithContext } from './RuleLink'
import PublicodesBlock from './PublicodesBlock'
export function LinkRenderer({
href,
children,
...otherProps
}: Omit<React.ComponentProps<'a'>, 'ref'>) {
const engine = useContext(EngineContext)
if (!engine) {
throw new Error('an engine should be provided in context')
}
const rules = engine.getParsedRules()
if (href && rules[href]) {
return (
<RuleLinkWithContext dottedName={href} {...otherProps}>
{children}
</RuleLinkWithContext>
)
}
if (href && !href.startsWith('http')) {
return (
<Link to={href} {...otherProps}>
{children}
</Link>
)
}
return (
<a target="_blank" href={href} {...otherProps}>
{children}
</a>
)
}
const CodeBlock = ({ value, language }: { value: string; language: string }) =>
language === 'yaml' ? (
<PublicodesBlock source={value} />
) : (
<pre>
<code>{value}</code>
</pre>
)
const TextRenderer = ({ children }: { children: string }) => (
<>{emoji(children)}</>
)
type MarkdownProps = ReactMarkdownProps & {
source: string | undefined
className?: string
}
export const Markdown = ({
source,
className = '',
renderers = {},
...otherProps
}: MarkdownProps) => (
<ReactMarkdown
source={source}
className={`markdown ${className}`}
renderers={{
link: LinkRenderer,
text: TextRenderer,
code: CodeBlock,
...renderers,
}}
{...otherProps}
/>
)