added markdown and greentext

This commit is contained in:
plebbitor
2023-03-29 13:37:36 +02:00
parent 6c7de6d69b
commit 281f87d54b
7 changed files with 76 additions and 72 deletions
+1 -1
View File
@@ -19,7 +19,6 @@
"eslint-config-react-app": "^7.0.1",
"ext-name": "^5.0.0",
"lodash": "^4.17.21",
"markdown-it": "^13.0.1",
"postcss": "^8.4.21",
"react": "^18.2.0",
"react-content-loader": "^6.2.1",
@@ -35,6 +34,7 @@
"react-toastify": "^9.1.1",
"react-tooltip": "^5.10.0",
"styled-components": "^5.3.9",
"unist-util-visit": "^4.1.2",
"web-vitals": "^3.3.0",
"zustand": "^4.3.6"
},
+44
View File
@@ -0,0 +1,44 @@
import React from 'react';
import ReactMarkdown from 'react-markdown';
import { visit } from 'unist-util-visit';
import DOMPurify from 'dompurify';
const blockquoteToGreentext = () => (tree) => {
visit(tree, 'blockquote', (node) => {
node.children.forEach((child) => {
if (child.type === 'paragraph' && child.children.length > 0) {
const prefix = {
type: 'text',
value: '>',
};
child.children.unshift(prefix);
}
});
node.type = 'div';
node.data = {
hName: 'div',
hProperties: {
className: 'greentext',
},
};
});
};
const Post = ({ content }) => {
const sanitizedContent = DOMPurify.sanitize(content);
return (
<ReactMarkdown
children={sanitizedContent}
remarkPlugins={[blockquoteToGreentext]}
components={{
img: () => null,
video: () => null,
source: () => null,
gif: () => null,
}}
/>
);
};
export default Post;
+14 -13
View File
@@ -8,6 +8,7 @@ import useAppStore from '../../useAppStore';
import { Container, NavBar, Header, Break, PostFormLink, PostFormTable, PostForm, TopBar, BoardForm } from './styles/Board.styled';
import CaptchaModal from '../CaptchaModal';
import ImageBanner from '../ImageBanner';
import Post from '../Post';
import PostLoader from '../PostLoader';
import ReplyModal from '../ReplyModal';
import SettingsModal from '../SettingsModal';
@@ -378,7 +379,7 @@ const Board = () => {
loadMore={tryLoadMore}
hasMore={hasMore}
>
{feed.map((thread) => {
{selectedFeed.map((thread) => {
const { replies: { pages: { topAll: { comments } } } } = thread;
const { renderedComments, omittedCount } = renderComments(comments);
const commentMediaInfo = getCommentMediaInfo(thread);
@@ -495,10 +496,10 @@ const Board = () => {
</div>
</span>
{thread.content ? (
thread.content.length > 2000 ?
thread.content.length > 1000 ?
<Fragment key={`fragment5-${thread.cid}`}>
<blockquote key={`bq-${thread.cid}`}>
{thread.content.slice(0, 2000)}
<Post content={thread.content.slice(0, 1000)} key={`post-${thread.cid}`} />
<span key={`ttl-s-${thread.cid}`} className="ttl"> (...)
<br key={`ttl-s-br1-${thread.cid}`} /><br key={`ttl-s-br2${thread.cid}`} />
Post too long.&nbsp;
@@ -507,7 +508,7 @@ const Board = () => {
</blockquote>
</Fragment>
: <blockquote key={`bq-${thread.cid}`}>
{thread.content}
<Post content={thread.content} key={`post-${thread.cid}`} />
</blockquote>)
: null}
</div>
@@ -586,13 +587,13 @@ const Board = () => {
</div>
</div>
{reply.content ? (
reply.content.length > 1000 ?
reply.content.length > 500 ?
<Fragment key={`fragment8-${reply.cid}`}>
<blockquote key={`pm-${reply.cid}`} className="post-message">
<Link to="" key={`r-pm-${reply.cid}`} className="quotelink" onClick={handleVoidClick}>
{`c/${reply.parentCid.slice(0, 8)}`}{<br />}
</Link>
{reply.content.slice(0, 1000)}
<Post content={reply.content.slice(0, 500)} key={`post-${reply.cid}`} />
<span key={`ttl-s-${reply.cid}`} className="ttl"> (...)
<br key={`ttl-s-br1-${reply.cid}`} /><br key={`ttl-s-br2${reply.cid}`} />
Comment too long.&nbsp;
@@ -604,7 +605,7 @@ const Board = () => {
<Link to={handleVoidClick} key={`r-pm-${reply.cid}`} className="quotelink" onClick={(event) => handleQuoteClick(reply, event)}>
{`c/${reply.parentCid.slice(0, 8)}`}{<br />}
</Link>
{reply.content}
<Post content={reply.content} key={`post-${reply.cid}`} />
</blockquote>)
: null}
</div>
@@ -705,10 +706,10 @@ const Board = () => {
) : null
) : null}
{thread.content ? (
thread.content.length > 1500 ?
thread.content.length > 500 ?
<Fragment key={`fragment12-${thread.cid}`}>
<blockquote key={`mob-bq-${thread.cid}`} className="post-message-mobile">
{thread.content.slice(0, 1500)}
<Post content={thread.content.slice(0, 500)} key={`post-mobile-${thread.cid}`} />
<span key={`mob-ttl-s-${thread.cid}`} className="ttl"> (...)
<br key={`mob-ttl-s-br1-${thread.cid}`} /><br key={`mob-ttl-s-br2${thread.cid}`} />
Post too long.&nbsp;
@@ -717,7 +718,7 @@ const Board = () => {
</blockquote>
</Fragment>
: <blockquote key={`mob-bq-${thread.cid}`} className="post-message-mobile">
{thread.content}
<Post content={thread.content} key={`post-mobile-${thread.cid}`} />
</blockquote>)
: null}
</div>
@@ -773,13 +774,13 @@ const Board = () => {
</span>
</div>
{reply.content ? (
reply.content.length > 1000 ?
reply.content.length > 500 ?
<Fragment key={`fragment15-${reply.cid}`}>
<blockquote key={`mob-pm-${reply.cid}`} className="post-message">
<Link to="" key={`mob-r-pm-${reply.cid}`} className="quotelink" onClick={handleVoidClick}>
{`c/${reply.parentCid.slice(0, 8)}`}{<br />}
</Link>
{reply.content.slice(0, 1000)}
<Post content={reply.content.slice(0, 500)} key={`post-mobile-${reply.cid}`} />
<span key={`mob-ttl-s-${reply.cid}`} className="ttl"> (...)
<br key={`mob-ttl-s-br1-${reply.cid}`} /><br key={`mob-ttl-s-br2${reply.cid}`} />
Comment too long.&nbsp;
@@ -791,7 +792,7 @@ const Board = () => {
<Link to={handleVoidClick} key={`mob-r-pm-${reply.cid}`} className="quotelink" onClick={(event) => handleQuoteClick(reply, event)}>
{`c/${reply.parentCid.slice(0, 8)}`}{<br />}
</Link>
{reply.content}
<Post content={reply.content} key={`post-mobile-${reply.cid}`} />
</blockquote>)
: null}
</div>
+3 -1
View File
@@ -10,6 +10,7 @@ import { TopBar } from './styles/Thread.styled';
import CaptchaModal from '../CaptchaModal';
import CatalogLoader from '../CatalogLoader';
import ImageBanner from '../ImageBanner';
import Post from '../Post';
import SettingsModal from '../SettingsModal';
import getCommentMediaInfo from '../../utils/getCommentMediaInfo';
import handleStyleChange from '../../utils/handleStyleChange';
@@ -385,7 +386,8 @@ const Catalog = () => {
</div>
<div key={`t-${thread.cid}`} className="teaser">
<b key={`b2-${thread.cid}`}>{thread.title ? `${thread.title}` : null}</b>
{thread.content ? `: ${thread.content}` : null}
{thread.content && `: `}
{thread.content && <Post content={thread.content} key="post"/>}
</div>
</div>
</Link>
+6 -5
View File
@@ -8,6 +8,7 @@ import { Container, NavBar, Header, Break, PostForm, PostFormTable, BoardForm }
import { ReplyFormLink, TopBar, BottomBar } from './styles/Thread.styled';
import CaptchaModal from '../CaptchaModal';
import ImageBanner from '../ImageBanner';
import Post from '../Post';
import PostLoader from '../PostLoader';
import ReplyModal from '../ReplyModal';
import SettingsModal from '../SettingsModal';
@@ -503,8 +504,8 @@ const Thread = () => {
}
</div>
</span>
<blockquote>
{comment.content}
<blockquote key={`blockquote-${comment.cid}`}>
<Post content={comment.content} key={`post-${comment.cid}`} />
</blockquote>
</div>
</div>
@@ -580,7 +581,7 @@ const Thread = () => {
onClick={(event) => handleQuoteClick(reply, event)}>
{`c/${reply.parentCid.slice(0, 8)}`}{<br />}
</Link>
{reply.content}
<Post content={reply.content} key={`post-${reply.cid}`} />
</blockquote>
</div>
</div>
@@ -682,7 +683,7 @@ const Thread = () => {
<blockquote key={`mob-bq-${comment.cid}`} className="post-message-mobile">
{comment.content ? (
<>
{comment.content}
<Post content={comment.content} key={`post-mobile-${comment.cid}`} />
</>
) : null}
</blockquote>
@@ -743,7 +744,7 @@ const Thread = () => {
onClick={(event) => handleQuoteClick(reply, event)}>
{`c/${reply.parentCid.slice(0, 8)}`}{<br />}
</Link>
{reply.content}
<Post content={reply.content} key={`post-mobile-${reply.cid}`} />
</blockquote>
</div>
</div>
+7 -18
View File
@@ -1691,7 +1691,6 @@ export const BoardForm = styled.div`
}
p:first-of-type::before {
content: '>';
color: #789922;
}
}
@@ -1805,7 +1804,6 @@ export const BoardForm = styled.div`
}
p:first-of-type::before {
content: '>';
color: #789922;
}
}
@@ -1922,7 +1920,6 @@ export const BoardForm = styled.div`
}
p:first-of-type::before {
content: '>';
color: #789922;
}
}
@@ -2035,7 +2032,6 @@ export const BoardForm = styled.div`
}
p:first-of-type::before {
content: '>';
color: #789922;
}
}
@@ -2159,7 +2155,6 @@ export const BoardForm = styled.div`
}
p:first-of-type::before {
content: '>';
color: #b5bd68;
}
}
@@ -2277,7 +2272,6 @@ export const BoardForm = styled.div`
}
p:first-of-type::before {
content: '>';
color: #789922;
}
}
@@ -2607,8 +2601,7 @@ export const BoardForm = styled.div`
font-weight: 700;
}
blockquote > p:first-of-type::before {
content: '>';
.greentext {
color: #789922;
}
@@ -2765,8 +2758,7 @@ export const BoardForm = styled.div`
font-weight: 700;
}
blockquote > p:first-of-type::before {
content: '>';
.greentext {
color: #789922;
}
@@ -2925,8 +2917,7 @@ export const BoardForm = styled.div`
font-weight: 700;
}
blockquote > p:first-of-type::before {
content: '>';
.greentext {
color: #789922;
}
@@ -3089,8 +3080,7 @@ export const BoardForm = styled.div`
font-weight: 700;
}
blockquote > p:first-of-type::before {
content: '>';
.greentext {
color: #789922;
}
@@ -3246,8 +3236,7 @@ export const BoardForm = styled.div`
font-weight: 700;
}
blockquote > p:first-of-type::before {
content: '>';
.greentext {
color: #b5bd68;
}
@@ -3408,8 +3397,8 @@ export const BoardForm = styled.div`
font-weight: 700;
}
blockquote > p:first-of-type::before {
content: '>';
.greentext {
color: #789922;
}
+1 -34
View File
@@ -5471,11 +5471,6 @@ entities@^4.2.0, entities@^4.4.0:
resolved "https://registry.yarnpkg.com/entities/-/entities-4.4.0.tgz#97bdaba170339446495e653cfd2db78962900174"
integrity sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==
entities@~3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4"
integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==
env-paths@^2.2.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
@@ -8489,13 +8484,6 @@ lines-and-columns@^1.1.6:
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
linkify-it@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-4.0.1.tgz#01f1d5e508190d06669982ba31a7d9f56a5751ec"
integrity sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==
dependencies:
uc.micro "^1.0.1"
loader-runner@^4.2.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1"
@@ -8699,17 +8687,6 @@ map-obj@^4.0.0:
resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a"
integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==
markdown-it@^13.0.1:
version "13.0.1"
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-13.0.1.tgz#c6ecc431cacf1a5da531423fc6a42807814af430"
integrity sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==
dependencies:
argparse "^2.0.1"
entities "~3.0.1"
linkify-it "^4.0.1"
mdurl "^1.0.1"
uc.micro "^1.0.5"
mdast-util-definitions@^5.0.0:
version "5.1.2"
resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz#9910abb60ac5d7115d6819b57ae0bcef07a3f7a7"
@@ -8768,11 +8745,6 @@ mdn-data@2.0.4:
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b"
integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==
mdurl@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==
media-typer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
@@ -12382,11 +12354,6 @@ typescript@^5.0.2:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.2.tgz#891e1a90c5189d8506af64b9ef929fca99ba1ee5"
integrity sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==
uc.micro@^1.0.1, uc.micro@^1.0.5:
version "1.0.6"
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac"
integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==
uint8arrays@^2.0.5, uint8arrays@^2.1.2:
version "2.1.10"
resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-2.1.10.tgz#34d023c843a327c676e48576295ca373c56e286a"
@@ -12502,7 +12469,7 @@ unist-util-visit-parents@^5.1.1:
"@types/unist" "^2.0.0"
unist-util-is "^5.0.0"
unist-util-visit@^4.0.0:
unist-util-visit@^4.0.0, unist-util-visit@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-4.1.2.tgz#125a42d1eb876283715a3cb5cceaa531828c72e2"
integrity sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==