From 3a7d9a7c31bea72d16be07304d3506df35a262b1 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 21 Jun 2026 15:42:39 +0000 Subject: [PATCH] fix: disable Milkdown ImageBlock so paste never strands an upload node MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Routing pasted images to the attachment strip wasn't enough — the editor's ImageBlock feature still handled the paste itself and left a stuck "upload in progress" node, since there's no public upload URL for it to resolve to. Turn the feature off entirely. It's the root cause: it's the only thing that registers paste/drop-to-upload. Image *links* still render through the base commonmark schema (a plain ), and pasted image files continue to go to the attachment strip via use-file-input. Drop the now-dead image-block upload/chrome CSS and keep a simple inline-image style. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01QtNQeBpkDJPC9obiB25pV6 --- .../src/features/compose/markdown-editor.css | 26 +++++-------------- .../src/features/compose/markdown-editor.tsx | 17 +++++------- 2 files changed, 12 insertions(+), 31 deletions(-) diff --git a/js/desktop/src/features/compose/markdown-editor.css b/js/desktop/src/features/compose/markdown-editor.css index 7227482..1262acc 100644 --- a/js/desktop/src/features/compose/markdown-editor.css +++ b/js/desktop/src/features/compose/markdown-editor.css @@ -110,26 +110,12 @@ margin-top: 0; } -/* Images come from URLs only (no stable public upload URL), so hide the - * file uploader — the placeholder then just prompts for a link. */ -.llink-crepe - .milkdown - :is(.milkdown-image-block, .milkdown-image-inline) - .placeholder - .uploader { - display: none; -} - -/* Read-only renders the image node view with inert editing chrome — hide it. */ -.llink-crepe:not(.llink-crepe--fill) .milkdown .milkdown-image-block .operation, -.llink-crepe:not(.llink-crepe--fill) - .milkdown - .milkdown-image-block - .image-resize-handle { - display: none; -} - -.llink-crepe .milkdown .milkdown-image-block img { +/* Image *links* render through the base commonmark schema (the ImageBlock + * feature is off — see markdown-editor.tsx). Keep them within the content + * column and softly rounded. */ +.llink-crepe .milkdown .ProseMirror img { + max-width: 100%; + max-height: 420px; border-radius: 8px; } diff --git a/js/desktop/src/features/compose/markdown-editor.tsx b/js/desktop/src/features/compose/markdown-editor.tsx index 43b3e00..fb45e35 100644 --- a/js/desktop/src/features/compose/markdown-editor.tsx +++ b/js/desktop/src/features/compose/markdown-editor.tsx @@ -57,23 +57,18 @@ export function MarkdownEditor({ [Crepe.Feature.BlockEdit]: !readOnly, [Crepe.Feature.Toolbar]: !readOnly, [Crepe.Feature.Placeholder]: !readOnly, - [Crepe.Feature.ImageBlock]: true, + // Off on purpose: file uploads aren't supported, so this feature's + // paste/drop handler would only strand an "upload in progress" node in + // the editor. Image *links* still render through the base commonmark + // schema, and pasted image files are routed to the compose attachment + // strip (see use-file-input). + [Crepe.Feature.ImageBlock]: false, [Crepe.Feature.Latex]: false, [Crepe.Feature.TopBar]: false, [Crepe.Feature.AI]: false, }, featureConfigs: { [Crepe.Feature.Placeholder]: { text: placeholder ?? '' }, - // Images come from URLs only (e.g. pasted markdown) — there is no - // stable public upload URL, so the file uploader is hidden in CSS and - // onUpload rejects in case a file ever reaches it anyway (the default - // would serialize an ephemeral blob: URL into the message). - [Crepe.Feature.ImageBlock]: { - blockUploadPlaceholderText: 'Paste an image link…', - inlineUploadPlaceholderText: 'paste an image link', - maxHeight: 420, - onUpload: () => Promise.reject(new Error('Image uploads disabled')), - }, }, });