Skip to content

Commit

Permalink
fix: mentions and emojis inside bold, italic and strikethrough (#29391)
Browse files Browse the repository at this point in the history
  • Loading branch information
jayesh-jain252 authored Jul 7, 2023
1 parent d91e480 commit e01bbcc
Show file tree
Hide file tree
Showing 9 changed files with 260 additions and 120 deletions.
6 changes: 6 additions & 0 deletions .changeset/mentions-emoji-emphasis.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@rocket.chat/gazzodown': minor
---

Fixed mentions and emojis inside inside bold, italic or strikethrough texts

Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,60 @@ import type * as MessageParser from '@rocket.chat/message-parser';
import ItalicSpan from './ItalicSpan';
import LinkSpan from './LinkSpan';
import StrikeSpan from './StrikeSpan';
import EmojiSpan from './EmojiSpan';

const styles = StyleSheet.create({
bold: {
fontWeight: 700,
},
});

type MessageBlock =
| MessageParser.Emoji
| MessageParser.ChannelMention
| MessageParser.UserMention
| MessageParser.Link
| MessageParser.MarkupExcluding<MessageParser.Bold>;

type BoldSpanProps = {
children: (MessageParser.Link | MessageParser.MarkupExcluding<MessageParser.Bold>)[];
children: MessageBlock[];
};

const BoldSpan = ({ children }: BoldSpanProps) => (
<View style={styles.bold}>
<>
{children.map((child, index) => {
switch (child.type) {
case 'LINK':
return <LinkSpan key={index} label={Array.isArray(child.value.label) ? child.value.label : [child.value.label]} />;
if (child.type === 'LINK' || child.type === 'PLAIN_TEXT' || child.type === 'ITALIC' || child.type === 'STRIKE') {
return (
<View style={styles.bold} key={index}>
{renderBlockComponent(child, index)}
</View>
);
}
return renderBlockComponent(child, index);
})}
</>
);

case 'PLAIN_TEXT':
return <Text key={index}>{child.value}</Text>;
const renderBlockComponent = (child: MessageBlock, index: number) => {
switch (child.type) {
case 'LINK':
return <LinkSpan key={index} label={Array.isArray(child.value.label) ? child.value.label : [child.value.label]} />;

case 'STRIKE':
return <StrikeSpan key={index} children={child.value} />;
case 'PLAIN_TEXT':
return <Text key={index}>{child.value}</Text>;

case 'ITALIC':
return <ItalicSpan key={index} children={child.value} />;
case 'STRIKE':
return <StrikeSpan key={index} children={child.value} />;

default:
return null;
}
})}
</View>
);
case 'ITALIC':
return <ItalicSpan key={index} children={child.value} />;

case 'EMOJI':
return <EmojiSpan key={index} {...child} />;

default:
return null;
}
};

export default BoldSpan;
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,60 @@ import type * as MessageParser from '@rocket.chat/message-parser';
import BoldSpan from './BoldSpan';
import LinkSpan from './LinkSpan';
import StrikeSpan from './StrikeSpan';
import EmojiSpan from './EmojiSpan';

const styles = StyleSheet.create({
italic: {
fontStyle: 'italic',
},
});

type MessageBlock =
| MessageParser.Emoji
| MessageParser.ChannelMention
| MessageParser.UserMention
| MessageParser.Link
| MessageParser.MarkupExcluding<MessageParser.Italic>;

type ItalicSpanProps = {
children: (MessageParser.Link | MessageParser.MarkupExcluding<MessageParser.Italic>)[];
children: MessageBlock[];
};

const ItalicSpan = ({ children }: ItalicSpanProps) => (
<View style={styles.italic}>
<>
{children.map((child, index) => {
switch (child.type) {
case 'LINK':
return <LinkSpan key={index} label={Array.isArray(child.value.label) ? child.value.label : [child.value.label]} />;
if (child.type === 'LINK' || child.type === 'PLAIN_TEXT' || child.type === 'STRIKE' || child.type === 'BOLD') {
return (
<View style={styles.italic} key={index}>
{renderBlockComponent(child, index)}
</View>
);
}
return renderBlockComponent(child, index);
})}
</>
);

case 'PLAIN_TEXT':
return <Text key={index}>{child.value}</Text>;
const renderBlockComponent = (child: MessageBlock, index: number) => {
switch (child.type) {
case 'LINK':
return <LinkSpan key={index} label={Array.isArray(child.value.label) ? child.value.label : [child.value.label]} />;

case 'STRIKE':
return <StrikeSpan key={index} children={child.value} />;
case 'PLAIN_TEXT':
return <Text key={index}>{child.value}</Text>;

case 'BOLD':
return <BoldSpan key={index} children={child.value} />;
case 'STRIKE':
return <StrikeSpan key={index} children={child.value} />;

default:
return null;
}
})}
</View>
);
case 'BOLD':
return <BoldSpan key={index} children={child.value} />;

case 'EMOJI':
return <EmojiSpan key={index} {...child} />;

default:
return null;
}
};

export default ItalicSpan;
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,60 @@ import type * as MessageParser from '@rocket.chat/message-parser';
import ItalicSpan from './ItalicSpan';
import LinkSpan from './LinkSpan';
import BoldSpan from './BoldSpan';
import EmojiSpan from './EmojiSpan';

