[MM-55339] Improve types for Markdown component (#25350)

This commit is contained in:
M-ZubairAhmed 2023-11-09 14:17:22 +05:30 committed by GitHub
parent ee6457c3df
commit cd58a5baaf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 134 additions and 180 deletions

View File

@ -231,7 +231,6 @@ exports[`components/drafts/panel/panel_body should have called handleFormattedTe
}
channelNamesMap={Object {}}
dispatch={[Function]}
editedAt={0}
emojiMap={
EmojiMap {
"customEmojis": Map {},
@ -240,7 +239,6 @@ exports[`components/drafts/panel/panel_body should have called handleFormattedTe
}
enableFormatting={true}
hasImageProxy={false}
imagesMetadata={Object {}}
managedResourcePaths={Array []}
mentionKeys={Array []}
message="message"
@ -251,8 +249,6 @@ exports[`components/drafts/panel/panel_body should have called handleFormattedTe
"mentionHighlight": false,
}
}
postId=""
proxyImages={true}
siteURL="http://localhost:8065"
team={
Object {
@ -508,7 +504,6 @@ exports[`components/drafts/panel/panel_body should match snapshot 1`] = `
}
channelNamesMap={Object {}}
dispatch={[Function]}
editedAt={0}
emojiMap={
EmojiMap {
"customEmojis": Map {},
@ -517,7 +512,6 @@ exports[`components/drafts/panel/panel_body should match snapshot 1`] = `
}
enableFormatting={true}
hasImageProxy={false}
imagesMetadata={Object {}}
managedResourcePaths={Array []}
mentionKeys={Array []}
message="message"
@ -528,8 +522,6 @@ exports[`components/drafts/panel/panel_body should match snapshot 1`] = `
"mentionHighlight": false,
}
}
postId=""
proxyImages={true}
siteURL="http://localhost:8065"
team={
Object {
@ -853,7 +845,6 @@ exports[`components/drafts/panel/panel_body should match snapshot for priority 1
}
channelNamesMap={Object {}}
dispatch={[Function]}
editedAt={0}
emojiMap={
EmojiMap {
"customEmojis": Map {},
@ -862,7 +853,6 @@ exports[`components/drafts/panel/panel_body should match snapshot for priority 1
}
enableFormatting={true}
hasImageProxy={false}
imagesMetadata={Object {}}
managedResourcePaths={Array []}
mentionKeys={Array []}
message="message"
@ -873,8 +863,6 @@ exports[`components/drafts/panel/panel_body should match snapshot for priority 1
"mentionHighlight": false,
}
}
postId=""
proxyImages={true}
siteURL="http://localhost:8065"
team={
Object {
@ -1277,7 +1265,6 @@ exports[`components/drafts/panel/panel_body should match snapshot for requested_
}
channelNamesMap={Object {}}
dispatch={[Function]}
editedAt={0}
emojiMap={
EmojiMap {
"customEmojis": Map {},
@ -1286,7 +1273,6 @@ exports[`components/drafts/panel/panel_body should match snapshot for requested_
}
enableFormatting={true}
hasImageProxy={false}
imagesMetadata={Object {}}
managedResourcePaths={Array []}
mentionKeys={Array []}
message="message"
@ -1297,8 +1283,6 @@ exports[`components/drafts/panel/panel_body should match snapshot for requested_
"mentionHighlight": false,
}
}
postId=""
proxyImages={true}
siteURL="http://localhost:8065"
team={
Object {

View File

@ -1,30 +1,31 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/Markdown should not render markdown when formatting is disabled 1`] = `
<span>
This _is_ some **Markdown**
<Connect(PostEditedIndicator)
editedAt={0}
postId=""
/>
</span>
<div>
<p>
This
<em>
is
</em>
some
<strong>
Markdown
</strong>
</p>
</div>
`;
exports[`components/Markdown should render properly 1`] = `
<p
key="0"
>
This
<em
key="1"
>
is
</em>
some
<strong
key="3"
>
Markdown
</strong>
</p>
<div>
<p>
This
<em>
is
</em>
some
<strong>
Markdown
</strong>
</p>
</div>
`;

View File

@ -1,7 +1,7 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {connect} from 'react-redux';
import {connect, type ConnectedProps} from 'react-redux';
import {Preferences} from 'mattermost-redux/constants';
import {createSelector} from 'mattermost-redux/selectors/create_selector';
@ -14,24 +14,17 @@ import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams';
import {getEmojiMap} from 'selectors/emojis';
import type {ChannelNamesMap, MentionKey} from 'utils/text_formatting';
import {getSiteURL} from 'utils/url';
import type {GlobalState} from 'types/store';
import Markdown from './markdown';
type Props = {
channelNamesMap?: ChannelNamesMap;
mentionKeys?: MentionKey[];
postId?: string;
}
import Markdown, {type OwnProps} from './markdown';
function makeGetChannelNamesMap() {
return createSelector(
'makeGetChannelNamesMap',
getChannelNameToDisplayNameMap,
(state: GlobalState, props: Props) => props && props.channelNamesMap,
(state: GlobalState, props: OwnProps) => props && props.channelNamesMap,
(channelNamesMap, channelMentions) => {
if (channelMentions) {
return Object.assign({}, channelMentions, channelNamesMap);
@ -45,7 +38,7 @@ function makeGetChannelNamesMap() {
function makeMapStateToProps() {
const getChannelNamesMap = makeGetChannelNamesMap();
return function mapStateToProps(state: GlobalState, ownProps: Props) {
return function mapStateToProps(state: GlobalState, ownProps: OwnProps) {
const config = getConfig(state);
let channelId;
@ -69,4 +62,7 @@ function makeMapStateToProps() {
};
}
export default connect(makeMapStateToProps)(Markdown);
const connector = connect(makeMapStateToProps);
export type PropsFromRedux = ConnectedProps<typeof connector>;
export default connector(Markdown);

View File

@ -1,13 +1,13 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {shallow} from 'enzyme';
import React from 'react';
import type {TeamType} from '@mattermost/types/teams';
import Markdown from 'components/markdown/markdown';
import Markdown from 'components/markdown';
import {renderWithContext} from 'tests/react_testing_utils';
import EmojiMap from 'utils/emoji_map';
import {TestHelper} from 'utils/test_helper';
@ -42,10 +42,8 @@ describe('components/Markdown', () => {
};
test('should render properly', () => {
const wrapper = shallow(
<Markdown {...baseProps}/>,
);
expect(wrapper).toMatchSnapshot();
const {container} = renderWithContext(<Markdown {...baseProps}/>);
expect(container).toMatchSnapshot();
});
test('should not render markdown when formatting is disabled', () => {
@ -54,9 +52,7 @@ describe('components/Markdown', () => {
enableFormatting: false,
};
const wrapper = shallow(
<Markdown {...props}/>,
);
expect(wrapper).toMatchSnapshot();
const {container} = renderWithContext(<Markdown {...props}/>);
expect(container).toMatchSnapshot();
});
});

View File

@ -4,93 +4,35 @@
import React from 'react';
import type {PostImage, PostType} from '@mattermost/types/posts';
import type {Team} from '@mattermost/types/teams';
import PostEditedIndicator from 'components/post_view/post_edited_indicator';
import type EmojiMap from 'utils/emoji_map';
import messageHtmlToComponent from 'utils/message_html_to_component';
import type {ChannelNamesMap, MentionKey, TextFormattingOptions} from 'utils/text_formatting';
import {formatText} from 'utils/text_formatting';
import type {ChannelNamesMap, TextFormattingOptions, MentionKey} from 'utils/text_formatting';
type Props = {
import type {PropsFromRedux} from './index';
/*
* An object mapping channel names to channels for the current team
*/
channelNamesMap?: ChannelNamesMap;
export type Props = PropsFromRedux & OwnProps;
/*
* An array of URL schemes that should be turned into links. Anything that looks
* like a link will be turned into a link if this is not provided.
*/
autolinkedUrlSchemes?: string[];
export type OwnProps = {
/*
* Whether or not to do Markdown rendering
*/
enableFormatting?: boolean;
/*
* An array of paths on the server that are managed by another server
*/
managedResourcePaths?: string[];
/*
* An array of words that can be used to mention a user
*/
mentionKeys?: MentionKey[];
/*
* The text to be rendered
*/
message: string;
/*
/**
* Any additional text formatting options to be used
*/
options: Partial<TextFormattingOptions>;
/*
* The root Site URL for the page
*/
siteURL?: string;
/*
* The current team
*/
team?: Team;
/**
* If an image proxy is enabled.
*/
hasImageProxy?: boolean;
/**
* Minimum number of characters in a hashtag.
*/
minimumHashtagLength?: number;
options?: Partial<TextFormattingOptions>;
/**
* Whether or not to proxy image URLs
*/
proxyImages?: boolean;
/**
* Any extra props that should be passed into the image component
*/
imageProps?: object;
/**
* prop for passed down to image component for dimensions
*/
imagesMetadata?: Record<string, PostImage>;
/**
* Whether or not to place the LinkTooltip component inside links
*/
hasPluginTooltips?: boolean;
/**
* Post id prop passed down to markdown image
*/
@ -101,13 +43,34 @@ type Props = {
*/
editedAt?: number;
/*
* The text to be rendered
*/
message?: string;
channelNamesMap?: ChannelNamesMap;
/*
* An array of words that can be used to mention a user
*/
mentionKeys?: MentionKey[];
/**
* Any extra props that should be passed into the image component
*/
imageProps?: object;
/**
* Whether or not to place the LinkTooltip component inside links
*/
hasPluginTooltips?: boolean;
channelId?: string;
/**
* Post id prop passed down to markdown image
*/
postType?: PostType;
emojiMap: EmojiMap;
emojiMap?: EmojiMap;
/**
* Some components processed by messageHtmlToComponent e.g. AtSumOfMembersMention require to have a list of userIds
@ -120,59 +83,73 @@ type Props = {
messageMetadata?: Record<string, string>;
}
export default class Markdown extends React.PureComponent<Props> {
static defaultProps: Partial<Props> = {
options: {},
proxyImages: true,
imagesMetadata: {},
postId: '', // Needed to avoid proptypes console errors for cases like channel header, which doesn't have a proper value
editedAt: 0,
};
render() {
const {postId, editedAt, message, enableFormatting} = this.props;
if (message === '' || !enableFormatting) {
return (
<span>
{message}
<PostEditedIndicator
postId={postId}
editedAt={editedAt}
/>
</span>
);
}
const options = Object.assign({
autolinkedUrlSchemes: this.props.autolinkedUrlSchemes,
siteURL: this.props.siteURL,
mentionKeys: this.props.mentionKeys,
atMentions: true,
channelNamesMap: this.props.channelNamesMap,
proxyImages: this.props.hasImageProxy && this.props.proxyImages,
team: this.props.team,
minimumHashtagLength: this.props.minimumHashtagLength,
managedResourcePaths: this.props.managedResourcePaths,
editedAt,
postId,
}, this.props.options);
const htmlFormattedText = formatText(message, options, this.props.emojiMap);
return messageHtmlToComponent(htmlFormattedText, {
imageProps: this.props.imageProps,
imagesMetadata: this.props.imagesMetadata,
hasPluginTooltips: this.props.hasPluginTooltips,
postId: this.props.postId,
userIds: this.props.userIds,
messageMetadata: this.props.messageMetadata,
channelId: this.props.channelId,
postType: this.props.postType,
mentionHighlight: this.props.options.mentionHighlight,
disableGroupHighlight: this.props.options.disableGroupHighlight,
editedAt,
atSumOfMembersMentions: this.props.options.atSumOfMembersMentions,
atPlanMentions: this.props.options.atPlanMentions,
});
function Markdown({
options = {},
proxyImages = true,
imagesMetadata = {},
postId = '', // Needed to avoid proptypes console errors for cases like channel header, which doesn't have a proper value
editedAt = 0,
message = '',
channelNamesMap,
mentionKeys,
imageProps,
channelId,
hasPluginTooltips,
postType,
emojiMap,
userIds,
messageMetadata,
enableFormatting,
autolinkedUrlSchemes,
siteURL,
hasImageProxy,
team,
minimumHashtagLength,
managedResourcePaths,
}: Props) {
if (message === '' || !enableFormatting) {
return (
<span>
{message}
<PostEditedIndicator
postId={postId}
editedAt={editedAt}
/>
</span>
);
}
const inputOptions = Object.assign({
autolinkedUrlSchemes,
siteURL,
mentionKeys,
atMentions: true,
channelNamesMap,
proxyImages: hasImageProxy && proxyImages,
team,
minimumHashtagLength,
managedResourcePaths,
editedAt,
postId,
}, options);
const htmlFormattedText = formatText(message, inputOptions, emojiMap);
return messageHtmlToComponent(htmlFormattedText, {
imageProps,
imagesMetadata,
hasPluginTooltips,
postId,
userIds,
messageMetadata,
channelId,
postType,
mentionHighlight: options?.mentionHighlight,
disableGroupHighlight: options?.disableGroupHighlight,
editedAt,
atSumOfMembersMentions: options?.atSumOfMembersMentions,
atPlanMentions: options?.atPlanMentions,
});
}
export default Markdown;