Skip to content

Commit

Permalink
[IMPROVE] Add support to Linebreak and Katex on markdown (#4361)
Browse files Browse the repository at this point in the history
* fix enableMessageParser logic

* create LineBreak component

* fix code style

* add KaTeX support

* add Katex and Inline Katex stories

* update snapshots

* add color prop

* update snapshot

* update snapshot
  • Loading branch information
dnlsilva authored Jul 20, 2022
1 parent 1c1dfe5 commit 376c8e8
Show file tree
Hide file tree
Showing 15 changed files with 248 additions and 20 deletions.
2 changes: 1 addition & 1 deletion app/containers/markdown/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ class Markdown extends PureComponent<IMarkdownProps, any> {

get isNewMarkdown(): boolean {
const { md, enableMessageParser } = this.props;
return !!enableMessageParser && !!md;
return (enableMessageParser ?? true) && !!md;
}

renderText = ({ context, literal }: { context: []; literal: string }) => {
Expand Down
16 changes: 7 additions & 9 deletions app/containers/markdown/new/Code.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
import React from 'react';
import { Text } from 'react-native';
import { View } from 'react-native';
import { Code as CodeProps } from '@rocket.chat/message-parser';

import styles from '../styles';
import { themes } from '../../../lib/constants';
import { useTheme } from '../../../theme';
import CodeLine from './CodeLine';

interface ICodeProps {
value: CodeProps['value'];
}

const Code = ({ value }: ICodeProps) => {
const { theme } = useTheme();
const Code = ({ value }: ICodeProps): React.ReactElement => {
const { colors } = useTheme();

return (
<Text
<View
style={[
styles.codeBlock,
{
color: themes[theme].bodyText,
backgroundColor: themes[theme].bannerBackground,
borderColor: themes[theme].borderColor
backgroundColor: colors.bannerBackground,
borderColor: colors.borderColor
}
]}>
{value.map(block => {
Expand All @@ -32,7 +30,7 @@ const Code = ({ value }: ICodeProps) => {
return null;
}
})}
</Text>
</View>
);
};

Expand Down
10 changes: 7 additions & 3 deletions app/containers/markdown/new/CodeLine.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import { CodeLine as CodeLineProps } from '@rocket.chat/message-parser';
import React from 'react';
import { Text } from 'react-native';
import { CodeLine as CodeLineProps } from '@rocket.chat/message-parser';

import { useTheme } from '../../../theme';
import styles from '../styles';

interface ICodeLineProps {
value: CodeLineProps['value'];
}

const CodeLine = ({ value }: ICodeLineProps) => {
const CodeLine = ({ value }: ICodeLineProps): React.ReactElement | null => {
const { colors } = useTheme();
if (value.type !== 'PLAIN_TEXT') {
return null;
}

return <Text>{value.value}</Text>;
return <Text style={[styles.codeBlockText, { color: colors.bodyText }]}>{value.value}</Text>;
};

export default CodeLine;
6 changes: 5 additions & 1 deletion app/containers/markdown/new/Inline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ import Emoji from './Emoji';
import InlineCode from './InlineCode';
import Image from './Image';
import MarkdownContext from './MarkdownContext';
// import { InlineKaTeX, KaTeX } from './Katex';

interface IParagraphProps {
value: ParagraphProps['value'];
}

const Inline = ({ value }: IParagraphProps) => {
const Inline = ({ value }: IParagraphProps): React.ReactElement | null => {
const { useRealName, username, navToRoomInfo, mentions, channels } = useContext(MarkdownContext);
return (
<Text style={styles.inline}>
Expand Down Expand Up @@ -53,6 +54,9 @@ const Inline = ({ value }: IParagraphProps) => {
return <Hashtag hashtag={block.value.value} navToRoomInfo={navToRoomInfo} channels={channels} />;
case 'INLINE_CODE':
return <InlineCode value={block.value} />;
case 'INLINE_KATEX':
// return <InlineKaTeX value={block.value} />;
return <Text>{block.value}</Text>;
default:
return null;
}
Expand Down
20 changes: 20 additions & 0 deletions app/containers/markdown/new/Katex.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import { KaTeX as KaTeXProps } from '@rocket.chat/message-parser';
// eslint-disable-next-line import/no-unresolved
import MathView, { MathText } from 'react-native-math-view';

import { useTheme } from '../../../theme';

interface IKaTeXProps {
value: KaTeXProps['value'];
}

export const KaTeX = ({ value }: IKaTeXProps): React.ReactElement | null => {
const { colors } = useTheme();
return <MathView math={value} style={{ color: colors.bodyText }} />;
};

export const InlineKaTeX = ({ value }: IKaTeXProps): React.ReactElement | null => {
const { colors } = useTheme();
return <MathText color value={`$$${value}$$`} direction='ltr' style={{ color: colors.bodyText }} />;
};
6 changes: 6 additions & 0 deletions app/containers/markdown/new/LineBreak.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import React from 'react';
import { View } from 'react-native';

export default function LineBreak() {
return <View style={{ height: 8 }} />;
}
12 changes: 11 additions & 1 deletion app/containers/markdown/new/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import UnorderedList from './UnorderedList';
import { IUserMention, IUserChannel, TOnLinkPress } from '../interfaces';
import TaskList from './TaskList';
import MarkdownContext from './MarkdownContext';
import LineBreak from './LineBreak';
import { KaTeX } from './Katex';

interface IBodyProps {
tokens?: MarkdownAST;
Expand All @@ -35,7 +37,7 @@ const Body = ({
getCustomEmoji,
baseUrl,
onLinkPress
}: IBodyProps) => {
}: IBodyProps): React.ReactElement | null => {
if (isEmpty(tokens)) {
return null;
}
Expand Down Expand Up @@ -70,6 +72,14 @@ const Body = ({
return <Code value={block.value} />;
case 'HEADING':
return <Heading value={block.value} level={block.level} />;
case 'LINE_BREAK':
return <LineBreak />;
// This prop exists, but not even on the web it is treated, so...
// https://github.com/RocketChat/Rocket.Chat/blob/develop/packages/gazzodown/src/Markup.tsx
// case 'LIST_ITEM':
// return <View />;
case 'KATEX':
return <KaTeX value={block.value} />;
default:
return null;
}
Expand Down
8 changes: 5 additions & 3 deletions app/containers/markdown/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,15 @@ export default StyleSheet.create({
paddingTop: 2
},
codeBlock: {
fontSize: 16,
...sharedStyles.textRegular,
...codeFontFamily,
borderWidth: 1,
borderRadius: 4,
padding: 4
},
codeBlockText: {
fontSize: 16,
...sharedStyles.textRegular,
...codeFontFamily
},
link: {
fontSize: 16,
...sharedStyles.textRegular
Expand Down
1 change: 1 addition & 0 deletions app/externalModules.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ declare module 'react-native-mime-types';
declare module 'react-native-restart';
declare module 'react-native-jitsi-meet';
declare module 'rn-root-view';
declare module 'react-native-math-view';
10 changes: 10 additions & 0 deletions jest.setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,13 @@ jest.mock('@gorhom/bottom-sheet', () => {
BottomSheetScrollView: react.ScrollView
};
});

// If you need to manually mock a lib use this mock pattern and set exports.
jest.mock('react-native-math-view', () => {
const react = require('react-native');
return {
__esModule: true,
default: react.View, // Default export
MathText: react.View // {...} Named export
};
});
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
"react-native-jitsi-meet": "RocketChat/react-native-jitsi-meet",
"react-native-keycommands": "2.0.3",
"react-native-localize": "2.1.1",
"react-native-math-view": "^3.9.5",
"react-native-mime-types": "2.3.0",
"react-native-mmkv-storage": "0.6.12",
"react-native-modal": "11.10.0",
Expand Down
39 changes: 39 additions & 0 deletions storybook/stories/NewMarkdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -692,3 +692,42 @@ stories.add('Lists', () => (
<NewMarkdown tokens={tasks} mentions={listMentions} channels={listChannels} />
</View>
));

const katex = [
{
type: 'KATEX',
value: ' f(x) = \\int_{-\\infty}^\\infty \\hat f(\\xi)\\,e^{2 \\pi i \\xi x} \\,d\\xi '
}
];

const inlineKatex = [
{
type: 'PARAGRAPH',
value: [
{
type: 'INLINE_KATEX',
value: 'This text includes math notations and should be wrapped correctly for $\\alpha$ and $\\beta$ within the view.'
},
{
type: 'INLINE_KATEX',
value: "The following formula shouldn't be inline:$$x_{1,2} = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}$$"
},
{
type: 'INLINE_KATEX',
value: 'However the following formula should be inline with the text: \\( a^2 + b^2 = c^2 \\)'
}
]
}
];

stories.add('Katex', () => (
<View style={styles.container}>
<NewMarkdown tokens={katex} />
</View>
));

stories.add('Inline Katex', () => (
<View style={styles.container}>
<NewMarkdown tokens={inlineKatex} />
</View>
));
2 changes: 1 addition & 1 deletion storybook/stories/__snapshots__/Markdown.storyshot

Large diffs are not rendered by default.

Loading

0 comments on commit 376c8e8

Please sign in to comment.