fix single text element, unique id and tests

This commit is contained in:
Aakansha Doshi 2023-05-25 14:12:01 +05:30
parent 6c41e507db
commit 1c291f8b3d
4 changed files with 60 additions and 23 deletions

View file

@ -135,23 +135,20 @@ export const loadSceneOrLibraryFromBlob = async (
try {
const data = JSON.parse(contents);
if (isValidExcalidrawData(data)) {
const excaldrawElements = convertToExcalidrawElements(
data.elements || [],
);
return {
type: MIME_TYPES.excalidraw,
data: restore(
{
elements: clearElementsForExport(
convertToExcalidrawElements(data.elements || []),
),
elements: clearElementsForExport(excaldrawElements),
appState: {
theme: localAppState?.theme,
fileHandle: fileHandle || blob.handle || null,
...cleanAppStateForExport(data.appState || {}),
...(localAppState
? calculateScrollCenter(
convertToExcalidrawElements(data.elements || []),
localAppState,
null,
)
? calculateScrollCenter(excaldrawElements, localAppState, null)
: {}),
},
files: data.files,

View file

@ -1,4 +1,9 @@
import { TEXT_ALIGN, VERTICAL_ALIGN } from "../constants";
import {
DEFAULT_FONT_FAMILY,
DEFAULT_FONT_SIZE,
TEXT_ALIGN,
VERTICAL_ALIGN,
} from "../constants";
import {
newElement,
newLinearElement,
@ -6,8 +11,17 @@ import {
} from "../element";
import { bindLinearElement } from "../element/binding";
import { mutateElement } from "../element/mutateElement";
import { ElementConstructorOpts, newTextElement } from "../element/newElement";
import { VALID_CONTAINER_TYPES } from "../element/textElement";
import {
ElementConstructorOpts,
newTextElement,
regenerateId,
} from "../element/newElement";
import {
VALID_CONTAINER_TYPES,
getDefaultLineHeight,
measureText,
normalizeText,
} from "../element/textElement";
import {
ExcalidrawBindableElement,
ExcalidrawElement,
@ -18,8 +32,8 @@ import {
TextAlign,
VerticalAlign,
} from "../element/types";
import { randomId } from "../random";
import { MarkOptional } from "../utility-types";
import { getFontString } from "../utils";
import { ImportedDataState } from "./types";
export const ELEMENTS_SUPPORTING_PROGRAMMATIC_API = [
@ -212,14 +226,20 @@ const excalidrawElements = (() => {
};
const clear = () => {
res.length = 0;
elementMap.clear();
};
const get = () => {
return res;
};
const hasElementWithId = (id: string) => {
const index = elementMap.get(id);
return index !== undefined && index >= 0;
};
return {
push,
clear,
get,
hasElementWithId,
};
})();
@ -234,6 +254,15 @@ export const convertToExcalidrawElements = (
if (!element) {
return;
}
let elementId = element.id || regenerateId(null);
// To make sure every element has a unique id
while (excalidrawElements.hasElementWithId(elementId)) {
elementId = regenerateId(elementId);
}
const elementWithid = { ...element, id: elementId };
if (!ELEMENTS_SUPPORTING_PROGRAMMATIC_API.includes(element.type)) {
excalidrawElements.push(element as ExcalidrawElement);
@ -242,7 +271,7 @@ export const convertToExcalidrawElements = (
//@ts-ignore
if (VALID_CONTAINER_TYPES.has(element.type) && element?.label?.text) {
//@ts-ignore
let [container, text] = bindTextToContainer(element, element.label);
let [container, text] = bindTextToContainer(elementWithid, element.label);
excalidrawElements.push(container);
excalidrawElements.push(text);
@ -263,15 +292,28 @@ export const convertToExcalidrawElements = (
} else {
let excalidrawElement;
if (element.type === "text") {
excalidrawElement = newTextElement({
...element,
});
const fontFamily = element?.fontFamily || DEFAULT_FONT_FAMILY;
const fontSize = element?.fontSize || DEFAULT_FONT_SIZE;
const lineHeight =
element?.lineHeight || getDefaultLineHeight(fontFamily);
const text = element.text ?? "";
const normalizedText = normalizeText(text);
const metrics = measureText(
normalizedText,
getFontString({ fontFamily, fontSize }),
lineHeight,
);
excalidrawElement = {
width: metrics.width,
height: metrics.height,
...elementWithid,
};
excalidrawElements.push(excalidrawElement);
excalidrawElements.push(excalidrawElement as ExcalidrawTextElement);
} else if (element.type === "arrow" || element.type === "line") {
const { linearElement, startBoundElement, endBoundElement } =
//@ts-ignore
bindLinearElementToElement(element);
bindLinearElementToElement(elementWithid);
excalidrawElements.push(linearElement);
excalidrawElements.push(startBoundElement);
excalidrawElements.push(endBoundElement);
@ -287,8 +329,7 @@ export const convertToExcalidrawElements = (
}
} else {
excalidrawElement = {
...element,
id: element.id || randomId(),
...elementWithid,
width:
element?.width ||
(ELEMENTS_SUPPORTING_PROGRAMMATIC_API.includes(element.type)

View file

@ -18,7 +18,6 @@ import type { cleanAppStateForExport } from "../appState";
import { VERSIONS } from "../constants";
import { MarkOptional } from "../utility-types";
import { ElementConstructorOpts } from "../element/newElement";
import { ELEMENTS_SUPPORTING_PROGRAMMATIC_API } from "./transform";
export interface ExportedDataState {
type: string;
@ -62,7 +61,7 @@ export interface ImportedDataState {
type: "text";
text: string;
id?: ExcalidrawTextElement["id"];
} & ElementConstructorOpts)
} & Partial<ExcalidrawTextElement>)
| ({
type: ExcalidrawLinearElement["type"];
x: number;

View file

@ -471,7 +471,7 @@ export const deepCopyElement = <T extends ExcalidrawElement>(
* utility wrapper to generate new id. In test env it reuses the old + postfix
* for test assertions.
*/
const regenerateId = (
export const regenerateId = (
/** supply null if no previous id exists */
previousId: string | null,
) => {