diff --git a/components/email/__tests__/compose-format.test.ts b/components/email/__tests__/compose-format.test.ts index 322c4e771..53b34f970 100644 --- a/components/email/__tests__/compose-format.test.ts +++ b/components/email/__tests__/compose-format.test.ts @@ -117,6 +117,17 @@ describe('switching identity swaps the signature', () => { .toBe(dom(`
Hi
${embed(other)}original`)); }); + it('keeps text typed on the line under the signature', () => { + const typedBelow = embed(identity).replace( + ``, + `
P.S. see you
`, + ); + expect(replaceEmbeddedSignature(`Hi
${typedBelow}`, embed(none))) + .toBe('Hi
P.S. see you
'); + expect(replaceEmbeddedSignature(`Hi
${typedBelow}`, embed(other))) + .toBe(dom(`Hi
${embed(other)}P.S. see you
`)); + }); + it('adds a signature at the end when there is no quote', () => { expect(replaceEmbeddedSignature('Hi
', embed(other))).toBe(dom(`Hi
${embed(other)}`)); }); diff --git a/components/email/compose-format.ts b/components/email/compose-format.ts index 7a0190dad..4cd9987a0 100644 --- a/components/email/compose-format.ts +++ b/components/email/compose-format.ts @@ -89,8 +89,17 @@ export function removeSignatureRange( if (!removeUntil && isQuoteBoundary(next)) break; cursor = next; } - const insertBefore = toRemove[toRemove.length - 1]?.nextSibling ?? null; + let insertBefore = toRemove[toRemove.length - 1]?.nextSibling ?? null; toRemove.forEach((node) => parent.removeChild(node)); + // The end marker is the empty line under the signature, so a click below + // the signature puts the caret there. Text typed into it is the user's, + // not part of the signature: keep it as an ordinary paragraph after it. + if (removeUntil && removeUntil.textContent?.trim()) { + const kept = removeUntil.cloneNode(true) as Element; + kept.removeAttribute(SIGNATURE_RANGE_MARKER); + parent.insertBefore(kept, insertBefore); + insertBefore = kept; + } return { parent, insertBefore }; }