From 7b51a6ac5496a4b000ac90731168754efc22dd84 Mon Sep 17 00:00:00 2001 From: Ryan Di Date: Fri, 20 Mar 2026 00:26:08 +1100 Subject: [PATCH] schema: add payload schemaVersion plumbing --- packages/excalidraw/clipboard.ts | 11 ++++++++++- packages/excalidraw/data/json.ts | 2 ++ packages/excalidraw/data/schema.ts | 5 +++++ packages/excalidraw/data/types.ts | 2 ++ .../tests/__snapshots__/export.test.tsx.snap | 2 +- 5 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 packages/excalidraw/data/schema.ts diff --git a/packages/excalidraw/clipboard.ts b/packages/excalidraw/clipboard.ts index 6033b857af..e7011a9b1d 100644 --- a/packages/excalidraw/clipboard.ts +++ b/packages/excalidraw/clipboard.ts @@ -40,9 +40,11 @@ import type { FileSystemHandle } from "./data/filesystem"; import type { Spreadsheet } from "./charts"; import type { BinaryFiles } from "./types"; +import { SCHEMA_VERSIONS } from "./data/schema"; type ElementsClipboard = { type: typeof EXPORT_DATA_TYPES.excalidrawClipboard; + schemaVersion: number; elements: readonly NonDeletedExcalidrawElement[]; files: BinaryFiles | undefined; }; @@ -53,6 +55,7 @@ export interface ClipboardData { spreadsheet?: Spreadsheet; elements?: readonly ExcalidrawElement[]; files?: BinaryFiles; + schemaVersion?: number; text?: string; mixedContent?: PastedMixedContent; errorMessage?: string; @@ -79,7 +82,11 @@ export const probablySupportsClipboardBlob = const clipboardContainsElements = ( contents: any, -): contents is { elements: ExcalidrawElement[]; files?: BinaryFiles } => { +): contents is { + elements: ExcalidrawElement[]; + files?: BinaryFiles; + schemaVersion?: number; +} => { if ( [ EXPORT_DATA_TYPES.excalidraw, @@ -178,6 +185,7 @@ export const serializeAsClipboardJSON = ({ // select bound text elements when copying const contents: ElementsClipboard = { type: EXPORT_DATA_TYPES.excalidrawClipboard, + schemaVersion: SCHEMA_VERSIONS.latest, elements: elements.map((element) => { if ( getContainingFrame(element, elementsMap) && @@ -572,6 +580,7 @@ export const parseClipboard = async ( return { elements: systemClipboardData.elements, files: systemClipboardData.files, + schemaVersion: systemClipboardData.schemaVersion, text: isPlainPaste ? JSON.stringify(systemClipboardData.elements, null, 2) : undefined, diff --git a/packages/excalidraw/data/json.ts b/packages/excalidraw/data/json.ts index 047a2ccdec..ea3e83b159 100644 --- a/packages/excalidraw/data/json.ts +++ b/packages/excalidraw/data/json.ts @@ -12,6 +12,7 @@ import { cleanAppStateForExport, clearAppStateForDatabase } from "../appState"; import { isImageFileHandle, loadFromBlob } from "./blob"; import { fileOpen, fileSave } from "./filesystem"; +import { SCHEMA_VERSIONS } from "./schema"; import type { AppState, BinaryFiles, LibraryItems } from "../types"; import type { @@ -51,6 +52,7 @@ export const serializeAsJSON = ( const data: ExportedDataState = { type: EXPORT_DATA_TYPES.excalidraw, version: VERSIONS.excalidraw, + schemaVersion: SCHEMA_VERSIONS.latest, source: getExportSource(), elements, appState: diff --git a/packages/excalidraw/data/schema.ts b/packages/excalidraw/data/schema.ts new file mode 100644 index 0000000000..696b64fbf7 --- /dev/null +++ b/packages/excalidraw/data/schema.ts @@ -0,0 +1,5 @@ +export const SCHEMA_VERSIONS = { + initial: 1, + latest: 2, +} as const; + diff --git a/packages/excalidraw/data/types.ts b/packages/excalidraw/data/types.ts index 94947c2b98..b2e149eb0d 100644 --- a/packages/excalidraw/data/types.ts +++ b/packages/excalidraw/data/types.ts @@ -14,6 +14,7 @@ import type { export interface ExportedDataState { type: string; version: number; + schemaVersion: number; source: string; elements: readonly ExcalidrawElement[]; appState: ReturnType; @@ -35,6 +36,7 @@ export type LegacyAppState = { export interface ImportedDataState { type?: string; version?: number; + schemaVersion?: number; source?: string; elements?: readonly ExcalidrawElement[] | null; appState?: Readonly< diff --git a/packages/excalidraw/tests/__snapshots__/export.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/export.test.tsx.snap index 48cc148196..5d9b80e0b0 100644 --- a/packages/excalidraw/tests/__snapshots__/export.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/export.test.tsx.snap @@ -1,7 +1,7 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html exports[`export > export svg-embedded scene > svg-embdedded scene export output 1`] = ` -"eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nHVTS27bMFx1MDAxMN33XHUwMDE0grItXHUwMDEy2UW68C7NXHUwMDA3zVwiXdRcdTAwMDW6KLpgxLE0ME1cdTAwMTLkKLZrXHUwMDE4yDG661x1MDAxNXOEXGZpVTTlRFx1MDAwMlxi8M3vzZvh7kNRlLS1UM6KXHUwMDEyNrVQKJ1Yl1x1MDAxZlx1MDAwM/5cdTAwMDTOo9Fsmsa7N52ro2dLZGdcdTAwMTdcdTAwMTfKcEBrPM0+VVV1XGJcdTAwMDJcdTAwMDUr0OTZ7Vx1MDAxN9+LYlx1MDAxN0+2oFxmoVfRLVx1MDAwMv/rXHUwMDEybCihXHUwMDFihqrhts1ua5TUMjL5PEAtYNNSjlx03SjIXHUwMDAyPTmzhGujjFx1MDAwYlx1MDAxNc8mXHUwMDEw/lT0UdTLxplOy8GHnNDeXG7HzSS/XHUwMDA1KjWnbczOerBa5ajGz57idIS/XHUwMDE3xUWbVoNcdTAwMGaCTVx1MDAwNtRYUSOF5idV6lwiMLT3Mmr7O3FyYlx1MDAwNfdBXFzdKTXAqCVsxmBssa+WXHUwMDE5PIDMXHUwMDE4pOGfYN+MrnN50d/w3CmmWFxi5SFcdFx1MDAxYlxu3qadyIp2VlxuXHUwMDFh1VWol2M/3rPlXHUwMDFiuePesKIv//4+XHUwMDFmjchomuOfQHBaZeidWKFcbppeZimuXHUwMDE0NqHPUsHiaNTcLCHv92AmY5O15nxcdTAwMDI1uFPhjcNcdTAwMDa1UD/epCc6Mt/BXHUwMDFmXGKS6+C4c/g6bPP59DJcdTAwMWH2fMZZl8LaObFebD28Kd5cdTAwMDeUo1ZcdTAwMGZcdTAwMTiBTW1G6MFIuNXiUY11LJ9cdTAwMTDWX07X/2xcdTAwMTG/nng/godOXHUwMDExznnUNfFcdTAwMWWEee5cdTAwMDK/feTHb1x1MDAwM3po/1xua2IoWiJ9