@@ -13,6 +13,7 @@ import {
1313 OPEN_LINK_HANDLER ,
1414} from './components/Editor.provider.ts'
1515import { ACTION_ATTACHMENT_PROMPT } from './components/Editor/MediaHandler.provider.js'
16+ import { encodeAttachmentFilename } from './helpers/attachmentFilename.ts'
1617import { openLink } from './helpers/links.js'
1718// eslint-disable-next-line import/no-unresolved, n/no-missing-import
1819import 'vite/modulepreload-polyfill'
@@ -70,6 +71,11 @@ class TextEditorEmbed {
7071 return this
7172 }
7273
74+ onAttachmentsUpdated ( onAttachmentsUpdatedCallback = ( ) => { } ) {
75+ subscribe ( 'text:editor:attachments:updated' , onAttachmentsUpdatedCallback )
76+ return this
77+ }
78+
7379 render ( el ) {
7480 el . innerHTML = ''
7581 const element = document . createElement ( 'div' )
@@ -138,6 +144,55 @@ class TextEditorEmbed {
138144 . run ( )
139145 }
140146
147+ replaceAttachmentFilename ( pageId , oldName , newName ) {
148+ const oldSrc =
149+ '.attachments.' + pageId + '/' + encodeAttachmentFilename ( oldName )
150+ const newSrc =
151+ '.attachments.' + pageId + '/' + encodeAttachmentFilename ( newName )
152+ const { view, state } = this . #getEditorComponent( ) . editor
153+ const { doc, schema, tr } = state
154+ let modified = false
155+
156+ doc . descendants ( ( node , pos ) => {
157+ if ( ! node . type === schema . nodes . image || node . attrs . src !== oldSrc ) {
158+ return
159+ }
160+
161+ tr . setNodeMarkup ( pos , undefined , {
162+ ...node . attrs ,
163+ src : newSrc ,
164+ alt : node . attrs . alt . replace ( oldName , newName ) ,
165+ } )
166+ modified = true
167+ } )
168+
169+ if ( modified ) {
170+ view . dispatch ( tr )
171+ this . save ( )
172+ }
173+ }
174+
175+ removeAttachmentReferences ( pageId , name ) {
176+ const src = '.attachments.' + pageId + '/' + encodeAttachmentFilename ( name )
177+ const { view, state } = this . #getEditorComponent( ) . editor
178+ const { doc, schema, tr } = state
179+ let modified = false
180+
181+ doc . descendants ( ( node , pos ) => {
182+ if ( ! node . type === schema . nodes . image || node . attrs . src !== src ) {
183+ return
184+ }
185+
186+ tr . delete ( pos , pos + node . nodeSize )
187+ modified = true
188+ } )
189+
190+ if ( modified ) {
191+ view . dispatch ( tr )
192+ this . save ( )
193+ }
194+ }
195+
141196 focus ( ) {
142197 this . #getEditorComponent( ) . editor ?. commands . focus ( )
143198 }
@@ -201,6 +256,7 @@ window.OCA.Text.createEditor = async function ({
201256 onMentionInsert = undefined ,
202257 openLinkHandler = undefined ,
203258 onSearch = undefined ,
259+ onAttachmentsUpdated = ( { attachmentSrcs } ) => { } ,
204260} ) {
205261 const { default : MarkdownContentEditor } = await import (
206262 /* webpackChunkName: "editor" */ './components/Editor/MarkdownContentEditor.vue'
@@ -286,6 +342,7 @@ window.OCA.Text.createEditor = async function ({
286342 . onUpdate ( onUpdate )
287343 . onOutlineToggle ( onOutlineToggle )
288344 . onSearch ( onSearch )
345+ . onAttachmentsUpdated ( onAttachmentsUpdated )
289346 . render ( el )
290347}
291348
0 commit comments