fix: bundle tldraw whiteboard assets

This commit is contained in:
lucaronin
2026-05-04 14:41:23 +02:00
parent e7e33c479d
commit 9973d8d4e6
4 changed files with 105 additions and 0 deletions

View File

@@ -55,6 +55,7 @@
"@tauri-apps/plugin-opener": "^2.5.3",
"@tauri-apps/plugin-process": "^2.3.1",
"@tauri-apps/plugin-updater": "^2.10.0",
"@tldraw/assets": "4.5.10",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"date-fns": "^4.1.0",

10
pnpm-lock.yaml generated
View File

@@ -125,6 +125,9 @@ importers:
'@tauri-apps/plugin-updater':
specifier: ^2.10.0
version: 2.10.0
'@tldraw/assets':
specifier: 4.5.10
version: 4.5.10
class-variance-authority:
specifier: ^0.7.1
version: 0.7.1
@@ -2499,6 +2502,9 @@ packages:
'@tiptap/starter-kit@3.22.5':
resolution: {integrity: sha512-LZ/LYbwH6rnDi5DnRyagkuNsYAVyhM+yJvvz+ZuYA0JkPiTXJV86J5PWSKew8M0gVfMHcNVtKjfQCvViFCeIgw==}
'@tldraw/assets@4.5.10':
resolution: {integrity: sha512-nJZ+dZgLcmeEtv4aZv/kEkeY4IU2qrFC8Ayftxql1B+2hXc9ZsjNMKOHyB/W2BsVWdUplZm2qjujKeGNs1VWrw==}
'@tldraw/editor@4.5.10':
resolution: {integrity: sha512-kM11sDK1ADXATE/wthBDY3ZOriT5Nzpieq1EoPz/HwSMVFuLq5NVmaOPKF+Pt/n43T1S5eLOfMOc7i3zojNc3g==}
peerDependencies:
@@ -7757,6 +7763,10 @@ snapshots:
'@tiptap/extensions': 3.22.5(@tiptap/core@3.22.5(@tiptap/pm@3.22.5))(@tiptap/pm@3.22.5)
'@tiptap/pm': 3.22.5
'@tldraw/assets@4.5.10':
dependencies:
'@tldraw/utils': 4.5.10
'@tldraw/editor@4.5.10(@floating-ui/dom@1.7.5)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
dependencies:
'@tiptap/core': 3.19.0(@tiptap/pm@3.19.0)

View File

@@ -0,0 +1,90 @@
import { render, screen } from '@testing-library/react'
import { describe, expect, it, vi } from 'vitest'
import { TldrawWhiteboard } from './TldrawWhiteboard'
interface MockTldrawProps {
assetUrls: MockAssetUrls
}
interface MockAssetUrls {
embedIcons: Record<string, string>
fonts: Record<string, string>
icons: Record<string, string>
translations: Record<string, string>
}
const tldrawMock = vi.hoisted(() => ({
Tldraw: vi.fn(),
}))
vi.mock('tldraw', async () => {
const { createElement } = await import('react')
tldrawMock.Tldraw.mockImplementation(({ assetUrls }: MockTldrawProps) =>
createElement('div', {
'data-testid': 'mock-tldraw',
'data-draw-font-url': assetUrls.fonts.tldraw_draw,
})
)
return {
Box: class Box {
x: number
y: number
w: number
h: number
constructor(x: number, y: number, w: number, h: number) {
this.x = x
this.y = y
this.w = w
this.h = h
}
},
Tldraw: tldrawMock.Tldraw,
createTLStore: vi.fn(() => ({
listen: vi.fn(() => vi.fn()),
})),
getSnapshot: vi.fn(() => ({ document: {} })),
loadSnapshot: vi.fn(),
}
})
function renderedTldrawAssetUrls(): MockAssetUrls {
const props = tldrawMock.Tldraw.mock.calls[0]?.[0] as MockTldrawProps
expect(props.assetUrls).toBeDefined()
return props.assetUrls
}
function expectNoCdnUrls(urls: Record<string, string>) {
Object.values(urls).forEach((url) => {
expect(url).not.toContain('cdn.tldraw.com')
})
}
function expectBundledTldrawAssetUrls(assetUrls: MockAssetUrls) {
expect(assetUrls.fonts.tldraw_draw).toContain('Shantell_Sans-Informal_Regular.woff2')
expect(assetUrls.icons['tool-pencil']).toContain('0_merged.svg#tool-pencil')
expect(assetUrls.translations.en).toContain('en.json')
expectNoCdnUrls(assetUrls.fonts)
expectNoCdnUrls(assetUrls.icons)
expectNoCdnUrls(assetUrls.translations)
}
describe('TldrawWhiteboard', () => {
it('uses bundled tldraw assets instead of CDN URLs', () => {
render(
<TldrawWhiteboard
boardId="board-1"
height="520"
snapshot=""
width=""
onSizeChange={vi.fn()}
onSnapshotChange={vi.fn()}
/>
)
expect(screen.getByTestId('mock-tldraw')).toHaveAttribute('data-draw-font-url')
expectBundledTldrawAssetUrls(renderedTldrawAssetUrls())
})
})

View File

@@ -1,4 +1,5 @@
import { useEffect, useMemo, useRef, useState, type CSSProperties, type PointerEvent as ReactPointerEvent } from 'react'
import { getAssetUrlsByImport } from '@tldraw/assets/imports.vite'
import {
Box,
Tldraw,
@@ -11,6 +12,8 @@ import {
} from 'tldraw'
import 'tldraw/tldraw.css'
const tldrawAssetUrls = getAssetUrlsByImport()
interface TldrawWhiteboardProps {
boardId: string
height: string
@@ -274,6 +277,7 @@ export function TldrawWhiteboard({
style={cssSize(visibleSize)}
>
<Tldraw
assetUrls={tldrawAssetUrls}
onMount={installZoomAwareViewport}
store={store}
/>