Files
5chan/src/components/Post.jsx
T

113 lines
3.1 KiB
React
Raw Normal View History

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={{
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);