diff --git a/apps/docs/content/getting-started/installation.mdx b/apps/docs/content/getting-started/installation.mdx index 9d1694daf..3928ccbba 100644 --- a/apps/docs/content/getting-started/installation.mdx +++ b/apps/docs/content/getting-started/installation.mdx @@ -137,11 +137,13 @@ const assetUrls = getAssetUrls() While these files must be available, you can overwrite the individual files: for example, by placing different icons under the same name or modifying / adding translations. -If you use a CDN for hosting these files you can specify the base url of your assets. To recreate the above option of serving the assets from unpkg you would do the following: +If you use a CDN for hosting these files you can specify the base url of your assets. To recreate the above option of serving the assets from our CDN you would do the following: ```ts +import { getDefaultCdnBaseUrl } from 'tldraw' + const assetUrls = getAssetUrls({ - baseUrl: 'https://unpkg.com/@tldraw/assets', + baseUrl: getDefaultCdnBaseUrl(), }) ``` diff --git a/apps/examples/src/examples/static-assets/StaticAssetsExample.tsx b/apps/examples/src/examples/static-assets/StaticAssetsExample.tsx index 38e27db15..78a7f68a0 100644 --- a/apps/examples/src/examples/static-assets/StaticAssetsExample.tsx +++ b/apps/examples/src/examples/static-assets/StaticAssetsExample.tsx @@ -22,5 +22,5 @@ export default function StaticAssetsExample() { /** These assets are stored in the /public folder of this Vite project, but this could be any URL. -By default, the Tldraw component will pull in assets from the @tldraw/assets package on Unpkg. +By default, the Tldraw component will pull in assets from tldraw's asset CDN. */ diff --git a/package.json b/package.json index eedc83815..7e35f74d5 100644 --- a/package.json +++ b/package.json @@ -120,6 +120,7 @@ "@sentry/cli": "^2.25.0", "@yarnpkg/types": "^4.0.0", "cross-env": "^7.0.3", + "mime": "^4.0.3", "purgecss": "^5.0.0", "svgo": "^3.0.2" } diff --git a/packages/tldraw/api-report.md b/packages/tldraw/api-report.md index 306004a20..680c612de 100644 --- a/packages/tldraw/api-report.md +++ b/packages/tldraw/api-report.md @@ -887,6 +887,9 @@ export function getAssetFromIndexedDb({ persistenceKey, assetId, }: { persistenceKey: string; }): Promise; +// @public (undocumented) +export function getDefaultCdnBaseUrl(): string; + // @public export function getEmbedInfo(inputUrl: string): TLEmbedResult; diff --git a/packages/tldraw/setupTests.js b/packages/tldraw/setupTests.js index 68f880da8..665c96602 100644 --- a/packages/tldraw/setupTests.js +++ b/packages/tldraw/setupTests.js @@ -38,7 +38,7 @@ Object.defineProperty(global.URL, 'createObjectURL', { const { version } = require('./package.json') window.fetch = async (input, init) => { - if (input === `https://unpkg.com/@tldraw/assets@${version}/translations/en.json`) { + if (input === `https://cdn.tldraw.com/${version}/translations/en.json`) { const json = await import('@tldraw/assets/translations/main.json') return { ok: true, diff --git a/packages/tldraw/src/index.ts b/packages/tldraw/src/index.ts index b8b96d6cb..ffa6dcd85 100644 --- a/packages/tldraw/src/index.ts +++ b/packages/tldraw/src/index.ts @@ -404,6 +404,7 @@ export { exportAs, type TLExportType } from './lib/utils/export/exportAs' export { fitFrameToContent, removeFrame } from './lib/utils/frames/frames' export { defaultEditorAssetUrls, + getDefaultCdnBaseUrl, setDefaultEditorAssetUrls, type TLEditorAssetUrls, } from './lib/utils/static-assets/assetUrls' diff --git a/packages/tldraw/src/lib/ui/assetUrls.ts b/packages/tldraw/src/lib/ui/assetUrls.ts index 0ffb79256..222175b45 100644 --- a/packages/tldraw/src/lib/ui/assetUrls.ts +++ b/packages/tldraw/src/lib/ui/assetUrls.ts @@ -1,6 +1,9 @@ import { EMBED_DEFINITIONS, LANGUAGES, RecursivePartial } from '@tldraw/editor' -import { version } from '../ui/version' -import { TLEditorAssetUrls, defaultEditorAssetUrls } from '../utils/static-assets/assetUrls' +import { + TLEditorAssetUrls, + defaultEditorAssetUrls, + getDefaultCdnBaseUrl, +} from '../utils/static-assets/assetUrls' import { TLUiIconType, iconTypes } from './icon-types' /** @public */ @@ -16,21 +19,18 @@ export type TLUiAssetUrlOverrides = RecursivePartial export let defaultUiAssetUrls: TLUiAssetUrls = { ...defaultEditorAssetUrls, icons: Object.fromEntries( - iconTypes.map((name) => [ - name, - `https://unpkg.com/@tldraw/assets@${version}/icons/icon/${name}.svg`, - ]) + iconTypes.map((name) => [name, `${getDefaultCdnBaseUrl()}/icons/icon/${name}.svg`]) ) as Record, translations: Object.fromEntries( LANGUAGES.map((lang) => [ lang.locale, - `https://unpkg.com/@tldraw/assets@${version}/translations/${lang.locale}.json`, + `${getDefaultCdnBaseUrl()}/translations/${lang.locale}.json`, ]) ) as Record<(typeof LANGUAGES)[number]['locale'], string>, embedIcons: Object.fromEntries( EMBED_DEFINITIONS.map((def) => [ def.type, - `https://unpkg.com/@tldraw/assets@${version}/embed-icons/${def.type}.png`, + `${getDefaultCdnBaseUrl()}/embed-icons/${def.type}.png`, ]) ) as Record<(typeof EMBED_DEFINITIONS)[number]['type'], string>, } diff --git a/packages/tldraw/src/lib/utils/static-assets/assetUrls.ts b/packages/tldraw/src/lib/utils/static-assets/assetUrls.ts index 64ec3885c..f7c1d21c6 100644 --- a/packages/tldraw/src/lib/utils/static-assets/assetUrls.ts +++ b/packages/tldraw/src/lib/utils/static-assets/assetUrls.ts @@ -2,6 +2,14 @@ import { RecursivePartial } from '@tldraw/editor' import { useMemo } from 'react' import { version } from '../../ui/version' +/** @internal */ +const CDN_BASE_URL = 'https://cdn.tldraw.com' + +/** @public */ +export function getDefaultCdnBaseUrl() { + return `${CDN_BASE_URL}/${version}` +} + /** @public */ export interface TLEditorAssetUrls { fonts: { @@ -15,10 +23,10 @@ export interface TLEditorAssetUrls { /** @public */ export let defaultEditorAssetUrls: TLEditorAssetUrls = { fonts: { - draw: `https://unpkg.com/@tldraw/assets@${version}/fonts/Shantell_Sans-Tldrawish.woff2`, - serif: `https://unpkg.com/@tldraw/assets@${version}/fonts/IBMPlexSerif-Medium.woff2`, - sansSerif: `https://unpkg.com/@tldraw/assets@${version}/fonts/IBMPlexSans-Medium.woff2`, - monospace: `https://unpkg.com/@tldraw/assets@${version}/fonts/IBMPlexMono-Medium.woff2`, + draw: `${getDefaultCdnBaseUrl()}/fonts/Shantell_Sans-Tldrawish.woff2`, + serif: `${getDefaultCdnBaseUrl()}/fonts/IBMPlexSerif-Medium.woff2`, + sansSerif: `${getDefaultCdnBaseUrl()}/fonts/IBMPlexSans-Medium.woff2`, + monospace: `${getDefaultCdnBaseUrl()}/fonts/IBMPlexMono-Medium.woff2`, }, } diff --git a/scripts/upload-static-assets.ts b/scripts/upload-static-assets.ts index d9169fd05..25da4507e 100644 --- a/scripts/upload-static-assets.ts +++ b/scripts/upload-static-assets.ts @@ -1,5 +1,6 @@ import { PutObjectCommand, S3Client } from '@aws-sdk/client-s3' import fs from 'fs' +import mime from 'mime' import path from 'path' import { makeEnv } from './lib/makeEnv' @@ -20,10 +21,12 @@ const R2 = new S3Client({ async function uploadFile(key: string, fullPath: string) { const fileStream = fs.createReadStream(fullPath) + const contentType = mime.getType(fullPath) ?? 'application/octet-stream' const uploadParams = { Bucket: R2_BUCKET, Key: key, Body: fileStream, + ContentType: contentType, } await R2.send(new PutObjectCommand(uploadParams)) } diff --git a/yarn.lock b/yarn.lock index 74b980ca7..b0bfeeeb4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6185,6 +6185,7 @@ __metadata: lazyrepo: "npm:0.0.0-alpha.27" license-report: "npm:^6.5.0" lint-staged: "npm:>=10" + mime: "npm:^4.0.3" prettier: "npm:^3.0.3" prettier-plugin-organize-imports: "npm:^3.2.3" purgecss: "npm:^5.0.0" @@ -17071,12 +17072,12 @@ __metadata: languageName: node linkType: hard -"mime@npm:^4.0.0": - version: 4.0.1 - resolution: "mime@npm:4.0.1" +"mime@npm:^4.0.0, mime@npm:^4.0.3": + version: 4.0.3 + resolution: "mime@npm:4.0.3" bin: mime: bin/cli.js - checksum: 4598030457488c240a4ba30561a619cfb627f96271ecced5d715eb5c44d33105e3f28d28fe46d72eeadb78d7de5aeb1f8e62d448c14b0e518a7ace76d2af5f2d + checksum: fdabb0f0aecd34c11be108e7a73d74a9f672bee8586d3353834ebebedfb8420bdf932efad11a343de994978504024dab5b7846fc4cae4b1855b571a01d27ee6e languageName: node linkType: hard