mirror of
https://github.com/docmost/docmost.git
synced 2026-05-07 06:23:06 +08:00
fix: image fallback regression (#1989)
* fix: image fallback regression * fix image preview on upload * fix image loading
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
max-width: 100%;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
animation: pulse 1.2s ease-in-out infinite;
|
animation: pulse 1.2s ease-in-out infinite;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Node, mergeAttributes, ResizableNodeView } from "@tiptap/core";
|
import { Node, mergeAttributes, ResizableNodeView } from "@tiptap/core";
|
||||||
import type { ResizableNodeViewDirection } from "@tiptap/core";
|
import type { ResizableNodeViewDirection } from "@tiptap/core";
|
||||||
import { ReactNodeViewRenderer } from "@tiptap/react";
|
import { ReactNodeViewRenderer } from "@tiptap/react";
|
||||||
|
import { normalizeFileUrl } from "./media-utils";
|
||||||
|
|
||||||
export type DrawioResizeOptions = {
|
export type DrawioResizeOptions = {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
@@ -223,7 +224,7 @@ export const Drawio = Node.create<DrawioOptions>({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const el = document.createElement("img");
|
const el = document.createElement("img");
|
||||||
el.src = node.attrs.src;
|
el.src = normalizeFileUrl(node.attrs.src);
|
||||||
el.alt = node.attrs.title || "";
|
el.alt = node.attrs.title || "";
|
||||||
el.style.display = "block";
|
el.style.display = "block";
|
||||||
el.style.maxWidth = "100%";
|
el.style.maxWidth = "100%";
|
||||||
@@ -259,7 +260,7 @@ export const Drawio = Node.create<DrawioOptions>({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (updatedNode.attrs.src !== currentNode.attrs.src) {
|
if (updatedNode.attrs.src !== currentNode.attrs.src) {
|
||||||
el.src = updatedNode.attrs.src || "";
|
el.src = normalizeFileUrl(updatedNode.attrs.src);
|
||||||
}
|
}
|
||||||
|
|
||||||
const w = updatedNode.attrs.width;
|
const w = updatedNode.attrs.width;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Node, mergeAttributes, ResizableNodeView } from "@tiptap/core";
|
import { Node, mergeAttributes, ResizableNodeView } from "@tiptap/core";
|
||||||
import type { ResizableNodeViewDirection } from "@tiptap/core";
|
import type { ResizableNodeViewDirection } from "@tiptap/core";
|
||||||
import { ReactNodeViewRenderer } from "@tiptap/react";
|
import { ReactNodeViewRenderer } from "@tiptap/react";
|
||||||
|
import { normalizeFileUrl } from "./media-utils";
|
||||||
|
|
||||||
export type ExcalidrawResizeOptions = {
|
export type ExcalidrawResizeOptions = {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
@@ -223,7 +224,7 @@ export const Excalidraw = Node.create<ExcalidrawOptions>({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const el = document.createElement("img");
|
const el = document.createElement("img");
|
||||||
el.src = node.attrs.src;
|
el.src = normalizeFileUrl(node.attrs.src);
|
||||||
el.alt = node.attrs.title || "";
|
el.alt = node.attrs.title || "";
|
||||||
el.style.display = "block";
|
el.style.display = "block";
|
||||||
el.style.maxWidth = "100%";
|
el.style.maxWidth = "100%";
|
||||||
@@ -259,7 +260,7 @@ export const Excalidraw = Node.create<ExcalidrawOptions>({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (updatedNode.attrs.src !== currentNode.attrs.src) {
|
if (updatedNode.attrs.src !== currentNode.attrs.src) {
|
||||||
el.src = updatedNode.attrs.src || "";
|
el.src = normalizeFileUrl(updatedNode.attrs.src);
|
||||||
}
|
}
|
||||||
|
|
||||||
const w = updatedNode.attrs.width;
|
const w = updatedNode.attrs.width;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
Range,
|
Range,
|
||||||
ResizableNodeView,
|
ResizableNodeView,
|
||||||
} from "@tiptap/core";
|
} from "@tiptap/core";
|
||||||
|
import { normalizeFileUrl } from "../media-utils";
|
||||||
import type { ResizableNodeViewDirection } from "@tiptap/core";
|
import type { ResizableNodeViewDirection } from "@tiptap/core";
|
||||||
|
|
||||||
export type ImageResizeOptions = {
|
export type ImageResizeOptions = {
|
||||||
@@ -252,11 +253,18 @@ export const TiptapImage = Image.extend<ImageOptions>({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
el.src = HTMLAttributes.src;
|
el.src = normalizeFileUrl(HTMLAttributes.src);
|
||||||
el.style.display = "block";
|
el.style.display = "block";
|
||||||
el.style.maxWidth = "100%";
|
el.style.maxWidth = "100%";
|
||||||
el.style.borderRadius = "8px";
|
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;
|
let currentNode = node;
|
||||||
|
|
||||||
const nodeView = new ResizableNodeView({
|
const nodeView = new ResizableNodeView({
|
||||||
@@ -287,7 +295,7 @@ export const TiptapImage = Image.extend<ImageOptions>({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (updatedNode.attrs.src !== currentNode.attrs.src) {
|
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) {
|
if (updatedNode.attrs.alt !== currentNode.attrs.alt) {
|
||||||
@@ -352,12 +360,16 @@ export const TiptapImage = Image.extend<ImageOptions>({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide until image loads (official TipTap pattern)
|
// Show skeleton background while image loads from server
|
||||||
dom.style.visibility = "hidden";
|
|
||||||
dom.style.pointerEvents = "none";
|
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 = () => {
|
el.onload = () => {
|
||||||
dom.style.visibility = "";
|
|
||||||
dom.style.pointerEvents = "";
|
dom.style.pointerEvents = "";
|
||||||
|
dom.style.background = "";
|
||||||
};
|
};
|
||||||
|
|
||||||
return nodeView;
|
return nodeView;
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
import { Editor } from "@tiptap/core";
|
import { Editor } from "@tiptap/core";
|
||||||
|
|
||||||
|
export function normalizeFileUrl(src: string): string {
|
||||||
|
if (src && src.startsWith("/files/")) {
|
||||||
|
return "/api" + src;
|
||||||
|
}
|
||||||
|
return src || "";
|
||||||
|
}
|
||||||
|
|
||||||
export type UploadFn = (
|
export type UploadFn = (
|
||||||
file: File,
|
file: File,
|
||||||
editor: Editor,
|
editor: Editor,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { ReactNodeViewRenderer } from "@tiptap/react";
|
import { ReactNodeViewRenderer } from "@tiptap/react";
|
||||||
import { Range, Node, mergeAttributes, ResizableNodeView } from "@tiptap/core";
|
import { Range, Node, mergeAttributes, ResizableNodeView } from "@tiptap/core";
|
||||||
|
import { normalizeFileUrl } from "../media-utils";
|
||||||
import type { ResizableNodeViewDirection } from "@tiptap/core";
|
import type { ResizableNodeViewDirection } from "@tiptap/core";
|
||||||
|
|
||||||
export type VideoResizeOptions = {
|
export type VideoResizeOptions = {
|
||||||
@@ -223,7 +224,7 @@ export const TiptapVideo = Node.create<VideoOptions>({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const el = document.createElement("video");
|
const el = document.createElement("video");
|
||||||
el.src = node.attrs.src;
|
el.src = normalizeFileUrl(node.attrs.src);
|
||||||
el.controls = true;
|
el.controls = true;
|
||||||
el.preload = "metadata";
|
el.preload = "metadata";
|
||||||
el.style.display = "block";
|
el.style.display = "block";
|
||||||
@@ -260,7 +261,7 @@ export const TiptapVideo = Node.create<VideoOptions>({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (updatedNode.attrs.src !== currentNode.attrs.src) {
|
if (updatedNode.attrs.src !== currentNode.attrs.src) {
|
||||||
el.src = updatedNode.attrs.src || "";
|
el.src = normalizeFileUrl(updatedNode.attrs.src);
|
||||||
}
|
}
|
||||||
|
|
||||||
const w = updatedNode.attrs.width;
|
const w = updatedNode.attrs.width;
|
||||||
|
|||||||
Reference in New Issue
Block a user