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) <noreply@anthropic.com>
This commit is contained in:
claude code agent 227
2026-06-28 23:38:28 +03:00
parent dc14a9a540
commit 607aed5997
2 changed files with 38 additions and 2 deletions

View File

@@ -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

View File

@@ -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<string, any>) =>
attrs.caption ? { "data-caption": attrs.caption } : {},
},
};
},
}).configure({ inline: false }),
TaskList,
TaskItem.configure({ nested: true }),
// Highlight stores its color unescaped and Docmost interpolates it into