From bb4aa764bc28d3bef572c023d7e541418caad85c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Tue, 10 Oct 2023 16:22:11 +0200 Subject: [PATCH] Migrating some files from javascript to typescript (#24663) * Migrating some files to typescript * Some other files migrated * Migrating more javascript to typescript * Migrating more javascript to typescript * Fixing types * Fixing linter errors * Fixing some imports * Fixing linter errors * Renaming the snapshots * Addressing PR review comments --- webapp/channels/package.json | 2 +- webapp/channels/src/actions/admin_actions.jsx | 2 +- .../channels/src/actions/global_actions.tsx | 4 +- ...ns.test.js => integration_actions.test.ts} | 42 +- ...on_actions.jsx => integration_actions.tsx} | 43 +- .../src/actions/telemetry_actions.jsx | 2 +- webapp/channels/src/actions/user_actions.ts | 2 +- .../src/actions/websocket_actions.jsx | 4 +- .../src/actions/websocket_actions.test.jsx | 2 +- ...et_client.jsx => web_websocket_client.tsx} | 2 +- .../trial_banner/trial_banner.tsx | 2 +- .../announcement_bar.test.tsx | 2 +- webapp/channels/src/components/app.tsx | 2 +- .../commands_container/commands_container.tsx | 4 +- .../installed_incoming_webhooks/index.ts | 2 +- .../invitation_modal.test.tsx | 2 +- .../invitation_modal/invite_view.test.tsx | 2 +- .../src/components/logged_in/logged_in.tsx | 2 +- .../src/components/overlay_trigger.tsx | 2 +- .../post_body_additional_content.tsx | 2 +- .../src/components/root/root.test.tsx | 2 +- webapp/channels/src/components/root/root.tsx | 2 +- .../suggestion/channel_mention_provider.tsx | 2 +- .../suggestion/emoticon_provider.tsx | 2 +- .../suggestion/search_channel_provider.tsx | 2 +- ...arch_channel_with_permissions_provider.tsx | 2 +- .../suggestion/switch_channel_provider.tsx | 2 +- .../modal/user_settings_modal.tsx | 2 +- webapp/channels/src/entry.tsx | 2 +- webapp/channels/src/i18n/i18n.jsx | 2 +- webapp/channels/src/plugins/index.js | 4 +- .../__snapshots__/pluggable.test.jsx.snap | 239 ------- .../__snapshots__/pluggable.test.tsx.snap | 660 ++++++++++++++++++ ...{pluggable.test.jsx => pluggable.test.tsx} | 39 +- webapp/channels/src/plugins/registry.ts | 2 +- ...sx.snap => main_menu_action.test.tsx.snap} | 0 ....test.jsx.snap => post_type.test.tsx.snap} | 54 +- ...ion.test.jsx => main_menu_action.test.tsx} | 7 +- ...{post_type.test.jsx => post_type.test.tsx} | 6 +- .../src/stores/local_storage_store.ts | 2 +- .../{redux_store.jsx => redux_store.tsx} | 2 +- ...in_console_plugin_index_sample_pluings.ts} | 0 .../{localstorage.jsx => localstorage.tsx} | 12 +- ...ser_agent_mocks.js => user_agent_mocks.ts} | 2 +- ...> message_html_to_component.test.tsx.snap} | 0 webapp/channels/src/utils/markdown/index.ts | 2 +- ...jsx => message_html_to_component.test.tsx} | 31 +- ...nent.jsx => message_html_to_component.tsx} | 87 ++- .../src/utils/text_formatting.test.ts | 2 +- webapp/channels/src/utils/utils.test.tsx | 2 +- webapp/channels/src/utils/utils.tsx | 2 +- webapp/channels/webpack.config.js | 2 +- webapp/package-lock.json | 19 +- 53 files changed, 942 insertions(+), 381 deletions(-) rename webapp/channels/src/actions/{integration_actions.test.js => integration_actions.test.ts} (66%) rename webapp/channels/src/actions/{integration_actions.jsx => integration_actions.tsx} (69%) rename webapp/channels/src/client/{web_websocket_client.jsx => web_websocket_client.tsx} (82%) delete mode 100644 webapp/channels/src/plugins/pluggable/__snapshots__/pluggable.test.jsx.snap create mode 100644 webapp/channels/src/plugins/pluggable/__snapshots__/pluggable.test.tsx.snap rename webapp/channels/src/plugins/pluggable/{pluggable.test.jsx => pluggable.test.tsx} (67%) rename webapp/channels/src/plugins/test/__snapshots__/{main_menu_action.test.jsx.snap => main_menu_action.test.tsx.snap} (100%) rename webapp/channels/src/plugins/test/__snapshots__/{post_type.test.jsx.snap => post_type.test.tsx.snap} (50%) rename webapp/channels/src/plugins/test/{main_menu_action.test.jsx => main_menu_action.test.tsx} (90%) rename webapp/channels/src/plugins/test/{post_type.test.jsx => post_type.test.tsx} (92%) rename webapp/channels/src/stores/{redux_store.jsx => redux_store.tsx} (94%) rename webapp/channels/src/tests/helpers/{admin_console_plugin_index_sample_pluings.js => admin_console_plugin_index_sample_pluings.ts} (100%) rename webapp/channels/src/tests/helpers/{localstorage.jsx => localstorage.tsx} (64%) rename webapp/channels/src/tests/helpers/{user_agent_mocks.js => user_agent_mocks.ts} (96%) rename webapp/channels/src/utils/__snapshots__/{message_html_to_component.test.jsx.snap => message_html_to_component.test.tsx.snap} (100%) rename webapp/channels/src/utils/{message_html_to_component.test.jsx => message_html_to_component.test.tsx} (79%) rename webapp/channels/src/utils/{message_html_to_component.jsx => message_html_to_component.tsx} (73%) diff --git a/webapp/channels/package.json b/webapp/channels/package.json index a0b64b3878..e0ce94fe73 100644 --- a/webapp/channels/package.json +++ b/webapp/channels/package.json @@ -43,7 +43,7 @@ "highlight.js": "11.6.0", "history": "4.10.1", "hoist-non-react-statics": "3.3.2", - "html-to-react": "1.5.0", + "html-to-react": "1.6.0", "inobounce": "0.2.1", "katex": "0.16.3", "key-mirror": "1.0.1", diff --git a/webapp/channels/src/actions/admin_actions.jsx b/webapp/channels/src/actions/admin_actions.jsx index 8831620e46..704940c740 100644 --- a/webapp/channels/src/actions/admin_actions.jsx +++ b/webapp/channels/src/actions/admin_actions.jsx @@ -10,7 +10,7 @@ import {Client4} from 'mattermost-redux/client'; import {emitUserLoggedOutEvent} from 'actions/global_actions'; import {trackEvent} from 'actions/telemetry_actions.jsx'; import {getOnNavigationConfirmed} from 'selectors/views/admin'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; import {ActionTypes} from 'utils/constants'; diff --git a/webapp/channels/src/actions/global_actions.tsx b/webapp/channels/src/actions/global_actions.tsx index 147629773f..f956405c3c 100644 --- a/webapp/channels/src/actions/global_actions.tsx +++ b/webapp/channels/src/actions/global_actions.tsx @@ -38,11 +38,11 @@ import {getCurrentLocale} from 'selectors/i18n'; import {getIsRhsOpen, getPreviousRhsState, getRhsState} from 'selectors/rhs'; import BrowserStore from 'stores/browser_store'; import LocalStorageStore from 'stores/local_storage_store'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; import SubMenuModal from 'components/widgets/menu/menu_modals/submenu_modal/submenu_modal'; -import WebSocketClient from 'client/web_websocket_client.jsx'; +import WebSocketClient from 'client/web_websocket_client'; import {getHistory} from 'utils/browser_history'; import {ActionTypes, PostTypes, RHSStates, ModalIdentifiers, PreviousViewedTypes} from 'utils/constants'; import {filterAndSortTeamsByDisplayName} from 'utils/team_utils'; diff --git a/webapp/channels/src/actions/integration_actions.test.js b/webapp/channels/src/actions/integration_actions.test.ts similarity index 66% rename from webapp/channels/src/actions/integration_actions.test.js rename to webapp/channels/src/actions/integration_actions.test.ts index be9328ccef..c62c788c0c 100644 --- a/webapp/channels/src/actions/integration_actions.test.js +++ b/webapp/channels/src/actions/integration_actions.test.ts @@ -1,9 +1,11 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. +import type {IncomingWebhook, OutgoingWebhook, Command, OAuthApp} from '@mattermost/types/integrations'; + import {getProfilesByIds} from 'mattermost-redux/actions/users'; -import * as Actions from 'actions/integration_actions.jsx'; +import * as Actions from 'actions/integration_actions'; import mockStore from 'tests/test_store'; @@ -13,6 +15,12 @@ jest.mock('mattermost-redux/actions/users', () => ({ }), })); +interface CustomMatchers { + arrayContainingExactly(stringArray: string[]): R; +} + +type GreatExpectations = typeof expect & CustomMatchers; + describe('actions/integration_actions', () => { const initialState = { entities: { @@ -35,14 +43,14 @@ describe('actions/integration_actions', () => { describe('loadProfilesForIncomingHooks', () => { test('load profiles for hooks including user we already have', () => { const testStore = mockStore(initialState); - testStore.dispatch(Actions.loadProfilesForIncomingHooks([{user_id: 'current_user_id'}, {user_id: 'user_id2'}])); - expect(getProfilesByIds).toHaveBeenCalledWith(expect.arrayContainingExactly(['user_id2'])); + testStore.dispatch(Actions.loadProfilesForIncomingHooks([{user_id: 'current_user_id'}, {user_id: 'user_id2'}] as IncomingWebhook[])); + expect(getProfilesByIds).toHaveBeenCalledWith((expect as GreatExpectations).arrayContainingExactly(['user_id2'])); }); test('load profiles for hooks including only users we don\'t have', () => { const testStore = mockStore(initialState); - testStore.dispatch(Actions.loadProfilesForIncomingHooks([{user_id: 'user_id1'}, {user_id: 'user_id2'}])); - expect(getProfilesByIds).toHaveBeenCalledWith(expect.arrayContainingExactly(['user_id1', 'user_id2'])); + testStore.dispatch(Actions.loadProfilesForIncomingHooks([{user_id: 'user_id1'}, {user_id: 'user_id2'}] as IncomingWebhook[])); + expect(getProfilesByIds).toHaveBeenCalledWith((expect as GreatExpectations).arrayContainingExactly(['user_id1', 'user_id2'])); }); test('load profiles for empty hooks', () => { @@ -55,14 +63,14 @@ describe('actions/integration_actions', () => { describe('loadProfilesForOutgoingHooks', () => { test('load profiles for hooks including user we already have', () => { const testStore = mockStore(initialState); - testStore.dispatch(Actions.loadProfilesForOutgoingHooks([{creator_id: 'current_user_id'}, {creator_id: 'user_id2'}])); - expect(getProfilesByIds).toHaveBeenCalledWith(expect.arrayContainingExactly(['user_id2'])); + testStore.dispatch(Actions.loadProfilesForOutgoingHooks([{creator_id: 'current_user_id'}, {creator_id: 'user_id2'}] as OutgoingWebhook[])); + expect(getProfilesByIds).toHaveBeenCalledWith((expect as GreatExpectations).arrayContainingExactly(['user_id2'])); }); test('load profiles for hooks including only users we don\'t have', () => { const testStore = mockStore(initialState); - testStore.dispatch(Actions.loadProfilesForOutgoingHooks([{creator_id: 'user_id1'}, {creator_id: 'user_id2'}])); - expect(getProfilesByIds).toHaveBeenCalledWith(expect.arrayContainingExactly(['user_id1', 'user_id2'])); + testStore.dispatch(Actions.loadProfilesForOutgoingHooks([{creator_id: 'user_id1'}, {creator_id: 'user_id2'}] as OutgoingWebhook[])); + expect(getProfilesByIds).toHaveBeenCalledWith((expect as GreatExpectations).arrayContainingExactly(['user_id1', 'user_id2'])); }); test('load profiles for empty hooks', () => { @@ -75,14 +83,14 @@ describe('actions/integration_actions', () => { describe('loadProfilesForCommands', () => { test('load profiles for commands including user we already have', () => { const testStore = mockStore(initialState); - testStore.dispatch(Actions.loadProfilesForCommands([{creator_id: 'current_user_id'}, {creator_id: 'user_id2'}])); - expect(getProfilesByIds).toHaveBeenCalledWith(expect.arrayContainingExactly(['user_id2'])); + testStore.dispatch(Actions.loadProfilesForCommands([{creator_id: 'current_user_id'}, {creator_id: 'user_id2'}] as Command[])); + expect(getProfilesByIds).toHaveBeenCalledWith((expect as GreatExpectations).arrayContainingExactly(['user_id2'])); }); test('load profiles for commands including only users we don\'t have', () => { const testStore = mockStore(initialState); - testStore.dispatch(Actions.loadProfilesForCommands([{creator_id: 'user_id1'}, {creator_id: 'user_id2'}])); - expect(getProfilesByIds).toHaveBeenCalledWith(expect.arrayContainingExactly(['user_id1', 'user_id2'])); + testStore.dispatch(Actions.loadProfilesForCommands([{creator_id: 'user_id1'}, {creator_id: 'user_id2'}] as Command[])); + expect(getProfilesByIds).toHaveBeenCalledWith((expect as GreatExpectations).arrayContainingExactly(['user_id1', 'user_id2'])); }); test('load profiles for empty commands', () => { @@ -95,14 +103,14 @@ describe('actions/integration_actions', () => { describe('loadProfilesForOAuthApps', () => { test('load profiles for apps including user we already have', () => { const testStore = mockStore(initialState); - testStore.dispatch(Actions.loadProfilesForOAuthApps([{creator_id: 'current_user_id'}, {creator_id: 'user_id2'}])); - expect(getProfilesByIds).toHaveBeenCalledWith(expect.arrayContainingExactly(['user_id2'])); + testStore.dispatch(Actions.loadProfilesForOAuthApps([{creator_id: 'current_user_id'}, {creator_id: 'user_id2'}] as OAuthApp[])); + expect(getProfilesByIds).toHaveBeenCalledWith((expect as GreatExpectations).arrayContainingExactly(['user_id2'])); }); test('load profiles for apps including only users we don\'t have', () => { const testStore = mockStore(initialState); - testStore.dispatch(Actions.loadProfilesForOAuthApps([{creator_id: 'user_id1'}, {creator_id: 'user_id2'}])); - expect(getProfilesByIds).toHaveBeenCalledWith(expect.arrayContainingExactly(['user_id1', 'user_id2'])); + testStore.dispatch(Actions.loadProfilesForOAuthApps([{creator_id: 'user_id1'}, {creator_id: 'user_id2'}] as OAuthApp[])); + expect(getProfilesByIds).toHaveBeenCalledWith((expect as GreatExpectations).arrayContainingExactly(['user_id1', 'user_id2'])); }); test('load profiles for empty apps', () => { diff --git a/webapp/channels/src/actions/integration_actions.jsx b/webapp/channels/src/actions/integration_actions.tsx similarity index 69% rename from webapp/channels/src/actions/integration_actions.jsx rename to webapp/channels/src/actions/integration_actions.tsx index d8a4b384cc..ab0457b38b 100644 --- a/webapp/channels/src/actions/integration_actions.jsx +++ b/webapp/channels/src/actions/integration_actions.tsx @@ -1,26 +1,30 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. +import type {IncomingWebhook, OutgoingWebhook, Command, OAuthApp} from '@mattermost/types/integrations'; + import * as IntegrationActions from 'mattermost-redux/actions/integrations'; import {getProfilesByIds} from 'mattermost-redux/actions/users'; import {appsEnabled} from 'mattermost-redux/selectors/entities/apps'; import {getUser} from 'mattermost-redux/selectors/entities/users'; +import type {ActionFunc} from 'mattermost-redux/types/actions'; const DEFAULT_PAGE_SIZE = 100; -export function loadIncomingHooksAndProfilesForTeam(teamId, page = 0, perPage = DEFAULT_PAGE_SIZE) { +export function loadIncomingHooksAndProfilesForTeam(teamId: string, page = 0, perPage = DEFAULT_PAGE_SIZE): ActionFunc { return async (dispatch) => { const {data} = await dispatch(IntegrationActions.getIncomingHooks(teamId, page, perPage)); if (data) { dispatch(loadProfilesForIncomingHooks(data)); } + return {data}; }; } -export function loadProfilesForIncomingHooks(hooks) { +export function loadProfilesForIncomingHooks(hooks: IncomingWebhook[]): ActionFunc { return async (dispatch, getState) => { const state = getState(); - const profilesToLoad = {}; + const profilesToLoad: {[key: string]: boolean} = {}; for (let i = 0; i < hooks.length; i++) { const hook = hooks[i]; if (!getUser(state, hook.user_id)) { @@ -30,26 +34,28 @@ export function loadProfilesForIncomingHooks(hooks) { const list = Object.keys(profilesToLoad); if (list.length === 0) { - return; + return {data: null}; } dispatch(getProfilesByIds(list)); + return {data: null}; }; } -export function loadOutgoingHooksAndProfilesForTeam(teamId, page = 0, perPage = DEFAULT_PAGE_SIZE) { +export function loadOutgoingHooksAndProfilesForTeam(teamId: string, page = 0, perPage = DEFAULT_PAGE_SIZE): ActionFunc { return async (dispatch) => { const {data} = await dispatch(IntegrationActions.getOutgoingHooks('', teamId, page, perPage)); if (data) { dispatch(loadProfilesForOutgoingHooks(data)); } + return {data}; }; } -export function loadProfilesForOutgoingHooks(hooks) { +export function loadProfilesForOutgoingHooks(hooks: OutgoingWebhook[]): ActionFunc { return async (dispatch, getState) => { const state = getState(); - const profilesToLoad = {}; + const profilesToLoad: {[key: string]: boolean} = {}; for (let i = 0; i < hooks.length; i++) { const hook = hooks[i]; if (!getUser(state, hook.creator_id)) { @@ -59,26 +65,28 @@ export function loadProfilesForOutgoingHooks(hooks) { const list = Object.keys(profilesToLoad); if (list.length === 0) { - return; + return {data: null}; } dispatch(getProfilesByIds(list)); + return {data: null}; }; } -export function loadCommandsAndProfilesForTeam(teamId) { +export function loadCommandsAndProfilesForTeam(teamId: string): ActionFunc { return async (dispatch) => { const {data} = await dispatch(IntegrationActions.getCustomTeamCommands(teamId)); if (data) { dispatch(loadProfilesForCommands(data)); } + return {data}; }; } -export function loadProfilesForCommands(commands) { +export function loadProfilesForCommands(commands: Command[]): ActionFunc { return async (dispatch, getState) => { const state = getState(); - const profilesToLoad = {}; + const profilesToLoad: {[key: string]: boolean} = {}; for (let i = 0; i < commands.length; i++) { const command = commands[i]; if (!getUser(state, command.creator_id)) { @@ -88,14 +96,15 @@ export function loadProfilesForCommands(commands) { const list = Object.keys(profilesToLoad); if (list.length === 0) { - return; + return {data: null}; } dispatch(getProfilesByIds(list)); + return {data: null}; }; } -export function loadOAuthAppsAndProfiles(page = 0, perPage = DEFAULT_PAGE_SIZE) { +export function loadOAuthAppsAndProfiles(page = 0, perPage = DEFAULT_PAGE_SIZE): ActionFunc { return async (dispatch, getState) => { if (appsEnabled(getState())) { dispatch(IntegrationActions.getAppsOAuthAppIDs()); @@ -104,13 +113,14 @@ export function loadOAuthAppsAndProfiles(page = 0, perPage = DEFAULT_PAGE_SIZE) if (data) { dispatch(loadProfilesForOAuthApps(data)); } + return {data: null}; }; } -export function loadProfilesForOAuthApps(apps) { +export function loadProfilesForOAuthApps(apps: OAuthApp[]): ActionFunc { return async (dispatch, getState) => { const state = getState(); - const profilesToLoad = {}; + const profilesToLoad: {[key: string]: boolean} = {}; for (let i = 0; i < apps.length; i++) { const app = apps[i]; if (!getUser(state, app.creator_id)) { @@ -120,9 +130,10 @@ export function loadProfilesForOAuthApps(apps) { const list = Object.keys(profilesToLoad); if (list.length === 0) { - return; + return {data: null}; } dispatch(getProfilesByIds(list)); + return {data: null}; }; } diff --git a/webapp/channels/src/actions/telemetry_actions.jsx b/webapp/channels/src/actions/telemetry_actions.jsx index 665e29e7aa..ed147d4174 100644 --- a/webapp/channels/src/actions/telemetry_actions.jsx +++ b/webapp/channels/src/actions/telemetry_actions.jsx @@ -8,7 +8,7 @@ import {getConfig, isPerformanceDebuggingEnabled} from 'mattermost-redux/selecto import {getBool} from 'mattermost-redux/selectors/entities/preferences'; import {isDevModeEnabled} from 'selectors/general'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; const SUPPORTS_CLEAR_MARKS = isSupported([performance.clearMarks]); const SUPPORTS_MARK = isSupported([performance.mark]); diff --git a/webapp/channels/src/actions/user_actions.ts b/webapp/channels/src/actions/user_actions.ts index 1e6b7b682e..bd8e7f745b 100644 --- a/webapp/channels/src/actions/user_actions.ts +++ b/webapp/channels/src/actions/user_actions.ts @@ -28,7 +28,7 @@ import {calculateUnreadCount} from 'mattermost-redux/utils/channel_utils'; import {loadCustomEmojisForCustomStatusesByUserIds} from 'actions/emoji_actions'; import {loadStatusesForProfilesList, loadStatusesForProfilesMap} from 'actions/status_actions'; import {getDisplayedChannels} from 'selectors/views/channel_sidebar'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; import {Constants, Preferences, UserStatuses} from 'utils/constants'; import * as Utils from 'utils/utils'; diff --git a/webapp/channels/src/actions/websocket_actions.jsx b/webapp/channels/src/actions/websocket_actions.jsx index 5cf8740a21..1cfbe92402 100644 --- a/webapp/channels/src/actions/websocket_actions.jsx +++ b/webapp/channels/src/actions/websocket_actions.jsx @@ -110,12 +110,12 @@ import {incrementWsErrorCount, resetWsErrorCount} from 'actions/views/system'; import {updateThreadLastOpened} from 'actions/views/threads'; import {getSelectedChannelId, getSelectedPost} from 'selectors/rhs'; import {isThreadOpen, isThreadManuallyUnread} from 'selectors/views/threads'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; import InteractiveDialog from 'components/interactive_dialog'; import RemovedFromChannelModal from 'components/removed_from_channel_modal'; -import WebSocketClient from 'client/web_websocket_client.jsx'; +import WebSocketClient from 'client/web_websocket_client'; import {loadPlugin, loadPluginsIfNecessary, removePlugin} from 'plugins'; import {getHistory} from 'utils/browser_history'; import {ActionTypes, Constants, AnnouncementBarMessages, SocketEvents, UserStatuses, ModalIdentifiers, WarnMetricTypes} from 'utils/constants'; diff --git a/webapp/channels/src/actions/websocket_actions.test.jsx b/webapp/channels/src/actions/websocket_actions.test.jsx index 8b50d69d25..958d46f7cd 100644 --- a/webapp/channels/src/actions/websocket_actions.test.jsx +++ b/webapp/channels/src/actions/websocket_actions.test.jsx @@ -13,7 +13,7 @@ import {getUser} from 'mattermost-redux/actions/users'; import {handleNewPost} from 'actions/post_actions'; import {syncPostsInChannel} from 'actions/views/channel'; import {closeRightHandSide} from 'actions/views/rhs'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; import mergeObjects from 'packages/mattermost-redux/test/merge_objects'; import configureStore from 'tests/test_store'; diff --git a/webapp/channels/src/client/web_websocket_client.jsx b/webapp/channels/src/client/web_websocket_client.tsx similarity index 82% rename from webapp/channels/src/client/web_websocket_client.jsx rename to webapp/channels/src/client/web_websocket_client.tsx index d10d95258d..2491cd9b84 100644 --- a/webapp/channels/src/client/web_websocket_client.jsx +++ b/webapp/channels/src/client/web_websocket_client.tsx @@ -3,5 +3,5 @@ import {WebSocketClient} from '@mattermost/client'; -var WebClient = new WebSocketClient(); +const WebClient = new WebSocketClient(); export default WebClient; diff --git a/webapp/channels/src/components/admin_console/license_settings/trial_banner/trial_banner.tsx b/webapp/channels/src/components/admin_console/license_settings/trial_banner/trial_banner.tsx index cc54554050..8cdad803e7 100644 --- a/webapp/channels/src/components/admin_console/license_settings/trial_banner/trial_banner.tsx +++ b/webapp/channels/src/components/admin_console/license_settings/trial_banner/trial_banner.tsx @@ -12,7 +12,7 @@ import {savePreferences} from 'mattermost-redux/actions/preferences'; import {makeGetCategory} from 'mattermost-redux/selectors/entities/preferences'; import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; import AlertBanner from 'components/alert_banner'; import withOpenStartTrialFormModal from 'components/common/hocs/cloud/with_open_start_trial_form_modal'; diff --git a/webapp/channels/src/components/announcement_bar/announcement_bar.test.tsx b/webapp/channels/src/components/announcement_bar/announcement_bar.test.tsx index b923db99a5..d56d577058 100644 --- a/webapp/channels/src/components/announcement_bar/announcement_bar.test.tsx +++ b/webapp/channels/src/components/announcement_bar/announcement_bar.test.tsx @@ -4,7 +4,7 @@ import {shallow} from 'enzyme'; import React from 'react'; -import 'tests/helpers/localstorage.jsx'; +import 'tests/helpers/localstorage'; import AnnouncementBar from 'components/announcement_bar/default_announcement_bar/announcement_bar'; diff --git a/webapp/channels/src/components/app.tsx b/webapp/channels/src/components/app.tsx index ebec589169..f46e18da80 100644 --- a/webapp/channels/src/components/app.tsx +++ b/webapp/channels/src/components/app.tsx @@ -6,7 +6,7 @@ import {hot} from 'react-hot-loader/root'; import {Provider} from 'react-redux'; import {Router, Route} from 'react-router-dom'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; import {makeAsyncComponent} from 'components/async_load'; import CRTPostsChannelResetWatcher from 'components/threading/channel_threads/posts_channel_reset_watcher'; diff --git a/webapp/channels/src/components/integrations/commands_container/commands_container.tsx b/webapp/channels/src/components/integrations/commands_container/commands_container.tsx index 77c2bead14..9963a52cb2 100644 --- a/webapp/channels/src/components/integrations/commands_container/commands_container.tsx +++ b/webapp/channels/src/components/integrations/commands_container/commands_container.tsx @@ -72,7 +72,7 @@ type Props = { /** * The function to call to fetch team commands */ - loadCommandsAndProfilesForTeam: (teamId?: string) => any; // TechDebt-TODO: This needs to be changed to 'Promise' + loadCommandsAndProfilesForTeam: (teamId: string) => any; // TechDebt-TODO: This needs to be changed to 'Promise' }; /** @@ -95,7 +95,7 @@ export default class CommandsContainer extends React.PureComponent componentDidMount() { if (this.props.enableCommands) { - this.props.actions.loadCommandsAndProfilesForTeam(this.props.team?.id).then( + this.props.actions.loadCommandsAndProfilesForTeam(this.props.team?.id || '').then( () => this.setState({loading: false}), ); } diff --git a/webapp/channels/src/components/integrations/installed_incoming_webhooks/index.ts b/webapp/channels/src/components/integrations/installed_incoming_webhooks/index.ts index 8cb9723b0b..3123e5a27f 100644 --- a/webapp/channels/src/components/integrations/installed_incoming_webhooks/index.ts +++ b/webapp/channels/src/components/integrations/installed_incoming_webhooks/index.ts @@ -17,7 +17,7 @@ import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams'; import {getUsers} from 'mattermost-redux/selectors/entities/users'; import type {ActionResult, GenericAction} from 'mattermost-redux/types/actions'; -import {loadIncomingHooksAndProfilesForTeam} from 'actions/integration_actions.jsx'; +import {loadIncomingHooksAndProfilesForTeam} from 'actions/integration_actions'; import InstalledIncomingWebhooks from './installed_incoming_webhooks'; diff --git a/webapp/channels/src/components/invitation_modal/invitation_modal.test.tsx b/webapp/channels/src/components/invitation_modal/invitation_modal.test.tsx index 99828812fd..205277dfa2 100644 --- a/webapp/channels/src/components/invitation_modal/invitation_modal.test.tsx +++ b/webapp/channels/src/components/invitation_modal/invitation_modal.test.tsx @@ -9,7 +9,7 @@ import type {Team} from '@mattermost/types/teams'; import deepFreeze from 'mattermost-redux/utils/deep_freeze'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; import {mountWithThemedIntl} from 'tests/helpers/themed-intl-test-helper'; import {SelfHostedProducts} from 'utils/constants'; diff --git a/webapp/channels/src/components/invitation_modal/invite_view.test.tsx b/webapp/channels/src/components/invitation_modal/invite_view.test.tsx index 5220bf29ec..8c347bfd3f 100644 --- a/webapp/channels/src/components/invitation_modal/invite_view.test.tsx +++ b/webapp/channels/src/components/invitation_modal/invite_view.test.tsx @@ -9,7 +9,7 @@ import type {Team} from '@mattermost/types/teams'; import deepFreeze from 'mattermost-redux/utils/deep_freeze'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; import {mountWithThemedIntl} from 'tests/helpers/themed-intl-test-helper'; import {SelfHostedProducts} from 'utils/constants'; diff --git a/webapp/channels/src/components/logged_in/logged_in.tsx b/webapp/channels/src/components/logged_in/logged_in.tsx index 05f0bcfed3..5c6cc6adf3 100644 --- a/webapp/channels/src/components/logged_in/logged_in.tsx +++ b/webapp/channels/src/components/logged_in/logged_in.tsx @@ -14,7 +14,7 @@ import BrowserStore from 'stores/browser_store'; import LoadingScreen from 'components/loading_screen'; -import WebSocketClient from 'client/web_websocket_client.jsx'; +import WebSocketClient from 'client/web_websocket_client'; import Constants from 'utils/constants'; import {isKeyPressed} from 'utils/keyboard'; import {getBrowserTimezone} from 'utils/timezone'; diff --git a/webapp/channels/src/components/overlay_trigger.tsx b/webapp/channels/src/components/overlay_trigger.tsx index 9427e859de..0c15a9fba7 100644 --- a/webapp/channels/src/components/overlay_trigger.tsx +++ b/webapp/channels/src/components/overlay_trigger.tsx @@ -8,7 +8,7 @@ import {IntlContext} from 'react-intl'; import type {IntlShape} from 'react-intl'; import {Provider} from 'react-redux'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; export type BaseOverlayTrigger = OriginalOverlayTrigger & { hide: () => void; diff --git a/webapp/channels/src/components/post_view/post_body_additional_content/post_body_additional_content.tsx b/webapp/channels/src/components/post_view/post_body_additional_content/post_body_additional_content.tsx index b7e1b85f2e..f35e5e877f 100644 --- a/webapp/channels/src/components/post_view/post_body_additional_content/post_body_additional_content.tsx +++ b/webapp/channels/src/components/post_view/post_body_additional_content/post_body_additional_content.tsx @@ -14,7 +14,7 @@ import PostImage from 'components/post_view/post_image'; import PostMessagePreview from 'components/post_view/post_message_preview'; import YoutubeVideo from 'components/youtube_video'; -import webSocketClient from 'client/web_websocket_client.jsx'; +import webSocketClient from 'client/web_websocket_client'; import type {TextFormattingOptions} from 'utils/text_formatting'; import type {PostWillRenderEmbedPluginComponent} from 'types/store/plugins'; diff --git a/webapp/channels/src/components/root/root.test.tsx b/webapp/channels/src/components/root/root.test.tsx index 103be24665..594cec6a0e 100644 --- a/webapp/channels/src/components/root/root.test.tsx +++ b/webapp/channels/src/components/root/root.test.tsx @@ -13,7 +13,7 @@ import {Client4} from 'mattermost-redux/client'; import type {Theme} from 'mattermost-redux/selectors/entities/preferences'; import * as GlobalActions from 'actions/global_actions'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; import Root from 'components/root/root'; diff --git a/webapp/channels/src/components/root/root.tsx b/webapp/channels/src/components/root/root.tsx index b363a1495a..6137458115 100644 --- a/webapp/channels/src/components/root/root.tsx +++ b/webapp/channels/src/components/root/root.tsx @@ -49,7 +49,7 @@ import SystemNotice from 'components/system_notice'; import TeamSidebar from 'components/team_sidebar'; import WindowSizeObserver from 'components/window_size_observer/WindowSizeObserver'; -import webSocketClient from 'client/web_websocket_client.jsx'; +import webSocketClient from 'client/web_websocket_client'; import {initializePlugins} from 'plugins'; import Pluggable from 'plugins/pluggable'; import A11yController from 'utils/a11y_controller'; diff --git a/webapp/channels/src/components/suggestion/channel_mention_provider.tsx b/webapp/channels/src/components/suggestion/channel_mention_provider.tsx index d638d30d52..1234ce44c6 100644 --- a/webapp/channels/src/components/suggestion/channel_mention_provider.tsx +++ b/webapp/channels/src/components/suggestion/channel_mention_provider.tsx @@ -9,7 +9,7 @@ import {getMyChannels, getMyChannelMemberships} from 'mattermost-redux/selectors import type {ActionResult} from 'mattermost-redux/types/actions.js'; import {sortChannelsByTypeAndDisplayName} from 'mattermost-redux/utils/channel_utils'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; import {Constants} from 'utils/constants'; diff --git a/webapp/channels/src/components/suggestion/emoticon_provider.tsx b/webapp/channels/src/components/suggestion/emoticon_provider.tsx index 3f94bba5ae..53861fbf43 100644 --- a/webapp/channels/src/components/suggestion/emoticon_provider.tsx +++ b/webapp/channels/src/components/suggestion/emoticon_provider.tsx @@ -9,7 +9,7 @@ import {autocompleteCustomEmojis} from 'mattermost-redux/actions/emojis'; import {getEmojiImageUrl, isSystemEmoji} from 'mattermost-redux/utils/emoji_utils'; import {getEmojiMap, getRecentEmojisNames} from 'selectors/emojis'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; import {Preferences} from 'utils/constants'; import {compareEmojis, emojiMatchesSkin} from 'utils/emoji_utils'; diff --git a/webapp/channels/src/components/suggestion/search_channel_provider.tsx b/webapp/channels/src/components/suggestion/search_channel_provider.tsx index 8bda46a027..a4e0c16551 100644 --- a/webapp/channels/src/components/suggestion/search_channel_provider.tsx +++ b/webapp/channels/src/components/suggestion/search_channel_provider.tsx @@ -7,7 +7,7 @@ import type {ActionFunc} from 'mattermost-redux/types/actions.js'; import {isDirectChannel, isGroupChannel, sortChannelsByTypeListAndDisplayName} from 'mattermost-redux/utils/channel_utils'; import {getCurrentLocale} from 'selectors/i18n'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; import Constants from 'utils/constants'; diff --git a/webapp/channels/src/components/suggestion/search_channel_with_permissions_provider.tsx b/webapp/channels/src/components/suggestion/search_channel_with_permissions_provider.tsx index 246083724d..9f79f57a59 100644 --- a/webapp/channels/src/components/suggestion/search_channel_with_permissions_provider.tsx +++ b/webapp/channels/src/components/suggestion/search_channel_with_permissions_provider.tsx @@ -18,7 +18,7 @@ import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams'; import type {ActionResult} from 'mattermost-redux/types/actions'; import {sortChannelsByTypeAndDisplayName} from 'mattermost-redux/utils/channel_utils'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; import {Constants} from 'utils/constants'; diff --git a/webapp/channels/src/components/suggestion/switch_channel_provider.tsx b/webapp/channels/src/components/suggestion/switch_channel_provider.tsx index 622ae5a802..8e1c61944c 100644 --- a/webapp/channels/src/components/suggestion/switch_channel_provider.tsx +++ b/webapp/channels/src/components/suggestion/switch_channel_provider.tsx @@ -49,7 +49,7 @@ import {getPreferenceKey} from 'mattermost-redux/utils/preference_utils'; import {isGuest} from 'mattermost-redux/utils/user_utils'; import {getPostDraft} from 'selectors/rhs'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; import CustomStatusEmoji from 'components/custom_status/custom_status_emoji'; import ProfilePicture from 'components/profile_picture'; diff --git a/webapp/channels/src/components/user_settings/modal/user_settings_modal.tsx b/webapp/channels/src/components/user_settings/modal/user_settings_modal.tsx index 2ffe221e2b..fa05f39ce3 100644 --- a/webapp/channels/src/components/user_settings/modal/user_settings_modal.tsx +++ b/webapp/channels/src/components/user_settings/modal/user_settings_modal.tsx @@ -15,7 +15,7 @@ import {Provider} from 'react-redux'; import type {StatusOK} from '@mattermost/types/client4'; import type {UserProfile} from '@mattermost/types/users'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; import ConfirmModal from 'components/confirm_modal'; diff --git a/webapp/channels/src/entry.tsx b/webapp/channels/src/entry.tsx index 1e34ad1b80..f3a92426cf 100644 --- a/webapp/channels/src/entry.tsx +++ b/webapp/channels/src/entry.tsx @@ -6,7 +6,7 @@ import ReactDOM from 'react-dom'; import {logError} from 'mattermost-redux/actions/errors'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; import App from 'components/app'; diff --git a/webapp/channels/src/i18n/i18n.jsx b/webapp/channels/src/i18n/i18n.jsx index 042e8fbcfa..99babb1416 100644 --- a/webapp/channels/src/i18n/i18n.jsx +++ b/webapp/channels/src/i18n/i18n.jsx @@ -25,7 +25,7 @@ import zhCN from './zh-CN.json'; import {getConfig} from 'mattermost-redux/selectors/entities/general'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; // should match the values in model/config.go const languages = { diff --git a/webapp/channels/src/plugins/index.js b/webapp/channels/src/plugins/index.js index ddbe36837d..ebac0fd8fd 100644 --- a/webapp/channels/src/plugins/index.js +++ b/webapp/channels/src/plugins/index.js @@ -11,8 +11,8 @@ import {getBool} from 'mattermost-redux/selectors/entities/preferences'; import {unregisterAdminConsolePlugin} from 'actions/admin_actions'; import {trackPluginInitialization} from 'actions/telemetry_actions'; import {unregisterPluginTranslationsSource} from 'actions/views/root'; -import {unregisterAllPluginWebSocketEvents, unregisterPluginReconnectHandler} from 'actions/websocket_actions.jsx'; -import store from 'stores/redux_store.jsx'; +import {unregisterAllPluginWebSocketEvents, unregisterPluginReconnectHandler} from 'actions/websocket_actions'; +import store from 'stores/redux_store'; import PluginRegistry from 'plugins/registry'; import {ActionTypes} from 'utils/constants'; diff --git a/webapp/channels/src/plugins/pluggable/__snapshots__/pluggable.test.jsx.snap b/webapp/channels/src/plugins/pluggable/__snapshots__/pluggable.test.jsx.snap deleted file mode 100644 index fe55f1110b..0000000000 --- a/webapp/channels/src/plugins/pluggable/__snapshots__/pluggable.test.jsx.snap +++ /dev/null @@ -1,239 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`plugins/Pluggable should match snapshot with extended component 1`] = ` - - - - - ProfilePopoverPlugin - - - - -`; - -exports[`plugins/Pluggable should match snapshot with extended component with pluggableName 1`] = ` - - - - - ProfilePopoverPlugin - - - - -`; - -exports[`plugins/Pluggable should match snapshot with no extended component 1`] = ` - -`; - -exports[`plugins/Pluggable should match snapshot with non-null pluggableId 1`] = ` - -`; - -exports[`plugins/Pluggable should match snapshot with null pluggableId 1`] = ` - - - - - ProfilePopoverPlugin - - - - -`; - -exports[`plugins/Pluggable should match snapshot with valid pluggableId 1`] = ` - - - - - ProfilePopoverPlugin - - - - -`; diff --git a/webapp/channels/src/plugins/pluggable/__snapshots__/pluggable.test.tsx.snap b/webapp/channels/src/plugins/pluggable/__snapshots__/pluggable.test.tsx.snap new file mode 100644 index 0000000000..d5b7233562 --- /dev/null +++ b/webapp/channels/src/plugins/pluggable/__snapshots__/pluggable.test.tsx.snap @@ -0,0 +1,660 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`plugins/Pluggable should match snapshot with extended component 1`] = ` + + + + + ProfilePopoverPlugin + + + + +`; + +exports[`plugins/Pluggable should match snapshot with extended component with pluggableName 1`] = ` + + + + + ProfilePopoverPlugin + + + + +`; + +exports[`plugins/Pluggable should match snapshot with no extended component 1`] = ` + +`; + +exports[`plugins/Pluggable should match snapshot with non-null pluggableId 1`] = ` + +`; + +exports[`plugins/Pluggable should match snapshot with null pluggableId 1`] = ` + + + + + ProfilePopoverPlugin + + + + +`; + +exports[`plugins/Pluggable should match snapshot with valid pluggableId 1`] = ` + + + + + ProfilePopoverPlugin + + + + +`; diff --git a/webapp/channels/src/plugins/pluggable/pluggable.test.jsx b/webapp/channels/src/plugins/pluggable/pluggable.test.tsx similarity index 67% rename from webapp/channels/src/plugins/pluggable/pluggable.test.jsx rename to webapp/channels/src/plugins/pluggable/pluggable.test.tsx index ce88562548..0c14d47ce9 100644 --- a/webapp/channels/src/plugins/pluggable/pluggable.test.jsx +++ b/webapp/channels/src/plugins/pluggable/pluggable.test.tsx @@ -3,6 +3,8 @@ import React from 'react'; +import {Preferences} from 'mattermost-redux/constants'; + import {mountWithIntl} from 'tests/helpers/intl-test-helper'; import Pluggable from './pluggable'; @@ -18,8 +20,28 @@ jest.mock('actions/views/profile_popover'); describe('plugins/Pluggable', () => { const baseProps = { pluggableName: '', - components: {}, - theme: {}, + components: { + Product: [], + CallButton: [], + PostDropdownMenu: [], + PostAction: [], + PostEditorAction: [], + CodeBlockAction: [], + NewMessagesSeparatorAction: [], + FilePreview: [], + MainMenu: [], + LinkTooltip: [], + RightHandSidebarComponent: [], + ChannelHeaderButton: [], + MobileChannelHeaderButton: [], + AppBar: [], + UserGuideDropdownItem: [], + FilesWillUploadHook: [], + NeedsTeamComponent: [], + CreateBoardFromTemplate: [], + DesktopNotificationHooks: [], + }, + theme: Preferences.THEMES.denim, }; test('should match snapshot with no extended component', () => { @@ -37,7 +59,7 @@ describe('plugins/Pluggable', () => { , ); @@ -51,7 +73,7 @@ describe('plugins/Pluggable', () => { , ); @@ -64,7 +86,7 @@ describe('plugins/Pluggable', () => { const wrapper = mountWithIntl( , ); @@ -85,9 +107,10 @@ describe('plugins/Pluggable', () => { test('should match snapshot with non-null pluggableId', () => { const wrapper = mountWithIntl( , ); @@ -100,7 +123,7 @@ describe('plugins/Pluggable', () => { , ); @@ -114,7 +137,7 @@ describe('plugins/Pluggable', () => { {...baseProps} pluggableName='PopoverSection1' pluggableId={'pluggableId'} - components={{PopoverSection1: [{id: 'pluggableId', component: ProfilePopoverPlugin}]}} + components={{...baseProps.components, PopoverSection1: [{id: 'pluggableId', pluginId: '', component: ProfilePopoverPlugin}]}} />, ); diff --git a/webapp/channels/src/plugins/registry.ts b/webapp/channels/src/plugins/registry.ts index e135b7c85e..0c5056bb1d 100644 --- a/webapp/channels/src/plugins/registry.ts +++ b/webapp/channels/src/plugins/registry.ts @@ -28,7 +28,7 @@ import { registerPluginReconnectHandler, unregisterPluginReconnectHandler, } from 'actions/websocket_actions.jsx'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; import {ActionTypes} from 'utils/constants'; import {reArg} from 'utils/func'; diff --git a/webapp/channels/src/plugins/test/__snapshots__/main_menu_action.test.jsx.snap b/webapp/channels/src/plugins/test/__snapshots__/main_menu_action.test.tsx.snap similarity index 100% rename from webapp/channels/src/plugins/test/__snapshots__/main_menu_action.test.jsx.snap rename to webapp/channels/src/plugins/test/__snapshots__/main_menu_action.test.tsx.snap diff --git a/webapp/channels/src/plugins/test/__snapshots__/post_type.test.jsx.snap b/webapp/channels/src/plugins/test/__snapshots__/post_type.test.tsx.snap similarity index 50% rename from webapp/channels/src/plugins/test/__snapshots__/post_type.test.jsx.snap rename to webapp/channels/src/plugins/test/__snapshots__/post_type.test.tsx.snap index b18f97dc85..350caf7da0 100644 --- a/webapp/channels/src/plugins/test/__snapshots__/post_type.test.jsx.snap +++ b/webapp/channels/src/plugins/test/__snapshots__/post_type.test.tsx.snap @@ -37,7 +37,32 @@ exports[`plugins/PostMessageView should match snapshot with extended post type 1 } theme={ Object { - "id": "theme_id", + "awayIndicator": "#ffbc1f", + "buttonBg": "#1c58d9", + "buttonColor": "#ffffff", + "centerChannelBg": "#ffffff", + "centerChannelColor": "#3f4350", + "codeTheme": "github", + "dndIndicator": "#d24b4e", + "errorTextColor": "#d24b4e", + "linkColor": "#386fe5", + "mentionBg": "#ffffff", + "mentionBj": "#ffffff", + "mentionColor": "#1e325c", + "mentionHighlightBg": "#ffd470", + "mentionHighlightLink": "#1b1d22", + "newMessageSeparator": "#cc8f00", + "onlineIndicator": "#3db887", + "sidebarBg": "#1e325c", + "sidebarHeaderBg": "#192a4d", + "sidebarHeaderTextColor": "#ffffff", + "sidebarTeamBarBg": "#14213e", + "sidebarText": "#ffffff", + "sidebarTextActiveBorder": "#5d89ea", + "sidebarTextActiveColor": "#ffffff", + "sidebarTextHoverBg": "#28427b", + "sidebarUnreadText": "#ffffff", + "type": "Denim", } } > @@ -52,7 +77,32 @@ exports[`plugins/PostMessageView should match snapshot with extended post type 1 } theme={ Object { - "id": "theme_id", + "awayIndicator": "#ffbc1f", + "buttonBg": "#1c58d9", + "buttonColor": "#ffffff", + "centerChannelBg": "#ffffff", + "centerChannelColor": "#3f4350", + "codeTheme": "github", + "dndIndicator": "#d24b4e", + "errorTextColor": "#d24b4e", + "linkColor": "#386fe5", + "mentionBg": "#ffffff", + "mentionBj": "#ffffff", + "mentionColor": "#1e325c", + "mentionHighlightBg": "#ffd470", + "mentionHighlightLink": "#1b1d22", + "newMessageSeparator": "#cc8f00", + "onlineIndicator": "#3db887", + "sidebarBg": "#1e325c", + "sidebarHeaderBg": "#192a4d", + "sidebarHeaderTextColor": "#ffffff", + "sidebarTeamBarBg": "#14213e", + "sidebarText": "#ffffff", + "sidebarTextActiveBorder": "#5d89ea", + "sidebarTextActiveColor": "#ffffff", + "sidebarTextHoverBg": "#28427b", + "sidebarUnreadText": "#ffffff", + "type": "Denim", } } > diff --git a/webapp/channels/src/plugins/test/main_menu_action.test.jsx b/webapp/channels/src/plugins/test/main_menu_action.test.tsx similarity index 90% rename from webapp/channels/src/plugins/test/main_menu_action.test.jsx rename to webapp/channels/src/plugins/test/main_menu_action.test.tsx index cb978c5fd3..5a51ce0f39 100644 --- a/webapp/channels/src/plugins/test/main_menu_action.test.jsx +++ b/webapp/channels/src/plugins/test/main_menu_action.test.tsx @@ -3,6 +3,8 @@ import React from 'react'; +import type {UserProfile} from '@mattermost/types/users'; + import MainMenu from 'components/main_menu/main_menu'; import {shallowWithIntl} from 'tests/helpers/intl-test-helper'; @@ -15,7 +17,7 @@ describe('plugins/MainMenuActions', () => { teamType: '', teamDisplayName: 'some name', teamName: 'somename', - currentUser: {id: 'someuserid', roles: 'system_user'}, + currentUser: {id: 'someuserid', roles: 'system_user'} as UserProfile, enableCommands: true, enableCustomEmoji: true, enableIncomingWebhooks: true, @@ -27,7 +29,7 @@ describe('plugins/MainMenuActions', () => { enablePluginMarketplace: true, showDropdown: true, onToggleDropdown: () => {}, //eslint-disable-line no-empty-function - pluginMenuItems: [{id: 'someplugin', text: 'some plugin text', action: pluginAction}], + pluginMenuItems: [{id: 'someplugin', pluginId: 'test', text: 'some plugin text', action: pluginAction}], canCreateOrDeleteCustomEmoji: true, canManageIntegrations: true, moreTeamsToJoin: true, @@ -54,6 +56,7 @@ describe('plugins/MainMenuActions', () => { isFreeTrial: false, teamsLimitReached: false, usageDeltaTeams: -1, + mobile: false, }; test('should match snapshot in web view', () => { diff --git a/webapp/channels/src/plugins/test/post_type.test.jsx b/webapp/channels/src/plugins/test/post_type.test.tsx similarity index 92% rename from webapp/channels/src/plugins/test/post_type.test.jsx rename to webapp/channels/src/plugins/test/post_type.test.tsx index 46bdc190a6..e8687e5257 100644 --- a/webapp/channels/src/plugins/test/post_type.test.jsx +++ b/webapp/channels/src/plugins/test/post_type.test.tsx @@ -4,6 +4,8 @@ import {shallow, mount} from 'enzyme'; import React from 'react'; +import {Preferences} from 'mattermost-redux/constants'; + import PostMessageView from 'components/post_view/post_message_view/post_message_view'; class PostTypePlugin extends React.PureComponent { @@ -13,7 +15,7 @@ class PostTypePlugin extends React.PureComponent { } describe('plugins/PostMessageView', () => { - const post = {type: 'testtype', message: 'this is some text', id: 'post_id'}; + const post = {type: 'testtype', message: 'this is some text', id: 'post_id'} as any; const pluginPostTypes = { testtype: {component: PostTypePlugin}, }; @@ -24,7 +26,7 @@ describe('plugins/PostMessageView', () => { currentUser: {username: 'username'}, team: {name: 'team_name'}, emojis: {name: 'smile'}, - theme: {id: 'theme_id'}, + theme: Preferences.THEMES.denim, enableFormatting: true, currentRelativeTeamUrl: 'team_url', }; diff --git a/webapp/channels/src/stores/local_storage_store.ts b/webapp/channels/src/stores/local_storage_store.ts index 5e31031b10..dc52cfba68 100644 --- a/webapp/channels/src/stores/local_storage_store.ts +++ b/webapp/channels/src/stores/local_storage_store.ts @@ -4,7 +4,7 @@ import {getRedirectChannelNameForTeam} from 'mattermost-redux/selectors/entities/channels'; import {getBasePath} from 'selectors/general'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; import {PreviousViewedTypes} from 'utils/constants'; diff --git a/webapp/channels/src/stores/redux_store.jsx b/webapp/channels/src/stores/redux_store.tsx similarity index 94% rename from webapp/channels/src/stores/redux_store.jsx rename to webapp/channels/src/stores/redux_store.tsx index 8a38c976d7..18c7387d75 100644 --- a/webapp/channels/src/stores/redux_store.jsx +++ b/webapp/channels/src/stores/redux_store.tsx @@ -10,6 +10,6 @@ const store = configureStore(); // Export the store to simplify debugging in production environments. This is not a supported API, // and should not be relied upon by plugins. -window.store = store; +(window as any).store = store; export default store; diff --git a/webapp/channels/src/tests/helpers/admin_console_plugin_index_sample_pluings.js b/webapp/channels/src/tests/helpers/admin_console_plugin_index_sample_pluings.ts similarity index 100% rename from webapp/channels/src/tests/helpers/admin_console_plugin_index_sample_pluings.js rename to webapp/channels/src/tests/helpers/admin_console_plugin_index_sample_pluings.ts diff --git a/webapp/channels/src/tests/helpers/localstorage.jsx b/webapp/channels/src/tests/helpers/localstorage.tsx similarity index 64% rename from webapp/channels/src/tests/helpers/localstorage.jsx rename to webapp/channels/src/tests/helpers/localstorage.tsx index 9a250c0a2b..54b9e54a31 100644 --- a/webapp/channels/src/tests/helpers/localstorage.jsx +++ b/webapp/channels/src/tests/helpers/localstorage.tsx @@ -3,6 +3,8 @@ // Based on https://stackoverflow.com/a/41434763 class LocalStorageMock { + store: {[key: string]: string}; + constructor() { this.store = {}; } @@ -11,17 +13,19 @@ class LocalStorageMock { this.store = {}; } - getItem(key) { + getItem(key: string): string | null { return this.store[key] || null; } - setItem(key, value) { + setItem(key: string, value: {toString: () => string}) { this.store[key] = value.toString(); } - removeItem(key) { + removeItem(key: string) { delete this.store[key]; } } -global.localStorage = new LocalStorageMock(); +(global as any).localStorage = new LocalStorageMock(); + +export {}; diff --git a/webapp/channels/src/tests/helpers/user_agent_mocks.js b/webapp/channels/src/tests/helpers/user_agent_mocks.ts similarity index 96% rename from webapp/channels/src/tests/helpers/user_agent_mocks.js rename to webapp/channels/src/tests/helpers/user_agent_mocks.ts index f8de89441f..b5bd7a0aa6 100644 --- a/webapp/channels/src/tests/helpers/user_agent_mocks.js +++ b/webapp/channels/src/tests/helpers/user_agent_mocks.ts @@ -20,7 +20,7 @@ Object.defineProperty(window.navigator, 'userAgent', { export function reset() { set(initialUA); } -export function set(ua) { +export function set(ua: string) { currentUA = ua; } export function mockSafari() { diff --git a/webapp/channels/src/utils/__snapshots__/message_html_to_component.test.jsx.snap b/webapp/channels/src/utils/__snapshots__/message_html_to_component.test.tsx.snap similarity index 100% rename from webapp/channels/src/utils/__snapshots__/message_html_to_component.test.jsx.snap rename to webapp/channels/src/utils/__snapshots__/message_html_to_component.test.tsx.snap diff --git a/webapp/channels/src/utils/markdown/index.ts b/webapp/channels/src/utils/markdown/index.ts index 505c661786..aba09a75ce 100644 --- a/webapp/channels/src/utils/markdown/index.ts +++ b/webapp/channels/src/utils/markdown/index.ts @@ -5,7 +5,7 @@ import marked from 'marked'; import {getConfig} from 'mattermost-redux/selectors/entities/general'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; import type EmojiMap from 'utils/emoji_map'; import RemoveMarkdown from 'utils/markdown/remove_markdown'; diff --git a/webapp/channels/src/utils/message_html_to_component.test.jsx b/webapp/channels/src/utils/message_html_to_component.test.tsx similarity index 79% rename from webapp/channels/src/utils/message_html_to_component.test.jsx rename to webapp/channels/src/utils/message_html_to_component.test.tsx index af3a829864..1bfccf5fd1 100644 --- a/webapp/channels/src/utils/message_html_to_component.test.jsx +++ b/webapp/channels/src/utils/message_html_to_component.test.tsx @@ -7,13 +7,16 @@ import AtMention from 'components/at_mention'; import MarkdownImage from 'components/markdown_image'; import Constants from 'utils/constants'; +import EmojiMap from 'utils/emoji_map'; import messageHtmlToComponent from 'utils/message_html_to_component'; import * as TextFormatting from 'utils/text_formatting'; +const emptyEmojiMap = new EmojiMap(new Map()); + describe('messageHtmlToComponent', () => { test('plain text', () => { const input = 'Hello, world!'; - const html = TextFormatting.formatText(input); + const html = TextFormatting.formatText(input, {}, emptyEmojiMap); expect(messageHtmlToComponent(html)).toMatchSnapshot(); }); @@ -29,7 +32,7 @@ F_m - 2 = F_0 F_1 \\dots F_{m-1} \`\`\` That was some latex!`; - const html = TextFormatting.formatText(input); + const html = TextFormatting.formatText(input, {}, emptyEmojiMap); expect(messageHtmlToComponent(html)).toMatchSnapshot(); }); @@ -41,7 +44,7 @@ const myFunction = () => { }; \`\`\` `; - const html = TextFormatting.formatText(input); + const html = TextFormatting.formatText(input, {}, emptyEmojiMap); expect(messageHtmlToComponent(html, {postId: 'randompostid'})).toMatchSnapshot(); }); @@ -51,28 +54,28 @@ const myFunction = () => {
This is a html div
\`\`\` `; - const html = TextFormatting.formatText(input); + const html = TextFormatting.formatText(input, {}, emptyEmojiMap); expect(messageHtmlToComponent(html, {postId: 'randompostid'})).toMatchSnapshot(); }); test('link without enabled tooltip plugins', () => { const input = 'lorem ipsum www.dolor.com sit amet'; - const html = TextFormatting.formatText(input); + const html = TextFormatting.formatText(input, {}, emptyEmojiMap); expect(messageHtmlToComponent(html)).toMatchSnapshot(); }); test('link with enabled a tooltip plugin', () => { const input = 'lorem ipsum www.dolor.com sit amet'; - const html = TextFormatting.formatText(input); + const html = TextFormatting.formatText(input, {}, emptyEmojiMap); expect(messageHtmlToComponent(html, {hasPluginTooltips: true})).toMatchSnapshot(); }); test('Inline markdown image', () => { const options = {markdown: true}; - const html = TextFormatting.formatText('![Mattermost](/images/icon.png) and a [link](link)', options); + const html = TextFormatting.formatText('![Mattermost](/images/icon.png) and a [link](link)', options, emptyEmojiMap); const component = messageHtmlToComponent(html, { hasPluginTooltips: false, @@ -85,7 +88,7 @@ const myFunction = () => { test('Inline markdown image where image is link', () => { const options = {markdown: true}; - const html = TextFormatting.formatText('[![Mattermost](images/icon.png)](images/icon.png)', options); + const html = TextFormatting.formatText('[![Mattermost](images/icon.png)](images/icon.png)', options, emptyEmojiMap); const component = messageHtmlToComponent(html, { hasPluginTooltips: false, @@ -98,7 +101,7 @@ const myFunction = () => { test('At mention', () => { const options = {mentionHighlight: true, atMentions: true, mentionKeys: [{key: '@joram'}]}; - let html = TextFormatting.formatText('@joram', options); + let html = TextFormatting.formatText('@joram', options, emptyEmojiMap); let component = messageHtmlToComponent(html, {mentionHighlight: true}); expect(component).toMatchSnapshot(); @@ -106,7 +109,7 @@ const myFunction = () => { options.mentionHighlight = false; - html = TextFormatting.formatText('@joram', options); + html = TextFormatting.formatText('@joram', options, emptyEmojiMap); component = messageHtmlToComponent(html, {mentionHighlight: false}); expect(component).toMatchSnapshot(); @@ -114,8 +117,8 @@ const myFunction = () => { }); test('At mention with group highlight disabled', () => { - const options = {mentionHighlight: true, atMentions: true, mentionKeys: [{key: '@joram'}]}; - let html = TextFormatting.formatText('@developers', options); + const options: TextFormatting.TextFormattingOptions = {mentionHighlight: true, atMentions: true, mentionKeys: [{key: '@joram'}]}; + let html = TextFormatting.formatText('@developers', options, emptyEmojiMap); let component = messageHtmlToComponent(html, {disableGroupHighlight: false}); expect(component).toMatchSnapshot(); @@ -123,7 +126,7 @@ const myFunction = () => { options.disableGroupHighlight = true; - html = TextFormatting.formatText('@developers', options); + html = TextFormatting.formatText('@developers', options, emptyEmojiMap); component = messageHtmlToComponent(html, {disableGroupHighlight: true}); expect(component).toMatchSnapshot(); @@ -139,7 +142,7 @@ const myFunction = () => { \`\`\` text after typescript block`; - const html = TextFormatting.formatText(input); + const html = TextFormatting.formatText(input, {}, emptyEmojiMap); expect(messageHtmlToComponent(html)).toMatchSnapshot(); }); diff --git a/webapp/channels/src/utils/message_html_to_component.jsx b/webapp/channels/src/utils/message_html_to_component.tsx similarity index 73% rename from webapp/channels/src/utils/message_html_to_component.jsx rename to webapp/channels/src/utils/message_html_to_component.tsx index ddcce3bdf1..c336881480 100644 --- a/webapp/channels/src/utils/message_html_to_component.jsx +++ b/webapp/channels/src/utils/message_html_to_component.tsx @@ -15,6 +15,34 @@ import MarkdownImage from 'components/markdown_image'; import PostEmoji from 'components/post_emoji'; import PostEditedIndicator from 'components/post_view/post_edited_indicator'; +export type Options = Partial<{ + postId: string; + editedAt: number; + hasPluginTooltips: boolean; + mentions: boolean; + mentionHighlight: boolean; + disableGroupHighlight: boolean; + markdown: boolean; + latex: boolean; + inlinelatex: boolean; + postType: string; + imageProps: {[key: string]: any}; + atSumOfMembersMentions: boolean; + userIds: string[]; + imagesMetadata: any; + emoji: boolean; + messageMetadata: any; + images: boolean; + atPlanMentions: boolean; + channelId: string; +}> + +type ProcessingInstruction = { + replaceChildren: boolean; + shouldProcessNode: (node: any) => boolean; + processNode: (node: any, children?: any, index?: number) => any; +} + /* * Converts HTML to React components using html-to-react. * The following options can be specified: @@ -29,25 +57,25 @@ import PostEditedIndicator from 'components/post_view/post_edited_indicator'; * - hasPluginTooltips - If specified, the LinkTooltip component is placed inside links. Defaults to false. * - channelId = If specified, to be passed along to ProfilePopover via AtMention */ -export function messageHtmlToComponent(html, options = {}) { +export function messageHtmlToComponent(html: string, options: Options = {}) { if (!html) { return null; } - const parser = new Parser(); - const processNodeDefinitions = new ProcessNodeDefinitions(React); + const parser = new (Parser as any)(); + const processNodeDefinitions = new (ProcessNodeDefinitions as any)(); function isValidNode() { return true; } - const processingInstructions = [ + const processingInstructions: ProcessingInstruction[] = [ // Workaround to fix MM-14931 { replaceChildren: false, - shouldProcessNode: (node) => node.type === 'tag' && node.name === 'input' && node.attribs.type === 'checkbox', - processNode: (node) => { + shouldProcessNode: (node: any) => node.type === 'tag' && node.name === 'input' && node.attribs.type === 'checkbox', + processNode: (node: any) => { const attribs = node.attribs || {}; node.attribs.checked = Boolean(attribs.checked); @@ -56,9 +84,9 @@ export function messageHtmlToComponent(html, options = {}) { }, { replaceChildren: false, - shouldProcessNode: (node) => node.type === 'tag' && node.name === 'span' && node.attribs['data-edited-post-id'] && node.attribs['data-edited-post-id'] === options.postId, + shouldProcessNode: (node: any) => node.type === 'tag' && node.name === 'span' && node.attribs['data-edited-post-id'] && node.attribs['data-edited-post-id'] === options.postId, processNode: () => { - return options.postId && options.editedAt > 0 ? ( + return options.postId && options.editedAt && options.editedAt > 0 ? ( {' '} node.type === 'tag' && node.name === 'a' && node.attribs[hrefAttrib], - processNode: (node, children) => { + shouldProcessNode: (node: any) => node.type === 'tag' && node.name === 'a' && node.attribs[hrefAttrib], + processNode: (node: any, children: any) => { return ( node.attribs && node.attribs[mentionAttrib], - processNode: (node, children) => { + processNode: (node: any, children: any) => { const mentionName = node.attribs[mentionAttrib]; const callAtMention = ( node.attribs && node.attribs[mentionAttrib], - processNode: (node) => { + shouldProcessNode: (node: any) => node.attribs && node.attribs[mentionAttrib], + processNode: (node: any) => { const mentionName = node.attribs[mentionAttrib]; const sumOfMembersMention = ( ); @@ -137,8 +165,8 @@ export function messageHtmlToComponent(html, options = {}) { const mentionAttrib = 'data-plan-mention'; processingInstructions.push({ replaceChildren: true, - shouldProcessNode: (node) => node.attribs && node.attribs[mentionAttrib], - processNode: (node) => { + shouldProcessNode: (node: any) => node.attribs && node.attribs[mentionAttrib], + processNode: (node: any) => { const mentionName = node.attribs[mentionAttrib]; const sumOfMembersMention = ( node.attribs && node.attribs[emojiAttrib], - processNode: (node) => { + shouldProcessNode: (node: any) => node.attribs && node.attribs[emojiAttrib], + processNode: (node: any) => { const emojiName = node.attribs[emojiAttrib]; return ; @@ -164,14 +192,15 @@ export function messageHtmlToComponent(html, options = {}) { if (!('images' in options) || options.images) { processingInstructions.push({ - shouldProcessNode: (node) => node.type === 'tag' && node.name === 'img', - processNode: (node) => { + replaceChildren: false, + shouldProcessNode: (node: any) => node.type === 'tag' && node.name === 'img', + processNode: (node: any) => { const { class: className, ...attribs } = node.attribs; - const imageIsLink = (parentNode) => { + const imageIsLink = (parentNode: any) => { if (parentNode && parentNode.type === 'tag' && parentNode.name === 'a' @@ -198,8 +227,9 @@ export function messageHtmlToComponent(html, options = {}) { if (!('latex' in options) || options.latex) { processingInstructions.push({ - shouldProcessNode: (node) => node.attribs && node.attribs['data-latex'], - processNode: (node) => { + replaceChildren: false, + shouldProcessNode: (node: any) => node.attribs && node.attribs['data-latex'], + processNode: (node: any) => { return ( node.attribs && node.attribs['data-inline-latex'], - processNode: (node) => { + processNode: (node: any) => { return ( ); @@ -223,8 +254,9 @@ export function messageHtmlToComponent(html, options = {}) { if (!('markdown' in options) || options.markdown) { processingInstructions.push({ + replaceChildren: false, shouldProcessNode: (node) => node.attribs && node.attribs['data-codeblock-code'], - processNode: (node) => { + processNode: (node: any) => { return ( true, - processNode: processNodeDefinitions.processDefaultNode, + processNode: processNodeDefinitions.processDefaultNode as (node: any, children?: any, index?: number) => any, }); return parser.parseWithInstructions(html, isValidNode, processingInstructions); diff --git a/webapp/channels/src/utils/text_formatting.test.ts b/webapp/channels/src/utils/text_formatting.test.ts index 9ea53f94d2..aa57dbef9d 100644 --- a/webapp/channels/src/utils/text_formatting.test.ts +++ b/webapp/channels/src/utils/text_formatting.test.ts @@ -4,7 +4,7 @@ import emojiRegex from 'emoji-regex'; import {getEmojiMap} from 'selectors/emojis'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; import EmojiMap from 'utils/emoji_map'; import LinkOnlyRenderer from 'utils/markdown/link_only_renderer'; diff --git a/webapp/channels/src/utils/utils.test.tsx b/webapp/channels/src/utils/utils.test.tsx index ff63605b27..41c6f25d0c 100644 --- a/webapp/channels/src/utils/utils.test.tsx +++ b/webapp/channels/src/utils/utils.test.tsx @@ -7,7 +7,7 @@ import type {UserProfile} from '@mattermost/types/users'; import {GeneralTypes} from 'mattermost-redux/action_types'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; import * as lineBreakHelpers from 'tests/helpers/line_break_helpers.js'; import * as ua from 'tests/helpers/user_agent_mocks'; diff --git a/webapp/channels/src/utils/utils.tsx b/webapp/channels/src/utils/utils.tsx index f3b84fadbc..e17f1dc85c 100644 --- a/webapp/channels/src/utils/utils.tsx +++ b/webapp/channels/src/utils/utils.tsx @@ -51,7 +51,7 @@ import {displayUsername, isSystemAdmin} from 'mattermost-redux/utils/user_utils' import {searchForTerm} from 'actions/post_actions'; import {addUserToTeam} from 'actions/team_actions'; import {getCurrentLocale, getTranslations} from 'selectors/i18n'; -import store from 'stores/redux_store.jsx'; +import store from 'stores/redux_store'; import {focusPost} from 'components/permalink_view/actions'; import type {TextboxElement} from 'components/textbox'; diff --git a/webapp/channels/webpack.config.js b/webapp/channels/webpack.config.js index deadf6fc6c..723bfa6b4d 100644 --- a/webapp/channels/webpack.config.js +++ b/webapp/channels/webpack.config.js @@ -358,7 +358,7 @@ async function initializeModuleFederation() { // Desktop specific code for remote module loading moduleFederationPluginOptions.exposes = { './app': 'components/app', - './store': 'stores/redux_store.jsx', + './store': 'stores/redux_store', './styles': './src/sass/styles.scss', './registry': 'module_registry', }; diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 3c7f6be63f..ac8e862b6e 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -90,7 +90,7 @@ "highlight.js": "11.6.0", "history": "4.10.1", "hoist-non-react-statics": "3.3.2", - "html-to-react": "1.5.0", + "html-to-react": "1.6.0", "inobounce": "0.2.1", "katex": "0.16.3", "key-mirror": "1.0.1", @@ -12421,13 +12421,16 @@ } }, "node_modules/html-to-react": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/html-to-react/-/html-to-react-1.5.0.tgz", - "integrity": "sha512-tjihXBgaJZRRYzmkrJZ/Qf9jFayilFYcb+sJxXXE2BVLk2XsNrGeuNCVvhXmvREULZb9dz6NFTBC96DTR/lQCQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/html-to-react/-/html-to-react-1.6.0.tgz", + "integrity": "sha512-W7HvCu2fipgz3F7fpEtIt2Ty6XcqFGQXOorR4+HQAk72y9mTtUH3BmJ43BEvXQHO+bt//z1Hbfe6JzojpSC/9w==", "dependencies": { "domhandler": "^5.0", "htmlparser2": "^8.0", "lodash.camelcase": "^4.3.0" + }, + "peerDependencies": { + "react": "^0.13.0 || ^0.14.0 || >=15" } }, "node_modules/html-webpack-plugin": { @@ -33070,9 +33073,9 @@ "dev": true }, "html-to-react": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/html-to-react/-/html-to-react-1.5.0.tgz", - "integrity": "sha512-tjihXBgaJZRRYzmkrJZ/Qf9jFayilFYcb+sJxXXE2BVLk2XsNrGeuNCVvhXmvREULZb9dz6NFTBC96DTR/lQCQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/html-to-react/-/html-to-react-1.6.0.tgz", + "integrity": "sha512-W7HvCu2fipgz3F7fpEtIt2Ty6XcqFGQXOorR4+HQAk72y9mTtUH3BmJ43BEvXQHO+bt//z1Hbfe6JzojpSC/9w==", "requires": { "domhandler": "^5.0", "htmlparser2": "^8.0", @@ -35677,7 +35680,7 @@ "highlight.js": "11.6.0", "history": "4.10.1", "hoist-non-react-statics": "3.3.2", - "html-to-react": "1.5.0", + "html-to-react": "1.6.0", "html-webpack-plugin": "5.5.0", "identity-obj-proxy": "3.0.0", "image-webpack-loader": "8.1.0",