Merge remote-tracking branch 'origin/release' into danieljgeiger-mathjax-maint-stage

This commit is contained in:
Daniel J. Geiger 2024-05-08 18:41:06 -05:00
commit 81e3dd5406
348 changed files with 57065 additions and 25106 deletions

View file

@ -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,
),
);
}