From a228d247c5b0bda093914eada9ea925b8cd08517 Mon Sep 17 00:00:00 2001 From: Jonas Date: Mon, 8 Jun 2026 18:58:13 +0200 Subject: [PATCH] fix(editorApi): allow to disable image lazy-loading Required in Collectives to load all images straight away in print view. Signed-off-by: Jonas --- src/EditorFactory.js | 8 +++++++- src/components/Editor.vue | 5 +++++ src/components/Editor/MarkdownContentEditor.vue | 5 +++++ src/editor.js | 1 + src/extensions/RichText.js | 4 ++-- src/nodes/Image.js | 1 + src/nodes/ImageInline.js | 1 + src/nodes/ImageView.vue | 6 ++++++ 8 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/EditorFactory.js b/src/EditorFactory.js index 62e919bb62b..9ac41d3acd2 100644 --- a/src/EditorFactory.js +++ b/src/EditorFactory.js @@ -42,11 +42,17 @@ const createRichEditor = ({ connection, relativePath, isEmbedded = false, + noLazyImages = false, } = {}) => { return new Editor({ editorProps, extensions: [ - RichText.configure({ connection, relativePath, isEmbedded }), + RichText.configure({ + connection, + relativePath, + isEmbedded, + noLazyImages, + }), FocusTrap, ...extensions, ], diff --git a/src/components/Editor.vue b/src/components/Editor.vue index 80b92ca46aa..003dd9fc076 100644 --- a/src/components/Editor.vue +++ b/src/components/Editor.vue @@ -218,6 +218,10 @@ export default defineComponent({ type: Boolean, default: false, }, + noLazyImages: { + type: Boolean, + default: false, + }, }, setup(props) { @@ -249,6 +253,7 @@ export default defineComponent({ relativePath: props.relativePath, extensions, isEmbedded: props.isEmbedded, + noLazyImages: props.noLazyImages, }) : createPlainEditor({ language, extensions }) provideEditor(editor) diff --git a/src/components/Editor/MarkdownContentEditor.vue b/src/components/Editor/MarkdownContentEditor.vue index 7436c795b4b..1bb5aacb24c 100644 --- a/src/components/Editor/MarkdownContentEditor.vue +++ b/src/components/Editor/MarkdownContentEditor.vue @@ -83,6 +83,10 @@ export default { type: Boolean, default: false, }, + noLazyImages: { + type: Boolean, + default: false, + }, }, emits: ['update:content'], @@ -90,6 +94,7 @@ export default { const extensions = [ RichText.configure({ extensions: [History], + noLazyImages: props.noLazyImages, }), FocusTrap, ] diff --git a/src/editor.js b/src/editor.js index 44d005b1b3a..3b5f8a2ceac 100644 --- a/src/editor.js +++ b/src/editor.js @@ -248,6 +248,7 @@ window.OCA.Text.createEditor = async function ({ props: null, }, menubarLinkCustomAction = undefined, + noLazyImages = false, onCreate = ({ markdown }) => {}, onLoaded = () => {}, diff --git a/src/extensions/RichText.js b/src/extensions/RichText.js index 8b784fdbfcf..b03d8b43486 100644 --- a/src/extensions/RichText.js +++ b/src/extensions/RichText.js @@ -98,8 +98,8 @@ export default Extension.create({ isEmbedded: this.options.isEmbedded, }), Underline, - Image, - ImageInline, + Image.configure({ noLazyImages: this.options.noLazyImages }), + ImageInline.configure({ noLazyImages: this.options.noLazyImages }), Dropcursor.configure({ color: 'var(--color-primary-element)', width: 2, diff --git a/src/nodes/Image.js b/src/nodes/Image.js index 93491b55847..6b8f4f09d00 100644 --- a/src/nodes/Image.js +++ b/src/nodes/Image.js @@ -36,6 +36,7 @@ const Image = TiptapImage.extend({ addOptions() { return { ...this.parent?.(), + noLazyImages: false, } }, diff --git a/src/nodes/ImageInline.js b/src/nodes/ImageInline.js index cf91f498bcd..f9b422948c6 100644 --- a/src/nodes/ImageInline.js +++ b/src/nodes/ImageInline.js @@ -31,6 +31,7 @@ const ImageInline = TiptapImage.extend({ addOptions() { return { ...this.parent?.(), + noLazyImages: false, inline: true, } }, diff --git a/src/nodes/ImageView.vue b/src/nodes/ImageView.vue index 3cbf2666c9e..95734d8875a 100644 --- a/src/nodes/ImageView.vue +++ b/src/nodes/ImageView.vue @@ -273,6 +273,12 @@ export default { this.loadAttachmentMetadata() this.setupResizeObserver() + // Load image directly if lazy loading is disabled + if (this.extension?.options?.noLazyImages === true) { + this.loadPreview().catch(this.onImageLoadFailure) + return + } + this.$nextTick(() => { // nextTick is necessary, intersection detection is slightly unreliable without it const options = {