const styles = StyleSheet.create({
strike: {
textDecoration: 'line-through',
},
});

type MessageBlock =
| MessageParser.Emoji
| MessageParser.ChannelMention
| MessageParser.UserMention
| MessageParser.Link
| MessageParser.MarkupExcluding<MessageParser.Strike>;

type StrikeSpanProps = {
children: (MessageParser.Link | MessageParser.MarkupExcluding<MessageParser.Strike>)[];
children: MessageBlock[];
};

const StrikeSpan = ({ children }: StrikeSpanProps) => (
<View style={styles.strike}>
<>
{children.map((child, index) => {
switch (child.type) {
case 'LINK':
return <LinkSpan key={index} label={Array.isArray(child.value.label) ? child.value.label : [child.value.label]} />;
if (child.type === 'LINK' || child.type === 'PLAIN_TEXT' || child.type === 'ITALIC' || child.type === 'BOLD') {
return (
<View style={styles.strike} key={index}>
{renderBlockComponent(child, index)}
</View>
);
}
return renderBlockComponent(child, index);
})}
</>
);

case 'PLAIN_TEXT':
return <Text key={index}>{child.value}</Text>;
const renderBlockComponent = (child: MessageBlock, index: number) => {
switch (child.type) {
case 'LINK':
return <LinkSpan key={index} label={Array.isArray(child.value.label) ? child.value.label : [child.value.label]} />;

case 'BOLD':
return <BoldSpan key={index} children={child.value} />;
case 'PLAIN_TEXT':
return <Text key={index}>{child.value}</Text>;

case 'ITALIC':
return <ItalicSpan key={index} children={child.value} />;
case 'ITALIC':
return <ItalicSpan key={index} children={child.value} />;

default:
return null;
}
})}
</View>
);
case 'BOLD':
return <BoldSpan key={index} children={child.value} />;

case 'EMOJI':
return <EmojiSpan key={index} {...child} />;

default:
return null;
}
};

export default StrikeSpan;
60 changes: 43 additions & 17 deletions packages/gazzodown/src/elements/BoldSpan.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,62 @@
import type * as MessageParser from '@rocket.chat/message-parser';
import type { ReactElement } from 'react';

import EmojiElement from '../emoji/EmojiElement';
import ChannelMentionElement from '../mentions/ChannelMentionElement';
import UserMentionElement from '../mentions/UserMentionElement';
import ItalicSpan from './ItalicSpan';
import LinkSpan from './LinkSpan';
import PlainSpan from './PlainSpan';
import StrikeSpan from './StrikeSpan';

type MessageBlock =
| MessageParser.Emoji
| MessageParser.ChannelMention
| MessageParser.UserMention
| MessageParser.Link
| MessageParser.MarkupExcluding<MessageParser.Bold>;

type BoldSpanProps = {
children: (MessageParser.Link | MessageParser.MarkupExcluding<MessageParser.Bold>)[];
children: MessageBlock[];
};

const BoldSpan = ({ children }: BoldSpanProps): ReactElement => (
<strong>
<>
{children.map((block, index) => {
switch (block.type) {
case 'LINK':
return <LinkSpan key={index} href={block.value.src.value} label={block.value.label} />;
if (block.type === 'LINK' || block.type === 'PLAIN_TEXT' || block.type === 'STRIKE' || block.type === 'ITALIC') {
return <strong key={index}>{renderBlockComponent(block, index)}</strong>;
}
return renderBlockComponent(block, index);
})}
</>
);

case 'PLAIN_TEXT':
return <PlainSpan key={index} text={block.value} />;
const renderBlockComponent = (block: MessageBlock, index: number): ReactElement | null => {
switch (block.type) {
case 'EMOJI':
return <EmojiElement key={index} {...block} />;

case 'STRIKE':
return <StrikeSpan key={index} children={block.value} />;
case 'MENTION_USER':
return <UserMentionElement key={index} mention={block.value.value} />;

case 'ITALIC':
return <ItalicSpan key={index} children={block.value} />;
case 'MENTION_CHANNEL':
return <ChannelMentionElement key={index} mention={block.value.value} />;

default:
return null;
}
})}
</strong>
);
case 'PLAIN_TEXT':
return <PlainSpan key={index} text={block.value} />;

case 'LINK':
return <LinkSpan key={index} href={block.value.src.value} label={block.value.label} />;

case 'STRIKE':
return <StrikeSpan key={index} children={block.value} />;

case 'ITALIC':
return <ItalicSpan key={index} children={block.value} />;

default:
return null;
}
};

export default BoldSpan;
4 changes: 3 additions & 1 deletion packages/gazzodown/src/elements/ImageElement.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import type * as MessageParser from '@rocket.chat/message-parser';
import { ReactElement, useMemo } from 'react';

const flattenMarkup = (markup: MessageParser.Markup | MessageParser.Link): string => {
const flattenMarkup = (
markup: MessageParser.Markup | MessageParser.Link | MessageParser.Emoji | MessageParser.ChannelMention | MessageParser.UserMention,
): string => {
switch (markup.type) {
case 'PLAIN_TEXT':
return markup.value;
Expand Down
Loading

0 comments on commit e01bbcc

Please sign in to comment.