feat(markdown): add spoiler text

This commit is contained in:
Tom (plebeius.eth)
2025-01-28 15:12:39 +01:00
parent cbed83cd10
commit 9a08b9572b
3 changed files with 71 additions and 5 deletions
+60 -4
View File
@@ -125,31 +125,84 @@ const blockquoteToGreentext = () => (tree: any) => {
});
};
const spoilerToDiv = () => (tree: any) => {
tree.children.forEach((node: any) => {
if (node.type === 'paragraph') {
const text = node.children.map((child: any) => child.value).join('');
if (text.includes('§§SPOILER_START§§')) {
node.type = 'span';
node.data = {
hName: 'span',
};
node.children.forEach((child: any) => {
if (child.type === 'text') {
const parts = child.value.split(/(§§SPOILER_START§§.*?§§SPOILER_END§§)/);
if (parts.length > 1) {
const newChildren = parts.map((part: string) => {
const spoilerMatch = part.match(/§§SPOILER_START§§(.*?)§§SPOILER_END§§/);
if (spoilerMatch) {
return {
type: 'span',
data: {
hName: 'span',
hProperties: {
className: 'spoilertext',
},
},
children: [
{
type: 'text',
value: spoilerMatch[1],
},
],
};
}
return {
type: 'text',
value: part,
};
});
node.children = newChildren;
}
}
});
}
}
});
};
interface MarkdownProps {
content: string;
title?: string;
}
const Markdown = ({ content, title }: MarkdownProps) => {
const preprocessedContent = useMemo(() => {
if (!content) return '';
return content.replace(/<spoiler>([^<]*)<\/spoiler>/g, '§§SPOILER_START§§$1§§SPOILER_END§§').replace(/<img[^>]*src=['"]([^'"]+)['"][^>]*>/gi, '$1');
}, [content]);
const remarkPlugins: any[] = [[supersub]];
if (content && content.length <= MAX_LENGTH_FOR_GFM) {
if (preprocessedContent && preprocessedContent.length <= MAX_LENGTH_FOR_GFM) {
remarkPlugins.push([remarkGfm, { singleTilde: false }]);
}
const customSchema = useMemo(
() => ({
...defaultSchema,
tagNames: [...(defaultSchema.tagNames || []), 'div'],
tagNames: [...(defaultSchema.tagNames || []), 'div', 'span'],
attributes: {
...defaultSchema.attributes,
div: ['className'],
span: ['className'],
},
}),
[],
);
remarkPlugins.push([blockquoteToGreentext]);
remarkPlugins.push([spoilerToDiv]);
const isInCatalogView = isCatalogView(useLocation().pathname, useParams());
@@ -162,7 +215,7 @@ const Markdown = ({ content, title }: MarkdownProps) => {
</span>
)}
<ReactMarkdown
children={content}
children={preprocessedContent}
remarkPlugins={remarkPlugins}
rehypePlugins={[[rehypeSanitize, customSchema]]}
components={{
@@ -173,7 +226,10 @@ const Markdown = ({ content, title }: MarkdownProps) => {
h4: ({ children }) => <p className={styles.header}>{children}</p>,
h5: ({ children }) => <p className={styles.header}>{children}</p>,
h6: ({ children }) => <p className={styles.header}>{children}</p>,
img: ({ src }) => <span>{src}</span>,
img: ({ src, alt }) => {
const displayText = src || alt || 'image';
return <span>{displayText}</span>;
},
video: ({ src }) => <span>{src}</span>,
iframe: ({ src }) => <span>{src}</span>,
source: ({ src }) => <span>{src}</span>,
+10
View File
@@ -26,6 +26,16 @@ hr {
color: var(--post-greentext-color);
}
.spoilertext {
color: #000 !important;
background: #000 !important;
text-decoration: none;
}
.spoilertext:hover {
color: #fff !important;
}
.capitalize {
text-transform: capitalize;
}
+1 -1
View File
@@ -14584,7 +14584,7 @@ react-scripts@5.0.1:
optionalDependencies:
fsevents "^2.3.2"
react-virtuoso@^4.12.3:
react-virtuoso@4.12.3:
version "4.12.3"
resolved "https://registry.yarnpkg.com/react-virtuoso/-/react-virtuoso-4.12.3.tgz#beecf0582b31058c5a6ed3ec58fc43fd780e5844"
integrity sha512-6X1p/sU7hecmjDZMAwN+r3go9EVjofKhwkUbVlL8lXhBZecPv9XVCkZ/kBPYOr0Mv0Vl5+Ziwgexg9Kh7+NNXQ==