From bea1637519d9587058eb188cf9be9dae800740f5 Mon Sep 17 00:00:00 2001 From: Philip Okugbe <16838612+Philipinho@users.noreply.github.com> Date: Wed, 4 Mar 2026 11:51:43 +0000 Subject: [PATCH] fix: image fallback regression (#1989) * fix: image fallback regression * fix image preview on upload * fix image loading --- .../components/image/image-view.module.css | 1 + packages/editor-ext/src/lib/drawio.ts | 5 +++-- packages/editor-ext/src/lib/excalidraw.ts | 5 +++-- packages/editor-ext/src/lib/image/image.ts | 22 ++++++++++++++----- packages/editor-ext/src/lib/media-utils.ts | 7 ++++++ packages/editor-ext/src/lib/video/video.ts | 5 +++-- 6 files changed, 34 insertions(+), 11 deletions(-) diff --git a/apps/client/src/features/editor/components/image/image-view.module.css b/apps/client/src/features/editor/components/image/image-view.module.css index 5d02184b..d326ee5a 100644 --- a/apps/client/src/features/editor/components/image/image-view.module.css +++ b/apps/client/src/features/editor/components/image/image-view.module.css @@ -2,6 +2,7 @@ display: flex; justify-content: center; align-items: center; + max-width: 100%; border-radius: 8px; overflow: hidden; animation: pulse 1.2s ease-in-out infinite; diff --git a/packages/editor-ext/src/lib/drawio.ts b/packages/editor-ext/src/lib/drawio.ts index bd42b0e4..3705032c 100644 --- a/packages/editor-ext/src/lib/drawio.ts +++ b/packages/editor-ext/src/lib/drawio.ts @@ -1,6 +1,7 @@ import { Node, mergeAttributes, ResizableNodeView } from "@tiptap/core"; import type { ResizableNodeViewDirection } from "@tiptap/core"; import { ReactNodeViewRenderer } from "@tiptap/react"; +import { normalizeFileUrl } from "./media-utils"; export type DrawioResizeOptions = { enabled: boolean; @@ -223,7 +224,7 @@ export const Drawio = Node.create({ } const el = document.createElement("img"); - el.src = node.attrs.src; + el.src = normalizeFileUrl(node.attrs.src); el.alt = node.attrs.title || ""; el.style.display = "block"; el.style.maxWidth = "100%"; @@ -259,7 +260,7 @@ export const Drawio = Node.create({ } if (updatedNode.attrs.src !== currentNode.attrs.src) { - el.src = updatedNode.attrs.src || ""; + el.src = normalizeFileUrl(updatedNode.attrs.src); } const w = updatedNode.attrs.width; diff --git a/packages/editor-ext/src/lib/excalidraw.ts b/packages/editor-ext/src/lib/excalidraw.ts index f132d37a..51d78362 100644 --- a/packages/editor-ext/src/lib/excalidraw.ts +++ b/packages/editor-ext/src/lib/excalidraw.ts @@ -1,6 +1,7 @@ import { Node, mergeAttributes, ResizableNodeView } from "@tiptap/core"; import type { ResizableNodeViewDirection } from "@tiptap/core"; import { ReactNodeViewRenderer } from "@tiptap/react"; +import { normalizeFileUrl } from "./media-utils"; export type ExcalidrawResizeOptions = { enabled: boolean; @@ -223,7 +224,7 @@ export const Excalidraw = Node.create({ } const el = document.createElement("img"); - el.src = node.attrs.src; + el.src = normalizeFileUrl(node.attrs.src); el.alt = node.attrs.title || ""; el.style.display = "block"; el.style.maxWidth = "100%"; @@ -259,7 +260,7 @@ export const Excalidraw = Node.create({ } if (updatedNode.attrs.src !== currentNode.attrs.src) { - el.src = updatedNode.attrs.src || ""; + el.src = normalizeFileUrl(updatedNode.attrs.src); } const w = updatedNode.attrs.width; diff --git a/packages/editor-ext/src/lib/image/image.ts b/packages/editor-ext/src/lib/image/image.ts index 8798a9bb..46a4d9c3 100644 --- a/packages/editor-ext/src/lib/image/image.ts +++ b/packages/editor-ext/src/lib/image/image.ts @@ -6,6 +6,7 @@ import { Range, ResizableNodeView, } from "@tiptap/core"; +import { normalizeFileUrl } from "../media-utils"; import type { ResizableNodeViewDirection } from "@tiptap/core"; export type ImageResizeOptions = { @@ -252,11 +253,18 @@ export const TiptapImage = Image.extend({ } }); - el.src = HTMLAttributes.src; + el.src = normalizeFileUrl(HTMLAttributes.src); el.style.display = "block"; el.style.maxWidth = "100%"; el.style.borderRadius = "8px"; + if (typeof node.attrs.width === "number" && node.attrs.width > 0) { + el.style.width = `${node.attrs.width}px`; + if (typeof node.attrs.height === "number" && node.attrs.height > 0) { + el.style.height = `${node.attrs.height}px`; + } + } + let currentNode = node; const nodeView = new ResizableNodeView({ @@ -287,7 +295,7 @@ export const TiptapImage = Image.extend({ } if (updatedNode.attrs.src !== currentNode.attrs.src) { - el.src = updatedNode.attrs.src || ""; + el.src = normalizeFileUrl(updatedNode.attrs.src); } if (updatedNode.attrs.alt !== currentNode.attrs.alt) { @@ -352,12 +360,16 @@ export const TiptapImage = Image.extend({ }); } - // Hide until image loads (official TipTap pattern) - dom.style.visibility = "hidden"; + // Show skeleton background while image loads from server dom.style.pointerEvents = "none"; + dom.style.overflow = "hidden"; + dom.style.borderRadius = "8px"; + dom.style.background = + "light-dark(var(--mantine-color-gray-2), var(--mantine-color-dark-6))"; + el.onload = () => { - dom.style.visibility = ""; dom.style.pointerEvents = ""; + dom.style.background = ""; }; return nodeView; diff --git a/packages/editor-ext/src/lib/media-utils.ts b/packages/editor-ext/src/lib/media-utils.ts index 02a4a1d1..d18bcb69 100644 --- a/packages/editor-ext/src/lib/media-utils.ts +++ b/packages/editor-ext/src/lib/media-utils.ts @@ -1,5 +1,12 @@ import { Editor } from "@tiptap/core"; +export function normalizeFileUrl(src: string): string { + if (src && src.startsWith("/files/")) { + return "/api" + src; + } + return src || ""; +} + export type UploadFn = ( file: File, editor: Editor, diff --git a/packages/editor-ext/src/lib/video/video.ts b/packages/editor-ext/src/lib/video/video.ts index a296d13e..9025377e 100644 --- a/packages/editor-ext/src/lib/video/video.ts +++ b/packages/editor-ext/src/lib/video/video.ts @@ -1,5 +1,6 @@ import { ReactNodeViewRenderer } from "@tiptap/react"; import { Range, Node, mergeAttributes, ResizableNodeView } from "@tiptap/core"; +import { normalizeFileUrl } from "../media-utils"; import type { ResizableNodeViewDirection } from "@tiptap/core"; export type VideoResizeOptions = { @@ -223,7 +224,7 @@ export const TiptapVideo = Node.create({ } const el = document.createElement("video"); - el.src = node.attrs.src; + el.src = normalizeFileUrl(node.attrs.src); el.controls = true; el.preload = "metadata"; el.style.display = "block"; @@ -260,7 +261,7 @@ export const TiptapVideo = Node.create({ } if (updatedNode.attrs.src !== currentNode.attrs.src) { - el.src = updatedNode.attrs.src || ""; + el.src = normalizeFileUrl(updatedNode.attrs.src); } const w = updatedNode.attrs.width;