diff --git a/__tests__/__snapshots__/Storyshots.test.js.snap b/__tests__/__snapshots__/Storyshots.test.js.snap
index a5c96752f..332732a14 100644
--- a/__tests__/__snapshots__/Storyshots.test.js.snap
+++ b/__tests__/__snapshots__/Storyshots.test.js.snap
@@ -201,35 +201,40 @@ exports[`Storyshots Message list 1`] = `
-
- Message
-
+ Message
@@ -426,35 +431,40 @@ exports[`Storyshots Message list 1`] = `
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
-
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
@@ -651,35 +661,40 @@ exports[`Storyshots Message list 1`] = `
-
- …
-
+ ...
@@ -858,35 +873,40 @@ exports[`Storyshots Message list 1`] = `
-
- Different user
-
+ Different user
@@ -947,35 +967,40 @@ exports[`Storyshots Message list 1`] = `
>
-
- This is the third message
-
+ This is the third message
@@ -1036,35 +1061,40 @@ exports[`Storyshots Message list 1`] = `
>
-
- This is the second message
-
+ This is the second message
@@ -1243,35 +1273,40 @@ exports[`Storyshots Message list 1`] = `
-
- This is the first message
-
+ This is the first message
@@ -1350,35 +1385,40 @@ exports[`Storyshots Message list 1`] = `
>
-
- Message
-
+ Message
@@ -1589,35 +1629,40 @@ exports[`Storyshots Message list 1`] = `
-
- Message
-
+ Message
@@ -1810,35 +1855,40 @@ exports[`Storyshots Message list 1`] = `
-
- Message
-
+ Message
@@ -2035,35 +2085,576 @@ exports[`Storyshots Message list 1`] = `
+
+ Message
+
+
+
+
+
+
+
+
+
+
+ Block Quote
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+ 10:00 AM
+
+
+
+
+
+
+
-
- Message
+
+
+ Testing block quote
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ diego.mello
+
+
+
+ 10:00 AM
+
+
+
+
+
+
+
+
+
+ Testing block quote
+
+
+
+
+
+
+
+
+ Testing block quote
@@ -2073,6 +2664,1160 @@ exports[`Storyshots Message list 1`] = `
+
+ Lists
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ diego.mello
+
+
+
+ 10:00 AM
+
+
+
+
+
+
+ •
+
+
+
+
+
+
+ Dogs
+
+
+
+
+
+
+ ◦
+
+
+
+
+
+
+ cats
+
+
+
+
+
+
+
+
+ ◦
+
+
+
+
+
+
+ cats
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Numerated lists
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ diego.mello
+
+
+
+ 10:00 AM
+
+
+
+
+
+
+ 1.
+
+
+
+
+
+
+ Dogs
+
+
+
+
+
+
+
+
+ 2.
+
+
+
+
+
+
+ Cats
+
+
+
+
+
+
+
+
+
+
+
+
+ Numerated lists in separated messages
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ diego.mello
+
+
+
+ 10:00 AM
+
+
+
+
+
+
+ 1.
+
+
+
+
+
+
+ Dogs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2.
+
+
+
+
+
+
+ Cats
+
+
+
+
+
+
+
+
+
+
+
-
- Message
-
+ Message
@@ -2485,35 +4235,40 @@ exports[`Storyshots Message list 1`] = `
-
- Message
-
+ Message
@@ -2710,124 +4465,187 @@ exports[`Storyshots Message list 1`] = `
-
+
-
- rocket.cat
-
-
-
-
-
-
+
+
+
-
- diego.mello
-
-
-
-
-
-
+ @diego.mello
+
+
-
- all
-
-
-
-
-
-
+
+
+
-
- here
-
-
-
-
-
-
+ @all
+
+
+
+
+
- #
- general
-
-
+ }
+ >
+ @here
+
+
+
+
+
+ #general
@@ -3024,35 +4842,40 @@ exports[`Storyshots Message list 1`] = `
-
- 👊🤙👏
-
+ 👊🤙👏
@@ -3249,35 +5072,40 @@ exports[`Storyshots Message list 1`] = `
-
- 👏
-
+ 👏
@@ -3474,78 +5302,104 @@ exports[`Storyshots Message list 1`] = `
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
@@ -3741,46 +5595,30 @@ exports[`Storyshots Message list 1`] = `
-
-
-
+ />
@@ -3976,49 +5814,54 @@ exports[`Storyshots Message list 1`] = `
-
- 🤙
-
-
+ 🤙
+
@@ -4214,51 +6057,77 @@ exports[`Storyshots Message list 1`] = `
-
- 🤙
-
-
+
-
- 🤙🤙
-
+ }
+ />
+
+ 🤙🤙
@@ -4455,35 +6324,40 @@ exports[`Storyshots Message list 1`] = `
-
- Testing
-
+ Testing
@@ -4680,35 +6554,40 @@ exports[`Storyshots Message list 1`] = `
-
- Reactions
-
+ Reactions
@@ -5205,35 +7084,40 @@ exports[`Storyshots Message list 1`] = `
-
- Multiple Reactions
-
+ Multiple Reactions
@@ -6103,35 +7987,40 @@ exports[`Storyshots Message list 1`] = `
-
- Fourth message
-
+ Fourth message
@@ -6310,35 +8199,40 @@ exports[`Storyshots Message list 1`] = `
-
- Third message
-
+ Third message
@@ -6517,35 +8411,40 @@ exports[`Storyshots Message list 1`] = `
-
- Second message
-
+ Second message
@@ -6724,35 +8623,40 @@ exports[`Storyshots Message list 1`] = `
-
- First message
-
+ First message
@@ -6949,35 +8853,40 @@ exports[`Storyshots Message list 1`] = `
-
- Fourth message
-
+ Fourth message
@@ -7221,35 +9130,40 @@ exports[`Storyshots Message list 1`] = `
-
- Third message
-
+ Third message
@@ -7357,35 +9271,40 @@ exports[`Storyshots Message list 1`] = `
>
-
- Second message
-
+ Second message
@@ -7564,35 +9483,40 @@ exports[`Storyshots Message list 1`] = `
-
- Second message
-
+ Second message
@@ -7810,35 +9734,40 @@ exports[`Storyshots Message list 1`] = `
-
- First message
-
+ First message
@@ -8090,34 +10019,37 @@ exports[`Storyshots Message list 1`] = `
/>
-
+ }
+ >
+
-
- This is a description
-
+ This is a description
@@ -8352,48 +10284,51 @@ exports[`Storyshots Message list 1`] = `
/>
-
+ }
+ >
+
-
- This is a description
-
-
+ This is a description
+
@@ -8637,48 +10572,51 @@ exports[`Storyshots Message list 1`] = `
-
+ }
+ >
+
-
- This is a description
-
-
+ This is a description
+
@@ -9289,48 +11227,51 @@ exports[`Storyshots Message list 1`] = `
-
+ }
+ >
+
-
- This is a description
-
-
+ This is a description
+
@@ -9389,35 +11330,40 @@ exports[`Storyshots Message list 1`] = `
>
-
- First message
-
+ First message
@@ -9674,34 +11620,37 @@ exports[`Storyshots Message list 1`] = `
-
+ }
+ >
+
-
- This is a description
-
+ This is a description
@@ -10399,35 +12348,88 @@ exports[`Storyshots Message list 1`] = `
-
- I’m fine!
-
+ I
+
+
+ 'm fine
+
+
+ !
@@ -10507,34 +12509,37 @@ exports[`Storyshots Message list 1`] = `
-
+ }
+ >
+
-
- How are you?
-
+ How are you?
@@ -10714,35 +12719,88 @@ exports[`Storyshots Message list 1`] = `
-
- I’m fine!
-
+ I
+
+
+ 'm fine
+
+
+ !
@@ -10822,48 +12880,51 @@ exports[`Storyshots Message list 1`] = `
-
+ }
+ >
+
-
- How are you?
-
-
+ How are you?
+
@@ -11060,35 +13121,88 @@ exports[`Storyshots Message list 1`] = `
-
- I’m fine!
-
+ I
+
+
+ 'm fine
+
+
+ !
@@ -11149,35 +13263,88 @@ exports[`Storyshots Message list 1`] = `
>
-
- I’m fine!
-
+ I
+
+
+ 'm fine
+
+
+ !
@@ -11356,35 +13523,88 @@ exports[`Storyshots Message list 1`] = `
-
- I’m fine!
-
+ I
+
+
+ 'm fine
+
+
+ !
@@ -11467,35 +13687,88 @@ exports[`Storyshots Message list 1`] = `
>
-
- I’m fine!
-
+ I
+
+
+ 'm fine
+
+
+ !
@@ -11714,35 +13987,40 @@ exports[`Storyshots Message list 1`] = `
-
- How are you?
-
+ How are you?
@@ -12002,35 +14280,40 @@ exports[`Storyshots Message list 1`] = `
-
- How are you?
-
+ How are you?
@@ -12320,35 +14603,88 @@ exports[`Storyshots Message list 1`] = `
>
-
- I’m fine!
-
+ I
+
+
+ 'm fine
+
+
+ !
@@ -12557,35 +14893,88 @@ exports[`Storyshots Message list 1`] = `
>
-
- I’m fine!
-
+ I
+
+
+ 'm fine
+
+
+ !
@@ -12794,35 +15183,88 @@ exports[`Storyshots Message list 1`] = `
>
-
- I’m fine!
-
+ I
+
+
+ 'm fine
+
+
+ !
@@ -13031,35 +15473,88 @@ exports[`Storyshots Message list 1`] = `
>
-
- I’m fine!
-
+ I
+
+
+ 'm fine
+
+
+ !
@@ -13268,35 +15763,40 @@ exports[`Storyshots Message list 1`] = `
>
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
-
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
@@ -13505,35 +16005,40 @@ exports[`Storyshots Message list 1`] = `
>
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
-
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
@@ -13947,35 +16452,40 @@ exports[`Storyshots Message list 1`] = `
-
- How are you?
-
+ How are you?
@@ -14190,35 +16700,88 @@ exports[`Storyshots Message list 1`] = `
>
-
- I’m fine!
-
+ I
+
+
+ 'm fine
+
+
+ !
@@ -14352,35 +16915,40 @@ exports[`Storyshots Message list 1`] = `
>
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
-
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
@@ -14749,35 +17317,88 @@ exports[`Storyshots Message list 1`] = `
>
-
- I’m fine!
-
+ I
+
+
+ 'm fine
+
+
+ !
@@ -14911,35 +17532,64 @@ exports[`Storyshots Message list 1`] = `
>
-
- Cool!
-
+ Cool
+
+
+ !
@@ -15073,35 +17723,40 @@ exports[`Storyshots Message list 1`] = `
>
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
-
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
@@ -16968,49 +19623,54 @@ exports[`Storyshots Message list 1`] = `
-
- Message
-
-
+ Message
+
@@ -17391,35 +20051,40 @@ exports[`Storyshots Message list 1`] = `
-
- Message
-
+ Message
@@ -17499,34 +20164,37 @@ exports[`Storyshots Message list 1`] = `
-
+ }
+ >
+
-
- Custom fields
-
+ Custom fields
@@ -17934,35 +20602,40 @@ exports[`Storyshots Message list 1`] = `
-
- Message
-
+ Message
@@ -18042,34 +20715,37 @@ exports[`Storyshots Message list 1`] = `
-
+ }
+ >
+
-
- Custom fields
-
+ Custom fields
@@ -18240,34 +20916,37 @@ exports[`Storyshots Message list 1`] = `
-
+ }
+ >
+
-
- Custom fields 2
-
+ Custom fields 2
@@ -18555,35 +21234,40 @@ exports[`Storyshots Message list 1`] = `
-
- Broadcasted message
-
+ Broadcasted message
@@ -18859,35 +21543,40 @@ exports[`Storyshots Message list 1`] = `
-
- This message is inside an archived room
-
+ This message is inside an archived room
@@ -19115,35 +21804,40 @@ exports[`Storyshots Message list 1`] = `
-
- This message has error
-
+ This message has error
@@ -19284,35 +21978,40 @@ exports[`Storyshots Message list 1`] = `
-
- This message has error too
-
+ This message has error too
@@ -19514,35 +22213,40 @@ exports[`Storyshots Message list 1`] = `
}
>
-
- Temp message
-
+ Temp message
@@ -19739,35 +22443,40 @@ exports[`Storyshots Message list 1`] = `
-
- Message being edited
-
+ Message being edited
@@ -22354,35 +25063,40 @@ exports[`Storyshots Message list 1`] = `
-
- Message
-
+ Message
@@ -22579,102 +25293,325 @@ exports[`Storyshots Message list 1`] = `
-
- Italic with
-
-
+
-
- asterisks
-
-
-
- or
-
-
+ underscore
+
+
+ or double
+
+
-
- underscores
-
-
-
- . Bold with
-
-
+ underscores
+
+
+ . Bold with single
+
+
-
- asterisks
-
-
-
- or
-
-
+ asterisk
+
+
+ or double
+
+
-
- underscores
-
-
-
- .
-
-
+ asterisks
+
+
+ . Strikethrough with single
+
+
-
- Strikethrough
-
-
+ },
+ ]
+ }
+ >
+ Strikethrough
+
+
+ or double
+
+
+ Strikethrough
@@ -22870,184 +25807,150 @@ exports[`Storyshots Message list 1`] = `
-
-
+
-
-
- H1
-
-
-
-
+
+
+
-
-
- H2
-
-
-
-
+
+
+
-
-
- H3
-
-
-
-
+
+
+
-
-
- H4
-
-
-
-
+
+
+
-
-
- H5
-
-
-
-
+
+
+
-
-
- H6
-
-
-
-
+ H6
+
+
@@ -23241,70 +26144,281 @@ exports[`Storyshots Message list 1`] = `
+ Support
+
+
-
- Support
-
-
- Google
-
+ Google
-
-
-
-
+
+
+
+
+
-
- I\`m an inline-style link
-
+ I
-
- https://google.com
+
+ \`
+
+
+ m an inline-style link
+
+
+
+
+
+
+
+ https://google.com
@@ -23502,20 +26616,16 @@ exports[`Storyshots Message list 1`] = `
+
+ Inline
+
-
- Inline
-
-
+
- code
-
-
- has
-
-
+ has
+
+
- back-ticks around
-
-
- it.
-
+ }
+ >
+ back-ticks around
+
+
+ it.
-
- Code block
-
-
+
+ Code block
+
+
@@ -23999,47 +27156,69 @@ exports[`Storyshots Message list 1`] = `
+
-
-
+
Quote
-
+
@@ -24235,99 +27414,52 @@ exports[`Storyshots Message list 1`] = `
-
-
-
-
-
-
- First Header
-
-
-
-
-
-
- Second Header
-
-
-
-
-
-
-
- Content from cell 1
+
+
+ First Header
+
-
+
+
+
+
+ Second Header
+
+
+
-
-
- Content from cell 2
+
+
+ Content from cell 1
+
-
-
-
-
-
-
+
-
- Content in the first column
+
+
+ Content from cell 2
+
-
+
-
-
- Content in the second column
+
+
+ Content in the first column
+
-
+
+
+
+
+ Content in the second column
+
+
+
-
+
+
+ Click to see full table
+
diff --git a/app/containers/MessageBox/ReplyPreview.js b/app/containers/MessageBox/ReplyPreview.js
index 7b821172c..15c070938 100644
--- a/app/containers/MessageBox/ReplyPreview.js
+++ b/app/containers/MessageBox/ReplyPreview.js
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
import moment from 'moment';
import { connect } from 'react-redux';
-import Markdown from '../message/Markdown';
+import Markdown from '../markdown';
import { getCustomEmoji } from '../message/utils';
import { CustomIcon } from '../../lib/Icons';
import sharedStyles from '../../views/Styles';
@@ -50,6 +50,7 @@ const styles = StyleSheet.create({
class ReplyPreview extends Component {
static propTypes = {
+ useMarkdown: PropTypes.bool,
message: PropTypes.object.isRequired,
Message_TimeFormat: PropTypes.string.isRequired,
close: PropTypes.func.isRequired,
@@ -68,7 +69,7 @@ class ReplyPreview extends Component {
render() {
const {
- message, Message_TimeFormat, baseUrl, username
+ message, Message_TimeFormat, baseUrl, username, useMarkdown
} = this.props;
const time = moment(message.ts).format(Message_TimeFormat);
return (
@@ -78,7 +79,7 @@ class ReplyPreview extends Component {
{message.u.username}
{time}
-
+
@@ -87,6 +88,7 @@ class ReplyPreview extends Component {
}
const mapStateToProps = state => ({
+ useMarkdown: state.markdown.useMarkdown,
Message_TimeFormat: state.settings.Message_TimeFormat,
baseUrl: state.settings.Site_Url || state.server ? state.server.server : ''
});
diff --git a/app/containers/markdown/AtMention.js b/app/containers/markdown/AtMention.js
new file mode 100644
index 000000000..375d5d6fe
--- /dev/null
+++ b/app/containers/markdown/AtMention.js
@@ -0,0 +1,51 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Text } from 'react-native';
+
+import styles from './styles';
+
+const AtMention = React.memo(({
+ mention, mentions, username, navToRoomInfo
+}) => {
+ let mentionStyle = styles.mention;
+ if (mention === 'all' || mention === 'here') {
+ mentionStyle = {
+ ...mentionStyle,
+ ...styles.mentionAll
+ };
+ } else if (mention === username) {
+ mentionStyle = {
+ ...mentionStyle,
+ ...styles.mentionLoggedUser
+ };
+ }
+
+ const handlePress = () => {
+ if (mentions && mentions.length && mentions.findIndex(m => m.username === mention) !== -1) {
+ const index = mentions.findIndex(m => m.username === mention);
+ const navParam = {
+ t: 'd',
+ rid: mentions[index]._id
+ };
+ navToRoomInfo(navParam);
+ }
+ };
+
+ return (
+
+ {`@${ mention }`}
+
+ );
+});
+
+AtMention.propTypes = {
+ mention: PropTypes.string,
+ username: PropTypes.string,
+ navToRoomInfo: PropTypes.func,
+ mentions: PropTypes.oneOfType([PropTypes.array, PropTypes.object])
+};
+
+export default AtMention;
diff --git a/app/containers/markdown/BlockQuote.js b/app/containers/markdown/BlockQuote.js
new file mode 100644
index 000000000..65a9963d1
--- /dev/null
+++ b/app/containers/markdown/BlockQuote.js
@@ -0,0 +1,20 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { View } from 'react-native';
+
+import styles from './styles';
+
+const BlockQuote = React.memo(({ children }) => (
+
+
+
+ {children}
+
+
+));
+
+BlockQuote.propTypes = {
+ children: PropTypes.node.isRequired
+};
+
+export default BlockQuote;
diff --git a/app/containers/markdown/Emoji.js b/app/containers/markdown/Emoji.js
new file mode 100644
index 000000000..f60c2cb9a
--- /dev/null
+++ b/app/containers/markdown/Emoji.js
@@ -0,0 +1,35 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Text } from 'react-native';
+import { emojify } from 'react-emojione';
+
+import CustomEmoji from '../EmojiPicker/CustomEmoji';
+
+import styles from './styles';
+
+const Emoji = React.memo(({
+ emojiName, literal, isMessageContainsOnlyEmoji, getCustomEmoji, baseUrl
+}) => {
+ const emojiUnicode = emojify(literal, { output: 'unicode' });
+ const emoji = getCustomEmoji && getCustomEmoji(emojiName);
+ if (emoji) {
+ return (
+
+ );
+ }
+ return {emojiUnicode};
+});
+
+Emoji.propTypes = {
+ emojiName: PropTypes.string,
+ literal: PropTypes.string,
+ isMessageContainsOnlyEmoji: PropTypes.bool,
+ getCustomEmoji: PropTypes.func,
+ baseUrl: PropTypes.string
+};
+
+export default Emoji;
diff --git a/app/containers/markdown/Hashtag.js b/app/containers/markdown/Hashtag.js
new file mode 100644
index 000000000..47e50cb3b
--- /dev/null
+++ b/app/containers/markdown/Hashtag.js
@@ -0,0 +1,38 @@
+import PropTypes from 'prop-types';
+import React from 'react';
+import { Text } from 'react-native';
+
+import styles from './styles';
+
+const Hashtag = React.memo(({
+ hashtag, channels, navToRoomInfo
+}) => {
+ const handlePress = () => {
+ const index = channels.findIndex(channel => channel.name === hashtag);
+ const navParam = {
+ t: 'c',
+ rid: channels[index]._id
+ };
+ navToRoomInfo(navParam);
+ };
+
+ if (channels && channels.length && channels.findIndex(channel => channel.name === hashtag) !== -1) {
+ return (
+
+ {`#${ hashtag }`}
+
+ );
+ }
+ return `#${ hashtag }`;
+});
+
+Hashtag.propTypes = {
+ hashtag: PropTypes.string,
+ navToRoomInfo: PropTypes.func,
+ channels: PropTypes.oneOfType([PropTypes.array, PropTypes.object])
+};
+
+export default Hashtag;
diff --git a/app/containers/markdown/Link.js b/app/containers/markdown/Link.js
new file mode 100644
index 000000000..79b1486c5
--- /dev/null
+++ b/app/containers/markdown/Link.js
@@ -0,0 +1,36 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Text } from 'react-native';
+
+import styles from './styles';
+import openLink from '../../utils/openLink';
+
+const Link = React.memo(({
+ children, link
+}) => {
+ const handlePress = () => {
+ if (!link) {
+ return;
+ }
+ openLink(link);
+ };
+
+ const childLength = React.Children.toArray(children).filter(o => o).length;
+
+ // if you have a [](https://rocket.chat) render https://rocket.chat
+ return (
+
+ { childLength !== 0 ? children : link }
+
+ );
+});
+
+Link.propTypes = {
+ children: PropTypes.node,
+ link: PropTypes.string
+};
+
+export default Link;
diff --git a/app/containers/markdown/List.js b/app/containers/markdown/List.js
new file mode 100644
index 000000000..951b1f306
--- /dev/null
+++ b/app/containers/markdown/List.js
@@ -0,0 +1,39 @@
+import PropTypes from 'prop-types';
+import React from 'react';
+
+const List = React.memo(({
+ children, ordered, start, tight
+}) => {
+ let bulletWidth = 15;
+
+ if (ordered) {
+ const lastNumber = (start + children.length) - 1;
+ bulletWidth = (9 * lastNumber.toString().length) + 7;
+ }
+
+ const _children = React.Children.map(children, (child, index) => React.cloneElement(child, {
+ bulletWidth,
+ ordered,
+ tight,
+ index: start + index
+ }));
+
+ return (
+ <>
+ {_children}
+ >
+ );
+});
+
+List.propTypes = {
+ children: PropTypes.node,
+ ordered: PropTypes.bool,
+ start: PropTypes.number,
+ tight: PropTypes.bool
+};
+
+List.defaultProps = {
+ start: 1
+};
+
+export default List;
diff --git a/app/containers/markdown/ListItem.js b/app/containers/markdown/ListItem.js
new file mode 100644
index 000000000..301c8fed9
--- /dev/null
+++ b/app/containers/markdown/ListItem.js
@@ -0,0 +1,60 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import {
+ StyleSheet,
+ Text,
+ View
+} from 'react-native';
+
+const style = StyleSheet.create({
+ container: {
+ flexDirection: 'row',
+ alignItems: 'flex-start'
+ },
+ bullet: {
+ alignItems: 'flex-end',
+ marginRight: 5
+ },
+ contents: {
+ flex: 1
+ }
+});
+
+const ListItem = React.memo(({
+ children, level, bulletWidth, continue: _continue, ordered, index
+}) => {
+ let bullet;
+ if (_continue) {
+ bullet = '';
+ } else if (ordered) {
+ bullet = `${ index }.`;
+ } else if (level % 2 === 0) {
+ bullet = '◦';
+ } else {
+ bullet = '•';
+ }
+
+ return (
+
+
+
+ {bullet}
+
+
+
+ {children}
+
+
+ );
+});
+
+ListItem.propTypes = {
+ children: PropTypes.node,
+ bulletWidth: PropTypes.number,
+ level: PropTypes.number,
+ ordered: PropTypes.bool,
+ continue: PropTypes.bool,
+ index: PropTypes.number
+};
+
+export default ListItem;
diff --git a/app/containers/markdown/Table.js b/app/containers/markdown/Table.js
new file mode 100644
index 000000000..30d6521b7
--- /dev/null
+++ b/app/containers/markdown/Table.js
@@ -0,0 +1,62 @@
+import { PropTypes } from 'prop-types';
+import React from 'react';
+import {
+ ScrollView,
+ TouchableOpacity,
+ View,
+ Text
+} from 'react-native';
+
+import { CELL_WIDTH } from './TableCell';
+import styles from './styles';
+import Navigation from '../../lib/Navigation';
+import I18n from '../../i18n';
+
+const MAX_HEIGHT = 300;
+
+const Table = React.memo(({
+ children, numColumns
+}) => {
+ const getTableWidth = () => numColumns * CELL_WIDTH;
+
+ const renderRows = (drawExtraBorders = true) => {
+ const tableStyle = [styles.table];
+ if (drawExtraBorders) {
+ tableStyle.push(styles.tableExtraBorders);
+ }
+
+ const rows = React.Children.toArray(children);
+ rows[rows.length - 1] = React.cloneElement(rows[rows.length - 1], {
+ isLastRow: true
+ });
+
+ return (
+
+ {rows}
+
+ );
+ };
+
+ const onPress = () => Navigation.navigate('TableView', { renderRows, tableWidth: getTableWidth() });
+
+ return (
+
+
+ {renderRows(false)}
+
+ {I18n.t('Full_table')}
+
+ );
+});
+
+Table.propTypes = {
+ children: PropTypes.node.isRequired,
+ numColumns: PropTypes.number.isRequired
+};
+
+export default Table;
diff --git a/app/containers/markdown/TableCell.js b/app/containers/markdown/TableCell.js
new file mode 100644
index 000000000..56c6a11de
--- /dev/null
+++ b/app/containers/markdown/TableCell.js
@@ -0,0 +1,39 @@
+import PropTypes from 'prop-types';
+import React from 'react';
+import { Text, View } from 'react-native';
+
+import styles from './styles';
+
+export const CELL_WIDTH = 100;
+
+const TableCell = React.memo(({
+ isLastCell, align, children
+}) => {
+ const cellStyle = [styles.cell];
+ if (!isLastCell) {
+ cellStyle.push(styles.cellRightBorder);
+ }
+
+ let textStyle = null;
+ if (align === 'center') {
+ textStyle = styles.alignCenter;
+ } else if (align === 'right') {
+ textStyle = styles.alignRight;
+ }
+
+ return (
+
+
+ {children}
+
+
+ );
+});
+
+TableCell.propTypes = {
+ align: PropTypes.oneOf(['', 'left', 'center', 'right']),
+ children: PropTypes.node,
+ isLastCell: PropTypes.bool
+};
+
+export default TableCell;
diff --git a/app/containers/markdown/TableRow.js b/app/containers/markdown/TableRow.js
new file mode 100644
index 000000000..6a9789804
--- /dev/null
+++ b/app/containers/markdown/TableRow.js
@@ -0,0 +1,28 @@
+import PropTypes from 'prop-types';
+import React from 'react';
+import { View } from 'react-native';
+
+import styles from './styles';
+
+const TableRow = React.memo(({
+ isLastRow, children: _children
+}) => {
+ const rowStyle = [styles.row];
+ if (!isLastRow) {
+ rowStyle.push(styles.rowBottomBorder);
+ }
+
+ const children = React.Children.toArray(_children);
+ children[children.length - 1] = React.cloneElement(children[children.length - 1], {
+ isLastCell: true
+ });
+
+ return {children};
+});
+
+TableRow.propTypes = {
+ children: PropTypes.node,
+ isLastRow: PropTypes.bool
+};
+
+export default TableRow;
diff --git a/app/containers/markdown/index.js b/app/containers/markdown/index.js
new file mode 100644
index 000000000..43e35c86c
--- /dev/null
+++ b/app/containers/markdown/index.js
@@ -0,0 +1,295 @@
+import React, { PureComponent } from 'react';
+import { View, Text, Image } from 'react-native';
+import { Parser, Node } from 'commonmark';
+import Renderer from 'commonmark-react-renderer';
+import PropTypes from 'prop-types';
+
+import I18n from '../../i18n';
+
+import MarkdownLink from './Link';
+import MarkdownList from './List';
+import MarkdownListItem from './ListItem';
+import MarkdownAtMention from './AtMention';
+import MarkdownHashtag from './Hashtag';
+import MarkdownBlockQuote from './BlockQuote';
+import MarkdownEmoji from './Emoji';
+import MarkdownTable from './Table';
+import MarkdownTableRow from './TableRow';
+import MarkdownTableCell from './TableCell';
+
+import styles from './styles';
+
+// Support
+const formatText = text => text.replace(
+ new RegExp('(?:<|<)((?:https|http):\\/\\/[^\\|]+)\\|(.+?)(?=>|>)(?:>|>)', 'gm'),
+ (match, url, title) => `[${ title }](${ url })`
+);
+
+const emojiRanges = [
+ '\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff]', // unicode emoji from https://www.regextester.com/106421
+ ':.{1,40}:', // custom emoji
+ ' |\n' // allow spaces and line breaks
+].join('|');
+
+const removeAllEmoji = str => str.replace(new RegExp(emojiRanges, 'g'), '');
+
+const isOnlyEmoji = str => !removeAllEmoji(str).length;
+
+const removeOneEmoji = str => str.replace(new RegExp(emojiRanges), '');
+
+const emojiCount = (str) => {
+ let oldLength = 0;
+ let counter = 0;
+
+ while (oldLength !== str.length) {
+ oldLength = str.length;
+ str = removeOneEmoji(str);
+ if (oldLength !== str.length) {
+ counter += 1;
+ }
+ }
+
+ return counter;
+};
+
+export default class Markdown extends PureComponent {
+ static propTypes = {
+ msg: PropTypes.string,
+ getCustomEmoji: PropTypes.func,
+ baseUrl: PropTypes.string,
+ username: PropTypes.string,
+ tmid: PropTypes.string,
+ isEdited: PropTypes.bool,
+ numberOfLines: PropTypes.number,
+ useMarkdown: PropTypes.bool,
+ channels: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
+ mentions: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
+ navToRoomInfo: PropTypes.func
+ };
+
+ constructor(props) {
+ super(props);
+
+ this.parser = this.createParser();
+ this.renderer = this.createRenderer();
+ }
+
+ createParser = () => new Parser();
+
+ createRenderer = () => new Renderer({
+ renderers: {
+ text: this.renderText,
+
+ emph: Renderer.forwardChildren,
+ strong: Renderer.forwardChildren,
+ del: Renderer.forwardChildren,
+ code: this.renderCodeInline,
+ link: this.renderLink,
+ image: this.renderImage,
+ atMention: this.renderAtMention,
+ emoji: this.renderEmoji,
+ hashtag: this.renderHashtag,
+
+ paragraph: this.renderParagraph,
+ heading: this.renderHeading,
+ codeBlock: this.renderCodeBlock,
+ blockQuote: this.renderBlockQuote,
+
+ list: this.renderList,
+ item: this.renderListItem,
+
+ hardBreak: this.renderBreak,
+ thematicBreak: this.renderBreak,
+ softBreak: this.renderBreak,
+
+ htmlBlock: this.renderText,
+ htmlInline: this.renderText,
+
+ table: this.renderTable,
+ table_row: this.renderTableRow,
+ table_cell: this.renderTableCell,
+
+ editedIndicator: this.renderEditedIndicator
+ },
+ renderParagraphsInLists: true
+ });
+
+ editedMessage = (ast) => {
+ const { isEdited } = this.props;
+ if (isEdited) {
+ const editIndicatorNode = new Node('edited_indicator');
+ if (ast.lastChild && ['heading', 'paragraph'].includes(ast.lastChild.type)) {
+ ast.lastChild.appendChild(editIndicatorNode);
+ } else {
+ const node = new Node('paragraph');
+ node.appendChild(editIndicatorNode);
+
+ ast.appendChild(node);
+ }
+ }
+ };
+
+ renderText = ({ context, literal }) => {
+ const { numberOfLines } = this.props;
+ return (
+ styles[type])
+ ]}
+ numberOfLines={numberOfLines}
+ >
+ {literal}
+
+ );
+ }
+
+ renderCodeInline = ({ literal }) => {literal};
+
+ renderCodeBlock = ({ literal }) => {literal};
+
+ renderBreak = () => {
+ const { tmid } = this.props;
+ return {tmid ? ' ' : '\n'};
+ }
+
+ renderParagraph = ({ children }) => {
+ const { numberOfLines } = this.props;
+
+ if (!children || children.length === 0) {
+ return null;
+ }
+ return (
+
+
+ {children}
+
+
+ );
+ };
+
+ renderLink = ({ children, href }) => (
+
+ {children}
+
+ );
+
+ renderHashtag = ({ hashtag }) => {
+ const { channels, navToRoomInfo } = this.props;
+ return (
+
+ );
+ }
+
+ renderAtMention = ({ mentionName }) => {
+ const { username, mentions, navToRoomInfo } = this.props;
+ return (
+
+ );
+ }
+
+ renderEmoji = ({ emojiName, literal }) => {
+ const { getCustomEmoji, baseUrl } = this.props;
+ return (
+
+ );
+ }
+
+ renderImage = ({ src }) => ;
+
+ renderEditedIndicator = () => ({I18n.t('edited')});
+
+ renderHeading = ({ children, level }) => {
+ const textStyle = styles[`heading${ level }Text`];
+ return (
+
+ {children}
+
+ );
+ };
+
+ renderList = ({
+ children, start, tight, type
+ }) => (
+
+ {children}
+
+ );
+
+ renderListItem = ({
+ children, context, ...otherProps
+ }) => {
+ const level = context.filter(type => type === 'list').length;
+
+ return (
+
+ {children}
+
+ );
+ };
+
+ renderBlockQuote = ({ children }) => (
+
+ {children}
+
+ );
+
+ renderTable = ({ children, numColumns }) => (
+
+ {children}
+
+ );
+
+ renderTableRow = args => ;
+
+ renderTableCell = args => ;
+
+ render() {
+ const {
+ msg, useMarkdown = true, numberOfLines
+ } = this.props;
+
+ if (!msg) {
+ return null;
+ }
+
+ let m = formatText(msg);
+
+ // Ex: '[ ](https://open.rocket.chat/group/test?msg=abcdef) Test'
+ // Return: 'Test'
+ m = m.replace(/^\[([\s]]*)\]\(([^)]*)\)\s/, '').trim();
+
+ if (!useMarkdown) {
+ return {m};
+ }
+
+ const ast = this.parser.parse(m);
+ this.isMessageContainsOnlyEmoji = isOnlyEmoji(m) && emojiCount(m) <= 3;
+
+ this.editedMessage(ast);
+
+ return this.renderer.render(ast);
+ }
+}
diff --git a/app/containers/markdown/styles.js b/app/containers/markdown/styles.js
new file mode 100644
index 000000000..b2642fdc6
--- /dev/null
+++ b/app/containers/markdown/styles.js
@@ -0,0 +1,183 @@
+import { StyleSheet, Platform } from 'react-native';
+
+import sharedStyles from '../../views/Styles';
+import {
+ COLOR_BORDER, COLOR_PRIMARY, COLOR_WHITE, COLOR_BACKGROUND_CONTAINER
+} from '../../constants/colors';
+
+const codeFontFamily = Platform.select({
+ ios: { fontFamily: 'Courier New' },
+ android: { fontFamily: 'monospace' }
+});
+
+export default StyleSheet.create({
+ container: {
+ alignItems: 'flex-start',
+ flexDirection: 'row'
+ },
+ childContainer: {
+ flex: 1
+ },
+ block: {
+ alignItems: 'flex-start',
+ flexDirection: 'row',
+ flexWrap: 'wrap'
+ },
+ emph: {
+ fontStyle: 'italic'
+ },
+ strong: {
+ fontWeight: 'bold'
+ },
+ del: {
+ textDecorationLine: 'line-through'
+ },
+ text: {
+ fontSize: 16,
+ ...sharedStyles.textColorNormal,
+ ...sharedStyles.textRegular
+ },
+ textInfo: {
+ fontStyle: 'italic',
+ fontSize: 16,
+ ...sharedStyles.textColorDescription,
+ ...sharedStyles.textRegular
+ },
+ textBig: {
+ fontSize: 30,
+ ...sharedStyles.textColorNormal,
+ ...sharedStyles.textRegular
+ },
+ customEmoji: {
+ width: 20,
+ height: 20
+ },
+ customEmojiBig: {
+ width: 30,
+ height: 30
+ },
+ temp: { opacity: 0.3 },
+ mention: {
+ fontSize: 16,
+ color: '#0072FE',
+ padding: 5,
+ ...sharedStyles.textMedium,
+ backgroundColor: '#E8F2FF'
+ },
+ mentionLoggedUser: {
+ color: COLOR_WHITE,
+ backgroundColor: COLOR_PRIMARY
+ },
+ mentionAll: {
+ color: COLOR_WHITE,
+ backgroundColor: '#FF5B5A'
+ },
+ paragraph: {
+ marginTop: 0,
+ marginBottom: 0,
+ flexWrap: 'wrap',
+ flexDirection: 'row',
+ alignItems: 'flex-start',
+ justifyContent: 'flex-start'
+ },
+ inlineImage: {
+ width: 300,
+ height: 300,
+ resizeMode: 'contain'
+ },
+ codeInline: {
+ ...sharedStyles.textRegular,
+ ...codeFontFamily,
+ borderWidth: 1,
+ backgroundColor: COLOR_BACKGROUND_CONTAINER,
+ borderRadius: 4
+ },
+ codeBlock: {
+ ...sharedStyles.textRegular,
+ ...codeFontFamily,
+ backgroundColor: COLOR_BACKGROUND_CONTAINER,
+ borderColor: COLOR_BORDER,
+ borderWidth: 1,
+ borderRadius: 4,
+ padding: 4
+ },
+ link: {
+ fontSize: 16,
+ color: COLOR_PRIMARY,
+ ...sharedStyles.textRegular
+ },
+ edited: {
+ fontSize: 14,
+ ...sharedStyles.textColorDescription,
+ ...sharedStyles.textRegular
+ },
+ heading1: {
+ ...sharedStyles.textBold,
+ fontSize: 24
+ },
+ heading2: {
+ ...sharedStyles.textBold,
+ fontSize: 22
+ },
+ heading3: {
+ ...sharedStyles.textSemibold,
+ fontSize: 20
+ },
+ heading4: {
+ ...sharedStyles.textSemibold,
+ fontSize: 18
+ },
+ heading5: {
+ ...sharedStyles.textMedium,
+ fontSize: 16
+ },
+ heading6: {
+ ...sharedStyles.textMedium,
+ fontSize: 14
+ },
+ quote: {
+ height: '100%',
+ width: 2,
+ backgroundColor: COLOR_BORDER,
+ marginRight: 5
+ },
+ touchableTable: {
+ justifyContent: 'center'
+ },
+ containerTable: {
+ borderBottomWidth: 1,
+ borderColor: COLOR_BORDER,
+ borderRightWidth: 1
+ },
+ table: {
+ borderColor: COLOR_BORDER,
+ borderLeftWidth: 1,
+ borderTopWidth: 1
+ },
+ tableExtraBorders: {
+ borderBottomWidth: 1,
+ borderRightWidth: 1
+ },
+ row: {
+ flexDirection: 'row'
+ },
+ rowBottomBorder: {
+ borderColor: COLOR_BORDER,
+ borderBottomWidth: 1
+ },
+ cell: {
+ borderColor: COLOR_BORDER,
+ justifyContent: 'flex-start',
+ paddingHorizontal: 13,
+ paddingVertical: 6
+ },
+ cellRightBorder: {
+ borderRightWidth: 1
+ },
+ alignCenter: {
+ textAlign: 'center'
+ },
+ alignRight: {
+ textAlign: 'right'
+ }
+});
diff --git a/app/containers/message/Audio.js b/app/containers/message/Audio.js
index e78e310f1..4d411df9d 100644
--- a/app/containers/message/Audio.js
+++ b/app/containers/message/Audio.js
@@ -9,7 +9,7 @@ import moment from 'moment';
import equal from 'deep-equal';
import Touchable from 'react-native-platform-touchable';
-import Markdown from './Markdown';
+import Markdown from '../markdown';
import { CustomIcon } from '../../lib/Icons';
import sharedStyles from '../../views/Styles';
import { COLOR_BACKGROUND_CONTAINER, COLOR_BORDER, COLOR_PRIMARY } from '../../constants/colors';
diff --git a/app/containers/message/Content.js b/app/containers/message/Content.js
index a9d899ab1..efcf43c8c 100644
--- a/app/containers/message/Content.js
+++ b/app/containers/message/Content.js
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
import I18n from '../../i18n';
import styles from './styles';
-import Markdown from './Markdown';
+import Markdown from '../markdown';
import { getInfoMessage } from './utils';
const Content = React.memo((props) => {
@@ -21,14 +21,15 @@ const Content = React.memo((props) => {
);
}
@@ -43,16 +44,16 @@ const Content = React.memo((props) => {
Content.propTypes = {
isTemp: PropTypes.bool,
isInfo: PropTypes.bool,
- isEdited: PropTypes.bool,
- useMarkdown: PropTypes.bool,
tmid: PropTypes.string,
msg: PropTypes.string,
+ isEdited: PropTypes.bool,
+ useMarkdown: PropTypes.bool,
baseUrl: PropTypes.string,
user: PropTypes.object,
- mentions: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
+ getCustomEmoji: PropTypes.func,
channels: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
- navToRoomInfo: PropTypes.func,
- getCustomEmoji: PropTypes.func
+ mentions: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
+ navToRoomInfo: PropTypes.func
};
Content.displayName = 'MessageContent';
diff --git a/app/containers/message/Image.js b/app/containers/message/Image.js
index 7848f43a4..e4af59257 100644
--- a/app/containers/message/Image.js
+++ b/app/containers/message/Image.js
@@ -5,7 +5,7 @@ import FastImage from 'react-native-fast-image';
import equal from 'deep-equal';
import Touchable from 'react-native-platform-touchable';
-import Markdown from './Markdown';
+import Markdown from '../markdown';
import styles from './styles';
import { formatAttachmentUrl } from '../../lib/utils';
diff --git a/app/containers/message/Markdown.js b/app/containers/message/Markdown.js
deleted file mode 100644
index b7622b0b2..000000000
--- a/app/containers/message/Markdown.js
+++ /dev/null
@@ -1,187 +0,0 @@
-import React from 'react';
-import { Text, Image } from 'react-native';
-import PropTypes from 'prop-types';
-import { emojify } from 'react-emojione';
-import MarkdownRenderer, { PluginContainer } from 'react-native-markdown-renderer';
-import MarkdownFlowdock from 'markdown-it-flowdock';
-
-import styles from './styles';
-import CustomEmoji from '../EmojiPicker/CustomEmoji';
-import MarkdownEmojiPlugin from './MarkdownEmojiPlugin';
-import I18n from '../../i18n';
-
-const EmojiPlugin = new PluginContainer(MarkdownEmojiPlugin);
-const MentionsPlugin = new PluginContainer(MarkdownFlowdock);
-const plugins = [EmojiPlugin, MentionsPlugin];
-
-// Support
-const formatText = text => text.replace(
- new RegExp('(?:<|<)((?:https|http):\\/\\/[^\\|]+)\\|(.+?)(?=>|>)(?:>|>)', 'gm'),
- (match, url, title) => `[${ title }](${ url })`
-);
-
-const emojiRanges = [
- '\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff]', // unicode emoji from https://www.regextester.com/106421
- ':.{1,40}:', // custom emoji
- ' |\n' // allow spaces and line breaks
-].join('|');
-
-const removeAllEmoji = str => str.replace(new RegExp(emojiRanges, 'g'), '');
-
-const isOnlyEmoji = str => !removeAllEmoji(str).length;
-
-const removeOneEmoji = str => str.replace(new RegExp(emojiRanges), '');
-
-const emojiCount = (str) => {
- let oldLength = 0;
- let counter = 0;
-
- while (oldLength !== str.length) {
- oldLength = str.length;
- str = removeOneEmoji(str);
- if (oldLength !== str.length) {
- counter += 1;
- }
- }
-
- return counter;
-};
-
-const Markdown = React.memo(({
- msg, style, rules, baseUrl, username, isEdited, numberOfLines, mentions, channels, getCustomEmoji, useMarkdown = true, navToRoomInfo
-}) => {
- if (!msg) {
- return null;
- }
- let m = formatText(msg);
- if (m) {
- m = emojify(m, { output: 'unicode' });
- }
- m = m.replace(/^\[([^\]]*)\]\(([^)]*)\)\s/, '').trim();
- if (numberOfLines > 0) {
- m = m.replace(/[\n]+/g, '\n').trim();
- }
-
- if (!useMarkdown) {
- return {m};
- }
-
- const isMessageContainsOnlyEmoji = isOnlyEmoji(m) && emojiCount(m) <= 3;
-
- return (
- (
-
- {children}
- {isEdited ? ({I18n.t('edited')}) : null}
-
- ),
- mention: (node) => {
- const { content, key } = node;
- let mentionStyle = styles.mention;
- if (content === 'all' || content === 'here') {
- mentionStyle = {
- ...mentionStyle,
- ...styles.mentionAll
- };
- } else if (content === username) {
- mentionStyle = {
- ...mentionStyle,
- ...styles.mentionLoggedUser
- };
- }
- if (mentions && mentions.length && mentions.findIndex(mention => mention.username === content) !== -1) {
- const index = mentions.findIndex(mention => mention.username === content);
- const navParam = {
- t: 'd',
- rid: mentions[index]._id
- };
- return (
- navToRoomInfo(navParam)}
- >
- {content}
-
- );
- }
- return `@${ content }`;
- },
- hashtag: (node) => {
- const { content, key } = node;
- if (channels && channels.length && channels.findIndex(channel => channel.name === content) !== -1) {
- const index = channels.findIndex(channel => channel.name === content);
- const navParam = {
- t: 'c',
- rid: channels[index]._id
- };
- return (
- navToRoomInfo(navParam)}
- >
- #{content}
-
- );
- }
- return `#${ content }`;
- },
- emoji: (node) => {
- if (node.children && node.children.length && node.children[0].content) {
- const { content } = node.children[0];
- const emoji = getCustomEmoji && getCustomEmoji(content);
- if (emoji) {
- return (
-
- );
- }
- return :{content}:;
- }
- return null;
- },
- hardbreak: () => null,
- blocklink: () => null,
- image: node => (
-
- ),
- ...rules
- }}
- style={{
- paragraph: styles.paragraph,
- text: isMessageContainsOnlyEmoji ? styles.textBig : styles.text,
- codeInline: styles.codeInline,
- codeBlock: styles.codeBlock,
- link: styles.link,
- ...style
- }}
- plugins={plugins}
- >{m}
-
- );
-});
-
-Markdown.propTypes = {
- msg: PropTypes.string,
- username: PropTypes.string,
- baseUrl: PropTypes.string,
- style: PropTypes.any,
- rules: PropTypes.object,
- isEdited: PropTypes.bool,
- numberOfLines: PropTypes.number,
- useMarkdown: PropTypes.bool,
- mentions: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
- channels: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
- getCustomEmoji: PropTypes.func,
- navToRoomInfo: PropTypes.func
-};
-Markdown.displayName = 'MessageMarkdown';
-
-export default Markdown;
diff --git a/app/containers/message/MarkdownEmojiPlugin.js b/app/containers/message/MarkdownEmojiPlugin.js
deleted file mode 100644
index 920c27b51..000000000
--- a/app/containers/message/MarkdownEmojiPlugin.js
+++ /dev/null
@@ -1,78 +0,0 @@
-export default function(md) {
- function tokenize(state, silent) {
- let token;
- const start = state.pos;
- const marker = state.src.charCodeAt(start);
-
- if (silent) {
- return false;
- }
-
- // :
- if (marker !== 58) {
- return false;
- }
-
- const scanned = state.scanDelims(state.pos, true);
- const len = scanned.length;
- const ch = String.fromCharCode(marker);
-
- for (let i = 0; i < len; i += 1) {
- token = state.push('text', '', 0);
- token.content = ch;
-
- state.delimiters.push({
- marker,
- jump: i,
- token: state.tokens.length - 1,
- level: state.level,
- end: -1,
- open: scanned.can_open,
- close: scanned.can_close
- });
- }
-
- state.pos += scanned.length;
- return true;
- }
-
- function postProcess(state) {
- let startDelim;
- let endDelim;
- let token;
- const { delimiters } = state;
- const max = delimiters.length;
-
- for (let i = 0; i < max; i += 1) {
- startDelim = delimiters[i];
-
- // :
- if (startDelim.marker !== 58) {
- continue; // eslint-disable-line
- }
-
- if (startDelim.end === -1) {
- continue; // eslint-disable-line
- }
-
- endDelim = delimiters[startDelim.end];
-
- token = state.tokens[startDelim.token];
- token.type = 'emoji_open';
- token.tag = 'emoji';
- token.nesting = 1;
- token.markup = ':';
- token.content = '';
-
- token = state.tokens[endDelim.token];
- token.type = 'emoji_close';
- token.tag = 'emoji';
- token.nesting = -1;
- token.markup = ':';
- token.content = '';
- }
- }
-
- md.inline.ruler.before('emphasis', 'emoji', tokenize);
- md.inline.ruler2.before('emphasis', 'emoji', postProcess);
-}
diff --git a/app/containers/message/Reply.js b/app/containers/message/Reply.js
index efa980b33..4b2af8e58 100644
--- a/app/containers/message/Reply.js
+++ b/app/containers/message/Reply.js
@@ -5,7 +5,7 @@ import moment from 'moment';
import Touchable from 'react-native-platform-touchable';
import isEqual from 'deep-equal';
-import Markdown from './Markdown';
+import Markdown from '../markdown';
import openLink from '../../utils/openLink';
import sharedStyles from '../../views/Styles';
import { COLOR_BACKGROUND_CONTAINER, COLOR_BORDER } from '../../constants/colors';
diff --git a/app/containers/message/Video.js b/app/containers/message/Video.js
index b56c41ac3..d67107795 100644
--- a/app/containers/message/Video.js
+++ b/app/containers/message/Video.js
@@ -4,7 +4,7 @@ import { StyleSheet } from 'react-native';
import Touchable from 'react-native-platform-touchable';
import isEqual from 'deep-equal';
-import Markdown from './Markdown';
+import Markdown from '../markdown';
import openLink from '../../utils/openLink';
import { isIOS } from '../../utils/deviceInfo';
import { CustomIcon } from '../../lib/Icons';
diff --git a/app/containers/message/styles.js b/app/containers/message/styles.js
index 605bc5c2e..3113f542a 100644
--- a/app/containers/message/styles.js
+++ b/app/containers/message/styles.js
@@ -1,15 +1,10 @@
-import { StyleSheet, Platform } from 'react-native';
+import { StyleSheet } from 'react-native';
import sharedStyles from '../../views/Styles';
import {
- COLOR_BORDER, COLOR_PRIMARY, COLOR_WHITE, COLOR_BACKGROUND_CONTAINER
+ COLOR_BORDER, COLOR_PRIMARY, COLOR_WHITE
} from '../../constants/colors';
-const codeFontFamily = Platform.select({
- ios: { fontFamily: 'Courier New' },
- android: { fontFamily: 'monospace' }
-});
-
export default StyleSheet.create({
root: {
flexDirection: 'row'
@@ -34,30 +29,6 @@ export default StyleSheet.create({
flexDirection: 'row'
// flex: 1
},
- text: {
- fontSize: 16,
- ...sharedStyles.textColorNormal,
- ...sharedStyles.textRegular
- },
- textBig: {
- fontSize: 30,
- ...sharedStyles.textColorNormal,
- ...sharedStyles.textRegular
- },
- textInfo: {
- fontStyle: 'italic',
- fontSize: 16,
- ...sharedStyles.textColorDescription,
- ...sharedStyles.textRegular
- },
- customEmoji: {
- width: 20,
- height: 20
- },
- customEmojiBig: {
- width: 30,
- height: 30
- },
temp: { opacity: 0.3 },
marginTop: {
marginTop: 6
@@ -143,28 +114,6 @@ export default StyleSheet.create({
fontSize: 14,
...sharedStyles.textMedium
},
- mention: {
- ...sharedStyles.textMedium,
- color: '#0072FE',
- padding: 5,
- backgroundColor: '#E8F2FF'
- },
- mentionLoggedUser: {
- color: COLOR_WHITE,
- backgroundColor: COLOR_PRIMARY
- },
- mentionAll: {
- color: COLOR_WHITE,
- backgroundColor: '#FF5B5A'
- },
- paragraph: {
- marginTop: 0,
- marginBottom: 0,
- flexWrap: 'wrap',
- flexDirection: 'row',
- alignItems: 'flex-start',
- justifyContent: 'flex-start'
- },
imageContainer: {
// flex: 1,
flexDirection: 'column',
@@ -186,29 +135,15 @@ export default StyleSheet.create({
height: 300,
resizeMode: 'contain'
},
- edited: {
- fontSize: 14,
- ...sharedStyles.textColorDescription,
+ text: {
+ fontSize: 16,
+ ...sharedStyles.textColorNormal,
...sharedStyles.textRegular
},
- codeInline: {
- ...sharedStyles.textRegular,
- ...codeFontFamily,
- borderWidth: 1,
- backgroundColor: COLOR_BACKGROUND_CONTAINER,
- borderRadius: 4
- },
- codeBlock: {
- ...sharedStyles.textRegular,
- ...codeFontFamily,
- backgroundColor: COLOR_BACKGROUND_CONTAINER,
- borderColor: COLOR_BORDER,
- borderWidth: 1,
- borderRadius: 4,
- padding: 4
- },
- link: {
- color: COLOR_PRIMARY,
+ textInfo: {
+ fontStyle: 'italic',
+ fontSize: 16,
+ ...sharedStyles.textColorDescription,
...sharedStyles.textRegular
},
startedDiscussion: {
diff --git a/app/i18n/locales/en.js b/app/i18n/locales/en.js
index 0bd3e712f..cf1803758 100644
--- a/app/i18n/locales/en.js
+++ b/app/i18n/locales/en.js
@@ -181,6 +181,7 @@ export default {
Forgot_password_If_this_email_is_registered: 'If this email is registered, we\'ll send instructions on how to reset your password. If you do not receive an email shortly, please come back and try again.',
Forgot_password: 'Forgot password',
Forgot_Password: 'Forgot Password',
+ Full_table: 'Click to see full table',
Group_by_favorites: 'Group favorites',
Group_by_type: 'Group by type',
Hide: 'Hide',
@@ -360,6 +361,7 @@ export default {
Start_of_conversation: 'Start of conversation',
Started_discussion: 'Started a discussion:',
Submit: 'Submit',
+ Table: 'Table',
Take_a_photo: 'Take a photo',
Take_a_video: 'Take a video',
tap_to_change_status: 'tap to change status',
diff --git a/app/i18n/locales/pt-BR.js b/app/i18n/locales/pt-BR.js
index 2e8ea6051..6653c136a 100644
--- a/app/i18n/locales/pt-BR.js
+++ b/app/i18n/locales/pt-BR.js
@@ -178,6 +178,7 @@ export default {
Forgot_password_If_this_email_is_registered: 'Se este e-mail estiver cadastrado, enviaremos instruções sobre como redefinir sua senha. Se você não receber um e-mail em breve, volte e tente novamente.',
Forgot_password: 'Esqueci minha senha',
Forgot_Password: 'Esqueci minha senha',
+ Full_table: 'Clique para ver a tabela completa',
Group_by_favorites: 'Agrupar favoritos',
Group_by_type: 'Agrupar por tipo',
Has_joined_the_channel: 'Entrou no canal',
@@ -326,6 +327,7 @@ export default {
Start_of_conversation: 'Início da conversa',
Started_discussion: 'Iniciou uma discussão:',
Submit: 'Enviar',
+ Table: 'Tabela',
Take_a_photo: 'Tirar uma foto',
Take_a_video: 'Gravar um vídeo',
Terms_of_Service: ' Termos de Serviço ',
diff --git a/app/index.js b/app/index.js
index 0a4f584c9..2b33616af 100644
--- a/app/index.js
+++ b/app/index.js
@@ -122,6 +122,9 @@ const ChatsStack = createStackNavigator({
DirectoryView: {
getScreen: () => require('./views/DirectoryView').default
},
+ TableView: {
+ getScreen: () => require('./views/TableView').default
+ },
NotificationPrefView: {
getScreen: () => require('./views/NotificationPreferencesView').default
}
diff --git a/app/views/SearchMessagesView/index.js b/app/views/SearchMessagesView/index.js
index 4465cd23b..2ac7a50b6 100644
--- a/app/views/SearchMessagesView/index.js
+++ b/app/views/SearchMessagesView/index.js
@@ -8,7 +8,7 @@ import equal from 'deep-equal';
import RCTextInput from '../../containers/TextInput';
import RCActivityIndicator from '../../containers/ActivityIndicator';
import styles from './styles';
-import Markdown from '../../containers/message/Markdown';
+import Markdown from '../../containers/markdown';
import debounce from '../../utils/debounce';
import RocketChat from '../../lib/rocketchat';
import Message from '../../containers/message/Message';
diff --git a/app/views/TableView.js b/app/views/TableView.js
new file mode 100644
index 000000000..6f61fee43
--- /dev/null
+++ b/app/views/TableView.js
@@ -0,0 +1,38 @@
+import React from 'react';
+import { ScrollView } from 'react-native';
+import PropTypes from 'prop-types';
+
+import I18n from '../i18n';
+import { isIOS } from '../utils/deviceInfo';
+
+export default class TableView extends React.Component {
+ static navigationOptions = () => ({
+ title: I18n.t('Table')
+ });
+
+ static propTypes = {
+ navigation: PropTypes.object
+ }
+
+ render() {
+ const { navigation } = this.props;
+ const renderRows = navigation.getParam('renderRows');
+ const tableWidth = navigation.getParam('tableWidth');
+
+ if (isIOS) {
+ return (
+
+ {renderRows()}
+
+ );
+ }
+
+ return (
+
+
+ {renderRows()}
+
+
+ );
+ }
+}
diff --git a/package.json b/package.json
index 33aa7a88f..ee4f5cf50 100644
--- a/package.json
+++ b/package.json
@@ -24,6 +24,8 @@
},
"dependencies": {
"@rocket.chat/sdk": "1.0.0-alpha.30",
+ "commonmark": "git+https://github.com/RocketChat/commonmark.js.git",
+ "commonmark-react-renderer": "git+https://github.com/RocketChat/commonmark-react-renderer.git",
"bugsnag-react-native": "^2.22.3",
"deep-equal": "^1.0.1",
"ejson": "2.2.0",
@@ -34,7 +36,6 @@
"js-base64": "^2.5.1",
"js-sha256": "^0.9.0",
"lodash": "4.17.15",
- "markdown-it-flowdock": "0.3.8",
"moment": "^2.24.0",
"prop-types": "15.7.2",
"react": "16.8.6",
@@ -56,7 +57,6 @@
"react-native-keyboard-input": "^5.3.1",
"react-native-keyboard-tracking-view": "^5.5.0",
"react-native-localize": "^1.1.4",
- "react-native-markdown-renderer": "^3.2.8",
"react-native-mime-types": "^2.2.1",
"react-native-modal": "^11.3.0",
"react-native-notifications": "^2.0.6",
@@ -90,7 +90,8 @@
"rn-user-defaults": "^1.3.5",
"semver": "6.3.0",
"snyk": "1.210.0",
- "strip-ansi": "5.2.0"
+ "strip-ansi": "5.2.0",
+ "url-parse": "^1.4.7"
},
"devDependencies": {
"@babel/core": "^7.5.5",
diff --git a/patches/react-native-markdown-renderer+3.2.8.patch b/patches/react-native-markdown-renderer+3.2.8.patch
deleted file mode 100644
index 02379a174..000000000
--- a/patches/react-native-markdown-renderer+3.2.8.patch
+++ /dev/null
@@ -1,23 +0,0 @@
-diff --git a/node_modules/react-native-markdown-renderer/src/index.js b/node_modules/react-native-markdown-renderer/src/index.js
-index 653bba2..e5cb521 100644
---- a/node_modules/react-native-markdown-renderer/src/index.js
-+++ b/node_modules/react-native-markdown-renderer/src/index.js
-@@ -88,9 +88,15 @@ export default class Markdown extends Component {
- }),
- };
-
-- copy = '';
-- renderer = null;
-- markdownParser = null;
-+ constructor(props) {
-+ super(props);
-+ this.copy = '';
-+ this.renderer = null;
-+ this.markdownParser = null;
-+ }
-+ // copy = '';
-+ // renderer = null;
-+ // markdownParser = null;
-
- /**
- * Only when the copy changes will the markdown render again.
diff --git a/storybook/stories/Message.js b/storybook/stories/Message.js
index 79511c744..8aca2ef6b 100644
--- a/storybook/stories/Message.js
+++ b/storybook/stories/Message.js
@@ -91,6 +91,20 @@ export default (
+
+
+ Testing block quote\nTesting block quote'} />
+
+
+
+
+
+
+
+
+
+
+
-
+
=0.50.0":
- version "0.57.33"
- resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.57.33.tgz#1d35a883c6e30d6f0b40385230fde2d8213b4dca"
- integrity sha512-mn6u8aeh7nxBGO82z/vQeFrlfkBIAAk69MIxSK0aIn8cQnaFqmsoaeSBPhc1K+oIbMXytfehl0w5U1H20OIk+A==
- dependencies:
- "@types/prop-types" "*"
- "@types/react" "*"
-
-"@types/react@*":
- version "16.7.22"
- resolved "https://registry.yarnpkg.com/@types/react/-/react-16.7.22.tgz#5bc6d166d5ac34b835756f0b736c7b1af0043e81"
- integrity sha512-j/3tVoY09kHcTfbia4l67ofQn9xvktUvlC/4QN0KuBHAXlbU/wuGKMb8WfEb/vIcWxsOxHv559uYprkFDFfP8Q==
- dependencies:
- "@types/prop-types" "*"
- csstype "^2.2.0"
-
"@types/stack-utils@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
@@ -3180,6 +3154,25 @@ commondir@^1.0.1:
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=
+"commonmark-react-renderer@git+https://github.com/RocketChat/commonmark-react-renderer.git":
+ version "4.3.4"
+ resolved "git+https://github.com/RocketChat/commonmark-react-renderer.git#1264ac7b1c13d9be3e2f67eec6702a3132f4fac2"
+ dependencies:
+ lodash.assign "^4.2.0"
+ lodash.isplainobject "^4.0.6"
+ pascalcase "^0.1.1"
+ xss-filters "^1.2.6"
+
+"commonmark@git+https://github.com/RocketChat/commonmark.js.git":
+ version "0.29.0"
+ resolved "git+https://github.com/RocketChat/commonmark.js.git#005849af59002665dea50353ae9991c49abb1380"
+ dependencies:
+ entities "~ 1.1.1"
+ mdurl "~ 1.0.1"
+ minimist "~ 1.2.0"
+ string.prototype.repeat "^0.2.0"
+ xregexp "4.1.1"
+
compare-versions@^3.4.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.4.0.tgz#e0747df5c9cb7f054d6d3dc3e1dbc444f9e92b26"
@@ -3473,11 +3466,6 @@ cssstyle@^1.0.0:
dependencies:
cssom "0.3.x"
-csstype@^2.2.0:
- version "2.6.2"
- resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.2.tgz#3043d5e065454579afc7478a18de41909c8a2f01"
- integrity sha512-Rl7PvTae0pflc1YtxtKbiSqq20Ts6vpIYOD5WBafl4y123DyHUeLrRdQP66sQW8/6gmX8jrYJLXwNeMqYVJcow==
-
csstype@^2.5.7:
version "2.6.6"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.6.tgz#c34f8226a94bbb10c32cc0d714afdf942291fc41"
@@ -3940,7 +3928,7 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1:
dependencies:
once "^1.4.0"
-entities@~1.1.1:
+"entities@~ 1.1.1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==
@@ -7262,13 +7250,6 @@ lines-and-columns@^1.1.6:
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=
-linkify-it@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.1.0.tgz#c4caf38a6cd7ac2212ef3c7d2bde30a91561f9db"
- integrity sha512-4REs8/062kV2DSHxNfq5183zrqXMl7WP0WzABH9IeJI+NLm429FgE1PDecltYfnOoFDFlZGh2T8PfZn0r+GTRg==
- dependencies:
- uc.micro "^1.0.1"
-
load-json-file@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
@@ -7363,6 +7344,11 @@ lodash.isequal@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
+lodash.isplainobject@^4.0.6:
+ version "4.0.6"
+ resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
+ integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=
+
lodash.memoize@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
@@ -7492,22 +7478,6 @@ map-visit@^1.0.0:
dependencies:
object-visit "^1.0.0"
-markdown-it-flowdock@0.3.8:
- version "0.3.8"
- resolved "https://registry.yarnpkg.com/markdown-it-flowdock/-/markdown-it-flowdock-0.3.8.tgz#fb768485e648d90f596c579d51aa70397d33d916"
- integrity sha512-VcI3/ZPC9Gb72KUKmf4VvVA9atvpbt+Hame8dMtyEXsp0Cdw6RF/wbgjcjh1+7EVvcvASm2Gw3zjXio8S3evJg==
-
-markdown-it@^8.4.0:
- version "8.4.2"
- resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.2.tgz#386f98998dc15a37722aa7722084f4020bdd9b54"
- integrity sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==
- dependencies:
- argparse "^1.0.7"
- entities "~1.1.1"
- linkify-it "^2.0.0"
- mdurl "^1.0.1"
- uc.micro "^1.0.5"
-
markdown-to-jsx@^6.9.1:
version "6.10.3"
resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-6.10.3.tgz#7f0946684acd321125ff2de7fd258a9b9c7c40b7"
@@ -7530,7 +7500,7 @@ md5.js@^1.3.4:
inherits "^2.0.1"
safe-buffer "^5.1.2"
-mdurl@^1.0.1:
+"mdurl@~ 1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=
@@ -7962,7 +7932,7 @@ minimist@0.0.8:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
-minimist@^1.1.0, minimist@^1.1.1, minimist@^1.2.0:
+minimist@^1.1.0, minimist@^1.1.1, minimist@^1.2.0, "minimist@~ 1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
@@ -9391,6 +9361,11 @@ querystringify@^2.0.0:
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.0.tgz#7ded8dfbf7879dcc60d0a644ac6754b283ad17ef"
integrity sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg==
+querystringify@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e"
+ integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==
+
random-bytes@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b"
@@ -9597,13 +9572,6 @@ react-native-firebase@^5.5.5:
opencollective-postinstall "^2.0.0"
prop-types "^15.7.2"
-react-native-fit-image@^1.5.2:
- version "1.5.4"
- resolved "https://registry.yarnpkg.com/react-native-fit-image/-/react-native-fit-image-1.5.4.tgz#73d2fccc7ad902cf2ffcd008a2a74749ad50134a"
- integrity sha512-wNHlGdDWsUU31qlM5SsvZrMH4eXBZt586FQNXFRFuOiXVqdA++6Xait7aiZ+5vxglgqLf+zzSnoICn0NEvDfrw==
- dependencies:
- prop-types "^15.5.10"
-
react-native-gesture-handler@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-1.3.0.tgz#d0386f565928ccc1849537f03f2e37fd5f6ad43f"
@@ -9660,17 +9628,6 @@ react-native-localize@^1.1.4:
resolved "https://registry.yarnpkg.com/react-native-localize/-/react-native-localize-1.1.4.tgz#d48aa4f75afd39a42dcd0bdf40f7f44a8ccd604c"
integrity sha512-NHsA812yvoH9ktPl1IqIxwDDwykipyH7K4zeW/nnipZuQb2g73SQEB3ryqKHmRASWD0DZl0hIxHr9IszzG5W5w==
-react-native-markdown-renderer@^3.2.8:
- version "3.2.8"
- resolved "https://registry.yarnpkg.com/react-native-markdown-renderer/-/react-native-markdown-renderer-3.2.8.tgz#217046cf198eca632a65f93cdf7dd7766f718070"
- integrity sha512-gDT5r3lwecNsEfpKagSaidEGfmCbpVcmV+HHLjaGYRALJoHkpOFni0rJZW1rCerOR9sjaUNGXE66U7BUrlEw0w==
- dependencies:
- "@types/markdown-it" "^0.0.4"
- "@types/react-native" ">=0.50.0"
- markdown-it "^8.4.0"
- prop-types "^15.5.10"
- react-native-fit-image "^1.5.2"
-
react-native-mime-types@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/react-native-mime-types/-/react-native-mime-types-2.2.1.tgz#a9760e9916e4e7df03512c60516668f23543f2c0"
@@ -11442,6 +11399,11 @@ string-width@^3.1.0:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^5.1.0"
+string.prototype.repeat@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/string.prototype.repeat/-/string.prototype.repeat-0.2.0.tgz#aba36de08dcee6a5a337d49b2ea1da1b28fc0ecf"
+ integrity sha1-q6Nt4I3O5qWjN9SbLqHaGyj8Ds8=
+
string_decoder@^1.1.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d"
@@ -12003,11 +11965,6 @@ ua-parser-js@^0.7.19:
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.20.tgz#7527178b82f6a62a0f243d1f94fd30e3e3c21098"
integrity sha512-8OaIKfzL5cpx8eCMAhhvTlft8GYF8b2eQr6JkCyVdrgjcytyOmPCXrqXFcUnhonRpLlh5yxEZVohm6mzaowUOw==
-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==
-
uglify-es@^3.1.9:
version "3.3.9"
resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677"
@@ -12235,6 +12192,14 @@ url-parse@^1.4.4:
querystringify "^2.0.0"
requires-port "^1.0.0"
+url-parse@^1.4.7:
+ version "1.4.7"
+ resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278"
+ integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==
+ dependencies:
+ querystringify "^2.1.1"
+ requires-port "^1.0.0"
+
urlgrey@^0.4.4:
version "0.4.4"
resolved "https://registry.yarnpkg.com/urlgrey/-/urlgrey-0.4.4.tgz#892fe95960805e85519f1cd4389f2cb4cbb7652f"
@@ -12605,6 +12570,16 @@ xregexp@2.0.0:
resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943"
integrity sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=
+xregexp@4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.1.1.tgz#eb8a032aa028d403f7b1b22c47a5f16c24b21d8d"
+ integrity sha512-QJ1gfSUV7kEOLfpKFCjBJRnfPErUzkNKFMso4kDSmGpp3x6ZgkyKf74inxI7PnnQCFYq5TqYJCd7DrgDN8Q05A==
+
+xss-filters@^1.2.6:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/xss-filters/-/xss-filters-1.2.7.tgz#59fa1de201f36f2f3470dcac5f58ccc2830b0a9a"
+ integrity sha1-Wfod4gHzby80cNysX1jMwoMLCpo=
+
xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"