79 lines
1.6 KiB
TypeScript
79 lines
1.6 KiB
TypeScript
|
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}
|
||
|
/>
|
||
|
)
|