Skip to content

🐛 Rich text editor loses image dimensions on re-edit #1030

@mrjbj

Description

@mrjbj

Description

When inserting an image into any rich text field (email footer, event description, pre-checkout message, etc.) and resizing it using the drag handles, the dimensions are saved correctly on the first save. However, when reopening the editor to make any text edit — even without touching the image — the image reverts to its original (large) size and the resize handles no longer appear.

Steps to Reproduce

  1. Go to Event Settings → any rich text field (e.g., Email Footer)
  2. Insert an image using the image toolbar button
  3. Click the image — resize handles and a dashed border appear
  4. Drag a corner handle to resize the image (e.g., to 100px wide)
  5. Save the page — the image displays at the resized dimensions ✅
  6. Reopen the same settings page and click into the text field to make any edit
  7. The image is now displayed at its original full size, with no resize handles

Root Cause

The Editor component (frontend/src/components/common/Editor/index.tsx) registers both the standard @tiptap/extension-image (Image) and the custom ImageResize extension:

extensions: [
    // ...
    Image,          // standard tiptap image extension
    ImageResize,    // custom extension with resize handles
    // ...
],

Both extensions match <img> tags during HTML parsing. When saved content is reloaded via editor.commands.setContent(value), the standard Image extension can claim the <img> node before ImageResize does. Since Image doesn't preserve the style attribute (which holds the width), the sizing is lost. Additionally, the resize handles (added by ImageResize's addNodeView) don't appear because the node is typed as image rather than imageResize.

Suggested Fix

Remove the standard Image import from the editor extensions, since ImageResize already extends it:

- import Image from '@tiptap/extension-image';
  // ...
  extensions: [
      // ...
-     Image,
      ImageResize,
      // ...
  ],

ImageResize is defined as Image.extend({ name: 'imageResize', ... }) so it already provides all Image functionality. Having both registered causes the conflict.

Alternatively, if both are needed for some reason, give ImageResize higher parsing priority or ensure Image doesn't match when ImageResize is present.

Environment

  • hi.events Docker image: daveearley/hi.events-all-in-one:latest (pulled ~Feb 1, 2026)
  • @tiptap/extension-image: v2.11.5
  • @tiptap/core: v2.7.0
  • Browser: Chrome & Safari (reproducible in both)

Evidence from Database

Saved HTML after successful resize:

<img src="..." style="width: 101px; height: auto; cursor: pointer; margin-bottom: 0px; display: block;">

Same field after re-editing and saving without touching the image:

<img src="...">

The style attribute (and thus the width) is stripped on re-save.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions