From 6abc35a07200c3befa2991a4549efed05c055b54 Mon Sep 17 00:00:00 2001 From: gelocraft Date: Mon, 17 Nov 2025 12:28:46 +0000 Subject: [PATCH 1/2] fix(eslint): auto-fix unicorn/no-array-foreach rule violations --- .../generateHelpPreviewComment.ts | 12 +- .github/libs/GitUtils.ts | 10 +- .github/libs/GithubUtils.ts | 16 +- .github/scripts/createDocsRoutes.ts | 14 +- __mocks__/react-native.ts | 4 +- assets/emojis/index.ts | 4 +- desktop/main.ts | 6 +- help/default.js | 12 +- jest/setup.ts | 14 +- jest/setupMockImages.ts | 4 +- scripts/checkLazyLoading.ts | 20 +-- scripts/compressSvg.ts | 18 +- scripts/generateTranslations.ts | 4 +- scripts/utils/parseCommandLineArguments.ts | 4 +- src/NAICS.ts | 10 +- src/components/AddPlaidBankAccount.tsx | 4 +- src/components/AddressForm.tsx | 6 +- src/components/AddressSearch/index.tsx | 6 +- .../AttachmentPicker/index.native.tsx | 6 +- .../AttachmentCarousel/extractAttachments.ts | 6 +- src/components/FlatList/index.tsx | 26 +-- src/components/Form/FormProvider.tsx | 18 +- src/components/InlineCodeBlock/index.tsx | 6 +- .../MoneyRequestConfirmationList.tsx | 8 +- src/components/PriorityModeController.tsx | 6 +- .../ScrollOffsetContextProvider.tsx | 6 +- .../Search/SearchFiltersCurrencyBase.tsx | 6 +- .../SearchRouter/buildSubstitutionsMap.ts | 4 +- src/components/Search/index.tsx | 24 +-- .../BaseSelectionListWithSections.tsx | 58 +++---- src/hooks/useBulkPayOptions.ts | 4 +- src/hooks/useDeleteTransactions.ts | 12 +- src/hooks/useFilesValidation.tsx | 16 +- src/hooks/useLazyAsset.ts | 16 +- src/hooks/useLetterAvatars.tsx | 4 +- src/hooks/useMarkdownStyle.ts | 8 +- src/hooks/useOnyx.ts | 6 +- src/hooks/useSearchHighlightAndScroll.ts | 18 +- src/hooks/useSearchTypeMenu.tsx | 4 +- src/hooks/useSelectedTransactionsActions.ts | 14 +- .../useTransactionViolationOfWorkspace.tsx | 6 +- src/hooks/useWaitForNavigation.ts | 4 +- src/languages/flattenObject.ts | 4 +- src/libs/CardFeedUtils.ts | 52 +++--- src/libs/CardUtils.ts | 28 ++-- src/libs/CategoryOptionListUtils.ts | 18 +- src/libs/ComposerFocusManager.ts | 12 +- src/libs/DateUtils.ts | 4 +- src/libs/DebugUtils.ts | 52 +++--- src/libs/DistanceRequestUtils.ts | 8 +- src/libs/E2E/utils/NetworkInterceptor.ts | 12 +- src/libs/EmojiTrie.ts | 4 +- src/libs/EmojiUtils.tsx | 36 ++-- src/libs/ExportOnyxState/common.ts | 26 +-- src/libs/Firebase/index.native.ts | 4 +- src/libs/Firebase/index.web.ts | 4 +- src/libs/Firebase/utils.ts | 4 +- src/libs/Formula.ts | 36 ++-- src/libs/GooglePlacesUtils.ts | 18 +- src/libs/ImportOnyxStateUtils.ts | 10 +- src/libs/KeyboardShortcut/index.ts | 6 +- src/libs/LocaleDigitUtils.ts | 4 +- src/libs/Log.ts | 4 +- src/libs/MentionUtils.ts | 6 +- src/libs/MergeTransactionUtils.ts | 18 +- .../Middleware/HandleUnusedOptimisticID.ts | 14 +- src/libs/ModifiedExpenseMessage.ts | 8 +- .../helpers/createNormalizedConfigs.ts | 4 +- .../linkingConfig/RELATIONS/index.ts | 4 +- src/libs/Network/MainQueue.ts | 6 +- src/libs/NetworkConnection.ts | 8 +- src/libs/NextStepUtils.ts | 40 ++--- .../clearReportNotifications/index.native.ts | 4 +- src/libs/OptionsListUtils/index.ts | 62 +++---- src/libs/Parser.ts | 12 +- src/libs/PaymentUtils.ts | 10 +- src/libs/PerDiemRequestUtils.ts | 6 +- src/libs/Performance.tsx | 8 +- src/libs/PersonalDetailsUtils.ts | 8 +- src/libs/PolicyUtils.ts | 47 +++--- src/libs/Pusher/index.native.ts | 4 +- src/libs/Pusher/index.ts | 4 +- src/libs/ReportUtils.ts | 42 ++--- src/libs/SearchUIUtils.ts | 6 +- src/libs/SelectionScraper/index.ts | 4 +- src/libs/SidebarUtils.ts | 12 +- src/libs/TagsOptionsListUtils.ts | 6 +- src/libs/TaxOptionsListUtils.ts | 6 +- src/libs/Timers.ts | 4 +- src/libs/TripReservationUtils.ts | 154 +++++++++--------- src/libs/ValidationUtils.ts | 18 +- src/libs/Violations/ViolationsUtils.ts | 24 +-- src/libs/WorkflowUtils.ts | 54 +++--- src/libs/actions/App.ts | 44 ++--- src/libs/actions/BankAccounts.ts | 6 +- src/libs/actions/IOU.ts | 138 ++++++++-------- .../utils/DeferredOnyxUpdates.ts | 6 +- .../utils/__mocks__/applyUpdates.ts | 4 +- src/libs/actions/Policy/Category.ts | 8 +- src/libs/actions/Policy/DistanceRate.ts | 4 +- src/libs/actions/Policy/Member.ts | 56 ++++--- src/libs/actions/Policy/PerDiem.ts | 4 +- src/libs/actions/Policy/ReportField.ts | 36 ++-- src/libs/actions/Policy/Tag.ts | 14 +- src/libs/actions/Report.ts | 78 ++++----- src/libs/actions/ReportActions.ts | 8 +- src/libs/actions/RequestConflictUtils.ts | 14 +- src/libs/actions/Task.ts | 6 +- src/libs/actions/TaxRate.ts | 4 +- src/libs/actions/Transaction.ts | 36 ++-- src/libs/actions/Workflow.ts | 4 +- src/libs/actions/__mocks__/App.ts | 4 +- src/libs/deepReplaceKeysAndValues.ts | 12 +- src/libs/memoize/index.ts | 4 +- src/libs/mergeRefs.ts | 4 +- .../prepareRequestPayload/index.native.ts | 4 +- src/libs/prepareRequestPayload/index.ts | 6 +- src/libs/requireParameters.ts | 12 +- src/pages/Debug/DebugDetails.tsx | 4 +- src/pages/InviteReportParticipantsPage.tsx | 6 +- .../substeps/Address.tsx | 6 +- src/pages/NewChatPage.tsx | 8 +- .../BaseOnboardingWorkspaceInvite.tsx | 6 +- .../utils/getSignerDetailsAndSignerFiles.ts | 6 +- .../subSteps/AccountHolderDetails.tsx | 32 ++-- ...DetailsAndOwnerFilesForBeneficialOwners.ts | 24 +-- ...ignerDetailsAndSignerFilesForSignerInfo.ts | 14 +- .../components/BankAccountValidationForm.tsx | 6 +- src/pages/ReportParticipantsPage.tsx | 6 +- src/pages/RoomInvitePage.tsx | 20 +-- src/pages/RoomMembersPage.tsx | 6 +- src/pages/Search/AdvancedSearchFilters.tsx | 16 +- .../SearchFiltersTagPage.tsx | 11 +- src/pages/Search/SearchPage.tsx | 12 +- .../TransactionMerge/DetailsReviewPage.tsx | 6 +- src/pages/home/report/LinkPreviewer.tsx | 6 +- .../useAttachmentUploadValidation.ts | 4 +- .../report/ReportActionItemParentAction.tsx | 4 +- .../MoneyRequestParticipantsSelector.tsx | 4 +- .../step/IOURequestStepConfirmation.tsx | 34 ++-- .../request/step/IOURequestStepDistance.tsx | 4 +- .../step/IOURequestStepDistanceMap.tsx | 4 +- .../step/IOURequestStepParticipants.tsx | 28 ++-- .../step/IOURequestStepScan/index.native.tsx | 4 +- .../request/step/IOURequestStepScan/index.tsx | 12 +- src/pages/settings/AboutPage/ConsolePage.tsx | 4 +- .../ExpensifyCardContextProvider.tsx | 10 +- .../substeps/Confirmation.tsx | 56 +++---- .../InternationalDepositAccount/utils.ts | 10 +- .../settings/Wallet/PaymentMethodList.tsx | 8 +- src/pages/workspace/WorkspaceInitialPage.tsx | 4 +- src/pages/workspace/WorkspaceInvitePage.tsx | 6 +- src/pages/workspace/WorkspaceMembersPage.tsx | 20 +-- .../EnterSageIntacctCredentialsPage.tsx | 6 +- .../SageIntacctImportTaxMappingPage.tsx | 4 +- .../substeps/NetSuiteTokenInputForm.tsx | 6 +- .../addNew/PlaidConnectionStep.tsx | 4 +- .../companyCards/assignCard/AssigneeStep.tsx | 6 +- .../expensifyCard/issueNew/AssigneeStep.tsx | 6 +- .../workspace/members/ImportedMembersPage.tsx | 42 ++--- .../members/WorkspaceMemberDetailsPage.tsx | 4 +- .../ChangeReceiptBillingAccountPage.tsx | 6 +- .../EditInviteReceiptPartnerPolicyPage.tsx | 6 +- .../InviteReceiptPartnerPolicyPage.tsx | 16 +- .../workflows/WorkspaceWorkflowsPayerPage.tsx | 8 +- src/stories/SelectionList.stories.tsx | 12 +- .../fontFamily/multiFontFamily/index.ts | 4 +- src/styles/utils/index.ts | 8 +- src/utils/keyboard/index.website.ts | 4 +- tests/actions/IOUTest.ts | 86 ++++++---- tests/actions/PolicyTagTest.ts | 32 ++-- tests/actions/PolicyTest.ts | 46 +++--- tests/actions/ReportTest.ts | 4 +- tests/e2e/compare/output/markdown.ts | 8 +- tests/e2e/server/index.ts | 12 +- tests/ui/AvatarSelector.test.tsx | 4 +- tests/ui/GroupChatNameTests.tsx | 16 +- tests/unit/CloseAccountPageTest.ts | 24 +-- tests/unit/ConvertToLTRForComposerTest.ts | 4 +- tests/unit/CountryUtils.test.ts | 8 +- tests/unit/ErrorUtilsTest.ts | 4 +- tests/unit/FirebaseUtilsTest.ts | 4 +- tests/unit/FormulaTest.ts | 4 +- tests/unit/IOUUtilsTest.ts | 4 +- tests/unit/PhoneNumberTest.ts | 12 +- tests/unit/Search/SearchQueryUtilsTest.ts | 4 +- tests/unit/Search/SearchUIUtilsTest.ts | 4 +- tests/unit/SearchAutocompleteUtilsTest.ts | 8 +- tests/unit/SettlementButtonUtilsTest.ts | 4 +- tests/unit/TranslateTest.ts | 4 +- tests/unit/WorkspaceReportFieldUtilsTest.ts | 8 +- tests/unit/hooks/useLetterAvatars.test.tsx | 4 +- tests/unit/isEmptyString.ts | 4 +- .../unit/keyboard/AndroidKeyboardUtilsTest.ts | 16 +- tests/unit/keyboard/KeyboardUtilsTest.ts | 12 +- tests/unit/removeInvisibleCharacters.ts | 4 +- tests/unit/useSidebarOrderedReportsTest.tsx | 4 +- tests/utils/LHNTestUtils.tsx | 4 +- tests/utils/TestHelper.ts | 4 +- tests/utils/collections/reportActions.ts | 4 +- tests/utils/createAddListenerMock.ts | 4 +- 201 files changed, 1463 insertions(+), 1373 deletions(-) diff --git a/.github/actions/javascript/generateHelpPreviewComment/generateHelpPreviewComment.ts b/.github/actions/javascript/generateHelpPreviewComment/generateHelpPreviewComment.ts index cbb119fa19a4..4b1575384e1b 100644 --- a/.github/actions/javascript/generateHelpPreviewComment/generateHelpPreviewComment.ts +++ b/.github/actions/javascript/generateHelpPreviewComment/generateHelpPreviewComment.ts @@ -27,20 +27,20 @@ async function getUpdatedDocRoutes(octokit: OctokitClient, owner: string, repo: const routes = new Set(); - files.forEach((file) => { + for (const file of files) { const filename = file.filename ?? ''; const status = file.status ?? ''; if (!INCLUDED_STATUSES.has(status)) { - return; + continue; } if (!filename.startsWith(DOCS_DIRECTORY_PREFIX) || !filename.endsWith(MARKDOWN_EXTENSION)) { - return; + continue; } routes.add(toRoutePath(filename)); - }); + } return [...routes].sort((a, b) => a.localeCompare(b)); } @@ -72,7 +72,9 @@ async function run(): Promise { core.setOutput('BODY', body); core.startGroup('Updated ExpensifyHelp routes'); - routes.forEach((route) => console.log(route)); + for (const route of routes) { + console.log(route); + } core.endGroup(); console.log(`Generated preview comment with ${routes.length} updated article(s)`); diff --git a/.github/libs/GitUtils.ts b/.github/libs/GitUtils.ts index d48f423762dd..441e97a17abe 100644 --- a/.github/libs/GitUtils.ts +++ b/.github/libs/GitUtils.ts @@ -79,16 +79,16 @@ function getPreviousExistingTag(tag: string, level: SemverLevel) { */ function getValidMergedPRs(commits: CommitType[]): number[] { const mergedPRs = new Set(); - commits.forEach((commit) => { + for (const commit of commits) { const author = commit.authorName; if (author === CONST.OS_BOTIFY) { - return; + continue; } // Retrieve the PR number from the commit subject, const match = commit.subject.match(/Merge pull request #(\d+) from (?!Expensify\/.*-cherry-pick-(staging|production))/); if (!Array.isArray(match) || match.length < 2) { - return; + continue; } const pr = Number.parseInt(match[1], 10); @@ -96,11 +96,11 @@ function getValidMergedPRs(commits: CommitType[]): number[] { // If a PR shows up in the log twice, that means that the PR was deployed in the previous checklist. // That also means that we don't want to include it in the current checklist, so we remove it now. mergedPRs.delete(pr); - return; + continue; } mergedPRs.add(pr); - }); + } return Array.from(mergedPRs); } diff --git a/.github/libs/GithubUtils.ts b/.github/libs/GithubUtils.ts index 8acedc4229a0..5a47cbf6aa0c 100644 --- a/.github/libs/GithubUtils.ts +++ b/.github/libs/GithubUtils.ts @@ -360,20 +360,20 @@ class GithubUtils { // PR list if (sortedPRList.length > 0) { issueBody += '**This release contains changes from the following pull requests:**\r\n'; - sortedPRList.forEach((URL) => { + for (const URL of sortedPRList) { issueBody += verifiedOrNoQAPRs.has(URL) ? '- [x]' : '- [ ]'; issueBody += ` ${URL}\r\n`; - }); + } issueBody += '\r\n\r\n'; } // Mobile-Expensify PR list if (sortedPRListMobileExpensify.length > 0) { issueBody += '**Mobile-Expensify PRs:**\r\n'; - sortedPRListMobileExpensify.forEach((URL) => { + for (const URL of sortedPRListMobileExpensify) { issueBody += verifiedOrNoQAPRs.has(URL) ? '- [x]' : '- [ ]'; issueBody += ` ${URL}\r\n`; - }); + } issueBody += '\r\n\r\n'; } @@ -381,25 +381,25 @@ class GithubUtils { if (!isEmptyObject(internalQAPRMap)) { console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs); issueBody += '**Internal QA:**\r\n'; - Object.keys(internalQAPRMap).forEach((URL) => { + for (const URL of Object.keys(internalQAPRMap)) { const merger = internalQAPRMap[URL]; const mergerMention = `@${merger}`; issueBody += `${resolvedInternalQAPRs.includes(URL) ? '- [x]' : '- [ ]'} `; issueBody += `${URL}`; issueBody += ` - ${mergerMention}`; issueBody += '\r\n'; - }); + } issueBody += '\r\n\r\n'; } // Deploy blockers if (deployBlockers.length > 0) { issueBody += '**Deploy Blockers:**\r\n'; - sortedDeployBlockers.forEach((URL) => { + for (const URL of sortedDeployBlockers) { issueBody += resolvedDeployBlockers.includes(URL) ? '- [x] ' : '- [ ] '; issueBody += URL; issueBody += '\r\n'; - }); + } issueBody += '\r\n\r\n'; } diff --git a/.github/scripts/createDocsRoutes.ts b/.github/scripts/createDocsRoutes.ts index dbdb203c1b95..cd118b974eec 100644 --- a/.github/scripts/createDocsRoutes.ts +++ b/.github/scripts/createDocsRoutes.ts @@ -109,14 +109,14 @@ function getOrderFromArticleFrontMatter(path: string): number | undefined { * @param routeHubs - The hubs insude docs/data/_routes.yml for a platform */ function createHubsWithArticles(hubs: string[], platformName: ValueOf, routeHubs: Hub[]) { - hubs.forEach((hub) => { + for (const hub of hubs) { // Iterate through each directory in articles - fs.readdirSync(`${docsDir}/articles/${platformName}/${hub}`).forEach((fileOrFolder) => { + for (const fileOrFolder of fs.readdirSync(`${docsDir}/articles/${platformName}/${hub}`)) { // If the directory content is a markdown file, then it is an article if (fileOrFolder.endsWith('.md')) { const articleObj = getArticleObj(fileOrFolder); pushOrCreateEntry(routeHubs, hub, 'articles', articleObj); - return; + continue; } // For readability, we will use the term section to refer to subfolders @@ -124,18 +124,18 @@ function createHubsWithArticles(hubs: string[], platformName: ValueOf { + for (const subArticle of fs.readdirSync(`${docsDir}/articles/${platformName}/${hub}/${section}`)) { const order = getOrderFromArticleFrontMatter(`${docsDir}/articles/${platformName}/${hub}/${section}/${subArticle}`); articles.push(getArticleObj(subArticle, order)); - }); + } pushOrCreateEntry(routeHubs, hub, 'sections', { href: section, title: toTitleCase(section.replaceAll('-', ' ')), articles, }); - }); - }); + } + } } function run() { diff --git a/__mocks__/react-native.ts b/__mocks__/react-native.ts index 292d4e9f1901..c3ac98fad922 100644 --- a/__mocks__/react-native.ts +++ b/__mocks__/react-native.ts @@ -63,7 +63,9 @@ jest.doMock('react-native', () => { }, emitCurrentTestState(state: ReactNative.AppStateStatus) { appState = state; - Object.entries(changeListeners).forEach(([, listener]) => listener(appState)); + for (const [, listener] of Object.entries(changeListeners)) { + listener(appState); + } }, addEventListener(type: ReactNative.AppStateEvent, listener: (state: ReactNative.AppStateStatus) => void) { if (type === 'change') { diff --git a/assets/emojis/index.ts b/assets/emojis/index.ts index a5d64aba2bb7..09fd839a7dcb 100644 --- a/assets/emojis/index.ts +++ b/assets/emojis/index.ts @@ -20,9 +20,9 @@ const emojiCodeTableWithSkinTones = emojis.reduce((prev, cur) => { newValue[cur.code] = cur; } if ('types' in cur && cur.types) { - cur.types.forEach((type) => { + for (const type of cur.types) { newValue[type] = cur; - }); + } } return newValue; }, {}); diff --git a/desktop/main.ts b/desktop/main.ts index 6c45cf208ef3..4fb3bfa24c0b 100644 --- a/desktop/main.ts +++ b/desktop/main.ts @@ -173,13 +173,13 @@ const EXPECTED_UPDATE_VERSION_FLAG = '--expected-update-version'; const APP_DOMAIN = __DEV__ ? `https://dev.new.expensify.com:${port}` : 'app://-'; let expectedUpdateVersion: string; -process.argv.forEach((arg) => { +for (const arg of process.argv) { if (!arg.startsWith(`${EXPECTED_UPDATE_VERSION_FLAG}=`)) { - return; + continue; } expectedUpdateVersion = arg.slice(`${EXPECTED_UPDATE_VERSION_FLAG}=`.length); -}); +} // Add the listeners and variables required to ensure that auto-updating // happens correctly. diff --git a/help/default.js b/help/default.js index 1c27ade6c9e1..744678cc0b8b 100644 --- a/help/default.js +++ b/help/default.js @@ -163,14 +163,14 @@ function selectPreviousResult() { } function updateSelectedResult() { - g_searchResultsArray.forEach((result, index) => { + for (const [index, result] of g_searchResultsArray.entries()) { if (index === g_currentSelectionIndex) { result.classList.add('highlight'); result.scrollIntoView({behavior: 'smooth', block: 'nearest'}); } else { result.classList.remove('highlight'); } - }); + } } function navigateToSelectedResult() { @@ -234,8 +234,8 @@ function performSearch(query) { if (results && results.length > 0) { g_searchResultsArray = []; - results.forEach((result) => { - result.result.forEach((docId) => { + for (const result of results) { + for (const docId of result.result) { const doc = g_index.store[docId]; if (doc && doc.content) { const searchTermIndex = doc.content.toLowerCase().indexOf(query); @@ -257,8 +257,8 @@ function performSearch(query) { updateSelectedResult(); } } - }); - }); + } + } g_searchResults.style.display = 'block'; g_searchResults.focus(); } else { diff --git a/jest/setup.ts b/jest/setup.ts index 696c018fcf6c..7240770ca366 100644 --- a/jest/setup.ts +++ b/jest/setup.ts @@ -157,27 +157,27 @@ jest.mock('../src/hooks/useLazyAsset.ts', () => ({ useMemoizedLazyIllustrations: jest.fn((names: readonly string[]) => { // Return a Record with all requested illustration names const mockIllustrations: Record = {}; - names.forEach((name) => { + for (const name of names) { mockIllustrations[name] = { src: `mock-${name}`, testID: `mock-illustration-${name}`, height: 20, width: 20, }; - }); + } return mockIllustrations; }), useMemoizedLazyExpensifyIcons: jest.fn((names: readonly string[]) => { // Return a Record with all requested icon names const mockIcons: Record = {}; - names.forEach((name) => { + for (const name of names) { mockIcons[name] = { src: `mock-${name}`, testID: `mock-expensify-icon-${name}`, height: 20, width: 20, }; - }); + } return mockIcons; }), default: jest.fn(() => { @@ -228,15 +228,15 @@ jest.mock('@libs/prepareRequestPayload/index.native.ts', () => ({ default: jest.fn((command: string, data: Record) => { const formData = new FormData(); - Object.keys(data).forEach((key) => { + for (const key of Object.keys(data)) { const value = data[key]; if (value === undefined) { - return; + continue; } formData.append(key, value as string | Blob); - }); + } return Promise.resolve(formData); }), diff --git a/jest/setupMockImages.ts b/jest/setupMockImages.ts index 7f9d50dab797..a02ef68088f3 100644 --- a/jest/setupMockImages.ts +++ b/jest/setupMockImages.ts @@ -4,11 +4,11 @@ import path from 'path'; function mockImages(imagePath: string) { const imageFilenames = fs.readdirSync(path.resolve(__dirname, `../assets/${imagePath}/`)); // eslint-disable-next-line rulesdir/prefer-early-return - imageFilenames.forEach((fileName) => { + for (const fileName of imageFilenames) { if (/\.svg/.test(fileName)) { jest.mock(`../assets/${imagePath}/${fileName}`, () => () => ''); } - }); + } } // We are mocking all images so that Icons and other assets cannot break tests. In the testing environment, importing things like .svg diff --git a/scripts/checkLazyLoading.ts b/scripts/checkLazyLoading.ts index 42f8f5c42113..7c8427e6dcd4 100644 --- a/scripts/checkLazyLoading.ts +++ b/scripts/checkLazyLoading.ts @@ -58,7 +58,7 @@ function checkFile(filePath: string): Violation[] { const content = fs.readFileSync(filePath, 'utf-8'); const lines = content.split('\n'); - lines.forEach((line, index) => { + for (const [index, line] of lines.entries()) { const lineNumber = index + 1; for (const check of IMPORT_CHECKS) { @@ -72,7 +72,7 @@ function checkFile(filePath: string): Violation[] { }); } } - }); + } } catch (error) { console.warn(`āš ļø Warning: Could not read file ${filePath}: ${error instanceof Error ? error.message : String(error)}`); } @@ -103,10 +103,10 @@ async function main() { console.log(`Checking ${files.length} files for lazy loading violations...\n`); - files.forEach((file) => { + for (const file of files) { const violations = checkFile(file); allViolations.push(...violations); - }); + } if (allViolations.length === 0) { console.log('āœ… No lazy loading violations found! All icons and illustrations are using lazy loading.'); @@ -115,21 +115,21 @@ async function main() { // Group violations by file const violationsByFile = new Map(); - allViolations.forEach((violation) => { + for (const violation of allViolations) { const existing = violationsByFile.get(violation.file) ?? []; existing.push(violation); violationsByFile.set(violation.file, existing); - }); + } - violationsByFile.forEach((violations, file) => { + for (const [file, violations] of violationsByFile.entries()) { console.error(`\nšŸ“„ ${file}`); - violations.forEach((violation) => { + for (const violation of violations) { const iconType = violation.type === 'illustration' ? 'Illustration' : 'Expensify Icon'; console.error(` Line ${violation.line}: ${iconType} import detected`); console.error(` āŒ ${violation.content}`); console.error(` āœ… ${violation.suggestedFix}`); - }); - }); + } + } console.error(`\nāŒ Found ${allViolations.length} lazy loading violation(s) in ${violationsByFile.size} file(s):\n`); console.error(`\n\nšŸ’” For migration help, see: docs/LAZY_ICONS_AND_ILLUSTRATIONS.md`); diff --git a/scripts/compressSvg.ts b/scripts/compressSvg.ts index 0ff2d80dd3c5..a74f69fbda10 100644 --- a/scripts/compressSvg.ts +++ b/scripts/compressSvg.ts @@ -180,7 +180,9 @@ function validateSvgFiles(filePaths: string[]): string[] { if (errors.length) { console.error('Validation errors:'); - errors.forEach((error) => console.error(` ${error}`)); + for (const error of errors) { + console.error(` ${error}`); + } throw new Error('SVG file validation failed'); } @@ -230,9 +232,9 @@ function logIgnoredFiles(ignoredFiles: string[]) { } console.log('\nFiles skipped (ignore-compression):'); - ignoredFiles.forEach((filePath) => { + for (const filePath of ignoredFiles) { console.log(`${filePath}: ā­ļø Skipped`); - }); + } } function logSummary(summary: CompressionSummary) { @@ -242,10 +244,10 @@ function logSummary(summary: CompressionSummary) { if (totalCompressedFilesLength) { console.log('\nFiles compressed:'); - results.forEach((result) => { + for (const result of results) { const {compressedSize, originalSize, savings, savingsPercent, filePath} = result; if (!result.savings) { - return; + continue; } const prefix = `${filePath}: āœ…`; console.log( @@ -257,7 +259,7 @@ function logSummary(summary: CompressionSummary) { savingsPercent, }), ); - }); + } const ignoreFilesLength = ignoredFiles.length; @@ -283,10 +285,10 @@ function logSummaryCheck(summary: CompressionSummary) { const {totalFiles, totalCompressedFilesLength, results, ignoredFiles} = summary; console.log(''); - results.forEach((result) => { + for (const result of results) { const {filePath, savings} = result; console.log(`${filePath}: ${savings > 0 ? 'Not properly compressed āŒ' : 'Compressed āœ…'}`); - }); + } logIgnoredFiles(ignoredFiles); console.log(`\nFiles processed: ${totalFiles}`); diff --git a/scripts/generateTranslations.ts b/scripts/generateTranslations.ts index 9a2937cb874b..411a1db7db60 100755 --- a/scripts/generateTranslations.ts +++ b/scripts/generateTranslations.ts @@ -551,7 +551,9 @@ class TranslationGenerator { if (this.verbose) { console.debug('šŸ˜µā€šŸ’« Encountered complex template, recursively translating its spans first:', node.getText()); } - node.templateSpans.forEach((span) => this.extractStringsToTranslate(span, stringsToTranslate, currentPath)); + for (const span of node.templateSpans) { + this.extractStringsToTranslate(span, stringsToTranslate, currentPath); + } stringsToTranslate.set(translationKey, {text: this.templateExpressionToString(node), context}); } } diff --git a/scripts/utils/parseCommandLineArguments.ts b/scripts/utils/parseCommandLineArguments.ts index 9bb1d340335e..e6ac8b15ab8f 100644 --- a/scripts/utils/parseCommandLineArguments.ts +++ b/scripts/utils/parseCommandLineArguments.ts @@ -4,7 +4,7 @@ type ArgsMap = Record; export default function parseCommandLineArguments(): ArgsMap { const args = process.argv.slice(2); // Skip node and script paths const argsMap: ArgsMap = {}; - args.forEach((arg) => { + for (const arg of args) { const [key, value] = arg.split('='); if (key.startsWith('--')) { const name = key.substring(2); @@ -14,6 +14,6 @@ export default function parseCommandLineArguments(): ArgsMap { argsMap[name] = 'true'; } } - }); + } return argsMap; } diff --git a/src/NAICS.ts b/src/NAICS.ts index 869ea9499dd1..b8bcc9687d38 100755 --- a/src/NAICS.ts +++ b/src/NAICS.ts @@ -12144,18 +12144,18 @@ function getNAICSMappingWithId(item: NAICSItem) { }; }); - item.options.forEach((option) => { + for (const option of item.options) { if (option.options.length === 0) { - return; + continue; } getNAICSMappingWithId(option); - }); + } } function buildNAICS() { - NAICS.forEach((item) => { + for (const item of NAICS) { getNAICSMappingWithId(item); - }); + } } buildNAICS(); diff --git a/src/components/AddPlaidBankAccount.tsx b/src/components/AddPlaidBankAccount.tsx index 4c50576b5417..1394a7138a0a 100644 --- a/src/components/AddPlaidBankAccount.tsx +++ b/src/components/AddPlaidBankAccount.tsx @@ -128,7 +128,9 @@ function AddPlaidBankAccount({ * Unblocks the keyboard shortcuts that can navigate */ const unsubscribeToNavigationShortcuts = () => { - subscribedKeyboardShortcuts.current.forEach((unsubscribe) => unsubscribe()); + for (const unsubscribe of subscribedKeyboardShortcuts.current) { + unsubscribe(); + } subscribedKeyboardShortcuts.current = []; }; diff --git a/src/components/AddressForm.tsx b/src/components/AddressForm.tsx index eec78316534c..a9be595ad7f6 100644 --- a/src/components/AddressForm.tsx +++ b/src/components/AddressForm.tsx @@ -99,14 +99,14 @@ function AddressForm({ } // Add "Field required" errors if any required field is empty - requiredFields.forEach((fieldKey) => { + for (const fieldKey of requiredFields) { const fieldValue = values[fieldKey] ?? ''; if (isRequiredFulfilled(fieldValue)) { - return; + continue; } errors[fieldKey] = translate('common.error.fieldRequired'); - }); + } if (values.addressLine1.length > CONST.FORM_CHARACTER_LIMIT) { errors.addressLine1 = translate('common.error.characterLimitExceedCounter', { diff --git a/src/components/AddressSearch/index.tsx b/src/components/AddressSearch/index.tsx index ac27c32700b3..259bdc5afd20 100644 --- a/src/components/AddressSearch/index.tsx +++ b/src/components/AddressSearch/index.tsx @@ -228,13 +228,13 @@ function AddressSearch({ } if (inputID) { - Object.entries(values).forEach(([key, inputValue]) => { + for (const [key, inputValue] of Object.entries(values)) { const inputKey = renamedInputKeys?.[key as keyof Omit] ?? key; if (!inputKey) { - return; + continue; } onInputChange?.(inputValue, inputKey); - }); + } } else { onInputChange?.(values); } diff --git a/src/components/AttachmentPicker/index.native.tsx b/src/components/AttachmentPicker/index.native.tsx index 063dece52985..d4cedd8f31ad 100644 --- a/src/components/AttachmentPicker/index.native.tsx +++ b/src/components/AttachmentPicker/index.native.tsx @@ -188,10 +188,10 @@ function AttachmentPicker({ } }; - assets.forEach((asset) => { + for (const asset of assets) { if (!asset.uri) { checkAllProcessed(); - return; + continue; } if (asset.type?.startsWith('image')) { @@ -238,7 +238,7 @@ function AttachmentPicker({ processedAssets.push(processedAsset); checkAllProcessed(); } - }); + } }); }), [fileLimit, showGeneralAlert, type], diff --git a/src/components/Attachments/AttachmentCarousel/extractAttachments.ts b/src/components/Attachments/AttachmentCarousel/extractAttachments.ts index 2c265030b61f..6dffd994d6a7 100644 --- a/src/components/Attachments/AttachmentCarousel/extractAttachments.ts +++ b/src/components/Attachments/AttachmentCarousel/extractAttachments.ts @@ -116,9 +116,9 @@ function extractAttachments( } const actions = [...(parentReportAction ? [parentReportAction] : []), ...getSortedReportActions(Object.values(reportActions ?? {}))]; - actions.forEach((action, key) => { + for (const [key, action] of actions.entries()) { if (!shouldReportActionBeVisible(action, key, canUserPerformAction) || isMoneyRequestAction(action)) { - return; + continue; } const decision = getReportActionMessage(action)?.moderationDecision?.decision; @@ -127,7 +127,7 @@ function extractAttachments( .replaceAll('/>', `data-flagged="${hasBeenFlagged}" data-id="${action.reportActionID}"/>`) .replaceAll('