perf(client): encode onboarding illustrations as lossless WebP

This commit is contained in:
kingwl committed 2026-09-30 20:08:02 +08:00
1 parent 97bbbdfa13
commit d5b6cd29bb
27 files changed
+37 -27

No files matched your search

@@ -9,8 +9,8 @@
en: 50c7c883a2115b7e
zh: 60533d618a3b2da7
/agent-note-device-local-desktop-onboarding/decision:
en: e228d2a308f8ad8a
zh: c5eee26119226f32
en: d9059d9a6e75875b
zh: 5e581dc8609ed14f
/agent-note-device-local-desktop-onboarding/alternatives-considered:
en: 82debfeba02ecfdb
zh: c15d8fcc012058e3
@@ -16,7 +16,7 @@ Welcome requires an explicit start. The credit page always appears, including fo
Purpose and process selections persist as drafts. Office-only completion selects compact presentation. Development or both purposes require a process choice. Skipping any supported step selects standard process with compact usage and developer tools off. Completion applies Chat and shared developer-tool preferences before saving the done marker so a refused preference write cannot silently finish onboarding. Compact, standard, and detailed persist their corresponding `ui-chat.transcriptView` values.
The existing [native welcome decision](../architecture/2026-09-08-desktop-welcome-window-material.md) owns credential entry, IPC restrictions, and window material. Desktop suppresses automatic Web credential onboarding while retaining explicit API-key editing. Onboarding creates no workspace, demonstration task, or Session event. Static Figma illustrations use transparent, palette-compressed 3× PNG assets; welcome layers are merged with local sidebar blur; recharge uses a 70% opaque foreground window with local blur of the covered illustration. The account package owns the full-window overlay and its control styling; shared primitives retain generic behavior. Brand headings load a bundled, licensed Montserrat WOFF2 font through the Web entry. Choices retain focus during writes, reduced-motion preferences disable animation, and the application remains inert until the exit overlay unmounts. The confirmation dialog blurs its source page instead of sampling another backdrop in the translucent window.
The existing [native welcome decision](../architecture/2026-09-08-desktop-welcome-window-material.md) owns credential entry, IPC restrictions, and window material. Desktop suppresses automatic Web credential onboarding while retaining explicit API-key editing. Onboarding creates no workspace, demonstration task, or Session event. Static Figma illustrations use transparent, lossless 3× WebP assets; welcome layers are merged with local sidebar blur; recharge uses a 70% opaque foreground window with local blur of the covered illustration. The account package owns the full-window overlay and its control styling; shared primitives retain generic behavior. Brand headings load a bundled, licensed Montserrat WOFF2 font through the Web entry. Choices retain focus during writes, reduced-motion preferences disable animation, and the application remains inert until the exit overlay unmounts. The confirmation dialog blurs its source page instead of sampling another backdrop in the translucent window.
## Alternatives considered
@@ -16,7 +16,7 @@ Status: implemented
用途和过程选择会作为草稿持久化。仅选办公用途时采用简洁展示并完成。选择开发或两种用途时必须选择过程详情。任意可跳过步骤均采用标准过程、简洁用量和关闭开发者工具。完成时先应用 Chat 和共享开发者工具偏好,再保存完成标记,避免偏好写入被拒绝后静默完成引导。compact、standard 和 detailed 各自持久化为对应的 `ui-chat.transcriptView` 值。
既有[原生欢迎决策](../architecture/2026-09-08-desktop-welcome-window-material.zh.md)负责凭证入口、IPC 限制和窗口材质。Desktop 抑制自动 Web 凭证引导,保留显式 API Key 编辑。引导不创建工作区、示例任务或 Session 事件。静态 Figma 插图使用透明、调色板压缩的 3× PNG 资源;欢迎页图层合并并烘焙侧栏局部模糊;充值页前景窗口不透明度为 70%,仅烘焙其覆盖插图区域的模糊。账号包负责整窗覆盖层及其控件样式,共享基础组件保留通用行为。品牌标题通过 Web 入口加载附带许可的 Montserrat WOFF2 字体。保存选择时保留焦点,减少动态效果偏好会禁用动画,应用在退出覆盖层卸载前保持不可交互。确认弹窗模糊源页面,避免在半透明窗口内再次采样背景。
既有[原生欢迎决策](../architecture/2026-09-08-desktop-welcome-window-material.zh.md)负责凭证入口、IPC 限制和窗口材质。Desktop 抑制自动 Web 凭证引导,保留显式 API Key 编辑。引导不创建工作区、示例任务或 Session 事件。静态 Figma 插图使用透明、无损编码的 3× WebP 资源;欢迎页图层合并并烘焙侧栏局部模糊;充值页前景窗口不透明度为 70%,仅烘焙其覆盖插图区域的模糊。账号包负责整窗覆盖层及其控件样式,共享基础组件保留通用行为。品牌标题通过 Web 入口加载附带许可的 Montserrat WOFF2 字体。保存选择时保留焦点,减少动态效果偏好会禁用动画,应用在退出覆盖层卸载前保持不可交互。确认弹窗模糊源页面,避免在半透明窗口内再次采样背景。
## 考虑过的替代方案
+11 -1
View File
@@ -100,6 +100,16 @@ describe.skipIf(MODE === 'record')('web e2e: App-only desktop onboarding', () =>
async function snapshot(name: string): Promise<void> {
await expect.poll(() => page.locator('[data-desktop-onboarding]').getAttribute('aria-busy')).toBe('false')
const hasIllustration = name.startsWith('welcome') || name.startsWith('credit')
if (hasIllustration) {
const decoded = await page.locator('[class*="illustration"] > img').evaluateAll(async elements =>
Promise.all(elements.map(async (element) => {
const image = element as HTMLImageElement
await image.decode()
return image.naturalWidth > 0 && image.naturalHeight > 0
})))
expect(decoded).toEqual([true, true])
}
const aria = await captureStableAria(page, '[data-desktop-onboarding]', scaffold.workspaceCwd)
await mkdir(EXPECTED, { recursive: true })
await compareOrRefreshGolden(join(EXPECTED, `${name}.expected.md`), aria, MODE)
@@ -171,7 +181,7 @@ describe.skipIf(MODE === 'record')('web e2e: App-only desktop onboarding', () =>
expect(action?.width).toBeCloseTo(240, 0)
expect(action!.y - (card!.y + card!.height)).toBeCloseTo(40, 0)
}
if (name === 'welcome' || name === 'credit') {
if (hasIllustration) {
const illustrations = await page.locator('[class*="illustration"] > img:visible').evaluateAll(elements => elements.map((element) => {
const image = element as HTMLImageElement
const box = image.getBoundingClientRect()
@@ -21,8 +21,8 @@
en: c1c4db71fd09ca13
zh: a40c0a01e9951945
/deepseek-ai-dsh-client-ui-settings-account/understand-the-implementation:
en: 6b3ad3b6860100cf
zh: aeced4fb37642f15
en: cae840b564f9b3b4
zh: 9227297ec51458da
/deepseek-ai-dsh-client-ui-settings-account/further-exploration:
en: a28acdef21b1643a
zh: 5e2e357a6b716274
@@ -33,8 +33,8 @@
en: ca3015e252db0114
zh: ebca9253cf15e8e9
/deepseek-ai-dsh-client-ui-settings-account/known-limitations-and-deferred-work:
en: 161a4d95bfdd5181
zh: b94c3e165e69d23b
en: d5c9f1ec3d81715b
zh: 93f66ba21737c50c
/deepseek-ai-dsh-client-ui-settings-account/known-limitations-and-deferred-work/dev-note:
en: 2facb0fc2e6c1a9c
zh: bd04803f5c9e132c
@@ -68,7 +68,7 @@ The welcome page requires Get started. The credit page always appears. A positiv
The Account section appears first in Settings only while signed in; it is hidden before account state loads and after sign-out. The plugin owns one Host snapshot stream shared through framework hooks by settings.section and settings.launcher. The launcher opens Settings and offers Sign out only while an account credential is stored. Platform failures leave the menu available for retry. It maintains no independent credential state, so no invariant companion is published.
The desktop controller writes progress to `ui-settings-account` through Host settings. Completion first applies `ui-chat.transcriptView` and `ui-chat.performanceUsage` together, then calls the shared Coding Tools preference to persist `ui-settings.enabled`, and finally saves the done marker; a rejected write keeps the flow available for retry. Successful completion reveals the workspace through a 180ms fade; choices and ordinary navigation preview immediately while writes run in order. A failed final queued write restores saved progress and allows retry. Completion waits for queued choices and retains the page until preferences persist; reduced motion skips the fade. Onboarding choices compact, standard, and detailed apply directly to the corresponding Chat work-detail modes. API-key entry and explicit skip select standard; onboarding does not select verbose. Complete Figma illustration layers are bundled as transparent, palette-compressed 3× PNG assets; welcome layers are merged with local sidebar blur; recharge uses a 70% opaque foreground window with local blur of the covered illustration, and headings use the bundled Montserrat brand font; English headings and descriptions use Light (300), except the DeepSeek Harness brand within headings uses Medium (500); card titles retain Regular (400) when selected. English footer navigation uses Light (300). Confirmed onboarding sets a 960px minimum window width and enlarges narrower windows; completion releases the minimum without restoring the previous size. Loading or already-completed onboarding does not resize the window. Empty footer navigation space passes pointer events through to the primary action. Cards exclude native window dragging and own the keyboard focus outline for their checkbox. The account package owns its onboarding overlay and control geometry. Each step and the confirmation dialog has a separate component; the flow coordinates navigation, transitions, and recharge. The overlay hides the workspace while initial account and progress state loads. Question headings and cards follow the Figma positions at 1440 × 920 and 960 × 600, independently of their action buttons. On macOS, content clears the body portal’s inherited no-drag region and a first-child drag band leaves an 8px native resize margin; interactive controls and later dialogs exclude their regions, and a native Platform page disables the underlying onboarding band. The upper workspace popup illustration has an opaque background in both languages and themes; the underlying sidebar omits its selected-row highlight. Welcome keeps its illustration at its original size, repositions and clips the artwork in narrow windows, and reveals the complete illustration on wide windows. The [onboarding decision](../../../.agents/notes/implemented/feature/2026-09-16-desktop-onboarding.md) owns persistence and presentation trade-offs.
The desktop controller writes progress to `ui-settings-account` through Host settings. Completion first applies `ui-chat.transcriptView` and `ui-chat.performanceUsage` together, then calls the shared Coding Tools preference to persist `ui-settings.enabled`, and finally saves the done marker; a rejected write keeps the flow available for retry. Successful completion reveals the workspace through a 180ms fade; choices and ordinary navigation preview immediately while writes run in order. A failed final queued write restores saved progress and allows retry. Completion waits for queued choices and retains the page until preferences persist; reduced motion skips the fade. Onboarding choices compact, standard, and detailed apply directly to the corresponding Chat work-detail modes. API-key entry and explicit skip select standard; onboarding does not select verbose. Complete Figma illustration layers are bundled as transparent, lossless 3× WebP assets; welcome layers are merged with local sidebar blur; recharge uses a 70% opaque foreground window with local blur of the covered illustration, and headings use the bundled Montserrat brand font; English headings and descriptions use Light (300), except the DeepSeek Harness brand within headings uses Medium (500); card titles retain Regular (400) when selected. English footer navigation uses Light (300). Confirmed onboarding sets a 960px minimum window width and enlarges narrower windows; completion releases the minimum without restoring the previous size. Loading or already-completed onboarding does not resize the window. Empty footer navigation space passes pointer events through to the primary action. Cards exclude native window dragging and own the keyboard focus outline for their checkbox. The account package owns its onboarding overlay and control geometry. Each step and the confirmation dialog has a separate component; the flow coordinates navigation, transitions, and recharge. The overlay hides the workspace while initial account and progress state loads. Question headings and cards follow the Figma positions at 1440 × 920 and 960 × 600, independently of their action buttons. On macOS, content clears the body portal’s inherited no-drag region and a first-child drag band leaves an 8px native resize margin; interactive controls and later dialogs exclude their regions, and a native Platform page disables the underlying onboarding band. The upper workspace popup illustration has an opaque background in both languages and themes; the underlying sidebar omits its selected-row highlight. Welcome keeps its illustration at its original size, repositions and clips the artwork in narrow windows, and reveals the complete illustration on wide windows. The [onboarding decision](../../../.agents/notes/implemented/feature/2026-09-16-desktop-onboarding.md) owns persistence and presentation trade-offs.
<a id="further-exploration"></a>
## Further Exploration
@@ -99,7 +99,7 @@ No model request prefix changes.
- Profile and recharge-wallet balances use the existing Platform Web endpoints through Host getProfile / getBalance. The page refreshes when opened and after login or reconnect, preserves server-masked contact data, and shows query failures independently without manufacturing a zero balance. Usage and top-up use Host-provided links derived from platformOrigin and the browser’s own login; the links never carry a DSH token.
- Completed installations do not reapply defaults or overwrite later user preferences. Completion does not synchronize across devices or create a per-account history.
- Onboarding follows the interface locale and theme, with four Figma PNG illustration sets covering Chinese and English in light and dark appearance. Export canvases include the full illustration geometry; Finder artwork uses the same vertical fade in both themes.
- Onboarding follows the interface locale and theme, with four Figma illustration sets covering Chinese and English in light and dark appearance. Export canvases include the full illustration geometry; Finder artwork uses the same vertical fade in both themes.
- The notice copy is server-localized for the UI language in effect when the client reads it. Switching language does not itself re-read the unnotified bonus, so a notice already on screen keeps the copy the server sent for the earlier language until the user refreshes or the account lifecycle restarts.
@@ -68,7 +68,7 @@ Desktop preload 标记在账号凭证已存储后启用引导。进度属于本
仅登录后在设置导航首位显示账号页;账号状态加载完成前以及退出登录后隐藏该页。 插件持有一条 Host 快照流,通过框架 hook 供 settings.section 和 settings.launcher 共享。入口菜单可打开设置,并仅在已存储账号凭证时提供退出登录。Platform 请求失败时保留菜单,以供重试。插件不维护独立凭证状态,因此不发布 invariant。
桌面控制器通过 Host 设置将进度写入 `ui-settings-account`。完成时先一并应用 `ui-chat.transcriptView` 与 `ui-chat.performanceUsage`,再通过共享代码工作工具偏好保存 `ui-settings.enabled`,最后保存完成标记;写入被拒绝时保留引导以供重试。成功完成后通过 180ms 淡出显露工作区;选择和普通翻页立即预览,写入在后台按顺序执行。队列最后一次写入失败时恢复已保存进度,并允许重试。完成操作会等待选择队列及偏好保存成功,再关闭页面;减少动态效果偏好会跳过淡出。onboarding 选项 compact、standard、detailed 直接应用到对应的 Chat 工作过程模式。API Key 进入与显式跳过均采用 standard;onboarding 不选择 verbose。完整 Figma 示意图层以透明、调色板压缩的 3× PNG 资源打包;欢迎页图层合并并烘焙侧栏局部模糊;充值页前景窗口不透明度为 70%,仅烘焙其覆盖插图区域的模糊,标题使用已打包的 Montserrat 品牌字体,英文标题和描述使用 Light(300),标题中的 DeepSeek Harness 使用 Medium(500);卡片标题选中前后均使用 Regular(400)。英文底部导航使用 Light(300)。确认进入引导后,窗口最小宽度设为 960px,较窄窗口自动放大;完成后解除宽度限制,但不恢复原尺寸。加载中或已完成引导的启动不改变窗口尺寸。底部导航空白区域透过鼠标事件,避免遮挡主操作。卡片区域不参与原生窗口拖动,复选框的键盘焦点仅在卡片外框展示。账号包负责引导覆盖层和控件尺寸样式。每个步骤和确认弹窗各有独立组件,流程组件协调导航、切换动画和充值。初始账号与进度加载期间,覆盖层隐藏工作区。答题标题和卡片独立于操作按钮,位置对齐 Figma 的 1440 × 920 和 960 × 600 断点。macOS 的内容层清除 body 浮层继承的 no-drag,位于内容之前的拖拽层保留 8px 原生缩放边缘;交互控件和后续弹窗排除自身区域;原生平台页面打开时禁用底层引导拖拽层。上方工作区弹窗插画在两种语言和主题下均使用不透明背景,下层侧边栏不绘制选中行高亮。欢迎页保持示意图的原始尺寸,在窄窗口内调整插图位置并裁切,在宽窗口内展示完整插图。[引导决策](../../../.agents/notes/implemented/feature/2026-09-16-desktop-onboarding.zh.md)记录持久化与展示方面的取舍。
桌面控制器通过 Host 设置将进度写入 `ui-settings-account`。完成时先一并应用 `ui-chat.transcriptView` 与 `ui-chat.performanceUsage`,再通过共享代码工作工具偏好保存 `ui-settings.enabled`,最后保存完成标记;写入被拒绝时保留引导以供重试。成功完成后通过 180ms 淡出显露工作区;选择和普通翻页立即预览,写入在后台按顺序执行。队列最后一次写入失败时恢复已保存进度,并允许重试。完成操作会等待选择队列及偏好保存成功,再关闭页面;减少动态效果偏好会跳过淡出。onboarding 选项 compact、standard、detailed 直接应用到对应的 Chat 工作过程模式。API Key 进入与显式跳过均采用 standard;onboarding 不选择 verbose。完整 Figma 示意图层以透明、无损编码的 3× WebP 资源打包;欢迎页图层合并并烘焙侧栏局部模糊;充值页前景窗口不透明度为 70%,仅烘焙其覆盖插图区域的模糊,标题使用已打包的 Montserrat 品牌字体,英文标题和描述使用 Light(300),标题中的 DeepSeek Harness 使用 Medium(500);卡片标题选中前后均使用 Regular(400)。英文底部导航使用 Light(300)。确认进入引导后,窗口最小宽度设为 960px,较窄窗口自动放大;完成后解除宽度限制,但不恢复原尺寸。加载中或已完成引导的启动不改变窗口尺寸。底部导航空白区域透过鼠标事件,避免遮挡主操作。卡片区域不参与原生窗口拖动,复选框的键盘焦点仅在卡片外框展示。账号包负责引导覆盖层和控件尺寸样式。每个步骤和确认弹窗各有独立组件,流程组件协调导航、切换动画和充值。初始账号与进度加载期间,覆盖层隐藏工作区。答题标题和卡片独立于操作按钮,位置对齐 Figma 的 1440 × 920 和 960 × 600 断点。macOS 的内容层清除 body 浮层继承的 no-drag,位于内容之前的拖拽层保留 8px 原生缩放边缘;交互控件和后续弹窗排除自身区域;原生平台页面打开时禁用底层引导拖拽层。上方工作区弹窗插画在两种语言和主题下均使用不透明背景,下层侧边栏不绘制选中行高亮。欢迎页保持示意图的原始尺寸,在窄窗口内调整插图位置并裁切,在宽窗口内展示完整插图。[引导决策](../../../.agents/notes/implemented/feature/2026-09-16-desktop-onboarding.zh.md)记录持久化与展示方面的取舍。
<a id="further-exploration"></a>
## 深入探索
@@ -99,7 +99,7 @@ Desktop preload 标记在账号凭证已存储后启用引导。进度属于本
- 资料和充值钱包余额通过 Host getProfile / getBalance 复用已有 Platform Web 接口。页面在打开、登录及重连后刷新,原样显示服务端脱敏后的联系方式,并分别处理查询失败,不将失败显示为零余额。用量和充值使用 Host 按 platformOrigin 派生的链接,并沿用浏览器自身登录态,不携带 DSH token。
- 已完成引导的安装不会重新应用默认值或覆盖用户后续调整的偏好。完成状态不跨设备同步,也不创建逐账号历史。
- 引导跟随界面语言和主题,使用中文、英文分别搭配浅色、深色外观的四套 Figma PNG 插图。导出画布包含完整插图范围,Finder 插图在两种主题下使用一致的纵向渐变。
- 引导跟随界面语言和主题,使用中文、英文分别搭配浅色、深色外观的四套 Figma 插图。导出画布包含完整插图范围,Finder 插图在两种主题下使用一致的纵向渐变。
- 通知文案按客户端读取时的界面语言由服务端本地化。切换语言本身不会重新读取未通知赠金,因此已在屏幕上的通知会沿用服务端先前语言下发的文案,直到用户手动刷新或登录生命周期重新开始。
@@ -3,10 +3,10 @@ import type { RefObject } from 'react'
import { Button } from '@deepseek-ai/dsh-client-ui-primitives'
import type { DesktopOnboardingProps } from './onboarding-contract.ts'
import { OnboardingIllustration } from './OnboardingIllustration.tsx'
import art from './assets/onboarding-recharge.png'
import artDark from './assets/onboarding-recharge-dark.png'
import artZh from './assets/onboarding-recharge-zh.png'
import artZhDark from './assets/onboarding-recharge-zh-dark.png'
import art from './assets/onboarding-recharge.webp'
import artDark from './assets/onboarding-recharge-dark.webp'
import artZh from './assets/onboarding-recharge-zh.webp'
import artZhDark from './assets/onboarding-recharge-zh-dark.webp'
import css from './DesktopOnboarding.module.css'
/** @param props - credit facts, localized content and recharge/navigation actions. @returns the credit step. */
@@ -3,10 +3,10 @@ import type { RefObject } from 'react'
import { Button } from '@deepseek-ai/dsh-client-ui-primitives'
import type { DesktopOnboardingProps } from './onboarding-contract.ts'
import { OnboardingIllustration } from './OnboardingIllustration.tsx'
import art from './assets/onboarding-welcome.png'
import artDark from './assets/onboarding-welcome-dark.png'
import artZh from './assets/onboarding-welcome-zh.png'
import artZhDark from './assets/onboarding-welcome-zh-dark.png'
import art from './assets/onboarding-welcome.webp'
import artDark from './assets/onboarding-welcome-dark.webp'
import artZh from './assets/onboarding-welcome-zh.webp'
import artZhDark from './assets/onboarding-welcome-zh-dark.webp'
import css from './DesktopOnboarding.module.css'
/** @param props - localized content, focus target and navigation. @returns the welcome step. */
+3 -3
View File
@@ -1,7 +1,7 @@
/** Illustration imports are embedded in the account client bundle. */
declare module '*.png' {
const svg: string
export default svg
declare module '*.webp' {
const url: string
export default url
}
declare module '*.svg' {
const url: string
Binary file not shown.

Before

Width:  |  Height:  |  Size: 374 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 417 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 333 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 338 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 575 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 547 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 551 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 581 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 KiB

@@ -10,17 +10,17 @@ export default ((options) => bundle(options).map(config => ({
plugins: [...(config.plugins ?? []), {
name: 'account-onboarding-assets',
resolveId(source: string) {
if (!/^\.\/assets\/[^/]+\.(?:svg|png)(\?raw)?$/.test(source)) return null
if (!/^\.\/assets\/[^/]+\.(?:svg|webp)(\?raw)?$/.test(source)) return null
const url = new URL(`./src/client/assets/${basename(source)}`, import.meta.url)
return fileURLToPath(url) + url.search
},
async load(id: string) {
if (!/\/ui-settings-account\/src\/client\/assets\/[^/]+\.(?:svg|png)(\?raw)?$/.test(id.replaceAll('\\', '/'))) return null
if (!/\/ui-settings-account\/src\/client\/assets\/[^/]+\.(?:svg|webp)(\?raw)?$/.test(id.replaceAll('\\', '/'))) return null
const path = id.replace(/\?raw$/, '')
this.addWatchFile(path)
const data = await readFile(path)
if (id.endsWith('?raw')) return `export default ${JSON.stringify(data.toString('utf8'))}`
return `export default ${JSON.stringify(`data:${path.endsWith('.png') ? 'image/png' : 'image/svg+xml'};base64,${data.toString('base64')}`)}`
return `export default ${JSON.stringify(`data:${path.endsWith('.webp') ? 'image/webp' : 'image/svg+xml'};base64,${data.toString('base64')}`)}`
},
}],
}))) satisfies typeof bundle