Files
webmail/components/email/styled-block-attributes.ts
T
dealerweb 3d1bdf0943 fix: let a double-click unlock the embedded signature for editing
Since the signature became a verbatim, non-editable atom (#476), there
was no way to edit it in the composer at all (#822) - the styling
guarantee silently cost the editability #329 had established. Keep the
atom as the default so branded signatures still survive 1:1, and let an
explicit gesture opt out: double-clicking the block dissolves it into
regular editable content at the same position. Double-clicks that land
on a link are ignored (the click is working the link), and Enter on the
selected block keeps ProseMirror's default create-paragraph-after
behaviour.

Faithfulness of the dissolved signature:
- Leaf <div> lines become paragraphs; only vertical margins the line
  does not declare are reset to 0 (how a div actually renders), so
  explicit spacing and indents survive. Divs carrying hr/pre and other
  non-line blocks are left to the schema parse.
- Inherited styles (font, color, ...) on wrapper divs - which have no
  schema node and would be dropped - are hoisted onto the generated
  line paragraphs, the line's own declarations winning.
- The content is parsed as a CLOSED document via the schema DOMParser
  and spliced in with one transaction; insertContentAt fits an open
  slice, which can split text runs at hard breaks and turned <br>-lined
  signatures into one spaced paragraph per line.

The bracketing data-signature-block markers live outside the atom and
stay put, so the identity-switch splice and the send path's
already-embedded detection keep working on unlocked content, and
switching identities re-embeds a fresh locked block. Undo restores the
atom. A translated tooltip on the block makes the gesture discoverable.
2026-08-18 17:31:47 +02:00

29 lines
1.2 KiB
TypeScript

// Pasted email content (signatures, replies, quoted text) commonly carries
// inline styles on block elements. StarterKit's default Paragraph/Heading
// drop unknown attributes; the composer extends them with these so `style`,
// `class` and the signature range marker round-trip the editor. Kept in its
// own module so tests can build the exact composer paragraph instead of
// hand-copying (and silently drifting from) this config.
export const styledBlockAttributes = {
style: {
default: null as string | null,
parseHTML: (el: HTMLElement) => el.getAttribute("style"),
renderHTML: (attrs: Record<string, string | null>) =>
attrs.style ? { style: attrs.style } : {},
},
class: {
default: null as string | null,
parseHTML: (el: HTMLElement) => el.getAttribute("class"),
renderHTML: (attrs: Record<string, string | null>) =>
attrs.class ? { class: attrs.class } : {},
},
"data-signature-block": {
default: null as string | null,
parseHTML: (el: HTMLElement) => el.getAttribute("data-signature-block"),
renderHTML: (attrs: Record<string, string | null>) =>
attrs["data-signature-block"]
? { "data-signature-block": attrs["data-signature-block"] }
: {},
},
};