2023-06-21 08:47:31 +02:00
|
|
|
import React, { useMemo } from 'react';
|
2023-04-21 16:38:14 +02:00
|
|
|
import ReactMarkdown from 'react-markdown';
|
2023-06-19 15:56:18 +02:00
|
|
|
import { Link } from 'react-router-dom';
|
2023-04-27 13:10:23 +02:00
|
|
|
import rehypeSanitize, { defaultSchema } from 'rehype-sanitize';
|
2023-04-23 18:53:47 +02:00
|
|
|
import breaks from 'remark-breaks';
|
2023-04-21 16:57:08 +02:00
|
|
|
|
|
|
|
|
|
2023-06-21 08:47:31 +02:00
|
|
|
const Post = ({ content }) => {
|
|
|
|
|
const doubleNewlineContent = useMemo(() => content?.replaceAll(/\n(?!\n)/g, '\n\n'), [content]);
|
|
|
|
|
|
|
|
|
|
const customSchema = useMemo(() => ({
|
|
|
|
|
...defaultSchema,
|
|
|
|
|
tagNames: [...defaultSchema.tagNames, 'div'],
|
|
|
|
|
attributes: {
|
|
|
|
|
...defaultSchema.attributes,
|
|
|
|
|
div: ['className'],
|
|
|
|
|
},
|
|
|
|
|
}), []);
|
2023-04-27 13:10:23 +02:00
|
|
|
|
|
|
|
|
|
2023-06-21 08:47:31 +02:00
|
|
|
const blockquoteToGreentext = () => (tree) => {
|
|
|
|
|
tree.children.forEach((node) => {
|
|
|
|
|
if (node.type === 'blockquote') {
|
|
|
|
|
node.children.forEach((child) => {
|
|
|
|
|
if (child.type === 'paragraph' && child.children.length > 0) {
|
|
|
|
|
const prefix = {
|
|
|
|
|
type: 'text',
|
|
|
|
|
value: '>',
|
|
|
|
|
};
|
|
|
|
|
child.children.unshift(prefix);
|
2023-06-19 15:56:18 +02:00
|
|
|
}
|
2023-06-21 08:47:31 +02:00
|
|
|
});
|
|
|
|
|
node.type = 'div';
|
|
|
|
|
node.data = {
|
|
|
|
|
hName: 'div',
|
|
|
|
|
hProperties: {
|
|
|
|
|
className: 'greentext',
|
|
|
|
|
},
|
|
|
|
|
};
|
2023-06-19 15:56:18 +02:00
|
|
|
}
|
|
|
|
|
});
|
2023-06-21 08:47:31 +02:00
|
|
|
};
|
2023-04-21 16:38:14 +02:00
|
|
|
|
|
|
|
|
|
2023-06-21 08:47:31 +02:00
|
|
|
const createQuotelink = (children) => {
|
|
|
|
|
const regexC = /(c\/[A-Za-z0-9]{46}|c\/[A-Za-z0-9]{12})/g;
|
|
|
|
|
const regexP = /(p\/([A-Za-z0-9]{52}|[A-Za-z0-9-.]*\.eth))/g;
|
|
|
|
|
const regexU = /(u\/([A-Za-z0-9]{52}|[A-Za-z0-9-.]*\.eth))/g;
|
|
|
|
|
const regexPC = /(p\/([A-Za-z0-9]{52}|[A-Za-z0-9-.]*\.eth)\/c\/[A-Za-z0-9]{46})/g;
|
|
|
|
|
|
|
|
|
|
const regexArray = [regexU, regexPC, regexP, regexC];
|
|
|
|
|
let parts = [children];
|
|
|
|
|
|
|
|
|
|
regexArray.forEach(regex => {
|
|
|
|
|
parts = parts.flatMap((child, i) => {
|
|
|
|
|
if (typeof child === 'string') {
|
|
|
|
|
const newParts = [];
|
|
|
|
|
let match;
|
|
|
|
|
let lastIndex = 0;
|
|
|
|
|
|
|
|
|
|
while ((match = regex.exec(child)) !== null) {
|
|
|
|
|
const matchedText = match[0];
|
|
|
|
|
const index = match.index;
|
|
|
|
|
|
|
|
|
|
if (index > lastIndex) {
|
|
|
|
|
newParts.push(child.substring(lastIndex, index));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
newParts.push(
|
|
|
|
|
<Link
|
|
|
|
|
key={`link-${i}-${matchedText}`}
|
|
|
|
|
className="quotelink"
|
|
|
|
|
to={() => {}}
|
|
|
|
|
>
|
|
|
|
|
{matchedText}
|
|
|
|
|
</Link>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
lastIndex = index + matchedText.length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (lastIndex < child.length) {
|
|
|
|
|
newParts.push(child.substring(lastIndex));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return newParts;
|
|
|
|
|
} else {
|
|
|
|
|
return child;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return parts;
|
|
|
|
|
};
|
2023-06-19 15:56:18 +02:00
|
|
|
|
2023-03-29 13:37:36 +02:00
|
|
|
|
2023-04-21 16:38:14 +02:00
|
|
|
return (
|
|
|
|
|
<ReactMarkdown
|
2023-04-25 15:26:46 +02:00
|
|
|
children={doubleNewlineContent}
|
2023-04-23 18:53:47 +02:00
|
|
|
remarkPlugins={[blockquoteToGreentext, breaks]}
|
2023-04-27 13:10:23 +02:00
|
|
|
rehypePlugins={[[rehypeSanitize, customSchema]]}
|
2023-04-21 16:38:14 +02:00
|
|
|
components={{
|
2023-04-30 15:44:35 +02:00
|
|
|
img: ({ src }) => <span>{src}</span>,
|
2023-05-02 13:28:32 +02:00
|
|
|
video: ({ src }) => <span>{src}</span>,
|
|
|
|
|
source: ({ src }) => <span>{src}</span>,
|
|
|
|
|
gif: ({ src }) => <span>{src}</span>,
|
2023-06-19 15:56:18 +02:00
|
|
|
p: ({ children }) => <div className='custom-paragraph'>{createQuotelink(children)}</div>,
|
2023-04-21 16:38:14 +02:00
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
);
|
2023-03-29 13:37:36 +02:00
|
|
|
};
|
|
|
|
|
|
2023-06-19 15:56:18 +02:00
|
|
|
export default React.memo(Post);
|