-
+
order executes at
diff --git a/apps/cowswap-frontend/src/modules/limitOrders/pure/OrderType/index.tsx b/apps/cowswap-frontend/src/modules/limitOrders/pure/OrderType/index.tsx
index 0c05ee0838..d106263eaa 100644
--- a/apps/cowswap-frontend/src/modules/limitOrders/pure/OrderType/index.tsx
+++ b/apps/cowswap-frontend/src/modules/limitOrders/pure/OrderType/index.tsx
@@ -1,6 +1,6 @@
import { ReactNode } from 'react'
-import IMAGE_CARET_DOWN from '@cowprotocol/assets/cow-swap/carret-down.svg'
+import svgCarretDownSrc from '@cowprotocol/assets/cow-swap/carret-down.svg'
import { InfoTooltip, RowFixed } from '@cowprotocol/ui'
import { Trans, useLingui } from '@lingui/react/macro'
@@ -60,7 +60,7 @@ function OrderTypePicker({ isPartiallyFillable, partiallyFillableOverride }: Ord
{labelText}
diff --git a/apps/cowswap-frontend/src/modules/notifications/containers/NotificationBell.tsx b/apps/cowswap-frontend/src/modules/notifications/containers/NotificationBell.tsx
index af659e31d5..c4322c6e93 100644
--- a/apps/cowswap-frontend/src/modules/notifications/containers/NotificationBell.tsx
+++ b/apps/cowswap-frontend/src/modules/notifications/containers/NotificationBell.tsx
@@ -1,6 +1,6 @@
import React from 'react'
-import ICON_NOTIFICATION from '@cowprotocol/assets/images/notification.svg'
+import svgNotificationSrc from '@cowprotocol/assets/images/notification.svg'
import { Command } from '@cowprotocol/types'
import { UI } from '@cowprotocol/ui'
@@ -75,7 +75,7 @@ export function NotificationBell({ onClick, unreadCount }: NotificationBellProps
label: `Unread count: ${unreadCount}`,
})}
>
-
+
)
}
diff --git a/apps/cowswap-frontend/src/modules/notifications/containers/NotificationSettings.tsx b/apps/cowswap-frontend/src/modules/notifications/containers/NotificationSettings.tsx
index 1aef8cdce8..de3429fb62 100644
--- a/apps/cowswap-frontend/src/modules/notifications/containers/NotificationSettings.tsx
+++ b/apps/cowswap-frontend/src/modules/notifications/containers/NotificationSettings.tsx
@@ -1,6 +1,6 @@
import { ReactNode } from 'react'
-import TELEGRAM_ICON from '@cowprotocol/assets/images/icon-telegram.svg'
+import iconTelegramSrc from '@cowprotocol/assets/images/icon-telegram.svg'
import { RowBetween, RowFixed, HoverTooltip, UI, Toggle } from '@cowprotocol/ui'
import SVG from 'react-inlinesvg'
@@ -130,7 +130,7 @@ export function NotificationSettings({ children }: NotificationSettingsProps): R
-
+
Telegram
{username &&
@{username}}
diff --git a/apps/cowswap-frontend/src/modules/notifications/containers/NotificationSidebar/index.tsx b/apps/cowswap-frontend/src/modules/notifications/containers/NotificationSidebar/index.tsx
index 5c4cef9e17..ce0f157ef1 100644
--- a/apps/cowswap-frontend/src/modules/notifications/containers/NotificationSidebar/index.tsx
+++ b/apps/cowswap-frontend/src/modules/notifications/containers/NotificationSidebar/index.tsx
@@ -1,6 +1,6 @@
import { ReactNode, useCallback, useEffect, useRef, useState } from 'react'
-import ICON_NOTIFICATION_SETTINGS from '@cowprotocol/assets/images/icon-notification-settings.svg'
+import iconNotificationSettingsSrc from '@cowprotocol/assets/images/icon-notification-settings.svg'
import { useMediaQuery, useOnClickOutside, useFeatureFlags } from '@cowprotocol/common-hooks'
import { Media } from '@cowprotocol/ui'
@@ -95,7 +95,7 @@ function NotificationsHeader({
label: 'notification sidebar',
})}
>
-
+
) : (
diff --git a/apps/cowswap-frontend/src/modules/notifications/containers/NotificationSidebar/styled.tsx b/apps/cowswap-frontend/src/modules/notifications/containers/NotificationSidebar/styled.tsx
index d57f3ef3ef..fa19b5b1e2 100644
--- a/apps/cowswap-frontend/src/modules/notifications/containers/NotificationSidebar/styled.tsx
+++ b/apps/cowswap-frontend/src/modules/notifications/containers/NotificationSidebar/styled.tsx
@@ -1,7 +1,7 @@
import { ReactNode } from 'react'
-import ICON_ARROW from '@cowprotocol/assets/images/arrow-left.svg'
-import ICON_BELL_ALERT from '@cowprotocol/assets/images/icon-bell-alert.svg'
+import svgArrowLeftSrc from '@cowprotocol/assets/images/arrow-left.svg'
+import iconBellAlertSrc from '@cowprotocol/assets/images/icon-bell-alert.svg'
import { Media, UI } from '@cowprotocol/ui'
import SVG from 'react-inlinesvg'
@@ -51,7 +51,7 @@ const IconBase = styled(SVG)<{ size?: string; opacity?: string }>`
export const ArrowLeft = ({ onClick }: IconProps): ReactNode => (
-
+
)
@@ -172,7 +172,7 @@ export const EnableAlertsButtonWithIcon = ({
...props
}: IconProps & React.ButtonHTMLAttributes
): ReactNode => (
-
+
Enable trade alerts
)
diff --git a/apps/cowswap-frontend/src/modules/notifications/containers/NotificationsList/index.tsx b/apps/cowswap-frontend/src/modules/notifications/containers/NotificationsList/index.tsx
index de3a4de778..cf882bc358 100644
--- a/apps/cowswap-frontend/src/modules/notifications/containers/NotificationsList/index.tsx
+++ b/apps/cowswap-frontend/src/modules/notifications/containers/NotificationsList/index.tsx
@@ -1,7 +1,7 @@
import { useSetAtom } from 'jotai'
import React, { ReactNode, useEffect, useMemo } from 'react'
-import ICON_MESSAGE_READ from '@cowprotocol/assets/images/icon-message-read.svg'
+import iconMessageReadSrc from '@cowprotocol/assets/images/icon-message-read.svg'
import { i18n } from '@lingui/core'
import { Trans } from '@lingui/react/macro'
@@ -33,7 +33,7 @@ interface EmptyNotificationsProps {
function EmptyNotifications({ hasSubscription, onToggleSettings }: EmptyNotificationsProps): ReactNode {
return (
-
+
You're all caught up
diff --git a/apps/cowswap-frontend/src/modules/orderProgressBar/constants.ts b/apps/cowswap-frontend/src/modules/orderProgressBar/constants.ts
index 9128c2cb62..6f04d96af8 100644
--- a/apps/cowswap-frontend/src/modules/orderProgressBar/constants.ts
+++ b/apps/cowswap-frontend/src/modules/orderProgressBar/constants.ts
@@ -1,7 +1,7 @@
-import PROGRESSBAR_COW_SURPLUS_1 from '@cowprotocol/assets/cow-swap/progressbar-finished-image-1.svg'
-import PROGRESSBAR_COW_SURPLUS_2 from '@cowprotocol/assets/cow-swap/progressbar-finished-image-2.svg'
-import PROGRESSBAR_COW_SURPLUS_3 from '@cowprotocol/assets/cow-swap/progressbar-finished-image-3.svg'
-import PROGRESSBAR_COW_SURPLUS_4 from '@cowprotocol/assets/cow-swap/progressbar-finished-image-4.svg'
+import svgProgressbarFinished1Src from '@cowprotocol/assets/cow-swap/progressbar-finished-image-1.svg'
+import svgProgressbarFinished2Src from '@cowprotocol/assets/cow-swap/progressbar-finished-image-2.svg'
+import svgProgressbarFinished3Src from '@cowprotocol/assets/cow-swap/progressbar-finished-image-3.svg'
+import svgProgressbarFinished4Src from '@cowprotocol/assets/cow-swap/progressbar-finished-image-4.svg'
import { getAvailableChainsText } from '@cowprotocol/common-const'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
@@ -110,8 +110,8 @@ export const CHAIN_SPECIFIC_BENEFITS: Record
@@ -81,7 +81,7 @@ export function SolvingTopSection({ countdown }: SolvingTopSectionProps): ReactN
}}
>
@@ -186,7 +186,7 @@ export function ExpiredTopSection({ stepName }: BaseTopSectionProps): ReactNode
}}
>
diff --git a/apps/cowswap-frontend/src/modules/orderProgressBar/pure/TransactionSubmittedContent/SurplusModal.tsx b/apps/cowswap-frontend/src/modules/orderProgressBar/pure/TransactionSubmittedContent/SurplusModal.tsx
index ce0c3e9dcd..c7bf830a34 100644
--- a/apps/cowswap-frontend/src/modules/orderProgressBar/pure/TransactionSubmittedContent/SurplusModal.tsx
+++ b/apps/cowswap-frontend/src/modules/orderProgressBar/pure/TransactionSubmittedContent/SurplusModal.tsx
@@ -1,6 +1,6 @@
-import CheckSingular from '@cowprotocol/assets/cow-swap/check-singular.svg'
-import SurplusCow from '@cowprotocol/assets/cow-swap/surplus-cow.svg'
-import twitterImage from '@cowprotocol/assets/cow-swap/twitter.svg'
+import svgCheckSingularSrc from '@cowprotocol/assets/cow-swap/check-singular.svg'
+import svgSurplusCowSrc from '@cowprotocol/assets/cow-swap/surplus-cow.svg'
+import svgTwitterSrc from '@cowprotocol/assets/cow-swap/twitter.svg'
import { isSellOrder } from '@cowprotocol/common-utils'
import { OrderKind } from '@cowprotocol/cow-sdk'
import { ExternalLink, FiatAmount, SymbolElement, TokenAmount, UI } from '@cowprotocol/ui'
@@ -167,10 +167,10 @@ export function SurplusModal(props: SurplusModalProps) {
return (
- Swap completed
+ Swap completed
-
+
Great! {surplusMsg}
@@ -192,7 +192,7 @@ export function SurplusModal(props: SurplusModalProps) {
action: 'Share on Twitter',
})}
>
-
+
Share this win!
diff --git a/apps/cowswap-frontend/src/modules/orderProgressBar/pure/steps/ExpiredStep.tsx b/apps/cowswap-frontend/src/modules/orderProgressBar/pure/steps/ExpiredStep.tsx
index a1ab807823..34497b5523 100644
--- a/apps/cowswap-frontend/src/modules/orderProgressBar/pure/steps/ExpiredStep.tsx
+++ b/apps/cowswap-frontend/src/modules/orderProgressBar/pure/steps/ExpiredStep.tsx
@@ -1,5 +1,5 @@
-import PROGRESS_BAR_BAD_NEWS from '@cowprotocol/assets/cow-swap/progressbar-bad-news.svg'
-import PROGRESS_BAR_GOOD_NEWS from '@cowprotocol/assets/cow-swap/progressbar-good-news.svg'
+import svgProgressbarBadNewsSrc from '@cowprotocol/assets/cow-swap/progressbar-bad-news.svg'
+import svgProgressbarGoodNewsSrc from '@cowprotocol/assets/cow-swap/progressbar-good-news.svg'
import { Command } from '@cowprotocol/types'
import { Trans } from '@lingui/react/macro'
@@ -43,7 +43,7 @@ export function ExpiredStep({ children, navigateToNewOrder }: ExpiredStepProps)
-
+
The bad news
@@ -54,7 +54,7 @@ export function ExpiredStep({ children, navigateToNewOrder }: ExpiredStepProps)
-
+
The good news
diff --git a/apps/cowswap-frontend/src/modules/orderProgressBar/pure/steps/FinishedStep.tsx b/apps/cowswap-frontend/src/modules/orderProgressBar/pure/steps/FinishedStep.tsx
index 14ac1cebba..1d80cadd81 100644
--- a/apps/cowswap-frontend/src/modules/orderProgressBar/pure/steps/FinishedStep.tsx
+++ b/apps/cowswap-frontend/src/modules/orderProgressBar/pure/steps/FinishedStep.tsx
@@ -1,6 +1,6 @@
import React, { ReactNode, useMemo, useState, Suspense, lazy } from 'react'
-import ICON_SOCIAL_X from '@cowprotocol/assets/images/icon-social-x.svg'
+import iconSocialXSrc from '@cowprotocol/assets/images/icon-social-x.svg'
import LOTTIE_GREEN_CHECKMARK_DARK from '@cowprotocol/assets/lottie/green-checkmark-dark.json'
import LOTTIE_GREEN_CHECKMARK from '@cowprotocol/assets/lottie/green-checkmark.json'
import { RECEIVED_LABEL } from '@cowprotocol/common-const'
@@ -204,7 +204,7 @@ export function FinishedStep({
label: shouldShowSurplus ? 'Surplus' : 'Tip',
})}
>
-
+
Share this {shouldShowSurplus ? win : tip}!
diff --git a/apps/cowswap-frontend/src/modules/orderProgressBar/pure/steps/styled.ts b/apps/cowswap-frontend/src/modules/orderProgressBar/pure/steps/styled.ts
index 4d81a94f91..95dc69d4f0 100644
--- a/apps/cowswap-frontend/src/modules/orderProgressBar/pure/steps/styled.ts
+++ b/apps/cowswap-frontend/src/modules/orderProgressBar/pure/steps/styled.ts
@@ -1,4 +1,4 @@
-import IMAGE_STAR_SHINE from '@cowprotocol/assets/cow-swap/star-shine.svg'
+import svgStarShineSrc from '@cowprotocol/assets/cow-swap/star-shine.svg'
import { SingleLetterLogoWrapper } from '@cowprotocol/tokens'
import { ButtonPrimary, Font, LinkStyledButton, Media, UI } from '@cowprotocol/ui'
@@ -140,7 +140,7 @@ export const TokenWrapper = styled.div<{
top: 0;
width: var(--size);
height: var(--size);
- background: url(${IMAGE_STAR_SHINE}) no-repeat;
+ background: url(${svgStarShineSrc}) no-repeat;
background-size: 100% 100%;
animation: star-shine 1s infinite;
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrderEstimatedExecutionPrice/OrderEstimatedExecutionPrice.pure.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrderEstimatedExecutionPrice/OrderEstimatedExecutionPrice.pure.tsx
index f95c81ed96..b7a54e3bf5 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrderEstimatedExecutionPrice/OrderEstimatedExecutionPrice.pure.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrderEstimatedExecutionPrice/OrderEstimatedExecutionPrice.pure.tsx
@@ -1,7 +1,7 @@
import { useEffect, useState } from 'react'
-import iconFilledAlertTriangle from '@cowprotocol/assets/cow-swap/alert.svg'
-import iconAllowance from '@cowprotocol/assets/images/icon-allowance.svg'
+import svgAlertSrc from '@cowprotocol/assets/cow-swap/alert.svg'
+import iconAllowanceSrc from '@cowprotocol/assets/images/icon-allowance.svg'
import { ZERO_FRACTION } from '@cowprotocol/common-const'
import { Currency, CurrencyAmount, Fraction, Percent, Price } from '@cowprotocol/currency'
import { Command } from '@cowprotocol/types'
@@ -140,7 +140,7 @@ export function OrderEstimatedExecutionPrice({
color={`var(${UI.COLOR_DANGER_TEXT})`}
>
-
+
{internationalizedWarningText}
@@ -257,7 +257,7 @@ function UnlikelyToExecuteWarning(props: UnlikelyToExecuteWarningProps) {
}
>
-
+
)
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrderFillsAt/OrderFillsAt.pure.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrderFillsAt/OrderFillsAt.pure.tsx
index b88952d407..517eb7f0f2 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrderFillsAt/OrderFillsAt.pure.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrderFillsAt/OrderFillsAt.pure.tsx
@@ -1,6 +1,6 @@
import { ReactNode } from 'react'
-import orderPresignaturePendingIcon from '@cowprotocol/assets/cow-swap/order-presignature-pending.svg'
+import svgOrderPresignaturePendingSrc from '@cowprotocol/assets/cow-swap/order-presignature-pending.svg'
import { ZERO_FRACTION } from '@cowprotocol/common-const'
import { Currency, Price } from '@cowprotocol/currency'
import { Command, UiOrderType } from '@cowprotocol/types'
@@ -90,7 +90,7 @@ export function OrderFillsAt({
}
>
-
+
Please sign order
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrderStatusBox/OrderStatusBox.pure.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrderStatusBox/OrderStatusBox.pure.tsx
index ed7168c2cb..cc2095c61c 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrderStatusBox/OrderStatusBox.pure.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrderStatusBox/OrderStatusBox.pure.tsx
@@ -1,6 +1,6 @@
import { ReactNode } from 'react'
-import orderPresignaturePending from '@cowprotocol/assets/cow-swap/order-presignature-pending.svg'
+import svgOrderPresignaturePendingSrc from '@cowprotocol/assets/cow-swap/order-presignature-pending.svg'
import { Command } from '@cowprotocol/types'
import { t } from '@lingui/core/macro'
@@ -122,7 +122,7 @@ export function OrderStatusBox({ order, widthAuto, withWarning, onClick, Warning
{withWarning && WarningTooltip}
{order.status === OrderStatus.PRESIGNATURE_PENDING && (
-
+
)}
{title}
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTable/Content/NoWallet/OrdersTableNoWalletContent.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTable/Content/NoWallet/OrdersTableNoWalletContent.tsx
index d2f0c6a853..86882b0437 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTable/Content/NoWallet/OrdersTableNoWalletContent.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTable/Content/NoWallet/OrdersTableNoWalletContent.tsx
@@ -1,6 +1,6 @@
import { ReactNode } from 'react'
-import ICON_WALLET from '@cowprotocol/assets/cow-swap/wallet-plus.svg'
+import svgWalletPlusSrc from '@cowprotocol/assets/cow-swap/wallet-plus.svg'
import { isInjectedWidget } from '@cowprotocol/common-utils'
import { t } from '@lingui/core/macro'
@@ -19,7 +19,7 @@ export function OrdersTableNoWalletContent(): ReactNode {
return (
-
+
Connect a wallet
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTable/Row/WarningTooltip/WarningTooltip.pure.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTable/Row/WarningTooltip/WarningTooltip.pure.tsx
index a06d6967fa..2d78b8bd86 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTable/Row/WarningTooltip/WarningTooltip.pure.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTable/Row/WarningTooltip/WarningTooltip.pure.tsx
@@ -1,6 +1,6 @@
import { ReactNode } from 'react'
-import iconInformation from '@cowprotocol/assets/cow-swap/filled-info-circle.svg'
+import svgFilledInfoCircleSrc from '@cowprotocol/assets/cow-swap/filled-info-circle.svg'
import { Command } from '@cowprotocol/types'
import { ButtonSecondary, TokenSymbol, UI } from '@cowprotocol/ui'
@@ -139,7 +139,7 @@ export function WarningTooltip({
placement="bottom"
bgColor={`var(${UI.COLOR_DANGER_BG})`}
color={`var(${UI.COLOR_DANGER_TEXT})`}
- Icon={}
+ Icon={}
/>
{children}
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTabs/OrdersTabs.pure.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTabs/OrdersTabs.pure.tsx
index 919ff740a0..4bb5cf6273 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTabs/OrdersTabs.pure.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTabs/OrdersTabs.pure.tsx
@@ -1,7 +1,7 @@
import { ReactNode, ChangeEvent } from 'react'
-import iconInformation from '@cowprotocol/assets/cow-swap/filled-info-circle.svg'
-import iconOrderPresignaturePending from '@cowprotocol/assets/cow-swap/order-presignature-pending.svg'
+import svgFilledInfoCircleSrc from '@cowprotocol/assets/cow-swap/filled-info-circle.svg'
+import svgOrderPresignaturePendingSrc from '@cowprotocol/assets/cow-swap/order-presignature-pending.svg'
import { useWalletInfo } from '@cowprotocol/wallet'
import { t } from '@lingui/core/macro'
@@ -65,8 +65,8 @@ export function OrdersTabs({ tabs }: OrdersTabsProps): ReactNode {
$isDisabled={!account}
to={buildOrdersTableUrl({ tabId: tab.id, pageNumber: 1 })}
>
- {isUnfillable && }
- {isSigning && }
+ {isUnfillable && }
+ {isSigning && }
{i18n._(tab.title)} {account && ({tab.count})}
)
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/fields/SafeTxFields.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/fields/SafeTxFields.tsx
index 50cee6bf54..bc22789901 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/fields/SafeTxFields.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/fields/SafeTxFields.tsx
@@ -1,4 +1,4 @@
-import safeLogo from '@cowprotocol/assets/cow-swap/safe-logo.svg'
+import svgSafeSrc from '@cowprotocol/assets/cow-swap/safe-logo.svg'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { t } from '@lingui/core/macro'
@@ -29,7 +29,7 @@ export function SafeTxFields(props: SafeTxFieldsProps) {
const { chainId, safeAddress, safeTxHash, nonce, confirmationsRequired, confirmations } = props
const safeTransaction = { safe: safeAddress, safeTxHash }
- const safeLogoImg =
+ const safeLogoImg =
return (
<>
diff --git a/apps/cowswap-frontend/src/modules/swap/containers/BottomBanners/BottomBanners.container.tsx b/apps/cowswap-frontend/src/modules/swap/containers/BottomBanners/BottomBanners.container.tsx
index 56dc7374a6..34ac760967 100644
--- a/apps/cowswap-frontend/src/modules/swap/containers/BottomBanners/BottomBanners.container.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/containers/BottomBanners/BottomBanners.container.tsx
@@ -1,6 +1,6 @@
import { ReactNode } from 'react'
-import HAND_SVG from '@cowprotocol/assets/cow-swap/hand.svg'
+import svgHandSrc from '@cowprotocol/assets/cow-swap/hand.svg'
import { BannerOrientation, InlineBanner, StatusColorVariant } from '@cowprotocol/ui'
import { useWalletInfo } from '@cowprotocol/wallet'
@@ -31,7 +31,7 @@ export function BottomBanners(): ReactNode {
bannerNode = (
-
+
diff --git a/apps/cowswap-frontend/src/modules/swap/pure/CrossChainUnlockScreen/styled.tsx b/apps/cowswap-frontend/src/modules/swap/pure/CrossChainUnlockScreen/styled.tsx
index db263dee1e..eaae0110c0 100644
--- a/apps/cowswap-frontend/src/modules/swap/pure/CrossChainUnlockScreen/styled.tsx
+++ b/apps/cowswap-frontend/src/modules/swap/pure/CrossChainUnlockScreen/styled.tsx
@@ -1,4 +1,4 @@
-import CROSS_CHAIN_BG from '@cowprotocol/assets/images/cross-chain-unlock-bg.svg'
+import svgCrossChainUnlockBgSrc from '@cowprotocol/assets/images/cross-chain-unlock-bg.svg'
import { Media, UI } from '@cowprotocol/ui'
import styled from 'styled-components/macro'
@@ -21,7 +21,7 @@ export const Container = styled.div<{ darkMode: boolean }>`
content: '';
position: absolute;
inset: 0;
- background: url(${CROSS_CHAIN_BG}) calc(100% - -12px) center/contain no-repeat;
+ background: url(${svgCrossChainUnlockBgSrc}) calc(100% - -12px) center/contain no-repeat;
opacity: ${({ darkMode }) => (darkMode ? 0.5 : 1)};
pointer-events: none;
z-index: 0;
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/ChainsSelector/ChainButton.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/ChainsSelector/ChainButton.tsx
index 1f99880139..ffc3dce777 100644
--- a/apps/cowswap-frontend/src/modules/tokensList/pure/ChainsSelector/ChainButton.tsx
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/ChainsSelector/ChainButton.tsx
@@ -1,6 +1,6 @@
import { ReactNode } from 'react'
-import OrderCheckIcon from '@cowprotocol/assets/cow-swap/order-check.svg'
+import svgOrderCheckSrc from '@cowprotocol/assets/cow-swap/order-check.svg'
import { ChainInfo } from '@cowprotocol/cow-sdk'
import { useLingui } from '@lingui/react/macro'
@@ -64,7 +64,7 @@ export function ChainButton({
{isActive && !isLoading && (
-
+
)}
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/TokenSourceTitle/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenSourceTitle/index.tsx
index ff3fb57344..2882a8d02b 100644
--- a/apps/cowswap-frontend/src/modules/tokensList/pure/TokenSourceTitle/index.tsx
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenSourceTitle/index.tsx
@@ -1,4 +1,4 @@
-import TokenListLogo from '@cowprotocol/assets/svg/tokenlist.svg'
+import svgTokenlistSrc from '@cowprotocol/assets/svg/tokenlist.svg'
import { HelpTooltip } from '@cowprotocol/ui'
import styled from 'styled-components/macro'
@@ -36,7 +36,7 @@ export function TokenSourceTitle(props: TokenSourceTitleProps) {
return (
-
+
{children}
{tooltipText ? (
diff --git a/apps/cowswap-frontend/src/modules/tokensList/pure/TokenTags/index.tsx b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenTags/index.tsx
index af6fc42c04..98cf9fd146 100644
--- a/apps/cowswap-frontend/src/modules/tokensList/pure/TokenTags/index.tsx
+++ b/apps/cowswap-frontend/src/modules/tokensList/pure/TokenTags/index.tsx
@@ -6,7 +6,7 @@ import { TagInfo, TokenListTags } from '@cowprotocol/tokens'
import { getStatusColorEnums, HoverTooltip, StatusColorVariant } from '@cowprotocol/ui'
import { msg } from '@lingui/core/macro'
-import ICON_GAS_FREE from 'assets/icon/gas-free.svg'
+import iconGasFreeSrc from 'assets/icon/gas-free.svg'
import SVG from 'react-inlinesvg'
import { NavLink } from 'react-router'
@@ -23,7 +23,7 @@ const APP_TOKEN_TAGS: TokenListTags = {
},
'gas-free': {
name: msg`Gas-free`,
- icon: ICON_GAS_FREE,
+ icon: iconGasFreeSrc,
description: msg`This token supports gas-free approvals. Enjoy! 🐮`,
id: '1',
color: StatusColorVariant.Success,
diff --git a/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/TradeWidgetForm.tsx b/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/TradeWidgetForm.tsx
index 541bb43048..1a76bb9326 100644
--- a/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/TradeWidgetForm.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/TradeWidgetForm.tsx
@@ -1,6 +1,6 @@
import React, { ReactNode, useCallback, useMemo } from 'react'
-import ICON_ORDERS from '@cowprotocol/assets/svg/orders.svg'
+import svgOrdersSrc from '@cowprotocol/assets/svg/orders.svg'
import { useFeatureFlags, useTheme, useMediaQuery } from '@cowprotocol/common-hooks'
import { isInjectedWidget, isSellOrder, maxAmountSpend } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
@@ -234,7 +234,7 @@ export function TradeWidgetForm(props: TradeWidgetProps): ReactNode {
{shouldShowMyOrdersButton && (
- My orders
+ My orders
)}
diff --git a/apps/cowswap-frontend/src/modules/trade/containers/TradeWidgetLinks/index.tsx b/apps/cowswap-frontend/src/modules/trade/containers/TradeWidgetLinks/index.tsx
index 323d078f73..a7a6013769 100644
--- a/apps/cowswap-frontend/src/modules/trade/containers/TradeWidgetLinks/index.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/containers/TradeWidgetLinks/index.tsx
@@ -5,7 +5,7 @@ import { Badge, BadgeTypes, ModalHeader } from '@cowprotocol/ui'
import type { TradeType } from '@cowprotocol/widget-lib'
import { Trans, useLingui } from '@lingui/react/macro'
-import IMAGE_CARET from 'assets/icon/caret.svg'
+import iconCaretSrc from 'assets/icon/caret.svg'
import SVG from 'react-inlinesvg'
import { useLocation } from 'react-router'
@@ -129,7 +129,7 @@ export function TradeWidgetLinks({ isDropdown = false }: TradeWidgetLinksProps)
>
{selectedMenuItem.props.item.label}
- {!singleMenuItem ? : null}
+ {!singleMenuItem ? : null}
diff --git a/apps/cowswap-frontend/src/modules/trade/pure/LimitOrdersPromoBanner/index.tsx b/apps/cowswap-frontend/src/modules/trade/pure/LimitOrdersPromoBanner/index.tsx
index a4af1c2728..f545542d36 100644
--- a/apps/cowswap-frontend/src/modules/trade/pure/LimitOrdersPromoBanner/index.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/pure/LimitOrdersPromoBanner/index.tsx
@@ -1,6 +1,6 @@
import { useState, useEffect } from 'react'
-import iconCompleted from '@cowprotocol/assets/cow-swap/check.svg'
+import svgCheckSrc from '@cowprotocol/assets/cow-swap/check.svg'
import { UI } from '@cowprotocol/ui'
import { MessageDescriptor } from '@lingui/core'
@@ -88,7 +88,7 @@ export function LimitOrdersPromoBanner({
{BULLET_POINTS.map((point, index) => (
-
+
{i18n._(point)}
diff --git a/apps/cowswap-frontend/src/modules/trade/pure/ReceiveAmountTitle/index.tsx b/apps/cowswap-frontend/src/modules/trade/pure/ReceiveAmountTitle/index.tsx
index 844f91e7f7..057f82b4af 100644
--- a/apps/cowswap-frontend/src/modules/trade/pure/ReceiveAmountTitle/index.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/pure/ReceiveAmountTitle/index.tsx
@@ -1,6 +1,6 @@
import { ReactNode } from 'react'
-import EqualIcon from '@cowprotocol/assets/cow-swap/equal.svg'
+import svgEqualSrc from '@cowprotocol/assets/cow-swap/equal.svg'
import { UI } from '@cowprotocol/ui'
import { t } from '@lingui/core/macro'
@@ -77,7 +77,7 @@ export function ReceiveAmountTitle({ className, children, icon, variant }: Recei
)
) : (
-
+
)}{' '}
{children}
diff --git a/apps/cowswap-frontend/src/modules/trade/pure/Settings/SettingsIcon.tsx b/apps/cowswap-frontend/src/modules/trade/pure/Settings/SettingsIcon.tsx
index cfb60a83ba..c1d2c973e0 100644
--- a/apps/cowswap-frontend/src/modules/trade/pure/Settings/SettingsIcon.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/pure/Settings/SettingsIcon.tsx
@@ -1,9 +1,9 @@
import { ReactNode } from 'react'
-import IMAGE_ICON_SETTINGS_ALT from '@cowprotocol/assets/images/icon-settings-alt.svg'
+import iconSettingsAltSrc from '@cowprotocol/assets/images/icon-settings-alt.svg'
import SVG from 'react-inlinesvg'
export function SettingsIcon(): ReactNode {
- return
+ return
}
diff --git a/apps/cowswap-frontend/src/modules/trade/pure/TradeNumberInput/index.tsx b/apps/cowswap-frontend/src/modules/trade/pure/TradeNumberInput/index.tsx
index 6cab2e6056..ae31697220 100644
--- a/apps/cowswap-frontend/src/modules/trade/pure/TradeNumberInput/index.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/pure/TradeNumberInput/index.tsx
@@ -1,6 +1,6 @@
import { useCallback, useEffect, useState } from 'react'
-import carretDown from '@cowprotocol/assets/cow-swap/carret-down.svg'
+import svgCarretDownSrc from '@cowprotocol/assets/cow-swap/carret-down.svg'
import { Command } from '@cowprotocol/types'
import { t } from '@lingui/core/macro'
@@ -46,13 +46,13 @@ export function InputArrows({ onClickUp, onClickDown }: InputArrowsProps) {
-
+
-
+
diff --git a/apps/cowswap-frontend/src/modules/trade/pure/UnlockWidgetScreen/index.tsx b/apps/cowswap-frontend/src/modules/trade/pure/UnlockWidgetScreen/index.tsx
index 764481f7c4..c54f5d0d02 100644
--- a/apps/cowswap-frontend/src/modules/trade/pure/UnlockWidgetScreen/index.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/pure/UnlockWidgetScreen/index.tsx
@@ -1,6 +1,6 @@
import { isValidElement } from 'react'
-import iconCompleted from '@cowprotocol/assets/cow-swap/check.svg'
+import svgCheckSrc from '@cowprotocol/assets/cow-swap/check.svg'
import { Command } from '@cowprotocol/types'
import { ButtonPrimary, ExternalLink } from '@cowprotocol/ui'
@@ -52,7 +52,7 @@ export function UnlockWidgetScreen({
{items.map(({ isNew, content }, index) => (
-
+
{' '}
{isValidElement(content) ? content : i18n._(content as MessageDescriptor)}
diff --git a/apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/SettingsDropdown/SettingsDropdown.container.tsx b/apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/SettingsDropdown/SettingsDropdown.container.tsx
index 822e43fea4..db07716856 100644
--- a/apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/SettingsDropdown/SettingsDropdown.container.tsx
+++ b/apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/SettingsDropdown/SettingsDropdown.container.tsx
@@ -1,6 +1,6 @@
import { ReactNode, useCallback, useRef } from 'react'
-import EXPERIMENT_ICON from '@cowprotocol/assets/cow-swap/experiment.svg'
+import svgExperimentSrc from '@cowprotocol/assets/cow-swap/experiment.svg'
import { isInjectedWidget } from '@cowprotocol/common-utils'
import { StatefulValue } from '@cowprotocol/types'
import { SettingsBox, SettingsBoxGroup, SettingsDropdownSection } from '@cowprotocol/ui'
@@ -122,7 +122,7 @@ export function SettingsDropdown({
tooltip={
- Experimental:
+ Experimental:
{' '}
Add DeFi interactions before and after your trade.
diff --git a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/tooltips.tsx b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/tooltips.tsx
index 90bbca097f..290beeaeac 100644
--- a/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/tooltips.tsx
+++ b/apps/cowswap-frontend/src/modules/twap/containers/TwapFormWidget/tooltips.tsx
@@ -1,4 +1,4 @@
-import ShieldImage from '@cowprotocol/assets/cow-swap/protection.svg'
+import svgProtectionSrc from '@cowprotocol/assets/cow-swap/protection.svg'
import { Trans, useLingui } from '@lingui/react/macro'
import SVG from 'react-inlinesvg'
@@ -69,7 +69,7 @@ export function useLabelsTooltips(): LabelTooltipItems {
label: (
<>
-
+
{' '}
Price protection
>
diff --git a/apps/cowswap-frontend/src/modules/wallet/pure/StatusIcon/index.tsx b/apps/cowswap-frontend/src/modules/wallet/pure/StatusIcon/index.tsx
index 254cbc2f18..da6cf72bac 100644
--- a/apps/cowswap-frontend/src/modules/wallet/pure/StatusIcon/index.tsx
+++ b/apps/cowswap-frontend/src/modules/wallet/pure/StatusIcon/index.tsx
@@ -1,4 +1,4 @@
-import { Identicon, ConnectionType, CoinbaseWalletIcon, WalletConnectIcon } from '@cowprotocol/wallet'
+import { Identicon, ConnectionType, svgCoinbaseSrc, iconWalletConnectSrc } from '@cowprotocol/wallet'
import { t } from '@lingui/core/macro'
import styled from 'styled-components/macro'
@@ -27,13 +27,13 @@ export function StatusIcon({ connectionType, account, size = 16 }: StatusIconPro
let image
switch (connectionType) {
case ConnectionType.COINBASE_WALLET:
- image =
+ image =
break
case ConnectionType.INJECTED:
image =
break
case ConnectionType.WALLET_CONNECT_V2:
- image =
+ image =
break
}
diff --git a/apps/cowswap-frontend/src/modules/wallet/pure/Web3StatusInner/index.tsx b/apps/cowswap-frontend/src/modules/wallet/pure/Web3StatusInner/index.tsx
index 093105e50b..030e0c2c00 100644
--- a/apps/cowswap-frontend/src/modules/wallet/pure/Web3StatusInner/index.tsx
+++ b/apps/cowswap-frontend/src/modules/wallet/pure/Web3StatusInner/index.tsx
@@ -8,7 +8,7 @@ import { ConnectionType } from '@cowprotocol/wallet'
import { t } from '@lingui/core/macro'
import { Trans } from '@lingui/react/macro'
-import ICON_WALLET from 'assets/icon/wallet.svg'
+import iconWalletSrc from 'assets/icon/wallet.svg'
import { AlertTriangle } from 'react-feather'
import SVG from 'react-inlinesvg'
@@ -78,7 +78,7 @@ export function Web3StatusInner(props: Web3StatusInnerProps): ReactNode {
Connect wallet
-
+
)
}
diff --git a/apps/cowswap-frontend/src/pages/Account/Balances.tsx b/apps/cowswap-frontend/src/pages/Account/Balances.tsx
index 66ab57a678..7aedd96789 100644
--- a/apps/cowswap-frontend/src/pages/Account/Balances.tsx
+++ b/apps/cowswap-frontend/src/pages/Account/Balances.tsx
@@ -1,8 +1,8 @@
import { useCallback, useEffect, useMemo, useState } from 'react'
-import ArrowIcon from '@cowprotocol/assets/cow-swap/arrow.svg'
-import CowImage from '@cowprotocol/assets/cow-swap/cow_token.svg'
-import vCOWImage from '@cowprotocol/assets/images/vCOW.svg'
+import svgArrowSrc from '@cowprotocol/assets/cow-swap/arrow.svg'
+import svgCowTokenSrc from '@cowprotocol/assets/cow-swap/cow_token.svg'
+import svgVCowSrc from '@cowprotocol/assets/images/vCOW.svg'
import { useCurrencyAmountBalance, useTokensBalances } from '@cowprotocol/balances-and-allowances'
import {
COW_TOKEN_TO_CHAIN,
@@ -193,7 +193,7 @@ export default function Profile() {
} else {
content = (
- Convert to COW
+ Convert to COW
)
}
@@ -252,7 +252,7 @@ export default function Profile() {
{hasVCowBalance && vCowToken && (
-
+
Total vCOW balance
@@ -298,7 +298,7 @@ export default function Profile() {
{cowContractAddress && (
-
+
Available COW balance
diff --git a/apps/cowswap-frontend/src/pages/Account/Delegate.tsx b/apps/cowswap-frontend/src/pages/Account/Delegate.tsx
index d71412dd2f..27edaa76fe 100644
--- a/apps/cowswap-frontend/src/pages/Account/Delegate.tsx
+++ b/apps/cowswap-frontend/src/pages/Account/Delegate.tsx
@@ -1,7 +1,7 @@
import { useCallback } from 'react'
-import CowImage from '@cowprotocol/assets/cow-swap/cow_token.svg'
-import DelegateCowIcon from '@cowprotocol/assets/cow-swap/delegate-cow.svg'
+import svgCowTokenSrc from '@cowprotocol/assets/cow-swap/cow_token.svg'
+import svgDelegateCowSrc from '@cowprotocol/assets/cow-swap/delegate-cow.svg'
import { ClosableBanner, ButtonPrimary } from '@cowprotocol/ui'
import { t } from '@lingui/core/macro'
@@ -28,7 +28,7 @@ export default function Delegate({ dismissable = false, rowOnMobile }: DelegateP
{dismissable && close && }
-
+
@@ -39,7 +39,7 @@ export default function Delegate({ dismissable = false, rowOnMobile }: DelegateP
Delegate your
-
(v)COW
+
(v)COW
Delegate Now ↗
diff --git a/apps/cowswap-frontend/src/pages/Account/LockedGnoVesting/index.tsx b/apps/cowswap-frontend/src/pages/Account/LockedGnoVesting/index.tsx
index 5bbb7c2ab4..07eb4d1778 100644
--- a/apps/cowswap-frontend/src/pages/Account/LockedGnoVesting/index.tsx
+++ b/apps/cowswap-frontend/src/pages/Account/LockedGnoVesting/index.tsx
@@ -1,8 +1,8 @@
import { useCallback, useEffect, useState } from 'react'
import { useCowAnalytics } from '@cowprotocol/analytics'
-import ArrowIcon from '@cowprotocol/assets/cow-swap/arrow.svg'
-import cowImage from '@cowprotocol/assets/cow-swap/cow_token.svg'
+import svgArrowSrc from '@cowprotocol/assets/cow-swap/arrow.svg'
+import svgCowTokenSrc from '@cowprotocol/assets/cow-swap/cow_token.svg'
import {
LOCKED_GNO_VESTING_START_DATE,
MERKLE_DROP_CONTRACT_ADDRESSES,
@@ -148,7 +148,7 @@ const LockedGnoVesting: React.FC = ({ openModal, closeModal, vested, allo
<>
-
+
COW vesting from locked GNO
@@ -220,7 +220,7 @@ const LockedGnoVesting: React.FC = ({ openModal, closeModal, vested, allo
Claiming COW...
) : (
- Claim COW
+ Claim COW
)}
diff --git a/apps/cowswap-frontend/src/pages/error/AnySwapAffectedUsers/index.tsx b/apps/cowswap-frontend/src/pages/error/AnySwapAffectedUsers/index.tsx
index 3507f5d876..95d76b015c 100644
--- a/apps/cowswap-frontend/src/pages/error/AnySwapAffectedUsers/index.tsx
+++ b/apps/cowswap-frontend/src/pages/error/AnySwapAffectedUsers/index.tsx
@@ -1,6 +1,6 @@
import { ReactNode } from 'react'
-import cow404IMG from '@cowprotocol/assets/cow-swap/cow-404.png'
+import imgCow404Src from '@cowprotocol/assets/cow-swap/cow-404.png'
import { ButtonPrimary, ExternalLink as ExternalLinkTheme, Media } from '@cowprotocol/ui'
import { t } from '@lingui/core/macro'
@@ -90,7 +90,7 @@ export default function AnySwapAffectedUsers(): ReactNode {
-
+
Read how to prevent losing funds
diff --git a/apps/cowswap-frontend/src/pages/error/NotFound/CowSaucerScene.tsx b/apps/cowswap-frontend/src/pages/error/NotFound/CowSaucerScene.tsx
index 324c761131..860801e4a7 100644
--- a/apps/cowswap-frontend/src/pages/error/NotFound/CowSaucerScene.tsx
+++ b/apps/cowswap-frontend/src/pages/error/NotFound/CowSaucerScene.tsx
@@ -1,7 +1,7 @@
import { ReactNode } from 'react'
-import cowDarkIMG from '@cowprotocol/assets/images/404/swap/dark/cow.svg'
-import cowLightIMG from '@cowprotocol/assets/images/404/swap/light/cow.svg'
+import svgCowDarkSrc from '@cowprotocol/assets/images/404/swap/dark/cow.svg'
+import svgCowLightSrc from '@cowprotocol/assets/images/404/swap/light/cow.svg'
import {
CowSaucerScene as BaseCowSaucerScene,
SWAP_SAUCER_PALETTE_DARK,
@@ -17,7 +17,7 @@ export function CowSaucerScene({ darkMode }: CowSaucerSceneProps): ReactNode {
)
}
diff --git a/apps/cowswap-frontend/src/pages/games/MevSlicer/index.tsx b/apps/cowswap-frontend/src/pages/games/MevSlicer/index.tsx
index af3dc42970..d1382f2608 100644
--- a/apps/cowswap-frontend/src/pages/games/MevSlicer/index.tsx
+++ b/apps/cowswap-frontend/src/pages/games/MevSlicer/index.tsx
@@ -1,6 +1,6 @@
import { ReactNode } from 'react'
-import ninjaCowImg from '@cowprotocol/assets/cow-swap/ninja-cow.png'
+import imgNinjaCowSrc from '@cowprotocol/assets/cow-swap/ninja-cow.png'
import { PAGE_TITLES } from '@cowprotocol/common-const'
import { ButtonPrimary } from '@cowprotocol/ui'
@@ -67,7 +67,7 @@ export default function MevSlicer(): ReactNode {
-
+
= ({ tooltip, placement = 'top', offset }) => {
- return
+ return (
+
+ )
}
diff --git a/apps/explorer/src/components/common/BlockExplorerLink/BlockExplorerLink.tsx b/apps/explorer/src/components/common/BlockExplorerLink/BlockExplorerLink.tsx
index 487b76c893..e3c4df0e23 100644
--- a/apps/explorer/src/components/common/BlockExplorerLink/BlockExplorerLink.tsx
+++ b/apps/explorer/src/components/common/BlockExplorerLink/BlockExplorerLink.tsx
@@ -65,7 +65,7 @@ export const BlockExplorerLink: React.FC = (props: Props) => {
return (
{label}
- {showLogo && }
+ {showLogo && }
)
}
diff --git a/apps/explorer/src/components/common/CardRow/CardRow.stories.tsx b/apps/explorer/src/components/common/CardRow/CardRow.stories.tsx
index 1425cab4bf..8de58f7fd7 100644
--- a/apps/explorer/src/components/common/CardRow/CardRow.stories.tsx
+++ b/apps/explorer/src/components/common/CardRow/CardRow.stories.tsx
@@ -4,7 +4,7 @@ import { Card, CardContent } from 'components/common/Card'
import { CardRow, CardRowProps } from 'components/common/CardRow'
import { GlobalStyles, ThemeToggler } from 'storybook/decorators'
-import QuestionIcon from '../../../assets/img/question1.svg'
+import svgQuestion1Src from '../../../assets/img/question1.svg'
export default {
title: 'Common/CardRow',
@@ -20,7 +20,7 @@ const Template: Story = (args) => (
}
+ icon1={
}
variant="3row"
label1="24h Transactions"
value1="194"
diff --git a/apps/explorer/src/components/common/CowLoading.tsx b/apps/explorer/src/components/common/CowLoading.tsx
index f027e7892e..f8ba185518 100644
--- a/apps/explorer/src/components/common/CowLoading.tsx
+++ b/apps/explorer/src/components/common/CowLoading.tsx
@@ -1,6 +1,6 @@
import React from 'react'
-import CowLoadingSVG from 'assets/img/CowProtocol-logo.svg'
+import svgCowProtocolSrc from 'assets/img/CowProtocol-logo.svg'
import SVG from 'react-inlinesvg'
import styled, { keyframes } from 'styled-components/macro'
@@ -36,7 +36,7 @@ export const StyledCowLoading = styled(SVG)`
export const CowLoading: React.FC = () => (
-
+
)
diff --git a/apps/explorer/src/components/common/LogoWrapper.ts b/apps/explorer/src/components/common/LogoWrapper.ts
index 9be6ec724a..fb0005f522 100644
--- a/apps/explorer/src/components/common/LogoWrapper.ts
+++ b/apps/explorer/src/components/common/LogoWrapper.ts
@@ -1,5 +1,5 @@
-import etherscan from 'assets/img/etherscan-logo.svg'
-import github from 'assets/img/github-logo.png'
+import svgEtherscanSrc from 'assets/img/etherscan-logo.svg'
+import imgGithubSrc from 'assets/img/github-logo.png'
import styled from 'styled-components/macro'
export default styled.img`
@@ -25,6 +25,6 @@ export default styled.img`
}
`
export const LOGO_MAP = {
- github,
- etherscan,
+ imgGithubSrc,
+ svgEtherscanSrc,
}
diff --git a/apps/explorer/src/components/common/MenuDropdown/MainMenuTree.stories.tsx b/apps/explorer/src/components/common/MenuDropdown/MainMenuTree.stories.tsx
index 46620677f1..46603ba37a 100644
--- a/apps/explorer/src/components/common/MenuDropdown/MainMenuTree.stories.tsx
+++ b/apps/explorer/src/components/common/MenuDropdown/MainMenuTree.stories.tsx
@@ -4,11 +4,11 @@ import { useMediaQuery } from '@cowprotocol/common-hooks'
import { Media } from '@cowprotocol/ui'
import { Story, Meta } from '@storybook/react/types-6-0'
-import IMAGE_APPDATA from 'assets/img/code.svg'
-import IMAGE_COW from 'assets/img/CowProtocol-logo.svg'
-import IMAGE_DISCORD from 'assets/img/discord.svg'
-import IMAGE_DOC from 'assets/img/doc.svg'
-import IMAGE_ANALYTICS from 'assets/img/pie.svg'
+import svgCodeSrc from 'assets/img/code.svg'
+import svgCowProtocolSrc from 'assets/img/CowProtocol-logo.svg'
+import svgDiscordSrc from 'assets/img/discord.svg'
+import svgDocSrc from 'assets/img/doc.svg'
+import svgPieSrc from 'assets/img/pie.svg'
import { MenuTree, MenuTreeProps } from 'components/common/MenuDropdown/MenuTree'
import { GlobalStyles, ThemeToggler, Router } from 'storybook/decorators'
@@ -45,25 +45,25 @@ const DropdownMenu: MenuTreeItem[] = [
title: 'CoW Swap',
url: COWSWAP_LINK,
kind: MenuItemKind.EXTERNAL_LINK,
- iconSVG: IMAGE_COW,
+ iconSVG: svgCowProtocolSrc,
},
{
title: 'CoW Protocol',
url: PROTOCOL_LINK,
kind: MenuItemKind.EXTERNAL_LINK,
- iconSVG: IMAGE_COW,
+ iconSVG: svgCowProtocolSrc,
},
{
title: 'Documentation',
url: DOCS_LINK,
kind: MenuItemKind.EXTERNAL_LINK,
- iconSVG: IMAGE_DOC,
+ iconSVG: svgDocSrc,
},
{
title: 'Analytics',
url: DUNE_DASHBOARD_LINK,
kind: MenuItemKind.EXTERNAL_LINK,
- iconSVG: IMAGE_ANALYTICS,
+ iconSVG: svgPieSrc,
},
],
},
@@ -73,7 +73,7 @@ const DropdownMenu: MenuTreeItem[] = [
{
title: 'Discord',
url: DISCORD_LINK,
- iconSVG: IMAGE_DISCORD, // If icon is a
{mobileMode && languagesContent}
@@ -719,7 +719,7 @@ const GlobalSettingsDropdown = forwardRef
{item.label}
-
+
>
)
@@ -967,7 +967,7 @@ export const MenuBar = (props: MenuBarProps) => {
{item.label}
-
+
)
@@ -975,7 +975,7 @@ export const MenuBar = (props: MenuBarProps) => {
{showGlobalSettings && settingsNavItems && (
<>
-
+
{isSettingsOpen &&
(isMedium ? (
@@ -1013,7 +1013,7 @@ export const MenuBar = (props: MenuBarProps) => {
{isMobile && (
-
+
)}
@@ -1052,10 +1052,7 @@ export const MenuBar = (props: MenuBarProps) => {
{item.label}
-
+
)
diff --git a/libs/ui/src/pure/ProductLogo/index.tsx b/libs/ui/src/pure/ProductLogo/index.tsx
index 7a68f21261..49e07d2a4c 100644
--- a/libs/ui/src/pure/ProductLogo/index.tsx
+++ b/libs/ui/src/pure/ProductLogo/index.tsx
@@ -1,16 +1,16 @@
import { ReactNode } from 'react'
-import LOGO_COWAMM from '@cowprotocol/assets/images/logo-cowamm.svg'
-import LOGO_COWDAO from '@cowprotocol/assets/images/logo-cowdao.svg'
-import LOGO_COWEXPLORER from '@cowprotocol/assets/images/logo-cowexplorer.svg'
-import LOGO_COWPROTOCOL from '@cowprotocol/assets/images/logo-cowprotocol.svg'
-import LOGO_COWSWAP_CHRISTMAS_DARK from '@cowprotocol/assets/images/logo-cowswap-christmas-dark.svg'
-import LOGO_COWSWAP_CHRISTMAS from '@cowprotocol/assets/images/logo-cowswap-christmas-light.svg'
-import LOGO_COWSWAP_HALLOWEEN from '@cowprotocol/assets/images/logo-cowswap-halloween.svg'
-import LOGO_COWSWAP from '@cowprotocol/assets/images/logo-cowswap.svg'
-import LOGO_ICON_COW from '@cowprotocol/assets/images/logo-icon-cow.svg'
-import LOGO_ICON_MEVBLOCKER from '@cowprotocol/assets/images/logo-icon-mevblocker.svg'
-import LOGO_MEVBLOCKER from '@cowprotocol/assets/images/logo-mevblocker.svg'
+import svgCowammSrc from '@cowprotocol/assets/images/logo-cowamm.svg'
+import svgCowdaoSrc from '@cowprotocol/assets/images/logo-cowdao.svg'
+import svgCowexplorerSrc from '@cowprotocol/assets/images/logo-cowexplorer.svg'
+import svgCowprotocolSrc from '@cowprotocol/assets/images/logo-cowprotocol.svg'
+import svgCowswapChristmasDarkSrc from '@cowprotocol/assets/images/logo-cowswap-christmas-dark.svg'
+import svgCowswapChristmasLightSrc from '@cowprotocol/assets/images/logo-cowswap-christmas-light.svg'
+import svgCowswapHalloweenSrc from '@cowprotocol/assets/images/logo-cowswap-halloween.svg'
+import svgCowswapSrc from '@cowprotocol/assets/images/logo-cowswap.svg'
+import iconCowSrc from '@cowprotocol/assets/images/logo-icon-cow.svg'
+import iconMevblockerSrc from '@cowprotocol/assets/images/logo-icon-mevblocker.svg'
+import svgMevblockerSrc from '@cowprotocol/assets/images/logo-mevblocker.svg'
import { useTheme } from '@cowprotocol/common-hooks'
import { toPixelValue } from '@cowprotocol/ui-utils'
@@ -52,38 +52,38 @@ const LOGOS: Record = {
[ProductVariant.CowSwap]: {
light: {
default: {
- src: LOGO_COWSWAP,
+ src: svgCowswapSrc,
alt: 'CoW Swap',
color: '#004293',
},
logoIconOnly: {
- src: LOGO_ICON_COW,
+ src: iconCowSrc,
alt: 'CoW Swap',
color: '#004293',
},
},
dark: {
default: {
- src: LOGO_COWSWAP,
+ src: svgCowswapSrc,
alt: 'CoW Swap',
color: Color.blue300Primary,
},
logoIconOnly: {
- src: LOGO_ICON_COW,
+ src: iconCowSrc,
alt: 'CoW Swap',
color: Color.blue300Primary,
},
},
darkHalloween: {
default: {
- src: LOGO_COWSWAP_HALLOWEEN,
+ src: svgCowswapHalloweenSrc,
alt: 'CoW Swap',
preserveOriginalColors: true,
},
},
darkChristmas: {
default: {
- src: LOGO_COWSWAP_CHRISTMAS_DARK,
+ src: svgCowswapChristmasDarkSrc,
alt: 'CoW Swap',
color: Color.blue300Primary,
height: '56px',
@@ -93,7 +93,7 @@ const LOGOS: Record = {
},
lightChristmas: {
default: {
- src: LOGO_COWSWAP_CHRISTMAS,
+ src: svgCowswapChristmasLightSrc,
alt: 'CoW Swap',
color: '#004293',
height: '56px',
@@ -107,24 +107,24 @@ const LOGOS: Record = {
[ProductVariant.CowExplorer]: {
light: {
default: {
- src: LOGO_COWEXPLORER,
+ src: svgCowexplorerSrc,
alt: 'CoW Explorer',
color: Color.neutral0,
},
logoIconOnly: {
- src: LOGO_ICON_COW,
+ src: iconCowSrc,
alt: 'CoW Explorer',
color: Color.neutral0,
},
},
dark: {
default: {
- src: LOGO_COWEXPLORER,
+ src: svgCowexplorerSrc,
alt: 'CoW Explorer',
color: Color.neutral100,
},
logoIconOnly: {
- src: LOGO_ICON_COW,
+ src: iconCowSrc,
alt: 'CoW Explorer',
color: Color.neutral100,
},
@@ -135,24 +135,24 @@ const LOGOS: Record = {
[ProductVariant.CowDao]: {
light: {
default: {
- src: LOGO_COWDAO,
+ src: svgCowdaoSrc,
alt: 'CoW DAO',
color: Color.neutral0,
},
logoIconOnly: {
- src: LOGO_ICON_COW,
+ src: iconCowSrc,
alt: 'CoW DAO',
color: Color.neutral0,
},
},
dark: {
default: {
- src: LOGO_COWDAO,
+ src: svgCowdaoSrc,
alt: 'CoW DAO',
color: Color.neutral100,
},
logoIconOnly: {
- src: LOGO_ICON_COW,
+ src: iconCowSrc,
alt: 'CoW DAO',
color: Color.neutral100,
},
@@ -163,24 +163,24 @@ const LOGOS: Record = {
[ProductVariant.CowProtocol]: {
light: {
default: {
- src: LOGO_COWPROTOCOL,
+ src: svgCowprotocolSrc,
alt: 'CoW Protocol',
color: Color.neutral0,
},
logoIconOnly: {
- src: LOGO_ICON_COW,
+ src: iconCowSrc,
alt: 'CoW Protocol',
color: Color.neutral0,
},
},
dark: {
default: {
- src: LOGO_COWPROTOCOL,
+ src: svgCowprotocolSrc,
alt: 'CoW Protocol',
color: Color.neutral100,
},
logoIconOnly: {
- src: LOGO_ICON_COW,
+ src: iconCowSrc,
alt: 'CoW Protocol',
color: Color.neutral100,
},
@@ -191,24 +191,24 @@ const LOGOS: Record = {
[ProductVariant.MevBlocker]: {
light: {
default: {
- src: LOGO_MEVBLOCKER,
+ src: svgMevblockerSrc,
alt: 'MEV Blocker',
color: '#EC4612',
},
logoIconOnly: {
- src: LOGO_ICON_MEVBLOCKER,
+ src: iconMevblockerSrc,
alt: 'MEV Blocker',
color: '#EC4612',
},
},
dark: {
default: {
- src: LOGO_MEVBLOCKER,
+ src: svgMevblockerSrc,
alt: 'MEV Blocker',
color: '#EC4612',
},
logoIconOnly: {
- src: LOGO_ICON_MEVBLOCKER,
+ src: iconMevblockerSrc,
alt: 'MEV Blocker',
color: '#EC4612',
},
@@ -219,24 +219,24 @@ const LOGOS: Record = {
[ProductVariant.CowAmm]: {
light: {
default: {
- src: LOGO_COWAMM,
+ src: svgCowammSrc,
alt: 'CoW AMM',
color: Color.blue900Primary,
},
logoIconOnly: {
- src: LOGO_ICON_COW,
+ src: iconCowSrc,
alt: 'CoW AMM',
color: Color.blue900Primary,
},
},
dark: {
default: {
- src: LOGO_COWAMM,
+ src: svgCowammSrc,
alt: 'CoW AMM',
color: '#007CDB',
},
logoIconOnly: {
- src: LOGO_ICON_COW,
+ src: iconCowSrc,
alt: 'CoW AMM',
color: '#007CDB',
},
@@ -310,7 +310,7 @@ export const ProductLogoWrapper = styled.span<{
`
// TODO: Reduce function complexity by extracting logic
-// eslint-disable-next-line complexity
+
export const ProductLogo = ({
variant,
theme: customThemeMode,
diff --git a/libs/wallet/src/assets.ts b/libs/wallet/src/assets.ts
index 9490184658..cfce9919f6 100644
--- a/libs/wallet/src/assets.ts
+++ b/libs/wallet/src/assets.ts
@@ -1,5 +1,5 @@
-import CoinbaseWalletIcon from './api/assets/coinbase.svg'
-import MetaMaskLogo from './api/assets/metamask.png'
-import WalletConnectIcon from './api/assets/walletConnectIcon.svg'
+import svgCoinbaseSrc from './api/assets/coinbase.svg'
+import imgMetamaskSrc from './api/assets/metamask.png'
+import iconWalletConnectSrc from './api/assets/walletConnectIcon.svg'
-export { CoinbaseWalletIcon, WalletConnectIcon, MetaMaskLogo }
+export { svgCoinbaseSrc, iconWalletConnectSrc, imgMetamaskSrc }
diff --git a/tools/codemods/rename-svg-import-bindings.mjs b/tools/codemods/rename-svg-import-bindings.mjs
new file mode 100644
index 0000000000..98962836c4
--- /dev/null
+++ b/tools/codemods/rename-svg-import-bindings.mjs
@@ -0,0 +1,487 @@
+/**
+ * Rename default asset import bindings to icon*Src / img*Src / svg*Src (outside string literals only).
+ * Prefix detection is filename-first, then path fallback, then default "img".
+ * Run from repo root: node tools/codemods/rename-svg-import-bindings.mjs
+ */
+import { execSync } from 'node:child_process'
+import { readFileSync, writeFileSync } from 'node:fs'
+import { resolve } from 'node:path'
+import { pathToFileURL } from 'node:url'
+
+// Generic words we strip from the semantic "tail" of the generated binding.
+const GENERIC_TAIL_WORDS = new Set(['icon', 'img', 'image', 'svg', 'logo', 'illustration', 'asset', 'assets'])
+// Common path words that should not be used as collision disambiguators.
+const GENERIC_PATH_WORDS = new Set([
+ ...GENERIC_TAIL_WORDS,
+ 'src',
+ 'public',
+ 'static',
+ 'media',
+ 'file',
+ 'files',
+])
+
+// Converts SCREAMING_SNAKE_CASE-like names into camelCase.
+// Example: COW_ICON -> cowIcon
+export function snakeToCamel(str) {
+ // Work in lowercase first to normalize mixed uppercase inputs.
+ const s = str.toLowerCase()
+ // Turn "_x" into "X".
+ return s.replace(/_([a-z0-9])/g, (_, c) => c.toUpperCase())
+}
+
+// Split identifiers/paths into lowercase words:
+// - handles kebab/snake/dots/slashes
+// - handles camelCase / PascalCase boundaries
+export function splitWords(value) {
+ return value
+ .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
+ .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')
+ .split(/[^A-Za-z0-9]+/)
+ .filter(Boolean)
+ .map((w) => w.toLowerCase())
+}
+
+// Extract the filename segment without ".svg".
+export function filenameNoExt(assetPath) {
+ const file = assetPath.split('/').pop() || assetPath
+ return file.replace(/\.(svg|png|jpe?g|webp|gif)$/i, '')
+}
+
+// Read normalized extension without the dot (svg/png/jpg/...).
+export function assetExt(assetPath) {
+ const m = assetPath.toLowerCase().match(/\.([a-z0-9]+)$/)
+ return m ? m[1] : ''
+}
+
+// Turn words into PascalCase tail.
+export function toPascal(words) {
+ return words.map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join('')
+}
+
+// Decide canonical prefix from words.
+// We accept plural/path variants via startsWith checks.
+export function prefixFromWords(words) {
+ if (words.some((w) => w.startsWith('icon'))) return 'icon'
+ if (words.some((w) => w === 'img' || w.startsWith('image') || w.startsWith('img'))) return 'img'
+ if (words.some((w) => w.startsWith('svg'))) return 'svg'
+ return null
+}
+
+/** For .svg: icon|svg only. For raster assets: icon|img|svg, fallback img. */
+export function prefixFromAssetPath(assetPath) {
+ const ext = assetExt(assetPath)
+ const isSvg = ext === 'svg'
+
+ // For SVG imports lint only allows icon*Src or svg*Src.
+ if (isSvg) {
+ const fileWords = splitWords(filenameNoExt(assetPath))
+ const pathWords = splitWords(assetPath.replace(/\.(svg|png|jpe?g|webp|gif)$/i, ''))
+
+ if (fileWords.some((w) => w.startsWith('icon')) || pathWords.some((w) => w.startsWith('icon'))) {
+ return 'icon'
+ }
+
+ return 'svg'
+ }
+
+ // 1) First, inspect file name (most specific source of intent).
+ const filePrefix = prefixFromWords(splitWords(filenameNoExt(assetPath)))
+ if (filePrefix) return filePrefix
+
+ // 2) Fallback to full path (directory names like images/icons/svg).
+ const pathPrefix = prefixFromWords(splitWords(assetPath.replace(/\.(svg|png|jpe?g|webp|gif)$/i, '')))
+ if (pathPrefix) return pathPrefix
+
+ // 3) Final fallback when no explicit hint is found.
+ return 'img'
+}
+
+// Valid final shape: iconFooSrc / imgFooSrc / svgFooSrc
+export function isValidBinding(name) {
+ return /^(icon|img|svg)[A-Za-z0-9]+Src$/.test(name)
+}
+
+// "fooBar" -> "FooBar"
+export function camelCaseToPascalFirst(s) {
+ return s.charAt(0).toUpperCase() + s.slice(1)
+}
+
+export function legacyToNew(name, assetPath) {
+ // Derive desired prefix from filename/path hints.
+ const prefix = prefixFromAssetPath(assetPath)
+
+ // Build semantic tail from filename first; remove generic words.
+ const fileWords = splitWords(filenameNoExt(assetPath))
+ let tailWords = fileWords.filter((w) => !GENERIC_TAIL_WORDS.has(w))
+
+ // If filename contains only generic words, fallback to current binding words.
+ if (tailWords.length === 0) {
+ const fallbackCore = name.replace(/Src$/, '').replace(/^(icon|img|image|svg)/i, '')
+ const fallbackWords = splitWords(fallbackCore).filter((w) => !GENERIC_TAIL_WORDS.has(w))
+ tailWords = fallbackWords
+ }
+
+ // Last-resort tail to keep output deterministic.
+ if (tailWords.length === 0) {
+ const fallback = snakeToCamel(name.replace(/Src$/i, '')) || 'asset'
+ tailWords = splitWords(fallback).filter((w) => !GENERIC_TAIL_WORDS.has(w))
+ }
+
+ // If still empty (extremely defensive), use "Asset".
+ const tail = toPascal(tailWords.length ? tailWords : ['asset'])
+
+ // Canonical output always follows "Src".
+ const candidate = `${prefix}${tail}Src`
+
+ // Keep unchanged only when name already matches canonical candidate.
+ if (name === candidate) return name
+ return candidate
+}
+
+// Produce candidate words from nearest parent directories first.
+// Example: /a/b/dark/cow.svg -> ['dark', 'b', 'a'] (generic words removed)
+export function disambiguationWordsFromPath(assetPath) {
+ const noExt = assetPath.replace(/\.(svg|png|jpe?g|webp|gif)$/i, '')
+ const parts = noExt.split('/').filter(Boolean)
+ const dirParts = parts.slice(0, -1)
+
+ const words = []
+ for (let i = dirParts.length - 1; i >= 0; i--) {
+ const segmentWords = splitWords(dirParts[i]).filter((w) => !GENERIC_PATH_WORDS.has(w))
+ for (const w of segmentWords) words.push(w)
+ }
+
+ return words
+}
+
+// Ensure generated binding is unique within a file.
+// On conflict, append nearest-path qualifiers (Dark/Light/...) before fallback numeric suffix.
+export function makeUniqueBinding(baseName, assetPath, usedNames, forceQualifier = false) {
+ if (!forceQualifier && !usedNames.has(baseName)) return baseName
+
+ const m = baseName.match(/^(icon|img|svg)([A-Za-z0-9]+)Src$/)
+ if (!m) {
+ if (!forceQualifier) {
+ let i = 2
+ let candidate = `${baseName}${i}`
+ while (usedNames.has(candidate)) {
+ i++
+ candidate = `${baseName}${i}`
+ }
+ return candidate
+ }
+ // If qualifier is forced but base format is unexpected, fall through to numeric suffix.
+ let i = 2
+ let candidate = `${baseName}${i}`
+ while (usedNames.has(candidate)) {
+ i++
+ candidate = `${baseName}${i}`
+ }
+ return candidate
+ }
+
+ const [, prefix, tail] = m
+ const tailWords = new Set(splitWords(tail))
+ const disambiguationWords = disambiguationWordsFromPath(assetPath)
+
+ for (const w of disambiguationWords) {
+ if (tailWords.has(w)) continue
+ const candidate = `${prefix}${tail}${camelCaseToPascalFirst(w)}Src`
+ if (!usedNames.has(candidate)) return candidate
+ }
+
+ let i = 2
+ let candidate = `${prefix}${tail}${i}Src`
+ while (usedNames.has(candidate)) {
+ i++
+ candidate = `${prefix}${tail}${i}Src`
+ }
+ return candidate
+}
+
+/** Replace `oldName` with `newName` only outside strings / line & block comments */
+export function replaceIdentifierOutsideStrings(code, oldName, newName) {
+ // Fast path for no-op replacements.
+ if (oldName === newName) return code
+ // Match only full identifier occurrences at the current cursor.
+ const boundaryRe = new RegExp(String.raw`^${oldName.replaceAll('$', String.raw`\$`)}\b`)
+
+ // out = rebuilt source; i = read cursor
+ let out = ''
+ let i = 0
+ // String parsing state: null | "'" | '"' | '`'
+ let inString = null
+ let stringEscaped = false
+ const n = code.length
+
+ while (i < n) {
+ const c = code[i]
+
+ // If currently inside a string, copy characters until the string closes.
+ if (inString) {
+ out += c
+ // Special handling for template string interpolations: `${ ... }`
+ // We DO run replacement in the expression body (recursive call) while
+ // still treating the surrounding template string as a string context.
+ if (inString === '`' && c === '$' && code[i + 1] === '{') {
+ out += '{'
+ i += 2
+ let depth = 1
+ let expr = ''
+ while (i < n && depth > 0) {
+ const ch = code[i]
+ if (ch === '{') depth++
+ else if (ch === '}') depth--
+ if (depth === 0) {
+ i++
+ break
+ }
+ expr += ch
+ i++
+ }
+ out += replaceIdentifierOutsideStrings(expr, oldName, newName)
+ out += '}'
+ continue
+ }
+ // Handle escaped chars inside strings.
+ if (stringEscaped) {
+ stringEscaped = false
+ i++
+ continue
+ }
+ if (c === '\\') {
+ stringEscaped = true
+ i++
+ continue
+ }
+ // End of current string literal.
+ if (c === inString) {
+ inString = null
+ }
+ i++
+ continue
+ }
+
+ // Skip line comments as opaque text.
+ if (c === '/' && code[i + 1] === '/') {
+ while (i < n && code[i] !== '\n') out += code[i++]
+ continue
+ }
+ // Skip block comments as opaque text.
+ if (c === '/' && code[i + 1] === '*') {
+ out += '/*'
+ i += 2
+ while (i < n - 1 && !(code[i] === '*' && code[i + 1] === '/')) {
+ out += code[i++]
+ }
+ if (i < n - 1) {
+ out += '*/'
+ i += 2
+ }
+ continue
+ }
+
+ // Enter string mode.
+ if (c === "'" || c === '"' || c === '`') {
+ inString = c
+ out += c
+ i++
+ continue
+ }
+
+ // Replace only when oldName starts at this exact cursor and is token-bounded.
+ const rest = code.slice(i)
+ const beforeOk = i === 0 || !/[\w$]/.test(code[i - 1])
+ if (beforeOk && boundaryRe.test(rest)) {
+ out += newName
+ i += oldName.length
+ continue
+ }
+
+ out += c
+ i++
+ }
+
+ return out
+}
+
+export function transformFile(content) {
+ // Keep all scheduled symbol replacements, then apply them after imports are rewritten.
+ const reassignments = []
+ const usedNames = new Set()
+ const assignedByOld = new Map()
+
+ // Pre-scan imports so we can force disambiguation when multiple SVG paths
+ // collapse to the same canonical binding (e.g. dark/cow.svg + light/cow.svg).
+ const imported = []
+ const importTail = '((?:\\r?\\n)+|$)'
+ const assetExt = String.raw`(?:svg|png|jpe?g|webp|gif)`
+ const captureAandB = new RegExp(
+ String.raw`^(\s*)import\s+\{\s*default\s+as\s+(\w+)\s*,\s*default\s+as\s+(\w+)\s*\}\s+from\s+(['"])([^'"]+\.${assetExt})\4${importTail}`,
+ 'gm',
+ )
+ const captureDefaultAs = new RegExp(
+ String.raw`^(\s*)import\s+\{\s*default\s+as\s+(\w+)\s*\}\s+from\s+(['"])([^'"]+\.${assetExt})\3${importTail}`,
+ 'gm',
+ )
+ const captureNamespace = new RegExp(
+ String.raw`^(\s*)import\s+\*\s+as\s+(\w+)\s+from\s+(['"])([^'"]+\.${assetExt})\3${importTail}`,
+ 'gm',
+ )
+ const captureDefault = new RegExp(
+ String.raw`^(\s*)import\s+(?!type\s)(\w+)\s+from\s+(['"])([^'"]+\.${assetExt})\3${importTail}`,
+ 'gm',
+ )
+
+ content.replace(captureAandB, (_, __, a, b, ___, path) => {
+ imported.push({ bind: a, path }, { bind: b, path })
+ return _
+ })
+ content.replace(captureDefaultAs, (_, __, bind, ___, path) => {
+ imported.push({ bind, path })
+ return _
+ })
+ content.replace(captureNamespace, (_, __, bind, ___, path) => {
+ imported.push({ bind, path })
+ return _
+ })
+ content.replace(captureDefault, (_, __, bind, ___, path) => {
+ imported.push({ bind, path })
+ return _
+ })
+
+ const baseToDistinctPaths = new Map()
+ for (const { bind, path } of imported) {
+ const base = legacyToNew(bind, path)
+ if (!baseToDistinctPaths.has(base)) baseToDistinctPaths.set(base, new Set())
+ baseToDistinctPaths.get(base).add(path)
+ }
+ const forcedQualifierBases = new Set(
+ [...baseToDistinctPaths.entries()].filter(([, paths]) => paths.size > 1).map(([base]) => base),
+ )
+
+ function schedule(oldName, newName, assetPath) {
+ if (assignedByOld.has(oldName)) return assignedByOld.get(oldName)
+
+ const forceQualifier = forcedQualifierBases.has(newName)
+ const uniqueName = makeUniqueBinding(newName, assetPath, usedNames, forceQualifier)
+ usedNames.add(uniqueName)
+ assignedByOld.set(oldName, uniqueName)
+
+ if (oldName !== uniqueName) reassignments.push({ oldName, newName: uniqueName })
+ return uniqueName
+ }
+
+ // Build transformed source incrementally.
+ let out = content
+ // Preserve either blank line(s) or EOF after each matched import.
+ const tail = '((?:\\r?\\n)+|$)'
+
+ // 1) import { default as A, default as B } from 'x.asset' -> import imgFooSrc from 'x.asset'
+ out = out.replace(
+ new RegExp(
+ String.raw`^(\s*)import\s+\{\s*default\s+as\s+(\w+)\s*,\s*default\s+as\s+(\w+)\s*\}\s+from\s+(['"])([^'"]+\.${assetExt})\4${tail}`,
+ 'gm',
+ ),
+ (_, indent, a, b, q, path, trail) => {
+ const next = legacyToNew(a, path)
+ const assigned = schedule(a, next, path)
+ schedule(b, next, path)
+ // Keep the collapsed single import binding; both old aliases map to it.
+ return `${indent}import ${assigned} from ${q}${path}${q}${trail}`
+ },
+ )
+
+ // 2) import { default as A } from 'x.asset' -> import imgFooSrc from 'x.asset'
+ out = out.replace(
+ new RegExp(
+ String.raw`^(\s*)import\s+\{\s*default\s+as\s+(\w+)\s*\}\s+from\s+(['"])([^'"]+\.${assetExt})\3${tail}`,
+ 'gm',
+ ),
+ (_, indent, bind, q, path, trail) => {
+ const next = legacyToNew(bind, path)
+ const assigned = schedule(bind, next, path)
+ return `${indent}import ${assigned} from ${q}${path}${q}${trail}`
+ },
+ )
+
+ // 3) import * as A from 'x.asset' -> keep style, only rename binding.
+ out = out.replace(
+ new RegExp(String.raw`^(\s*)import\s+\*\s+as\s+(\w+)\s+from\s+(['"])([^'"]+\.${assetExt})\3${tail}`, 'gm'),
+ (_, indent, bind, q, path, trail) => {
+ const next = legacyToNew(bind, path)
+ const assigned = schedule(bind, next, path)
+ return `${indent}import * as ${assigned} from ${q}${path}${q}${trail}`
+ },
+ )
+
+ // 4) import A from 'x.asset' -> rename default binding.
+ out = out.replace(
+ new RegExp(String.raw`^(\s*)import\s+(?!type\s)(\w+)\s+from\s+(['"])([^'"]+\.${assetExt})\3${tail}`, 'gm'),
+ (_, indent, bind, q, path, trail) => {
+ const next = legacyToNew(bind, path)
+ const assigned = schedule(bind, next, path)
+ return `${indent}import ${assigned} from ${q}${path}${q}${trail}`
+ },
+ )
+
+ // Deduplicate by oldName: last scheduled value wins.
+ const byOld = new Map()
+ for (const { oldName, newName } of reassignments) {
+ byOld.set(oldName, newName)
+ }
+ // Replace longer names first to avoid partial collisions.
+ const unique = [...byOld.entries()]
+ .map(([oldName, newName]) => ({ oldName, newName }))
+ .sort((a, b) => b.oldName.length - a.oldName.length)
+
+ // Update usage sites in code (excluding comments/strings via parser above).
+ for (const { oldName, newName } of unique) {
+ out = replaceIdentifierOutsideStrings(out, oldName, newName)
+ }
+
+ // Return null when unchanged, so caller can skip writes.
+ return out === content ? null : out
+}
+
+export function main() {
+ // Enumerate tracked files only.
+ const files = execSync('git ls-files', { encoding: 'utf8' })
+ .split('\n')
+ // Restrict to JS/TS source-like files.
+ .filter((f) => /\.(tsx|ts|jsx|js|mts)$/.test(f))
+ // Keep only files that contain a supported asset import-like string.
+ .filter((f) => {
+ try {
+ return /\.(svg|png|jpe?g|webp|gif)['"]/.test(readFileSync(f, 'utf8'))
+ } catch {
+ // Ignore unreadable files defensively.
+ return false
+ }
+ })
+
+ let changed = 0
+ for (const f of files) {
+ // Read -> transform -> write only when a change is needed.
+ const content = readFileSync(f, 'utf8')
+ const next = transformFile(content)
+ if (next) {
+ writeFileSync(f, next, 'utf8')
+ changed++
+ // Print touched file to help review/diff.
+ console.log(f)
+ }
+ }
+ // Final summary count.
+ console.log(`Updated ${changed} files`)
+}
+
+// CLI entrypoint: execute only when file is run directly with node.
+const isDirectRun = process.argv[1]
+ ? import.meta.url === pathToFileURL(resolve(process.argv[1])).href
+ : false
+
+if (isDirectRun) {
+ main()
+}
diff --git a/tools/codemods/rename-svg-import-bindings.test.mjs b/tools/codemods/rename-svg-import-bindings.test.mjs
new file mode 100644
index 0000000000..6bb98e2542
--- /dev/null
+++ b/tools/codemods/rename-svg-import-bindings.test.mjs
@@ -0,0 +1,140 @@
+import {
+ legacyToNew,
+ prefixFromAssetPath,
+ replaceIdentifierOutsideStrings,
+ transformFile,
+} from './rename-svg-import-bindings.mjs'
+
+const CHECK = '✓'
+const CROSS = '✗'
+
+let failures = 0
+
+function report(name, ok, details = '') {
+ if (ok) {
+ console.log(`${CHECK} ${name}`)
+ return
+ }
+
+ failures++
+ console.error(`${CROSS} ${name}`)
+ if (details) console.error(` ${details}`)
+}
+
+function expectEqual(name, actual, expected) {
+ report(name, actual === expected, `expected: ${expected}\n actual: ${actual}`)
+}
+
+function run() {
+ console.log('Running rename-svg-import-bindings self-tests...\n')
+
+ expectEqual('prefix: icon from path hint', prefixFromAssetPath('/assets/icon-social-x.svg'), 'icon')
+ expectEqual('prefix: svg from generic svg file', prefixFromAssetPath('/assets/images/hero-banner.svg'), 'svg')
+ expectEqual('prefix: svg from path hint', prefixFromAssetPath('/assets/svg-set/brand-mark.svg'), 'svg')
+ expectEqual('prefix: default to svg for .svg files', prefixFromAssetPath('/assets/brand-mark.svg'), 'svg')
+
+ expectEqual('legacy: old icon name can become svg', legacyToNew('iconSearch', '/assets/search.svg'), 'svgSearchSrc')
+ expectEqual('legacy: old image name becomes svg', legacyToNew('imageHero', '/assets/images/hero.svg'), 'svgHeroSrc')
+ expectEqual('legacy: old svg name keeps svg', legacyToNew('svgBadge', '/assets/svg/badge.svg'), 'svgBadgeSrc')
+ expectEqual(
+ 'legacy: CONSTANT_STYLE uses filename tail with icon prefix',
+ legacyToNew('COW_PROTOCOL_LOGO', '/assets/icons/cow.svg'),
+ 'iconCowSrc',
+ )
+
+ const replaced = replaceIdentifierOutsideStrings(
+ "const a = iconSearch\nconst b = 'iconSearch'\n// iconSearch\n",
+ 'iconSearch',
+ 'svgSearchSrc',
+ )
+ expectEqual(
+ 'replace: updates code but not strings/comments',
+ replaced,
+ "const a = svgSearchSrc\nconst b = 'iconSearch'\n// iconSearch\n",
+ )
+
+ const transformed = transformFile(
+ "import iconSearch from 'assets/search.svg'\nconst img = iconSearch\nconst text = 'iconSearch'\n",
+ )
+ expectEqual(
+ 'transform: rewrites import + references',
+ transformed,
+ "import svgSearchSrc from 'assets/search.svg'\nconst img = svgSearchSrc\nconst text = 'iconSearch'\n",
+ )
+
+ const transformedLogo = transformFile("import imageEtherscanSrc from 'assets/img/etherscan-logo.svg'\n")
+ expectEqual(
+ 'transform: uses "svg" prefix for non-icon svg and removes generic "logo" token',
+ transformedLogo,
+ "import svgEtherscanSrc from 'assets/img/etherscan-logo.svg'\n",
+ )
+
+ const transformedImgArrow = transformFile(
+ "import imageImgIconArrowRightSrc from '@cowprotocol/assets/images/arrow-right.svg'\n",
+ )
+ expectEqual(
+ 'transform: removes redundant img/icon tokens and normalizes to svg prefix',
+ transformedImgArrow,
+ "import svgArrowRightSrc from '@cowprotocol/assets/images/arrow-right.svg'\n",
+ )
+
+ const transformedIconMinus = transformFile(
+ "import iconImgIconMinusSrc from '@cowprotocol/assets/images/icon-minus.svg'\n",
+ )
+ expectEqual(
+ 'transform: keeps icon token from filename and drops redundant img token',
+ transformedIconMinus,
+ "import iconMinusSrc from '@cowprotocol/assets/images/icon-minus.svg'\n",
+ )
+
+ const transformedTemplateInterpolation = transformFile(
+ "import IMAGE_BACKGROUND_DARK from '@cowprotocol/assets/images/background-cowswap-darkmode.svg'\n" +
+ 'const styles = `background: url(${IMAGE_BACKGROUND_DARK}) no-repeat;`\n',
+ )
+ expectEqual(
+ 'transform: replaces identifiers used inside template interpolation',
+ transformedTemplateInterpolation,
+ "import svgBackgroundCowswapDarkmodeSrc from '@cowprotocol/assets/images/background-cowswap-darkmode.svg'\n" +
+ 'const styles = `background: url(${svgBackgroundCowswapDarkmodeSrc}) no-repeat;`\n',
+ )
+
+ const transformedSameBasenameCollision = transformFile(
+ "import CowDark from '@cowprotocol/assets/images/404/swap/dark/cow.svg'\n" +
+ "import CowLight from '@cowprotocol/assets/images/404/swap/light/cow.svg'\n",
+ )
+ expectEqual(
+ 'transform: avoids collisions for same filename in different folders',
+ transformedSameBasenameCollision,
+ "import svgCowDarkSrc from '@cowprotocol/assets/images/404/swap/dark/cow.svg'\n" +
+ "import svgCowLightSrc from '@cowprotocol/assets/images/404/swap/light/cow.svg'\n",
+ )
+
+ const transformedWalletAssets = transformFile(
+ "import CoinbaseWalletIcon from './api/assets/coinbase.svg'\n" +
+ "import MetaMaskLogo from './api/assets/metamask.png'\n" +
+ "import WalletConnectIcon from './api/assets/walletConnectIcon.svg'\n" +
+ '\n' +
+ 'export { CoinbaseWalletIcon, WalletConnectIcon, MetaMaskLogo }\n',
+ )
+ expectEqual(
+ 'transform: updates asset imports and export bindings in wallet assets re-export file',
+ transformedWalletAssets,
+ "import svgCoinbaseSrc from './api/assets/coinbase.svg'\n" +
+ "import imgMetamaskSrc from './api/assets/metamask.png'\n" +
+ "import iconWalletConnectSrc from './api/assets/walletConnectIcon.svg'\n" +
+ '\n' +
+ 'export { svgCoinbaseSrc, iconWalletConnectSrc, imgMetamaskSrc }\n',
+ )
+
+
+ console.log('')
+ if (failures === 0) {
+ console.log(`${CHECK} All tests passed`)
+ return
+ }
+
+ console.error(`${CROSS} ${failures} test(s) failed`)
+ process.exitCode = 1
+}
+
+run()