fix: merge existing text with new when pasted (#5856)
* Fix #5855. * fix test * tweak * Add specs * Add more snaps Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
This commit is contained in:
parent
dc97dc30bf
commit
335aff8838
@ -439,7 +439,7 @@ describe("textWysiwyg", () => {
|
|||||||
it("should paste text correctly", async () => {
|
it("should paste text correctly", async () => {
|
||||||
Keyboard.keyPress(KEYS.ENTER);
|
Keyboard.keyPress(KEYS.ENTER);
|
||||||
await new Promise((r) => setTimeout(r, 0));
|
await new Promise((r) => setTimeout(r, 0));
|
||||||
const text = "A quick brown fox jumps over the lazy dog.";
|
let text = "A quick brown fox jumps over the lazy dog.";
|
||||||
|
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
textarea.onpaste({
|
textarea.onpaste({
|
||||||
@ -453,6 +453,23 @@ describe("textWysiwyg", () => {
|
|||||||
await new Promise((cb) => setTimeout(cb, 0));
|
await new Promise((cb) => setTimeout(cb, 0));
|
||||||
textarea.blur();
|
textarea.blur();
|
||||||
expect(textElement.text).toBe(text);
|
expect(textElement.text).toBe(text);
|
||||||
|
|
||||||
|
Keyboard.keyPress(KEYS.ENTER);
|
||||||
|
await new Promise((r) => setTimeout(r, 0));
|
||||||
|
text = "Hello this text should get merged with the existing one";
|
||||||
|
//@ts-ignore
|
||||||
|
textarea.onpaste({
|
||||||
|
preventDefault: () => {},
|
||||||
|
//@ts-ignore
|
||||||
|
clipboardData: {
|
||||||
|
getData: () => text,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await new Promise((cb) => setTimeout(cb, 0));
|
||||||
|
textarea.blur();
|
||||||
|
expect(textElement.text).toMatchInlineSnapshot(
|
||||||
|
`"A quick brown fox jumps over the lazy dog.Hello this text should get merged with the existing one"`,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -905,9 +922,11 @@ describe("textWysiwyg", () => {
|
|||||||
) as HTMLTextAreaElement;
|
) as HTMLTextAreaElement;
|
||||||
await new Promise((r) => setTimeout(r, 0));
|
await new Promise((r) => setTimeout(r, 0));
|
||||||
const font = "20px Cascadia, width: Segoe UI Emoji" as FontString;
|
const font = "20px Cascadia, width: Segoe UI Emoji" as FontString;
|
||||||
|
let text =
|
||||||
|
"Wikipedia is hosted by the Wikimedia Foundation, a non-profit organization that also hosts a range of other projects.";
|
||||||
|
|
||||||
const wrappedText = textElementUtils.wrapText(
|
let wrappedText = textElementUtils.wrapText(
|
||||||
"Wikipedia is hosted by the Wikimedia Foundation, a non-profit organization that also hosts a range of other projects.",
|
text,
|
||||||
font,
|
font,
|
||||||
getMaxContainerWidth(rectangle),
|
getMaxContainerWidth(rectangle),
|
||||||
);
|
);
|
||||||
@ -926,17 +945,94 @@ describe("textWysiwyg", () => {
|
|||||||
preventDefault: () => {},
|
preventDefault: () => {},
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
clipboardData: {
|
clipboardData: {
|
||||||
getData: () =>
|
getData: () => text,
|
||||||
"Wikipedia is hosted by the Wikimedia Foundation, a non-profit organization that also hosts a range of other projects.",
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await new Promise((cb) => setTimeout(cb, 0));
|
await new Promise((cb) => setTimeout(cb, 0));
|
||||||
editor.blur();
|
editor.blur();
|
||||||
expect(rectangle.width).toBe(110);
|
expect(rectangle.width).toBe(100);
|
||||||
expect(rectangle.height).toBe(210);
|
expect(rectangle.height).toBe(210);
|
||||||
const textElement = h.elements[1] as ExcalidrawTextElement;
|
expect((h.elements[1] as ExcalidrawTextElement).text)
|
||||||
expect(textElement.text).toBe(wrappedText);
|
.toMatchInlineSnapshot(`
|
||||||
|
"Wikipedi
|
||||||
|
a is
|
||||||
|
hosted
|
||||||
|
by the
|
||||||
|
Wikimedi
|
||||||
|
a
|
||||||
|
Foundati
|
||||||
|
on, a
|
||||||
|
non-prof
|
||||||
|
it
|
||||||
|
organiza
|
||||||
|
tion
|
||||||
|
that
|
||||||
|
also
|
||||||
|
hosts a
|
||||||
|
range of
|
||||||
|
other
|
||||||
|
projects
|
||||||
|
."
|
||||||
|
`);
|
||||||
|
expect(
|
||||||
|
(h.elements[1] as ExcalidrawTextElement).originalText,
|
||||||
|
).toMatchInlineSnapshot(
|
||||||
|
`"Wikipedia is hosted by the Wikimedia Foundation, a non-profit organization that also hosts a range of other projects."`,
|
||||||
|
);
|
||||||
|
|
||||||
|
text = "Hello this text should get merged with the existing one";
|
||||||
|
wrappedText = textElementUtils.wrapText(
|
||||||
|
text,
|
||||||
|
font,
|
||||||
|
getMaxContainerWidth(rectangle),
|
||||||
|
);
|
||||||
|
//@ts-ignore
|
||||||
|
editor.onpaste({
|
||||||
|
preventDefault: () => {},
|
||||||
|
//@ts-ignore
|
||||||
|
clipboardData: {
|
||||||
|
getData: () => text,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await new Promise((cb) => setTimeout(cb, 0));
|
||||||
|
editor.blur();
|
||||||
|
expect((h.elements[1] as ExcalidrawTextElement).text)
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
"Wikipedi
|
||||||
|
a is
|
||||||
|
hosted
|
||||||
|
by the
|
||||||
|
Wikimedi
|
||||||
|
a
|
||||||
|
Foundati
|
||||||
|
on, a
|
||||||
|
non-prof
|
||||||
|
it
|
||||||
|
organiza
|
||||||
|
tion
|
||||||
|
that
|
||||||
|
also
|
||||||
|
hosts a
|
||||||
|
range of
|
||||||
|
other
|
||||||
|
projects
|
||||||
|
.Hello
|
||||||
|
this
|
||||||
|
text
|
||||||
|
should
|
||||||
|
get
|
||||||
|
merged
|
||||||
|
with the
|
||||||
|
existing
|
||||||
|
one"
|
||||||
|
`);
|
||||||
|
expect(
|
||||||
|
(h.elements[1] as ExcalidrawTextElement).originalText,
|
||||||
|
).toMatchInlineSnapshot(
|
||||||
|
`"Wikipedia is hosted by the Wikimedia Foundation, a non-profit organization that also hosts a range of other projects.Hello this text should get merged with the existing one"`,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -284,20 +284,30 @@ export const textWysiwyg = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const data = normalizeText(clipboardData.text);
|
const data = normalizeText(clipboardData.text);
|
||||||
|
if (!data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const text = editable.value;
|
||||||
|
const start = Math.min(editable.selectionStart, editable.selectionEnd);
|
||||||
|
const end = Math.max(editable.selectionStart, editable.selectionEnd);
|
||||||
|
const newText = `${text.substring(0, start)}${data}${text.substring(
|
||||||
|
end,
|
||||||
|
)}`;
|
||||||
|
|
||||||
const container = getContainerElement(element);
|
const container = getContainerElement(element);
|
||||||
|
|
||||||
const font = getFontString({
|
const font = getFontString({
|
||||||
fontSize: app.state.currentItemFontSize,
|
fontSize: app.state.currentItemFontSize,
|
||||||
fontFamily: app.state.currentItemFontFamily,
|
fontFamily: app.state.currentItemFontFamily,
|
||||||
});
|
});
|
||||||
const wrappedText = container
|
|
||||||
? wrapText(data, font, getMaxContainerWidth(container))
|
|
||||||
: data;
|
|
||||||
|
|
||||||
|
const wrappedText = container
|
||||||
|
? wrapText(newText, font, getMaxContainerWidth(container))
|
||||||
|
: newText;
|
||||||
const dimensions = measureText(wrappedText, font);
|
const dimensions = measureText(wrappedText, font);
|
||||||
editable.style.height = `${dimensions.height}px`;
|
editable.style.height = `${dimensions.height}px`;
|
||||||
|
onChange(newText);
|
||||||
onChange(wrappedText);
|
|
||||||
};
|
};
|
||||||
editable.oninput = () => {
|
editable.oninput = () => {
|
||||||
const updatedTextElement = Scene.getScene(element)?.getElement(
|
const updatedTextElement = Scene.getScene(element)?.getElement(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user