2021-04-14 23:56:29 +00:00
|
|
|
|
import styles from './text.module.css'
|
2021-06-27 22:28:30 +00:00
|
|
|
|
import ReactMarkdown from 'react-markdown'
|
|
|
|
|
import gfm from 'remark-gfm'
|
|
|
|
|
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
|
|
|
|
|
/* Use `…/dist/cjs/…` if you’re not in ESM! */
|
|
|
|
|
import { atomDark } from 'react-syntax-highlighter/dist/cjs/styles/prism'
|
2021-07-15 19:56:23 +00:00
|
|
|
|
import mention from '../lib/remark-mention'
|
2022-03-03 22:18:38 +00:00
|
|
|
|
import sub from '../lib/remark-sub'
|
2022-02-03 22:01:42 +00:00
|
|
|
|
import remarkDirective from 'remark-directive'
|
|
|
|
|
import { visit } from 'unist-util-visit'
|
2022-02-10 22:41:13 +00:00
|
|
|
|
import reactStringReplace from 'react-string-replace'
|
2022-02-03 22:01:42 +00:00
|
|
|
|
|
|
|
|
|
function myRemarkPlugin () {
|
|
|
|
|
return (tree) => {
|
|
|
|
|
visit(tree, (node) => {
|
|
|
|
|
if (
|
|
|
|
|
node.type === 'textDirective' ||
|
|
|
|
|
node.type === 'leafDirective'
|
|
|
|
|
) {
|
|
|
|
|
if (node.name !== 'high') return
|
|
|
|
|
|
|
|
|
|
const data = node.data || (node.data = {})
|
|
|
|
|
data.hName = 'mark'
|
|
|
|
|
data.hProperties = {}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-04-14 23:56:29 +00:00
|
|
|
|
|
2021-09-02 18:11:27 +00:00
|
|
|
|
export default function Text ({ nofollow, children }) {
|
2022-02-10 22:41:13 +00:00
|
|
|
|
// all the reactStringReplace calls are to facilitate search highlighting
|
2021-04-14 23:56:29 +00:00
|
|
|
|
return (
|
2021-06-27 22:28:30 +00:00
|
|
|
|
<div className={styles.text}>
|
|
|
|
|
<ReactMarkdown
|
|
|
|
|
components={{
|
|
|
|
|
h1: 'h6',
|
|
|
|
|
h2: 'h6',
|
|
|
|
|
h3: 'h6',
|
|
|
|
|
h4: 'h6',
|
|
|
|
|
h5: 'h6',
|
|
|
|
|
h6: 'h6',
|
|
|
|
|
table: ({ node, ...props }) =>
|
|
|
|
|
<div className='table-responsive'>
|
|
|
|
|
<table className='table table-bordered table-sm' {...props} />
|
|
|
|
|
</div>,
|
|
|
|
|
code ({ node, inline, className, children, ...props }) {
|
|
|
|
|
const match = /language-(\w+)/.exec(className || '')
|
|
|
|
|
return !inline
|
|
|
|
|
? (
|
|
|
|
|
<SyntaxHighlighter showLineNumbers style={atomDark} language={match && match[1]} PreTag='div' {...props}>
|
2022-02-10 22:41:13 +00:00
|
|
|
|
{reactStringReplace(String(children).replace(/\n$/, ''), /:high\[([^\]]+)\]/g, (match, i) => {
|
|
|
|
|
return match
|
|
|
|
|
}).join('')}
|
2021-06-27 22:28:30 +00:00
|
|
|
|
</SyntaxHighlighter>
|
|
|
|
|
)
|
|
|
|
|
: (
|
|
|
|
|
<code className={className} style={atomDark} {...props}>
|
2022-02-10 22:41:13 +00:00
|
|
|
|
{reactStringReplace(String(children), /:high\[([^\]]+)\]/g, (match, i) => {
|
|
|
|
|
return <mark key={`mark-${match}`}>{match}</mark>
|
|
|
|
|
})}
|
2021-06-27 22:28:30 +00:00
|
|
|
|
</code>
|
|
|
|
|
)
|
2021-09-02 18:11:27 +00:00
|
|
|
|
},
|
2022-02-10 22:41:13 +00:00
|
|
|
|
a: ({ node, href, children, ...props }) => {
|
2022-05-18 18:30:36 +00:00
|
|
|
|
children = children?.map(e => typeof e === 'string'
|
2022-02-10 22:41:13 +00:00
|
|
|
|
? reactStringReplace(e, /:high\[([^\]]+)\]/g, (match, i) => {
|
|
|
|
|
return <mark key={`mark-${match}-${i}`}>{match}</mark>
|
|
|
|
|
})
|
|
|
|
|
: e)
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
/* eslint-disable-next-line */
|
|
|
|
|
<a
|
|
|
|
|
target='_blank' rel={nofollow ? 'nofollow' : 'noreferrer'}
|
|
|
|
|
href={reactStringReplace(href, /:high%5B([^%5D]+)%5D/g, (match, i) => {
|
|
|
|
|
return match
|
|
|
|
|
}).join('')} {...props}
|
|
|
|
|
>
|
|
|
|
|
{children}
|
|
|
|
|
</a>
|
|
|
|
|
)
|
|
|
|
|
}
|
2021-06-27 22:28:30 +00:00
|
|
|
|
}}
|
2022-03-03 22:18:38 +00:00
|
|
|
|
remarkPlugins={[gfm, mention, sub, remarkDirective, myRemarkPlugin]}
|
2021-06-27 22:28:30 +00:00
|
|
|
|
>
|
|
|
|
|
{children}
|
|
|
|
|
</ReactMarkdown>
|
|
|
|
|
</div>
|
2021-04-14 23:56:29 +00:00
|
|
|
|
)
|
|
|
|
|
}
|