From 39d9a00933e213ed9cb6de99e1cded50c47fef20 Mon Sep 17 00:00:00 2001 From: Diego Mello Date: Fri, 28 Feb 2020 13:18:03 -0300 Subject: [PATCH] [IMPROVEMENT] Markdown perf (#1796) --- .../__snapshots__/Storyshots.test.js.snap | 862 ++---------------- app/containers/markdown/AtMention.js | 7 +- app/containers/markdown/Hashtag.js | 7 +- app/containers/markdown/Link.js | 15 +- app/containers/markdown/index.js | 89 +- app/containers/markdown/mergeTextNodes.js | 27 + app/presentation/RoomItem/LastMessage.js | 7 +- 7 files changed, 164 insertions(+), 850 deletions(-) create mode 100644 app/containers/markdown/mergeTextNodes.js diff --git a/__tests__/__snapshots__/Storyshots.test.js.snap b/__tests__/__snapshots__/Storyshots.test.js.snap index 2b740852..cc06e5a5 100644 --- a/__tests__/__snapshots__/Storyshots.test.js.snap +++ b/__tests__/__snapshots__/Storyshots.test.js.snap @@ -13048,59 +13048,7 @@ exports[`Storyshots Message list message 1`] = ` ] } > - I - - - 'm fine - - - ! + I'm fine! @@ -13441,59 +13389,7 @@ exports[`Storyshots Message list message 1`] = ` ] } > - I - - - 'm fine - - - ! + I'm fine! @@ -13888,59 +13784,7 @@ exports[`Storyshots Message list message 1`] = ` ] } > - I - - - 'm fine - - - ! + I'm fine! @@ -14034,59 +13878,7 @@ exports[`Storyshots Message list message 1`] = ` ] } > - I - - - 'm fine - - - ! + I'm fine! @@ -14307,59 +14099,7 @@ exports[`Storyshots Message list message 1`] = ` ] } > - I - - - 'm fine - - - ! + I'm fine! @@ -14475,59 +14215,7 @@ exports[`Storyshots Message list message 1`] = ` ] } > - I - - - 'm fine - - - ! + I'm fine! @@ -15423,61 +15111,19 @@ exports[`Storyshots Message list message 1`] = ` numberOfLines={1} style={ Array [ - undefined, + Object { + "backgroundColor": "transparent", + "fontFamily": "System", + "fontSize": 16, + "fontWeight": "400", + }, Object { "color": "#2f343d", }, ] } > - - I - - - 'm fine - - - ! - + I'm fine! @@ -15696,61 +15342,19 @@ exports[`Storyshots Message list message 1`] = ` numberOfLines={1} style={ Array [ - undefined, + Object { + "backgroundColor": "transparent", + "fontFamily": "System", + "fontSize": 16, + "fontWeight": "400", + }, Object { "color": "#2f343d", }, ] } > - - I - - - 'm fine - - - ! - + I'm fine! @@ -15969,61 +15573,19 @@ exports[`Storyshots Message list message 1`] = ` numberOfLines={1} style={ Array [ - undefined, + Object { + "backgroundColor": "transparent", + "fontFamily": "System", + "fontSize": 16, + "fontWeight": "400", + }, Object { "color": "#2f343d", }, ] } > - - I - - - 'm fine - - - ! - + I'm fine! @@ -16242,61 +15804,19 @@ exports[`Storyshots Message list message 1`] = ` numberOfLines={1} style={ Array [ - undefined, + Object { + "backgroundColor": "transparent", + "fontFamily": "System", + "fontSize": 16, + "fontWeight": "400", + }, Object { "color": "#2f343d", }, ] } > - - I - - - 'm fine - - - ! - + I'm fine! @@ -16515,29 +16035,19 @@ exports[`Storyshots Message list message 1`] = ` numberOfLines={1} style={ Array [ - undefined, + Object { + "backgroundColor": "transparent", + "fontFamily": "System", + "fontSize": 16, + "fontWeight": "400", + }, Object { "color": "#2f343d", }, ] } > - - 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. @@ -16756,29 +16266,19 @@ exports[`Storyshots Message list message 1`] = ` numberOfLines={1} style={ Array [ - undefined, + Object { + "backgroundColor": "transparent", + "fontFamily": "System", + "fontSize": 16, + "fontWeight": "400", + }, Object { "color": "#2f343d", }, ] } > - - 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. @@ -17482,61 +16982,19 @@ exports[`Storyshots Message list message 1`] = ` numberOfLines={1} style={ Array [ - undefined, + Object { + "backgroundColor": "transparent", + "fontFamily": "System", + "fontSize": 16, + "fontWeight": "400", + }, Object { "color": "#2f343d", }, ] } > - - I - - - 'm fine - - - ! - + I'm fine! @@ -17672,29 +17130,19 @@ exports[`Storyshots Message list message 1`] = ` numberOfLines={1} style={ Array [ - undefined, + Object { + "backgroundColor": "transparent", + "fontFamily": "System", + "fontSize": 16, + "fontWeight": "400", + }, Object { "color": "#2f343d", }, ] } > - - 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. @@ -18082,61 +17530,19 @@ exports[`Storyshots Message list message 1`] = ` numberOfLines={1} style={ Array [ - undefined, + Object { + "backgroundColor": "transparent", + "fontFamily": "System", + "fontSize": 16, + "fontWeight": "400", + }, Object { "color": "#2f343d", }, ] } > - - I - - - 'm fine - - - ! - + I'm fine! @@ -18272,45 +17678,19 @@ exports[`Storyshots Message list message 1`] = ` numberOfLines={1} style={ Array [ - undefined, + Object { + "backgroundColor": "transparent", + "fontFamily": "System", + "fontSize": 16, + "fontWeight": "400", + }, Object { "color": "#2f343d", }, ] } > - - Cool - - - ! - + Cool! @@ -18446,29 +17826,19 @@ exports[`Storyshots Message list message 1`] = ` numberOfLines={1} style={ Array [ - undefined, + Object { + "backgroundColor": "transparent", + "fontFamily": "System", + "fontSize": 16, + "fontWeight": "400", + }, Object { "color": "#2f343d", }, ] } > - - 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. @@ -27665,71 +27035,7 @@ exports[`Storyshots Message list message 1`] = ` ] } > - I - - - \` - - - m an inline-style link + I\`m an inline-style link { let mentionStyle = { ...styles.mention, color: themes[theme].buttonText }; if (mention === 'all' || mention === 'here') { @@ -40,8 +40,8 @@ const AtMention = React.memo(({ if (user) { return ( {useRealName ? user.name : user.username} @@ -60,7 +60,6 @@ AtMention.propTypes = { username: PropTypes.string, navToRoomInfo: PropTypes.func, style: PropTypes.array, - preview: PropTypes.bool, useRealName: PropTypes.bool, theme: PropTypes.string, mentions: PropTypes.oneOfType([PropTypes.array, PropTypes.object]) diff --git a/app/containers/markdown/Hashtag.js b/app/containers/markdown/Hashtag.js index 594192ca..655d3a73 100644 --- a/app/containers/markdown/Hashtag.js +++ b/app/containers/markdown/Hashtag.js @@ -7,7 +7,7 @@ import { themes } from '../../constants/colors'; import styles from './styles'; const Hashtag = React.memo(({ - hashtag, channels, navToRoomInfo, preview, style = [], theme + hashtag, channels, navToRoomInfo, style = [], theme }) => { const handlePress = () => { const index = channels.findIndex(channel => channel.name === hashtag); @@ -21,8 +21,8 @@ const Hashtag = React.memo(({ if (channels && channels.length && channels.findIndex(channel => channel.name === hashtag) !== -1) { return ( {hashtag} @@ -39,7 +39,6 @@ Hashtag.propTypes = { hashtag: PropTypes.string, navToRoomInfo: PropTypes.func, style: PropTypes.array, - preview: PropTypes.bool, theme: PropTypes.string, channels: PropTypes.oneOfType([PropTypes.array, PropTypes.object]) }; diff --git a/app/containers/markdown/Link.js b/app/containers/markdown/Link.js index c974a0f2..1c157711 100644 --- a/app/containers/markdown/Link.js +++ b/app/containers/markdown/Link.js @@ -10,7 +10,7 @@ import EventEmitter from '../../utils/events'; import I18n from '../../i18n'; const Link = React.memo(({ - children, link, preview, theme + children, link, theme }) => { const handlePress = () => { if (!link) { @@ -28,13 +28,9 @@ const Link = React.memo(({ // if you have a [](https://rocket.chat) render https://rocket.chat return ( { childLength !== 0 ? children : link } @@ -44,8 +40,7 @@ const Link = React.memo(({ Link.propTypes = { children: PropTypes.node, link: PropTypes.string, - theme: PropTypes.string, - preview: PropTypes.bool + theme: PropTypes.string }; export default Link; diff --git a/app/containers/markdown/index.js b/app/containers/markdown/index.js index 7e7812be..294bc3b7 100644 --- a/app/containers/markdown/index.js +++ b/app/containers/markdown/index.js @@ -3,6 +3,7 @@ import { Text, Image } from 'react-native'; import { Parser, Node } from 'commonmark'; import Renderer from 'commonmark-react-renderer'; import PropTypes from 'prop-types'; +import removeMarkdown from 'remove-markdown'; import shortnameToUnicode from '../../utils/shortnameToUnicode'; import I18n from '../../i18n'; @@ -18,6 +19,7 @@ import MarkdownEmoji from './Emoji'; import MarkdownTable from './Table'; import MarkdownTableRow from './TableRow'; import MarkdownTableCell from './TableCell'; +import mergeTextNodes from './mergeTextNodes'; import styles from './styles'; @@ -83,10 +85,10 @@ class Markdown extends PureComponent { constructor(props) { super(props); - this.renderer = this.createRenderer(props.preview); + this.renderer = this.createRenderer(); } - createRenderer = (preview = false) => new Renderer({ + createRenderer = () => new Renderer({ renderers: { text: this.renderText, @@ -119,7 +121,7 @@ class Markdown extends PureComponent { table_row: this.renderTableRow, table_cell: this.renderTableCell, - editedIndicator: preview ? () => null : this.renderEditedIndicator + editedIndicator: this.renderEditedIndicator }, renderParagraphsInLists: true }); @@ -141,19 +143,15 @@ class Markdown extends PureComponent { renderText = ({ context, literal }) => { const { - numberOfLines, preview, style = [] + numberOfLines, style = [] } = this.props; const defaultStyle = [ - this.isMessageContainsOnlyEmoji && !preview ? styles.textBig : {}, + this.isMessageContainsOnlyEmoji ? styles.textBig : {}, ...context.map(type => styles[type]) ]; return ( {literal} @@ -162,18 +160,16 @@ class Markdown extends PureComponent { } renderCodeInline = ({ literal }) => { - const { preview, theme, style = [] } = this.props; + const { theme, style = [] } = this.props; return ( @@ -183,18 +179,16 @@ class Markdown extends PureComponent { }; renderCodeBlock = ({ literal }) => { - const { preview, theme, style = [] } = this.props; + const { theme, style = [] } = this.props; return ( @@ -221,11 +215,10 @@ class Markdown extends PureComponent { }; renderLink = ({ children, href }) => { - const { preview, theme } = this.props; + const { theme } = this.props; return ( {children} @@ -235,14 +228,13 @@ class Markdown extends PureComponent { renderHashtag = ({ hashtag }) => { const { - channels, navToRoomInfo, style, preview, theme + channels, navToRoomInfo, style, theme } = this.props; return ( @@ -251,7 +243,7 @@ class Markdown extends PureComponent { renderAtMention = ({ mentionName }) => { const { - username, mentions, navToRoomInfo, useRealName, preview, style, theme + username, mentions, navToRoomInfo, useRealName, style, theme } = this.props; return ( @@ -269,13 +260,13 @@ class Markdown extends PureComponent { renderEmoji = ({ emojiName, literal }) => { const { - getCustomEmoji, baseUrl, customEmojis = true, preview, style, theme + getCustomEmoji, baseUrl, customEmojis = true, style, theme } = this.props; return ( { - const { preview, theme } = this.props; - if (preview) { - return children; - } + const { theme } = this.props; return ( {children} @@ -367,7 +355,9 @@ class Markdown extends PureComponent { } render() { - const { msg, preview = false } = this.props; + const { + msg, numberOfLines, preview = false, theme, style = [] + } = this.props; if (!msg) { return null; @@ -378,19 +368,22 @@ class Markdown extends PureComponent { // Ex: '[ ](https://open.rocket.chat/group/test?msg=abcdef) Test' // Return: 'Test' m = m.replace(/^\[([\s]]*)\]\(([^)]*)\)\s/, '').trim(); - m = shortnameToUnicode(m); if (preview) { - m = m.split('\n').reduce((lines, line) => `${ lines } ${ line }`, ''); - const ast = parser.parse(m); - return this.renderer.render(ast); + m = m.replace(/\n+/g, ' '); + m = shortnameToUnicode(m); + m = removeMarkdown(m); + return ( + + {m} + + ); } - const ast = parser.parse(m); + let ast = parser.parse(m); + ast = mergeTextNodes(ast); this.isMessageContainsOnlyEmoji = isOnlyEmoji(m) && emojiCount(m) <= 3; - this.editedMessage(ast); - return this.renderer.render(ast); } } diff --git a/app/containers/markdown/mergeTextNodes.js b/app/containers/markdown/mergeTextNodes.js new file mode 100644 index 00000000..76839523 --- /dev/null +++ b/app/containers/markdown/mergeTextNodes.js @@ -0,0 +1,27 @@ +// TODO: should we add this to our commonmark fork instead? +// we loop through nodes and try to merge all texts +export default function mergeTextNodes(ast) { + // https://github.com/commonmark/commonmark.js/blob/master/lib/node.js#L268 + const walker = ast.walker(); + let event; + // eslint-disable-next-line no-cond-assign + while (event = walker.next()) { + const { entering, node } = event; + const { type } = node; + if (entering && type === 'text') { + while (node._next && node._next.type === 'text') { + const next = node._next; + node.literal += next.literal; + node._next = next._next; + if (node._next) { + node._next._prev = node; + } + if (node._parent._lastChild === next) { + node._parent._lastChild = node; + } + } + walker.resumeAt(node, false); + } + } + return ast; +} diff --git a/app/presentation/RoomItem/LastMessage.js b/app/presentation/RoomItem/LastMessage.js index a972f42f..54ee09f1 100644 --- a/app/presentation/RoomItem/LastMessage.js +++ b/app/presentation/RoomItem/LastMessage.js @@ -6,7 +6,6 @@ import I18n from '../../i18n'; import styles from './styles'; import Markdown from '../../containers/markdown'; import { themes } from '../../constants/colors'; -import shortnameToUnicode from '../../utils/shortnameToUnicode'; const formatMsg = ({ lastMessage, type, showLastMessage, username, useRealName @@ -37,11 +36,7 @@ const formatMsg = ({ prefix = `${ useRealName ? name : lastMessage.u.username }: `; } - let msg = `${ prefix }${ lastMessage.msg.replace(/[\n\t\r]/igm, '') }`; - if (msg) { - msg = shortnameToUnicode(msg); - } - return msg; + return `${ prefix }${ lastMessage.msg }`; }; const arePropsEqual = (oldProps, newProps) => _.isEqual(oldProps, newProps);