pl-fe: handle mentions and hashtag links in bio

Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
marcin mikołajczak
2024-09-02 12:35:47 +02:00
parent db3c895731
commit 752f10fac2
3 changed files with 148 additions and 59 deletions

View File

@ -109,69 +109,71 @@ const StatusContent: React.FC<IStatusContent> = React.memo(({
[status.contentHtml, status.translation, status.currentLanguage],
);
if (status.content.length === 0) {
return null;
}
const content = useMemo(() => {
if (status.content.length === 0) {
return null;
}
const options: HTMLReactParserOptions = {
replace(domNode) {
if (domNode instanceof Element && ['script', 'iframe'].includes(domNode.name)) {
return null;
}
if (domNode instanceof Element && domNode.name === 'a') {
const classes = domNode.attribs.class?.split(' ');
if (classes?.includes('mention')) {
const mention = status.mentions.find(({ url }) => domNode.attribs.href === url);
if (mention) {
return (
<HoverRefWrapper accountId={mention.id} inline>
<Link
to={`/@${mention.acct}`}
className='text-primary-600 hover:underline dark:text-accent-blue'
dir='ltr'
onClick={(e) => e.stopPropagation()}
>
@{mention.username}
</Link>
</HoverRefWrapper>
);
}
}
if (classes?.includes('hashtag')) {
const child = domToReact(domNode.children as DOMNode[]);
const hashtag = typeof child === 'string' ? child.replace(/^#/, '') : undefined;
if (hashtag) {
return <HashtagLink hashtag={hashtag} />;
}
}
return (
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
<a
{...domNode.attribs}
onClick={(e) => e.stopPropagation()}
rel='nofollow noopener'
target='_blank'
title={domNode.attribs.href}
>
{domToReact(domNode.children as DOMNode[], options)}
</a>
);
}
},
};
return parse(parsedHtml, options);
}, [parsedHtml]);
const withSpoiler = status.spoiler_text.length > 0;
const options: HTMLReactParserOptions = {
replace(domNode) {
if (domNode instanceof Element && ['script', 'iframe'].includes(domNode.name)) {
return null;
}
if (domNode instanceof Element && domNode.name === 'a') {
const classes = domNode.attribs.class?.split(' ');
if (classes?.includes('mention')) {
const mention = status.mentions.find(({ url }) => domNode.attribs.href === url);
if (mention) {
return (
<HoverRefWrapper accountId={mention.id} inline>
<Link
to={`/@${mention.acct}`}
className='text-primary-600 hover:underline dark:text-accent-blue'
dir='ltr'
onClick={(e) => e.stopPropagation()}
>
@{mention.username}
</Link>
</HoverRefWrapper>
);
}
}
if (classes?.includes('hashtag')) {
const child = domToReact(domNode.children as DOMNode[]);
const hashtag = typeof child === 'string' ? child.replace(/^#/, '') : undefined;
if (hashtag) {
return <HashtagLink hashtag={hashtag} />;
}
}
return (
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
<a
{...domNode.attribs}
onClick={(e) => e.stopPropagation()}
rel='nofollow noopener'
target='_blank'
title={domNode.attribs.href}
>
{domToReact(domNode.children as DOMNode[], options)}
</a>
);
}
},
};
const spoilerText = status.spoilerMapHtml && status.currentLanguage
? status.spoilerMapHtml[status.currentLanguage] || status.spoilerHtml
: status.spoilerHtml;
const content = parse(parsedHtml, options);
const direction = getTextDirection(status.search_index);
const className = clsx('relative overflow-hidden text-ellipsis break-words text-gray-900 focus:outline-none dark:text-gray-100', {
'cursor-pointer': onClick,

View File

@ -0,0 +1,36 @@
import React from 'react';
import { Link } from 'react-router-dom';
import { useAccount } from 'pl-fe/api/hooks';
import HoverRefWrapper from './hover-ref-wrapper';
interface IStatusMention {
accountId: string;
fallback?: JSX.Element;
}
const StatusMention: React.FC<IStatusMention> = ({ accountId, fallback }) => {
const { account } = useAccount(accountId);
if (!account) return (
<HoverRefWrapper accountId={accountId} inline>
{fallback}
</HoverRefWrapper>
);
return (
<HoverRefWrapper accountId={accountId} inline>
<Link
to={`/@${account.acct}`}
className='text-primary-600 hover:underline dark:text-accent-blue'
dir='ltr'
onClick={(e) => e.stopPropagation()}
>
@{account.acct}
</Link>
</HoverRefWrapper>
);
};
export { StatusMention as default };