diff --git a/packages/pl-fe/src/components/account-hover-card.tsx b/packages/pl-fe/src/components/account-hover-card.tsx index d7380682c..b9df8ca04 100644 --- a/packages/pl-fe/src/components/account-hover-card.tsx +++ b/packages/pl-fe/src/components/account-hover-card.tsx @@ -13,6 +13,7 @@ import { useAppSelector, useAppDispatch } from 'pl-fe/hooks'; import { useAccountHoverCardStore } from 'pl-fe/stores'; import { showAccountHoverCard } from './hover-ref-wrapper'; +import { ParsedContent } from './parsed-content'; import { dateFormatOptions } from './relative-timestamp'; import Scrobble from './scrobble'; import { Card, CardBody, HStack, Icon, Stack, Text } from './ui'; @@ -98,7 +99,6 @@ const AccountHoverCard: React.FC = ({ visible = true }) => { }; if (!account) return null; - const accountBio = { __html: account.note_emojified }; const memberSinceDate = intl.formatDate(account.created_at, { month: 'long', year: 'numeric' }); const followedBy = me !== account.id && account.relationship?.followed_by === true; @@ -153,9 +153,10 @@ const AccountHoverCard: React.FC = ({ visible = true }) => { + > + + )} diff --git a/packages/pl-fe/src/components/account.tsx b/packages/pl-fe/src/components/account.tsx index b43bbee98..0234012c0 100644 --- a/packages/pl-fe/src/components/account.tsx +++ b/packages/pl-fe/src/components/account.tsx @@ -10,6 +10,7 @@ import { getAcct } from 'pl-fe/utils/accounts'; import { displayFqn } from 'pl-fe/utils/state'; import Badge from './badge'; +import { ParsedContent } from './parsed-content'; import RelativeTimestamp from './relative-timestamp'; import { Avatar, Emoji, HStack, Icon, IconButton, Stack, Text } from './ui'; @@ -348,9 +349,9 @@ const Account = ({ + > + + )} diff --git a/packages/pl-fe/src/components/parsed-content.tsx b/packages/pl-fe/src/components/parsed-content.tsx index 90aa0f4ac..30fa3a03b 100644 --- a/packages/pl-fe/src/components/parsed-content.tsx +++ b/packages/pl-fe/src/components/parsed-content.tsx @@ -5,6 +5,7 @@ import { Link } from 'react-router-dom'; import HashtagLink from './hashtag-link'; import HoverRefWrapper from './hover-ref-wrapper'; +import StatusMention from './status-mention'; import type { Mention } from 'pl-api'; @@ -12,7 +13,9 @@ const nodesToText = (nodes: Array): string => nodes.map(node => node.type === 'text' ? node.data : node.type === 'tag' ? nodesToText(node.children as Array) : '').join(''); interface IParsedContent { + /** HTML content to display. */ html: string; + /** Array of mentioned accounts. */ mentions?: Array; /** Whether it's a status which has a quote. */ hasQuote?: boolean; @@ -62,20 +65,26 @@ const ParsedContent: React.FC = (({ html, mentions, hasQuote }) ); - if (classes?.includes('mention') && mentions) { - const mention = mentions.find(({ url }) => domNode.attribs.href === url); - if (mention) { + if (classes?.includes('mention')) { + if (mentions) { + const mention = mentions.find(({ url }) => domNode.attribs.href === url); + if (mention) { + return ( + + e.stopPropagation()} + > + @{mention.username} + + + ); + } + } else if (domNode.attribs['data-user']) { return ( - - e.stopPropagation()} - > - @{mention.username} - - + ); } } diff --git a/packages/pl-fe/src/features/directory/components/account-card.tsx b/packages/pl-fe/src/features/directory/components/account-card.tsx index c60a9efb0..8d04b1377 100644 --- a/packages/pl-fe/src/features/directory/components/account-card.tsx +++ b/packages/pl-fe/src/features/directory/components/account-card.tsx @@ -7,6 +7,7 @@ import { useAccount } from 'pl-fe/api/hooks'; import Account from 'pl-fe/components/account'; import Badge from 'pl-fe/components/badge'; import HoverRefWrapper from 'pl-fe/components/hover-ref-wrapper'; +import { ParsedContent } from 'pl-fe/components/parsed-content'; import RelativeTimestamp from 'pl-fe/components/relative-timestamp'; import { Avatar, Stack, Text } from 'pl-fe/components/ui'; import ActionButton from 'pl-fe/features/ui/components/action-button'; @@ -67,12 +68,15 @@ const AccountCard: React.FC = ({ id }) => { withRelationship={false} /> - + {!!account.note_emojified && ( + + + + )}
diff --git a/packages/pl-fe/src/features/group/components/group-header.tsx b/packages/pl-fe/src/features/group/components/group-header.tsx index e19a1826d..e1c1f61ea 100644 --- a/packages/pl-fe/src/features/group/components/group-header.tsx +++ b/packages/pl-fe/src/features/group/components/group-header.tsx @@ -3,6 +3,7 @@ import React, { useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import GroupAvatar from 'pl-fe/components/groups/group-avatar'; +import { ParsedContent } from 'pl-fe/components/parsed-content'; import StillImage from 'pl-fe/components/still-image'; import { HStack, Icon, Stack, Text } from 'pl-fe/components/ui'; import { useModalsStore } from 'pl-fe/stores'; @@ -150,9 +151,10 @@ const GroupHeader: React.FC = ({ group }) => { + > + + diff --git a/packages/pl-fe/src/features/ui/components/modals/manage-group-modal/steps/confirmation-step.tsx b/packages/pl-fe/src/features/ui/components/modals/manage-group-modal/steps/confirmation-step.tsx index 09663a756..825dafdaa 100644 --- a/packages/pl-fe/src/features/ui/components/modals/manage-group-modal/steps/confirmation-step.tsx +++ b/packages/pl-fe/src/features/ui/components/modals/manage-group-modal/steps/confirmation-step.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { FormattedMessage, defineMessages, useIntl } from 'react-intl'; +import { ParsedContent } from 'pl-fe/components/parsed-content'; import { Avatar, Divider, HStack, Stack, Text, Button } from 'pl-fe/components/ui'; import toast from 'pl-fe/toast'; import copy from 'pl-fe/utils/copy'; @@ -57,8 +58,9 @@ const ConfirmationStep: React.FC = ({ group }) => { + > + + diff --git a/packages/pl-fe/src/features/ui/components/panels/profile-info-panel.tsx b/packages/pl-fe/src/features/ui/components/panels/profile-info-panel.tsx index a1b73251c..dbc360f31 100644 --- a/packages/pl-fe/src/features/ui/components/panels/profile-info-panel.tsx +++ b/packages/pl-fe/src/features/ui/components/panels/profile-info-panel.tsx @@ -1,13 +1,11 @@ -import parse, { Element, type HTMLReactParserOptions, domToReact, type DOMNode } from 'html-react-parser'; -import React, { useMemo } from 'react'; +import React from 'react'; import { defineMessages, useIntl, FormattedMessage } from 'react-intl'; import Badge from 'pl-fe/components/badge'; -import HashtagLink from 'pl-fe/components/hashtag-link'; import Markup from 'pl-fe/components/markup'; +import { ParsedContent } from 'pl-fe/components/parsed-content'; import { dateFormatOptions } from 'pl-fe/components/relative-timestamp'; import Scrobble from 'pl-fe/components/scrobble'; -import StatusMention from 'pl-fe/components/status-mention'; import { Icon, HStack, Stack, Text } from 'pl-fe/components/ui'; import { useAppSelector, usePlFeConfig } from 'pl-fe/hooks'; import { capitalize } from 'pl-fe/utils/strings'; @@ -104,54 +102,6 @@ const ProfileInfoPanel: React.FC = ({ account, username }) => ); }; - const note = useMemo(() => { - if (!account) return false; - - 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(' '); - const id = domNode.attribs['data-user']; - - const fallback = ( - // eslint-disable-next-line jsx-a11y/no-static-element-interactions - e.stopPropagation()} - rel='nofollow noopener' - target='_blank' - title={domNode.attribs.href} - > - {domToReact(domNode.children as DOMNode[], options)} - - ); - - if (classes?.includes('mention') && id) { - return ( - - ); - } - - if (classes?.includes('hashtag')) { - const child = domToReact(domNode.children as DOMNode[]); - const hashtag = typeof child === 'string' ? child.replace(/^#/, '') : undefined; - if (hashtag) { - return ; - } - } - - return fallback; - } - }, - }; - - return !!account.note.length && parse(account.note_emojified, options); - }, [account?.note_emojified]); - if (!account) { return (
@@ -206,8 +156,10 @@ const ProfileInfoPanel: React.FC = ({ account, username }) => - {note && ( - {note} + {!!account.note_emojified && ( + + + )}