From 607aed5997807085a27a542a2a44ea9b7cc54451 Mon Sep 17 00:00:00 2001 From: claude code agent 227 Date: Sun, 28 Jun 2026 23:38:28 +0300 Subject: [PATCH] fix(mcp): restore image caption on markdown round-trip (F1) Stock @tiptap/extension-image carries no caption attribute, so markdownToProseMirror through docmostExtensions dropped the data-caption the client emits, breaking the lossless claim. Extend the Image node (mirroring editor-ext image.ts and the nearby Highlight extend) to parse/render data-caption. Rebuilt build/. Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/mcp/build/lib/docmost-schema.js | 19 ++++++++++++++++++- packages/mcp/src/lib/docmost-schema.ts | 21 ++++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/packages/mcp/build/lib/docmost-schema.js b/packages/mcp/build/lib/docmost-schema.js index 6b6c221d..123d58d5 100644 --- a/packages/mcp/build/lib/docmost-schema.js +++ b/packages/mcp/build/lib/docmost-schema.js @@ -1070,7 +1070,24 @@ export const docmostExtensions = [ heading: {}, link: { openOnClick: false }, }), - Image.configure({ inline: false }), + // Stock @tiptap/extension-image has no caption attribute, so a round-trip + // through this schema would drop the data-caption the client TiptapImage + // emits. Mirror editor-ext image.ts: add a caption attribute that parses + // data-caption and re-renders it only when set (caption-less images stay + // clean), keeping the MCP markdown round-trip lossless. + Image.extend({ + addAttributes() { + const parent = this.parent?.() ?? {}; + return { + ...parent, + caption: { + default: undefined, + parseHTML: (el) => el.getAttribute("data-caption") || undefined, + renderHTML: (attrs) => attrs.caption ? { "data-caption": attrs.caption } : {}, + }, + }; + }, + }).configure({ inline: false }), TaskList, TaskItem.configure({ nested: true }), // Highlight stores its color unescaped and Docmost interpolates it into diff --git a/packages/mcp/src/lib/docmost-schema.ts b/packages/mcp/src/lib/docmost-schema.ts index 546b9844..b26a45ea 100644 --- a/packages/mcp/src/lib/docmost-schema.ts +++ b/packages/mcp/src/lib/docmost-schema.ts @@ -1164,7 +1164,26 @@ export const docmostExtensions = [ heading: {}, link: { openOnClick: false }, }), - Image.configure({ inline: false }), + // Stock @tiptap/extension-image has no caption attribute, so a round-trip + // through this schema would drop the data-caption the client TiptapImage + // emits. Mirror editor-ext image.ts: add a caption attribute that parses + // data-caption and re-renders it only when set (caption-less images stay + // clean), keeping the MCP markdown round-trip lossless. + Image.extend({ + addAttributes() { + const parent = this.parent?.() ?? {}; + return { + ...parent, + caption: { + default: undefined, + parseHTML: (el: HTMLElement) => + el.getAttribute("data-caption") || undefined, + renderHTML: (attrs: Record) => + attrs.caption ? { "data-caption": attrs.caption } : {}, + }, + }; + }, + }).configure({ inline: false }), TaskList, TaskItem.configure({ nested: true }), // Highlight stores its color unescaped and Docmost interpolates it into