From 36b4b234d0e51b1ab99fb364426a7f5e73705960 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 2 Jul 2024 15:37:08 +0200 Subject: [PATCH 1/8] Implement Parser --- src/libs/OnyxAwareParser.ts | 52 -------------------------------- src/libs/Parser.ts | 59 +++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 52 deletions(-) delete mode 100644 src/libs/OnyxAwareParser.ts create mode 100644 src/libs/Parser.ts diff --git a/src/libs/OnyxAwareParser.ts b/src/libs/OnyxAwareParser.ts deleted file mode 100644 index c058775341c2..000000000000 --- a/src/libs/OnyxAwareParser.ts +++ /dev/null @@ -1,52 +0,0 @@ -import {ExpensiMark} from 'expensify-common'; -import Onyx from 'react-native-onyx'; -import ONYXKEYS from '@src/ONYXKEYS'; - -const parser = new ExpensiMark(); - -const reportIDToNameMap: Record = {}; -const accountIDToNameMap: Record = {}; - -Onyx.connect({ - key: ONYXKEYS.COLLECTION.REPORT, - callback: (report) => { - if (!report) { - return; - } - - reportIDToNameMap[report.reportID] = report.reportName ?? report.displayName ?? report.reportID; - }, -}); - -Onyx.connect({ - key: ONYXKEYS.PERSONAL_DETAILS_LIST, - callback: (personalDetailsList) => { - Object.values(personalDetailsList ?? {}).forEach((personalDetails) => { - if (!personalDetails) { - return; - } - - accountIDToNameMap[personalDetails.accountID] = personalDetails.login ?? String(personalDetails.accountID); - }); - }, -}); - -function parseHtmlToMarkdown( - html: string, - reportIDToName?: Record, - accountIDToName?: Record, - cacheVideoAttributes?: (videoSource: string, videoAttrs: string) => void, -): string { - return parser.htmlToMarkdown(html, {reportIDToName: reportIDToName ?? reportIDToNameMap, accountIDToName: accountIDToName ?? accountIDToNameMap, cacheVideoAttributes}); -} - -function parseHtmlToText( - html: string, - reportIDToName?: Record, - accountIDToName?: Record, - cacheVideoAttributes?: (videoSource: string, videoAttrs: string) => void, -): string { - return parser.htmlToText(html, {reportIDToName: reportIDToName ?? reportIDToNameMap, accountIDToName: accountIDToName ?? accountIDToNameMap, cacheVideoAttributes}); -} - -export {parseHtmlToMarkdown, parseHtmlToText}; diff --git a/src/libs/Parser.ts b/src/libs/Parser.ts new file mode 100644 index 000000000000..746b9670a295 --- /dev/null +++ b/src/libs/Parser.ts @@ -0,0 +1,59 @@ +import {ExpensiMark} from 'expensify-common'; +import Onyx from 'react-native-onyx'; +import ONYXKEYS from '@src/ONYXKEYS'; + +const reportIDToNameMap: Record = {}; +const accountIDToNameMap: Record = {}; + +Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT, + callback: (report) => { + if (!report) { + return; + } + + reportIDToNameMap[report.reportID] = report.reportName ?? report.displayName ?? report.reportID; + }, +}); + +Onyx.connect({ + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + callback: (personalDetailsList) => { + Object.values(personalDetailsList ?? {}).forEach((personalDetails) => { + if (!personalDetails) { + return; + } + + accountIDToNameMap[personalDetails.accountID] = personalDetails.login ?? String(personalDetails.accountID); + }); + }, +}); + +type Extras = { + reportIDToName?: Record; + accountIDToName?: Record; + cacheVideoAttributes?: (vidSource: string, attrs: string) => void; + videoAttributeCache?: Record; +}; + +class ExpensiMarkWithContext extends ExpensiMark { + htmlToMarkdown(htmlString: string, extras?: Extras): string { + return super.htmlToMarkdown(htmlString, { + reportIDToName: extras?.reportIDToName ?? reportIDToNameMap, + accountIDToName: extras?.accountIDToName ?? accountIDToNameMap, + cacheVideoAttributes: extras?.cacheVideoAttributes, + }); + } + + htmlToText(htmlString: string, extras?: Extras): string { + return super.htmlToText(htmlString, { + reportIDToName: extras?.reportIDToName ?? reportIDToNameMap, + accountIDToName: extras?.accountIDToName ?? accountIDToNameMap, + cacheVideoAttributes: extras?.cacheVideoAttributes, + }); + } +} + +const Parser = new ExpensiMarkWithContext(); + +export default Parser; From 29470645763e01a4c8a320166b368361a74ab698 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 2 Jul 2024 15:37:30 +0200 Subject: [PATCH 2/8] Disallow importing ExpeniMark --- .eslintrc.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 22bb0158bc8e..ae3cedaec690 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -8,7 +8,7 @@ const restrictedImportPaths = [ '', "For 'useWindowDimensions', please use '@src/hooks/useWindowDimensions' instead.", "For 'TouchableOpacity', 'TouchableWithoutFeedback', 'TouchableNativeFeedback', 'TouchableHighlight', 'Pressable', please use 'PressableWithFeedback' and/or 'PressableWithoutFeedback' from '@components/Pressable' instead.", - "For 'StatusBar', please use '@src/libs/StatusBar' instead.", + "For 'StatusBar', please use '@libs/StatusBar' instead.", "For 'Text', please use '@components/Text' instead.", "For 'ScrollView', please use '@components/ScrollView' instead.", ].join('\n'), @@ -59,8 +59,12 @@ const restrictedImportPaths = [ }, { name: 'expensify-common', - importNames: ['Device'], - message: "Do not import Device directly, it's known to make VSCode's IntelliSense crash. Please import the desired module from `expensify-common/dist/Device` instead.", + importNames: ['Device', 'ExpensiMark'], + message: [ + '', + "For 'Device', do not import it directly, it's known to make VSCode's IntelliSense crash. Please import the desired module from `expensify-common/dist/Device` instead.", + "For 'ExpensiMark', please use '@libs/Parser' instead.", + ].join('\n'), }, ]; From 1912a3610776ef570304711db50c7b47b2b793ee Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 2 Jul 2024 15:37:57 +0200 Subject: [PATCH 3/8] Ignore ExpeniMark import --- src/libs/Parser.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/Parser.ts b/src/libs/Parser.ts index 746b9670a295..f979b3b5c563 100644 --- a/src/libs/Parser.ts +++ b/src/libs/Parser.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line no-restricted-imports import {ExpensiMark} from 'expensify-common'; import Onyx from 'react-native-onyx'; import ONYXKEYS from '@src/ONYXKEYS'; From 00b1c98d3fe9131c5d7cd63427246bfaf701325d Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 2 Jul 2024 15:38:25 +0200 Subject: [PATCH 4/8] Change usage of OnyxAwareParser --- src/components/LHNOptionsList/OptionRowLHN.tsx | 4 ++-- src/hooks/useCopySelectionHelper.ts | 6 +++--- src/hooks/useHtmlPaste/index.ts | 4 ++-- src/libs/ReportActionsUtils.ts | 6 +++--- src/libs/ReportUtils.ts | 12 ++++++------ src/libs/actions/Report.ts | 6 +++--- src/pages/PrivateNotes/PrivateNotesEditPage.tsx | 6 +++--- src/pages/RoomDescriptionPage.tsx | 4 ++-- .../home/report/ContextMenu/ContextMenuActions.tsx | 8 ++++---- .../ComposerWithSuggestions.tsx | 4 ++-- .../home/report/ReportActionItemMessageEdit.tsx | 4 ++-- src/pages/tasks/NewTaskDescriptionPage.tsx | 4 ++-- src/pages/tasks/NewTaskDetailsPage.tsx | 6 +++--- src/pages/tasks/TaskDescriptionPage.tsx | 6 +++--- src/pages/workspace/WorkspaceInviteMessagePage.tsx | 4 ++-- .../workspace/WorkspaceProfileDescriptionPage.tsx | 4 ++-- src/pages/workspace/taxes/NamePage.tsx | 4 ++-- 17 files changed, 46 insertions(+), 46 deletions(-) diff --git a/src/components/LHNOptionsList/OptionRowLHN.tsx b/src/components/LHNOptionsList/OptionRowLHN.tsx index c7797a37fd12..ffb31b3db7ec 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.tsx +++ b/src/components/LHNOptionsList/OptionRowLHN.tsx @@ -20,8 +20,8 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import DateUtils from '@libs/DateUtils'; import DomUtils from '@libs/DomUtils'; -import {parseHtmlToText} from '@libs/OnyxAwareParser'; import * as OptionsListUtils from '@libs/OptionsListUtils'; +import Parser from '@libs/Parser'; import Performance from '@libs/Performance'; import ReportActionComposeFocusManager from '@libs/ReportActionComposeFocusManager'; import * as ReportUtils from '@libs/ReportUtils'; @@ -242,7 +242,7 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti numberOfLines={1} accessibilityLabel={translate('accessibilityHints.lastChatMessagePreview')} > - {parseHtmlToText(optionItem.alternateText)} + {Parser.htmlToText(optionItem.alternateText)} ) : null} diff --git a/src/hooks/useCopySelectionHelper.ts b/src/hooks/useCopySelectionHelper.ts index ed379bfcf2e6..9bcb9b8b0139 100644 --- a/src/hooks/useCopySelectionHelper.ts +++ b/src/hooks/useCopySelectionHelper.ts @@ -1,7 +1,7 @@ import {useEffect} from 'react'; import Clipboard from '@libs/Clipboard'; import KeyboardShortcut from '@libs/KeyboardShortcut'; -import {parseHtmlToMarkdown, parseHtmlToText} from '@libs/OnyxAwareParser'; +import Parser from '@libs/Parser'; import SelectionScraper from '@libs/SelectionScraper'; import CONST from '@src/CONST'; @@ -11,10 +11,10 @@ function copySelectionToClipboard() { return; } if (!Clipboard.canSetHtml()) { - Clipboard.setString(parseHtmlToMarkdown(selection)); + Clipboard.setString(Parser.htmlToMarkdown(selection)); return; } - Clipboard.setHtml(selection, parseHtmlToText(selection)); + Clipboard.setHtml(selection, Parser.htmlToText(selection)); } export default function useCopySelectionHelper() { diff --git a/src/hooks/useHtmlPaste/index.ts b/src/hooks/useHtmlPaste/index.ts index 4705a170c3bd..a17bc0134333 100644 --- a/src/hooks/useHtmlPaste/index.ts +++ b/src/hooks/useHtmlPaste/index.ts @@ -1,6 +1,6 @@ import {useNavigation} from '@react-navigation/native'; import {useCallback, useEffect} from 'react'; -import {parseHtmlToMarkdown} from '@libs/OnyxAwareParser'; +import Parser from '@libs/Parser'; import type UseHtmlPaste from './types'; const insertByCommand = (text: string) => { @@ -71,7 +71,7 @@ const useHtmlPaste: UseHtmlPaste = (textInputRef, preHtmlPasteCallback, removeLi */ const handlePastedHTML = useCallback( (html: string) => { - paste(parseHtmlToMarkdown(html)); + paste(Parser.htmlToMarkdown(html)); }, [paste], ); diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index c8599d785b22..f47ae594d1a5 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -20,7 +20,7 @@ import isReportMessageAttachment from './isReportMessageAttachment'; import * as Localize from './Localize'; import Log from './Log'; import type {MessageElementBase, MessageTextElement} from './MessageElement'; -import {parseHtmlToText} from './OnyxAwareParser'; +import {Parser.htmlToText} from './OnyxAwareParser'; import * as PersonalDetailsUtils from './PersonalDetailsUtils'; import type {OptimisticIOUReportAction, PartialReportAction} from './ReportUtils'; import StringUtils from './StringUtils'; @@ -1142,11 +1142,11 @@ function getReportActionText(reportAction: PartialReportAction): string { // Sometime html can be an empty string // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const text = (message?.html || message?.text) ?? ''; - return text ? parseHtmlToText(text) : ''; + return text ? Parser.htmlToText(text) : ''; } function getTextFromHtml(html?: string): string { - return html ? parseHtmlToText(html) : ''; + return html ? Parser.htmlToText(html) : ''; } function getMemberChangeMessageFragment(reportAction: OnyxEntry): Message { diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index cf47864a779e..1fe4e6b3ea42 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -63,7 +63,7 @@ import ModifiedExpenseMessage from './ModifiedExpenseMessage'; import linkingConfig from './Navigation/linkingConfig'; import Navigation from './Navigation/Navigation'; import * as NumberUtils from './NumberUtils'; -import {parseHtmlToText} from './OnyxAwareParser'; +import {Parser.htmlToText} from './OnyxAwareParser'; import Permissions from './Permissions'; import * as PersonalDetailsUtils from './PersonalDetailsUtils'; import * as PhoneNumber from './PhoneNumber'; @@ -3288,7 +3288,7 @@ function parseReportActionHtmlToText(reportAction: OnyxEntry, repo const logins = PersonalDetailsUtils.getLoginsByAccountIDs(accountIDs); accountIDs.forEach((id, index) => (accountIDToName[id] = logins[index])); - const textMessage = Str.removeSMSDomain(parseHtmlToText(html, reportIDToName, accountIDToName)); + const textMessage = Str.removeSMSDomain(Parser.htmlToText(html, reportIDToName, accountIDToName)); parsedReportActionMessageCache[key] = textMessage; return textMessage; @@ -3660,7 +3660,7 @@ function getReportDescriptionText(report: Report): string { return ''; } - return parseHtmlToText(report.description); + return Parser.htmlToText(report.description); } function getPolicyDescriptionText(policy: OnyxEntry): string { @@ -3668,7 +3668,7 @@ function getPolicyDescriptionText(policy: OnyxEntry): string { return ''; } - return parseHtmlToText(policy.description); + return Parser.htmlToText(policy.description); } function buildOptimisticAddCommentReportAction( @@ -3690,10 +3690,10 @@ function buildOptimisticAddCommentReportAction( textForNewComment = CONST.ATTACHMENT_UPLOADING_MESSAGE_HTML; } else if (isTextOnly) { htmlForNewComment = commentText; - textForNewComment = parseHtmlToText(htmlForNewComment); + textForNewComment = Parser.htmlToText(htmlForNewComment); } else { htmlForNewComment = `${commentText}${CONST.ATTACHMENT_UPLOADING_MESSAGE_HTML}`; - textForNewComment = `${parseHtmlToText(commentText)}\n${CONST.ATTACHMENT_UPLOADING_MESSAGE_HTML}`; + textForNewComment = `${Parser.htmlToText(commentText)}\n${CONST.ATTACHMENT_UPLOADING_MESSAGE_HTML}`; } const isAttachment = !text && file !== undefined; diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index d05f77f9c7ac..7e0e583e6ec0 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -61,7 +61,7 @@ import Log from '@libs/Log'; import Navigation from '@libs/Navigation/Navigation'; import type {NetworkStatus} from '@libs/NetworkConnection'; import LocalNotification from '@libs/Notification/LocalNotification'; -import {parseHtmlToMarkdown, parseHtmlToText} from '@libs/OnyxAwareParser'; +import Parser from '@libs/Parser'; import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; import * as PhoneNumber from '@libs/PhoneNumber'; import getPolicyEmployeeAccountIDs from '@libs/PolicyEmployeeListUtils'; @@ -1495,7 +1495,7 @@ function editReportComment(reportID: string, originalReportAction: OnyxEntry ReportActions.getDraftPrivateNote(report.reportID).trim() || parseHtmlToMarkdown(report?.privateNotes?.[Number(route.params.accountID)]?.note ?? '').trim(), + () => ReportActions.getDraftPrivateNote(report.reportID).trim() || Parser.htmlToMarkdown(report?.privateNotes?.[Number(route.params.accountID)]?.note ?? '').trim(), ); /** @@ -93,7 +93,7 @@ function PrivateNotesEditPage({route, personalDetailsList, report, session}: Pri const originalNote = report?.privateNotes?.[Number(route.params.accountID)]?.note ?? ''; let editedNote = ''; if (privateNote.trim() !== originalNote.trim()) { - editedNote = ReportActions.handleUserDeletedLinksInHtml(privateNote.trim(), parseHtmlToMarkdown(originalNote).trim()); + editedNote = ReportActions.handleUserDeletedLinksInHtml(privateNote.trim(), Parser.htmlToMarkdown(originalNote).trim()); ReportActions.updatePrivateNotes(report.reportID, Number(route.params.accountID), editedNote); } diff --git a/src/pages/RoomDescriptionPage.tsx b/src/pages/RoomDescriptionPage.tsx index 9f8586292895..1d64ca9e1129 100644 --- a/src/pages/RoomDescriptionPage.tsx +++ b/src/pages/RoomDescriptionPage.tsx @@ -12,7 +12,7 @@ import TextInput from '@components/TextInput'; import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import {parseHtmlToMarkdown} from '@libs/OnyxAwareParser'; +import Parser from '@libs/Parser'; import * as ReportUtils from '@libs/ReportUtils'; import updateMultilineInputRange from '@libs/updateMultilineInputRange'; import variables from '@styles/variables'; @@ -32,7 +32,7 @@ type RoomDescriptionPageProps = { function RoomDescriptionPage({report, policies}: RoomDescriptionPageProps) { const styles = useThemeStyles(); - const [description, setDescription] = useState(() => parseHtmlToMarkdown(report?.description ?? '')); + const [description, setDescription] = useState(() => Parser.htmlToMarkdown(report?.description ?? '')); const reportDescriptionInputRef = useRef(null); const focusTimeoutRef = useRef | null>(null); const {translate} = useLocalize(); diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx index bf634b4ac8ae..45045912ed50 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx @@ -18,7 +18,7 @@ import getAttachmentDetails from '@libs/fileDownload/getAttachmentDetails'; import * as Localize from '@libs/Localize'; import ModifiedExpenseMessage from '@libs/ModifiedExpenseMessage'; import Navigation from '@libs/Navigation/Navigation'; -import {parseHtmlToMarkdown, parseHtmlToText} from '@libs/OnyxAwareParser'; +import Parser from '@libs/Parser'; import ReportActionComposeFocusManager from '@libs/ReportActionComposeFocusManager'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import * as ReportUtils from '@libs/ReportUtils'; @@ -42,11 +42,11 @@ function getActionHtml(reportAction: OnyxInputOrEntry): string { /** Sets the HTML string to Clipboard */ function setClipboardMessage(content: string) { if (!Clipboard.canSetHtml()) { - Clipboard.setString(parseHtmlToMarkdown(content)); + Clipboard.setString(Parser.htmlToMarkdown(content)); } else { const anchorRegex = CONST.REGEX_LINK_IN_ANCHOR; const isAnchorTag = anchorRegex.test(content); - const plainText = isAnchorTag ? parseHtmlToMarkdown(content) : parseHtmlToText(content); + const plainText = isAnchorTag ? Parser.htmlToMarkdown(content) : Parser.htmlToText(content); Clipboard.setHtml(content, plainText); } } @@ -238,7 +238,7 @@ const ContextMenuActions: ContextMenuAction[] = [ } const editAction = () => { if (!draftMessage) { - Report.saveReportActionDraft(reportID, reportAction, parseHtmlToMarkdown(getActionHtml(reportAction))); + Report.saveReportActionDraft(reportID, reportAction, Parser.htmlToMarkdown(getActionHtml(reportAction))); } else { Report.deleteReportActionDraft(reportID, reportAction); } diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx index c744ad589306..81d5fc58ae12 100644 --- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx +++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx @@ -38,7 +38,7 @@ import * as EmojiUtils from '@libs/EmojiUtils'; import focusComposerWithDelay from '@libs/focusComposerWithDelay'; import getPlatform from '@libs/getPlatform'; import * as KeyDownListener from '@libs/KeyboardShortcut/KeyDownPressListener'; -import {parseHtmlToMarkdown} from '@libs/OnyxAwareParser'; +import Parser from '@libs/Parser'; import ReportActionComposeFocusManager from '@libs/ReportActionComposeFocusManager'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import * as ReportUtils from '@libs/ReportUtils'; @@ -543,7 +543,7 @@ function ComposerWithSuggestions( event.preventDefault(); if (lastReportAction) { const message = Array.isArray(lastReportAction?.message) ? lastReportAction?.message?.at(-1) ?? null : lastReportAction?.message ?? null; - Report.saveReportActionDraft(reportID, lastReportAction, parseHtmlToMarkdown(message?.html ?? '')); + Report.saveReportActionDraft(reportID, lastReportAction, Parser.htmlToMarkdown(message?.html ?? '')); } } }, diff --git a/src/pages/home/report/ReportActionItemMessageEdit.tsx b/src/pages/home/report/ReportActionItemMessageEdit.tsx index d3c8ca3af8de..2d87d84dbd6b 100644 --- a/src/pages/home/report/ReportActionItemMessageEdit.tsx +++ b/src/pages/home/report/ReportActionItemMessageEdit.tsx @@ -26,8 +26,8 @@ import * as EmojiUtils from '@libs/EmojiUtils'; import focusComposerWithDelay from '@libs/focusComposerWithDelay'; import type {Selection} from '@libs/focusComposerWithDelay/types'; import focusEditAfterCancelDelete from '@libs/focusEditAfterCancelDelete'; -import {parseHtmlToMarkdown} from '@libs/OnyxAwareParser'; import onyxSubscribe from '@libs/onyxSubscribe'; +import Parser from '@libs/Parser'; import ReportActionComposeFocusManager from '@libs/ReportActionComposeFocusManager'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import * as ReportUtils from '@libs/ReportUtils'; @@ -113,7 +113,7 @@ function ReportActionItemMessageEdit( useEffect(() => { draftMessageVideoAttributeCache.clear(); - const originalMessage = parseHtmlToMarkdown(ReportActionsUtils.getReportActionHtml(action), undefined, undefined, (videoSource, attrs) => { + const originalMessage = Parser.htmlToMarkdown(ReportActionsUtils.getReportActionHtml(action), undefined, undefined, (videoSource, attrs) => { draftMessageVideoAttributeCache.set(videoSource, attrs); }); if (ReportActionsUtils.isDeletedAction(action) || !!(action.message && draftMessage === originalMessage) || !!(prevDraftMessage === draftMessage || isCommentPendingSaved.current)) { diff --git a/src/pages/tasks/NewTaskDescriptionPage.tsx b/src/pages/tasks/NewTaskDescriptionPage.tsx index e9b632a0cee9..a4ff9d0f07ac 100644 --- a/src/pages/tasks/NewTaskDescriptionPage.tsx +++ b/src/pages/tasks/NewTaskDescriptionPage.tsx @@ -16,7 +16,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import type {NewTaskNavigatorParamList} from '@libs/Navigation/types'; -import {parseHtmlToMarkdown} from '@libs/OnyxAwareParser'; +import Parser from '@libs/Parser'; import * as ReportUtils from '@libs/ReportUtils'; import updateMultilineInputRange from '@libs/updateMultilineInputRange'; import variables from '@styles/variables'; @@ -80,7 +80,7 @@ function NewTaskDescriptionPage({task}: NewTaskDescriptionPageProps) { { setTaskTitle(task?.title ?? ''); - setTaskDescription(parseHtmlToMarkdown(parser.replace(task?.description ?? ''))); + setTaskDescription(Parser.htmlToMarkdown(parser.replace(task?.description ?? ''))); }, [task]); const validate = (values: FormOnyxValues): FormInputErrors => { @@ -136,7 +136,7 @@ function NewTaskDetailsPage({task}: NewTaskDetailsPageProps) { autoGrowHeight maxAutoGrowHeight={variables.textInputAutoGrowMaxHeight} shouldSubmitForm - defaultValue={parseHtmlToMarkdown(parser.replace(taskDescription))} + defaultValue={Parser.htmlToMarkdown(parser.replace(taskDescription))} value={taskDescription} onValueChange={setTaskDescription} isMarkdownEnabled diff --git a/src/pages/tasks/TaskDescriptionPage.tsx b/src/pages/tasks/TaskDescriptionPage.tsx index 66bd7d9e9a82..92f5b2394308 100644 --- a/src/pages/tasks/TaskDescriptionPage.tsx +++ b/src/pages/tasks/TaskDescriptionPage.tsx @@ -15,7 +15,7 @@ import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; -import {parseHtmlToMarkdown} from '@libs/OnyxAwareParser'; +import Parser from '@libs/Parser'; import * as ReportUtils from '@libs/ReportUtils'; import updateMultilineInputRange from '@libs/updateMultilineInputRange'; import withReportOrNotFound from '@pages/home/report/withReportOrNotFound'; @@ -48,7 +48,7 @@ function TaskDescriptionPage({report, currentUserPersonalDetails}: TaskDescripti const submit = useCallback( (values: FormOnyxValues) => { - if (values.description !== parseHtmlToMarkdown(report?.description ?? '') && !isEmptyObject(report)) { + if (values.description !== Parser.htmlToMarkdown(report?.description ?? '') && !isEmptyObject(report)) { // Set the description of the report in the store and then call EditTask API // to update the description of the report on the server Task.editTask(report, {description: values.description}); @@ -111,7 +111,7 @@ function TaskDescriptionPage({report, currentUserPersonalDetails}: TaskDescripti name={INPUT_IDS.DESCRIPTION} label={translate('newTaskPage.descriptionOptional')} accessibilityLabel={translate('newTaskPage.descriptionOptional')} - defaultValue={parseHtmlToMarkdown(report?.description ?? '')} + defaultValue={Parser.htmlToMarkdown(report?.description ?? '')} ref={(element: AnimatedTextInputRef) => { if (!element) { return; diff --git a/src/pages/workspace/WorkspaceInviteMessagePage.tsx b/src/pages/workspace/WorkspaceInviteMessagePage.tsx index 9bab92bc38b0..63528de3fa30 100644 --- a/src/pages/workspace/WorkspaceInviteMessagePage.tsx +++ b/src/pages/workspace/WorkspaceInviteMessagePage.tsx @@ -22,8 +22,8 @@ import useAutoFocusInput from '@hooks/useAutoFocusInput'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; -import {parseHtmlToMarkdown} from '@libs/OnyxAwareParser'; import * as OptionsListUtils from '@libs/OptionsListUtils'; +import Parser from '@libs/Parser'; import * as PolicyUtils from '@libs/PolicyUtils'; import updateMultilineInputRange from '@libs/updateMultilineInputRange'; import type {SettingsNavigatorParamList} from '@navigation/types'; @@ -96,7 +96,7 @@ function WorkspaceInviteMessagePage({ useEffect(() => { if (!isEmptyObject(invitedEmailsToAccountIDsDraft)) { - setWelcomeNote(parseHtmlToMarkdown(getDefaultWelcomeNote())); + setWelcomeNote(Parser.htmlToMarkdown(getDefaultWelcomeNote())); return; } Navigation.goBack(ROUTES.WORKSPACE_INVITE.getRoute(route.params.policyID), true); diff --git a/src/pages/workspace/WorkspaceProfileDescriptionPage.tsx b/src/pages/workspace/WorkspaceProfileDescriptionPage.tsx index 54dcfd62ac44..e31a6fdb0a3d 100644 --- a/src/pages/workspace/WorkspaceProfileDescriptionPage.tsx +++ b/src/pages/workspace/WorkspaceProfileDescriptionPage.tsx @@ -12,7 +12,7 @@ import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; -import {parseHtmlToMarkdown} from '@libs/OnyxAwareParser'; +import Parser from '@libs/Parser'; import updateMultilineInputRange from '@libs/updateMultilineInputRange'; import variables from '@styles/variables'; import * as Policy from '@userActions/Policy/Policy'; @@ -30,7 +30,7 @@ function WorkspaceProfileDescriptionPage({policy}: Props) { const styles = useThemeStyles(); const {translate} = useLocalize(); const [description, setDescription] = useState(() => - parseHtmlToMarkdown( + Parser.htmlToMarkdown( // policy?.description can be an empty string // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing policy?.description || diff --git a/src/pages/workspace/taxes/NamePage.tsx b/src/pages/workspace/taxes/NamePage.tsx index 3d589e7339a8..0fb495a04574 100644 --- a/src/pages/workspace/taxes/NamePage.tsx +++ b/src/pages/workspace/taxes/NamePage.tsx @@ -13,7 +13,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import {renamePolicyTax, validateTaxName} from '@libs/actions/TaxRate'; import Navigation from '@libs/Navigation/Navigation'; import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; -import {parseHtmlToMarkdown} from '@libs/OnyxAwareParser'; +import Parser from '@libs/Parser'; import * as PolicyUtils from '@libs/PolicyUtils'; import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; @@ -38,7 +38,7 @@ function NamePage({ const currentTaxRate = PolicyUtils.getTaxByID(policy, taxID); const {inputCallbackRef} = useAutoFocusInput(); - const [name, setName] = useState(() => parseHtmlToMarkdown(currentTaxRate?.name ?? '')); + const [name, setName] = useState(() => Parser.htmlToMarkdown(currentTaxRate?.name ?? '')); const goBack = useCallback(() => Navigation.goBack(ROUTES.WORKSPACE_TAX_EDIT.getRoute(policyID ?? '-1', taxID)), [policyID, taxID]); From 01e3d0190992fffa4874abdc63d5b4e705f5c5c2 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 2 Jul 2024 15:54:29 +0200 Subject: [PATCH 5/8] set the logger in PArser lib --- src/libs/Log.ts | 3 +-- src/libs/Parser.ts | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libs/Log.ts b/src/libs/Log.ts index 64271dee2265..83965807263a 100644 --- a/src/libs/Log.ts +++ b/src/libs/Log.ts @@ -2,7 +2,7 @@ // action would likely cause confusion about which one to use. But most other API methods should happen inside an action file. /* eslint-disable rulesdir/no-api-in-views */ -import {ExpensiMark, Logger} from 'expensify-common'; +import {Logger} from 'expensify-common'; import Onyx from 'react-native-onyx'; import type {Merge} from 'type-fest'; import CONST from '@src/CONST'; @@ -80,6 +80,5 @@ const Log = new Logger({ isDebug: true, }); timeout = setTimeout(() => Log.info('Flushing logs older than 10 minutes', true, {}, true), 10 * 60 * 1000); -ExpensiMark.setLogger(Log); export default Log; diff --git a/src/libs/Parser.ts b/src/libs/Parser.ts index f979b3b5c563..3f9d3c48b49c 100644 --- a/src/libs/Parser.ts +++ b/src/libs/Parser.ts @@ -2,6 +2,7 @@ import {ExpensiMark} from 'expensify-common'; import Onyx from 'react-native-onyx'; import ONYXKEYS from '@src/ONYXKEYS'; +import Log from './Log'; const reportIDToNameMap: Record = {}; const accountIDToNameMap: Record = {}; @@ -55,6 +56,7 @@ class ExpensiMarkWithContext extends ExpensiMark { } } +ExpensiMarkWithContext.setLogger(Log); const Parser = new ExpensiMarkWithContext(); export default Parser; From 69bafc75b14f942295f3b64ae729c644c6dd7d3b Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 2 Jul 2024 15:54:54 +0200 Subject: [PATCH 6/8] Remove all ExpeniMark imports and use PArser instead --- src/components/MenuItem.tsx | 8 +++----- src/libs/ReportActionsUtils.ts | 2 +- src/libs/ReportUtils.ts | 9 ++++----- src/libs/actions/Policy/Member.ts | 4 ++-- src/libs/actions/Report.ts | 12 +++++------- .../home/report/ReportActionItemMessageEdit.tsx | 4 ++-- src/pages/tasks/NewTaskDescriptionPage.tsx | 5 +---- src/pages/tasks/NewTaskDetailsPage.tsx | 7 ++----- src/pages/workspace/WorkspaceInviteMessagePage.tsx | 5 +---- .../workspace/WorkspaceProfileDescriptionPage.tsx | 5 +---- src/pages/workspace/WorkspaceProfilePage.tsx | 6 ++---- 11 files changed, 24 insertions(+), 43 deletions(-) diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index 9fd18524158d..357ef60d5161 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -1,4 +1,3 @@ -import {ExpensiMark} from 'expensify-common'; import type {ImageContentFit} from 'expo-image'; import type {ReactElement, ReactNode} from 'react'; import React, {forwardRef, useContext, useMemo} from 'react'; @@ -14,6 +13,7 @@ import ControlSelection from '@libs/ControlSelection'; import convertToLTR from '@libs/convertToLTR'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; import getButtonState from '@libs/getButtonState'; +import Parser from '@libs/Parser'; import type {AvatarSource} from '@libs/UserUtils'; import variables from '@styles/variables'; import * as Session from '@userActions/Session'; @@ -429,16 +429,14 @@ function MenuItem( if (!title || !shouldParseTitle) { return ''; } - const parser = new ExpensiMark(); - return parser.replace(title, {shouldEscapeText}); + return Parser.replace(title, {shouldEscapeText}); }, [title, shouldParseTitle, shouldEscapeText]); const helperHtml = useMemo(() => { if (!helperText || !shouldParseHelperText) { return ''; } - const parser = new ExpensiMark(); - return parser.replace(helperText, {shouldEscapeText}); + return Parser.replace(helperText, {shouldEscapeText}); }, [helperText, shouldParseHelperText, shouldEscapeText]); const processedTitle = useMemo(() => { diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index f47ae594d1a5..680fef414732 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -20,7 +20,7 @@ import isReportMessageAttachment from './isReportMessageAttachment'; import * as Localize from './Localize'; import Log from './Log'; import type {MessageElementBase, MessageTextElement} from './MessageElement'; -import {Parser.htmlToText} from './OnyxAwareParser'; +import Parser from './Parser'; import * as PersonalDetailsUtils from './PersonalDetailsUtils'; import type {OptimisticIOUReportAction, PartialReportAction} from './ReportUtils'; import StringUtils from './StringUtils'; diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 1fe4e6b3ea42..3553d3e7cbc5 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -1,5 +1,5 @@ import {format} from 'date-fns'; -import {ExpensiMark, Str} from 'expensify-common'; +import {Str} from 'expensify-common'; import {isEmpty} from 'lodash'; import lodashEscape from 'lodash/escape'; import lodashFindLastIndex from 'lodash/findLastIndex'; @@ -63,7 +63,7 @@ import ModifiedExpenseMessage from './ModifiedExpenseMessage'; import linkingConfig from './Navigation/linkingConfig'; import Navigation from './Navigation/Navigation'; import * as NumberUtils from './NumberUtils'; -import {Parser.htmlToText} from './OnyxAwareParser'; +import Parser from './Parser'; import Permissions from './Permissions'; import * as PersonalDetailsUtils from './PersonalDetailsUtils'; import * as PhoneNumber from './PhoneNumber'; @@ -3288,7 +3288,7 @@ function parseReportActionHtmlToText(reportAction: OnyxEntry, repo const logins = PersonalDetailsUtils.getLoginsByAccountIDs(accountIDs); accountIDs.forEach((id, index) => (accountIDToName[id] = logins[index])); - const textMessage = Str.removeSMSDomain(Parser.htmlToText(html, reportIDToName, accountIDToName)); + const textMessage = Str.removeSMSDomain(Parser.htmlToText(html, {reportIDToName, accountIDToName})); parsedReportActionMessageCache[key] = textMessage; return textMessage; @@ -3640,7 +3640,6 @@ function getParsedComment(text: string, parsingDetails?: ParsingDetails): string isGroupPolicyReport = isReportInGroupPolicy(currentReport); } - const parser = new ExpensiMark(); const textWithMention = text.replace(CONST.REGEX.SHORT_MENTION, (match) => { if (!Str.isValidMention(match)) { return match; @@ -3651,7 +3650,7 @@ function getParsedComment(text: string, parsingDetails?: ParsingDetails): string }); return text.length <= CONST.MAX_MARKUP_LENGTH - ? parser.replace(textWithMention, {shouldEscapeText: parsingDetails?.shouldEscapeText, disabledRules: isGroupPolicyReport ? [] : ['reportMentions']}) + ? Parser.replace(textWithMention, {shouldEscapeText: parsingDetails?.shouldEscapeText, disabledRules: isGroupPolicyReport ? [] : ['reportMentions']}) : lodashEscape(text); } diff --git a/src/libs/actions/Policy/Member.ts b/src/libs/actions/Policy/Member.ts index f8472bd43098..218bf3a93c69 100644 --- a/src/libs/actions/Policy/Member.ts +++ b/src/libs/actions/Policy/Member.ts @@ -1,4 +1,3 @@ -import {ExpensiMark} from 'expensify-common'; import type {NullishDeep, OnyxCollection, OnyxCollectionInputValue, OnyxEntry, OnyxUpdate} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import * as API from '@libs/API'; @@ -12,6 +11,7 @@ import type { import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types'; import * as ErrorUtils from '@libs/ErrorUtils'; import Log from '@libs/Log'; +import Parser from '@libs/Parser'; import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; import * as PhoneNumber from '@libs/PhoneNumber'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; @@ -627,7 +627,7 @@ function addMembersToWorkspace(invitedEmailsToAccountIDs: InvitedEmailsToAccount const params: AddMembersToWorkspaceParams = { employees: JSON.stringify(logins.map((login) => ({email: login}))), - welcomeNote: new ExpensiMark().replace(welcomeNote), + welcomeNote: Parser.replace(welcomeNote), policyID, }; if (!isEmptyObject(membersChats.reportCreationData)) { diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 7e0e583e6ec0..54039fc9dadb 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -1,5 +1,5 @@ import {format as timezoneFormat, utcToZonedTime} from 'date-fns-tz'; -import {ExpensiMark, Str} from 'expensify-common'; +import {Str} from 'expensify-common'; import isEmpty from 'lodash/isEmpty'; import {DeviceEventEmitter, InteractionManager, Linking} from 'react-native'; import type {NullishDeep, OnyxCollection, OnyxEntry, OnyxUpdate} from 'react-native-onyx'; @@ -1470,21 +1470,19 @@ function removeLinksFromHtml(html: string, links: string[]): string { * @param videoAttributeCache cache of video attributes ([videoSource]: videoAttributes) */ function handleUserDeletedLinksInHtml(newCommentText: string, originalCommentMarkdown: string, videoAttributeCache?: Record): string { - const parser = new ExpensiMark(); if (newCommentText.length > CONST.MAX_MARKUP_LENGTH) { return newCommentText; } - const htmlForNewComment = parser.replace(newCommentText, { + const htmlForNewComment = Parser.replace(newCommentText, { extras: {videoAttributeCache}, }); - const removedLinks = parser.getRemovedMarkdownLinks(originalCommentMarkdown, newCommentText); + const removedLinks = Parser.getRemovedMarkdownLinks(originalCommentMarkdown, newCommentText); return removeLinksFromHtml(htmlForNewComment, removedLinks); } /** Saves a new message for a comment. Marks the comment as edited, which will be reflected in the UI. */ function editReportComment(reportID: string, originalReportAction: OnyxEntry, textForNewComment: string, videoAttributeCache?: Record) { - const parser = new ExpensiMark(); const originalReportID = ReportUtils.getOriginalReportID(reportID, originalReportAction); if (!originalReportID || !originalReportAction) { @@ -1509,8 +1507,8 @@ function editReportComment(reportID: string, originalReportAction: OnyxEntry rule.name).filter((name) => name !== 'autolink')}; - parsedOriginalCommentHTML = parser.replace(originalCommentMarkdown, autolinkFilter); + const autolinkFilter = {filterRules: Parser.rules.map((rule) => rule.name).filter((name) => name !== 'autolink')}; + parsedOriginalCommentHTML = Parser.replace(originalCommentMarkdown, autolinkFilter); } // Delete the comment if it's empty diff --git a/src/pages/home/report/ReportActionItemMessageEdit.tsx b/src/pages/home/report/ReportActionItemMessageEdit.tsx index 2d87d84dbd6b..2766de157dd3 100644 --- a/src/pages/home/report/ReportActionItemMessageEdit.tsx +++ b/src/pages/home/report/ReportActionItemMessageEdit.tsx @@ -113,8 +113,8 @@ function ReportActionItemMessageEdit( useEffect(() => { draftMessageVideoAttributeCache.clear(); - const originalMessage = Parser.htmlToMarkdown(ReportActionsUtils.getReportActionHtml(action), undefined, undefined, (videoSource, attrs) => { - draftMessageVideoAttributeCache.set(videoSource, attrs); + const originalMessage = Parser.htmlToMarkdown(ReportActionsUtils.getReportActionHtml(action), { + cacheVideoAttributes: (videoSource, attrs) => draftMessageVideoAttributeCache.set(videoSource, attrs), }); if (ReportActionsUtils.isDeletedAction(action) || !!(action.message && draftMessage === originalMessage) || !!(prevDraftMessage === draftMessage || isCommentPendingSaved.current)) { return; diff --git a/src/pages/tasks/NewTaskDescriptionPage.tsx b/src/pages/tasks/NewTaskDescriptionPage.tsx index a4ff9d0f07ac..f5aaf9ea8ffd 100644 --- a/src/pages/tasks/NewTaskDescriptionPage.tsx +++ b/src/pages/tasks/NewTaskDescriptionPage.tsx @@ -1,5 +1,4 @@ import type {StackScreenProps} from '@react-navigation/stack'; -import {ExpensiMark} from 'expensify-common'; import React from 'react'; import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; @@ -35,8 +34,6 @@ type NewTaskDescriptionPageOnyxProps = { type NewTaskDescriptionPageProps = NewTaskDescriptionPageOnyxProps & StackScreenProps; -const parser = new ExpensiMark(); - function NewTaskDescriptionPage({task}: NewTaskDescriptionPageProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -80,7 +77,7 @@ function NewTaskDescriptionPage({task}: NewTaskDescriptionPageProps) { ; -const parser = new ExpensiMark(); - function NewTaskDetailsPage({task}: NewTaskDetailsPageProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -50,7 +47,7 @@ function NewTaskDetailsPage({task}: NewTaskDetailsPageProps) { useEffect(() => { setTaskTitle(task?.title ?? ''); - setTaskDescription(Parser.htmlToMarkdown(parser.replace(task?.description ?? ''))); + setTaskDescription(Parser.htmlToMarkdown(Parser.replace(task?.description ?? ''))); }, [task]); const validate = (values: FormOnyxValues): FormInputErrors => { @@ -136,7 +133,7 @@ function NewTaskDetailsPage({task}: NewTaskDetailsPageProps) { autoGrowHeight maxAutoGrowHeight={variables.textInputAutoGrowMaxHeight} shouldSubmitForm - defaultValue={Parser.htmlToMarkdown(parser.replace(taskDescription))} + defaultValue={Parser.htmlToMarkdown(Parser.replace(taskDescription))} value={taskDescription} onValueChange={setTaskDescription} isMarkdownEnabled diff --git a/src/pages/workspace/WorkspaceInviteMessagePage.tsx b/src/pages/workspace/WorkspaceInviteMessagePage.tsx index 63528de3fa30..f7742ecd1361 100644 --- a/src/pages/workspace/WorkspaceInviteMessagePage.tsx +++ b/src/pages/workspace/WorkspaceInviteMessagePage.tsx @@ -1,5 +1,4 @@ import type {StackScreenProps} from '@react-navigation/stack'; -import {ExpensiMark} from 'expensify-common'; import lodashDebounce from 'lodash/debounce'; import React, {useEffect, useMemo, useState} from 'react'; import {Keyboard, View} from 'react-native'; @@ -59,8 +58,6 @@ type WorkspaceInviteMessagePageProps = WithPolicyAndFullscreenLoadingProps & WorkspaceInviteMessagePageOnyxProps & StackScreenProps; -const parser = new ExpensiMark(); - function WorkspaceInviteMessagePage({ workspaceInviteMessageDraft, invitedEmailsToAccountIDsDraft, @@ -88,7 +85,7 @@ function WorkspaceInviteMessagePage({ // policy?.description can be an empty string // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing policy?.description || - parser.replace( + Parser.replace( translate('workspace.common.welcomeNote', { workspaceName: policy?.name ?? '', }), diff --git a/src/pages/workspace/WorkspaceProfileDescriptionPage.tsx b/src/pages/workspace/WorkspaceProfileDescriptionPage.tsx index e31a6fdb0a3d..527fdf28f8d1 100644 --- a/src/pages/workspace/WorkspaceProfileDescriptionPage.tsx +++ b/src/pages/workspace/WorkspaceProfileDescriptionPage.tsx @@ -1,4 +1,3 @@ -import {ExpensiMark} from 'expensify-common'; import React, {useCallback, useState} from 'react'; import {Keyboard, View} from 'react-native'; import FormProvider from '@components/Form/FormProvider'; @@ -24,8 +23,6 @@ import type {WithPolicyProps} from './withPolicy'; type Props = WithPolicyProps; -const parser = new ExpensiMark(); - function WorkspaceProfileDescriptionPage({policy}: Props) { const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -34,7 +31,7 @@ function WorkspaceProfileDescriptionPage({policy}: Props) { // policy?.description can be an empty string // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing policy?.description || - parser.replace( + Parser.replace( translate('workspace.common.welcomeNote', { workspaceName: policy?.name ?? '', }), diff --git a/src/pages/workspace/WorkspaceProfilePage.tsx b/src/pages/workspace/WorkspaceProfilePage.tsx index 6a86a83b5d11..9163afdf24f6 100644 --- a/src/pages/workspace/WorkspaceProfilePage.tsx +++ b/src/pages/workspace/WorkspaceProfilePage.tsx @@ -1,4 +1,3 @@ -import {ExpensiMark} from 'expensify-common'; import React, {useCallback, useState} from 'react'; import type {ImageStyle, StyleProp} from 'react-native'; import {Image, StyleSheet, View} from 'react-native'; @@ -21,6 +20,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; +import Parser from '@libs/Parser'; import * as PolicyUtils from '@libs/PolicyUtils'; import * as ReportUtils from '@libs/ReportUtils'; import StringUtils from '@libs/StringUtils'; @@ -42,8 +42,6 @@ type WorkSpaceProfilePageOnyxProps = { type WorkSpaceProfilePageProps = WithPolicyProps & WorkSpaceProfilePageOnyxProps; -const parser = new ExpensiMark(); - function WorkspaceProfilePage({policy, currencyList = {}, route}: WorkSpaceProfilePageProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -73,7 +71,7 @@ function WorkspaceProfilePage({policy, currencyList = {}, route}: WorkSpaceProfi // policy?.description can be an empty string // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing policy?.description || - parser.replace( + Parser.replace( translate('workspace.common.welcomeNote', { workspaceName: policy?.name ?? '', }), From a4d0160daa425280b827bf94339256614f622f9a Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 2 Jul 2024 15:55:24 +0200 Subject: [PATCH 7/8] Add eslint disable for storybook ExpeniMark import --- src/stories/Composer.stories.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/stories/Composer.stories.tsx b/src/stories/Composer.stories.tsx index 7244479b4c58..805f2b4c7448 100644 --- a/src/stories/Composer.stories.tsx +++ b/src/stories/Composer.stories.tsx @@ -1,4 +1,5 @@ import type {Meta} from '@storybook/react'; +// eslint-disable-next-line no-restricted-imports import {ExpensiMark} from 'expensify-common'; import React, {useState} from 'react'; import {Image, View} from 'react-native'; From 6c32800a015c42a4cb7153301ed052daac7849a9 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 8 Jul 2024 11:43:04 +0200 Subject: [PATCH 8/8] Change ExpensiMark usage to Parser --- .../NetSuiteTokenInput/substeps/NetSuiteTokenInputForm.tsx | 6 ++---- .../substeps/NetSuiteTokenSetupContent.tsx | 6 ++---- .../import/NetSuiteImportCustomersOrProjectsPage.tsx | 6 ++---- .../netsuite/import/NetSuiteImportMappingPage.tsx | 6 ++---- src/pages/workspace/workflows/ToggleSettingsOptionRow.tsx | 5 ++--- 5 files changed, 10 insertions(+), 19 deletions(-) diff --git a/src/pages/workspace/accounting/netsuite/NetSuiteTokenInput/substeps/NetSuiteTokenInputForm.tsx b/src/pages/workspace/accounting/netsuite/NetSuiteTokenInput/substeps/NetSuiteTokenInputForm.tsx index 08e2ab9460ec..3747bf1b6e4e 100644 --- a/src/pages/workspace/accounting/netsuite/NetSuiteTokenInput/substeps/NetSuiteTokenInputForm.tsx +++ b/src/pages/workspace/accounting/netsuite/NetSuiteTokenInput/substeps/NetSuiteTokenInputForm.tsx @@ -1,4 +1,3 @@ -import {ExpensiMark} from 'expensify-common'; import React, {useCallback} from 'react'; import {View} from 'react-native'; import FormProvider from '@components/Form/FormProvider'; @@ -12,12 +11,11 @@ import type {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; import {connectPolicyToNetSuite} from '@libs/actions/connections/NetSuiteCommands'; import * as ErrorUtils from '@libs/ErrorUtils'; +import Parser from '@libs/Parser'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/NetSuiteTokenInputForm'; -const parser = new ExpensiMark(); - function NetSuiteTokenInputForm({onNext, policyID}: SubStepProps & {policyID: string}) { const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -76,7 +74,7 @@ function NetSuiteTokenInputForm({onNext, policyID}: SubStepProps & {policyID: st {formInput === INPUT_IDS.NETSUITE_ACCOUNT_ID && ( ${parser.replace( + html={`${Parser.replace( translate(`workspace.netsuite.tokenInput.formSteps.enterCredentials.${formInput}Description`), )}`} /> diff --git a/src/pages/workspace/accounting/netsuite/NetSuiteTokenInput/substeps/NetSuiteTokenSetupContent.tsx b/src/pages/workspace/accounting/netsuite/NetSuiteTokenInput/substeps/NetSuiteTokenSetupContent.tsx index f1b9ed258d7d..889e3101fb32 100644 --- a/src/pages/workspace/accounting/netsuite/NetSuiteTokenInput/substeps/NetSuiteTokenSetupContent.tsx +++ b/src/pages/workspace/accounting/netsuite/NetSuiteTokenInput/substeps/NetSuiteTokenSetupContent.tsx @@ -1,4 +1,3 @@ -import {ExpensiMark} from 'expensify-common'; import React from 'react'; import {View} from 'react-native'; import Button from '@components/Button'; @@ -8,11 +7,10 @@ import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import type {SubStepProps} from '@hooks/useSubStep/types'; import useThemeStyles from '@hooks/useThemeStyles'; +import Parser from '@libs/Parser'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; -const parser = new ExpensiMark(); - function NetSuiteTokenSetupContent({onNext, screenIndex}: SubStepProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -27,7 +25,7 @@ function NetSuiteTokenSetupContent({onNext, screenIndex}: SubStepProps) { {translate(titleKey)} - ${parser.replace(translate(description))}`} /> + ${Parser.replace(translate(description))}`} />