mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
Merge remote-tracking branch 'origin/release' into danieljgeiger-mathjax-maint-stage
This commit is contained in:
commit
81e3dd5406
348 changed files with 57065 additions and 25106 deletions
|
@ -1,19 +1,20 @@
|
|||
import {
|
||||
import type {
|
||||
ExcalidrawElement,
|
||||
ExcalidrawElementType,
|
||||
ExcalidrawSelectionElement,
|
||||
ExcalidrawTextElement,
|
||||
FontFamilyValues,
|
||||
OrderedExcalidrawElement,
|
||||
PointBinding,
|
||||
StrokeRoundness,
|
||||
} from "../element/types";
|
||||
import {
|
||||
import type {
|
||||
AppState,
|
||||
BinaryFiles,
|
||||
LibraryItem,
|
||||
NormalizedZoomValue,
|
||||
} from "../types";
|
||||
import { ImportedDataState, LegacyAppState } from "./types";
|
||||
import type { ImportedDataState, LegacyAppState } from "./types";
|
||||
import {
|
||||
getNonDeletedElements,
|
||||
getNormalizedDimensions,
|
||||
|
@ -26,7 +27,6 @@ import {
|
|||
DEFAULT_FONT_FAMILY,
|
||||
DEFAULT_TEXT_ALIGN,
|
||||
DEFAULT_VERTICAL_ALIGN,
|
||||
PRECEDING_ELEMENT_KEY,
|
||||
FONT_FAMILY,
|
||||
ROUNDNESS,
|
||||
DEFAULT_SIDEBAR,
|
||||
|
@ -37,14 +37,14 @@ import { LinearElementEditor } from "../element/linearElementEditor";
|
|||
import { bumpVersion } from "../element/mutateElement";
|
||||
import { getUpdatedTimestamp, updateActiveTool } from "../utils";
|
||||
import { arrayToMap } from "../utils";
|
||||
import { MarkOptional, Mutable } from "../utility-types";
|
||||
import type { MarkOptional, Mutable } from "../utility-types";
|
||||
import {
|
||||
detectLineHeight,
|
||||
getContainerElement,
|
||||
getDefaultLineHeight,
|
||||
measureTextElement,
|
||||
} from "../element/textElement";
|
||||
import { normalizeLink } from "./url";
|
||||
import { syncInvalidIndices } from "../fractionalIndex";
|
||||
|
||||
type RestoredAppState = Omit<
|
||||
AppState,
|
||||
|
@ -74,7 +74,7 @@ export const AllowedExcalidrawActiveTools: Record<
|
|||
};
|
||||
|
||||
export type RestoredDataState = {
|
||||
elements: ExcalidrawElement[];
|
||||
elements: OrderedExcalidrawElement[];
|
||||
appState: RestoredAppState;
|
||||
files: BinaryFiles;
|
||||
};
|
||||
|
@ -103,8 +103,6 @@ const restoreElementWithProperties = <
|
|||
boundElementIds?: readonly ExcalidrawElement["id"][];
|
||||
/** @deprecated */
|
||||
strokeSharpness?: StrokeRoundness;
|
||||
/** metadata that may be present in elements during collaboration */
|
||||
[PRECEDING_ELEMENT_KEY]?: string;
|
||||
},
|
||||
K extends Pick<T, keyof Omit<Required<T>, keyof ExcalidrawElement>>,
|
||||
>(
|
||||
|
@ -117,14 +115,13 @@ const restoreElementWithProperties = <
|
|||
> &
|
||||
Partial<Pick<ExcalidrawElement, "type" | "x" | "y" | "customData">>,
|
||||
): T => {
|
||||
const base: Pick<T, keyof ExcalidrawElement> & {
|
||||
[PRECEDING_ELEMENT_KEY]?: string;
|
||||
} = {
|
||||
const base: Pick<T, keyof ExcalidrawElement> = {
|
||||
type: extra.type || element.type,
|
||||
// all elements must have version > 0 so getSceneVersion() will pick up
|
||||
// newly added elements
|
||||
version: element.version || 1,
|
||||
versionNonce: element.versionNonce ?? 0,
|
||||
index: element.index ?? null,
|
||||
isDeleted: element.isDeleted ?? false,
|
||||
id: element.id || randomId(),
|
||||
fillStyle: element.fillStyle || DEFAULT_ELEMENT_PROPS.fillStyle,
|
||||
|
@ -171,10 +168,6 @@ const restoreElementWithProperties = <
|
|||
"customData" in extra ? extra.customData : element.customData;
|
||||
}
|
||||
|
||||
if (PRECEDING_ELEMENT_KEY in element) {
|
||||
base[PRECEDING_ELEMENT_KEY] = element[PRECEDING_ELEMENT_KEY];
|
||||
}
|
||||
|
||||
return {
|
||||
...base,
|
||||
...getNormalizedDimensions(base),
|
||||
|
@ -211,7 +204,6 @@ const restoreElement = (
|
|||
: // no element height likely means programmatic use, so default
|
||||
// to a fixed line height
|
||||
getDefaultLineHeight(element.fontFamily));
|
||||
const baseline = measureTextElement(element, { text }).baseline;
|
||||
element = restoreElementWithProperties(element, {
|
||||
fontSize,
|
||||
fontFamily,
|
||||
|
@ -222,7 +214,6 @@ const restoreElement = (
|
|||
originalText: element.originalText || text,
|
||||
|
||||
lineHeight,
|
||||
baseline,
|
||||
});
|
||||
|
||||
// if empty text, mark as deleted. We keep in array
|
||||
|
@ -307,7 +298,7 @@ const restoreElement = (
|
|||
};
|
||||
|
||||
/**
|
||||
* Repairs contaienr element's boundElements array by removing duplicates and
|
||||
* Repairs container element's boundElements array by removing duplicates and
|
||||
* fixing containerId of bound elements if not present. Also removes any
|
||||
* bound elements that do not exist in the elements array.
|
||||
*
|
||||
|
@ -414,30 +405,35 @@ export const restoreElements = (
|
|||
/** NOTE doesn't serve for reconciliation */
|
||||
localElements: readonly ExcalidrawElement[] | null | undefined,
|
||||
opts?: { refreshDimensions?: boolean; repairBindings?: boolean } | undefined,
|
||||
): ExcalidrawElement[] => {
|
||||
): OrderedExcalidrawElement[] => {
|
||||
// used to detect duplicate top-level element ids
|
||||
const existingIds = new Set<string>();
|
||||
const localElementsMap = localElements ? arrayToMap(localElements) : null;
|
||||
const restoredElements = (elements || []).reduce((elements, element) => {
|
||||
// filtering out selection, which is legacy, no longer kept in elements,
|
||||
// and causing issues if retained
|
||||
if (element.type !== "selection" && !isInvisiblySmallElement(element)) {
|
||||
let migratedElement: ExcalidrawElement | null = restoreElement(element);
|
||||
if (migratedElement) {
|
||||
const localElement = localElementsMap?.get(element.id);
|
||||
if (localElement && localElement.version > migratedElement.version) {
|
||||
migratedElement = bumpVersion(migratedElement, localElement.version);
|
||||
}
|
||||
if (existingIds.has(migratedElement.id)) {
|
||||
migratedElement = { ...migratedElement, id: randomId() };
|
||||
}
|
||||
existingIds.add(migratedElement.id);
|
||||
const restoredElements = syncInvalidIndices(
|
||||
(elements || []).reduce((elements, element) => {
|
||||
// filtering out selection, which is legacy, no longer kept in elements,
|
||||
// and causing issues if retained
|
||||
if (element.type !== "selection" && !isInvisiblySmallElement(element)) {
|
||||
let migratedElement: ExcalidrawElement | null = restoreElement(element);
|
||||
if (migratedElement) {
|
||||
const localElement = localElementsMap?.get(element.id);
|
||||
if (localElement && localElement.version > migratedElement.version) {
|
||||
migratedElement = bumpVersion(
|
||||
migratedElement,
|
||||
localElement.version,
|
||||
);
|
||||
}
|
||||
if (existingIds.has(migratedElement.id)) {
|
||||
migratedElement = { ...migratedElement, id: randomId() };
|
||||
}
|
||||
existingIds.add(migratedElement.id);
|
||||
|
||||
elements.push(migratedElement);
|
||||
elements.push(migratedElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
return elements;
|
||||
}, [] as ExcalidrawElement[]);
|
||||
return elements;
|
||||
}, [] as ExcalidrawElement[]),
|
||||
);
|
||||
|
||||
if (!opts?.repairBindings) {
|
||||
return restoredElements;
|
||||
|
@ -462,6 +458,7 @@ export const restoreElements = (
|
|||
refreshTextDimensions(
|
||||
element,
|
||||
getContainerElement(element, restoredElementsMap),
|
||||
restoredElementsMap,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue