diff --git a/public/editor/bridge-core.js b/public/editor/bridge-core.js index eb6a890..64f9e32 100644 --- a/public/editor/bridge-core.js +++ b/public/editor/bridge-core.js @@ -776,6 +776,13 @@ const setupPlainTextPreserver = (editor) => { const isTextLike = (model) => !!(model && model.is && (model.is('text') || model.is('button') || model.is('link') || model.is('textnode'))); + const resolveTextModel = (model) => { + if (!model) return model; + if (model.is && model.is('textnode') && typeof model.parent === 'function') { + return model.parent(); + } + return model; + }; const lastContent = new Map(); const normalizeHtml = (value) => { return String(value || '') @@ -795,31 +802,52 @@ normalized: normalizeHtml(composite), }; }; + const storeSnapshot = (model, snap) => { + if (!model || !snap) return; + const key = model.cid || model; + lastContent.set(key, snap); + model.__bridgeLastHtml = snap.html; + model.__bridgeLastNormalized = snap.normalized; + const el = model.view && model.view.el; + if (el) { + el.__bridgeLastHtml = snap.html; + el.__bridgeLastNormalized = snap.normalized; + } + }; const rememberIfPresent = (model) => { - if (!isTextLike(model)) return; - const snap = snapshotContent(model); + const target = resolveTextModel(model); + if (!isTextLike(target)) return; + const snap = snapshotContent(target); if (!snap.normalized) return; - lastContent.set(model.cid || model, snap); + storeSnapshot(target, snap); }; const restoreIfEmpty = (model) => { - if (!isTextLike(model) || !model.get) return; - const current = snapshotContent(model); + const target = resolveTextModel(model); + if (!isTextLike(target) || !target.get) return; + const current = snapshotContent(target); if (current.normalized) { - rememberIfPresent(model); + rememberIfPresent(target); return; } - const stored = lastContent.get(model.cid || model); + const key = target.cid || target; + const stored = lastContent.get(key) + || (target.__bridgeLastNormalized ? { html: target.__bridgeLastHtml, normalized: target.__bridgeLastNormalized } : null) + || ((target.view && target.view.el && target.view.el.__bridgeLastNormalized) + ? { html: target.view.el.__bridgeLastHtml, normalized: target.view.el.__bridgeLastNormalized } + : null); if (!stored || !stored.normalized) return; try { - if (model.components) { - model.components(stored.html); + if (target.components) { + target.components(stored.html); } - model.set('content', stored.html); - model.trigger && model.trigger('change:content'); + target.set('content', stored.html); + target.trigger && target.trigger('change:content'); + try { console.log('[PLAIN TEXT RESTORE] Inhalt wiederhergestellt.'); } catch {} } catch {} }; editor.on('component:update', (model) => restoreIfEmpty(model)); editor.on('component:input', (model) => restoreIfEmpty(model)); + editor.on('component:deselected', (model) => restoreIfEmpty(model)); editor.on('component:add', (model) => rememberIfPresent(model)); editor.on('rte:disable', (model) => { const target = model || (editor.getSelected && editor.getSelected()); @@ -1108,7 +1136,7 @@ } }); - const ensurePlaceholderCommandStub = (editor) => { + const ensureCommandStubs = (editor) => { if (!editor || !editor.Commands || !editor.Commands.add) return; editor.Commands.add('bridge-placeholder:edit', { __bridgePlaceholderStub: true, @@ -1120,8 +1148,22 @@ } }, }); + editor.Commands.add('bridge-open-richtext', { + __bridgeRteStub: true, + run(ed, sender, opts = {}) { + if (sender && sender.set) sender.set('active', 0); + const component = opts.component || ed.getSelected(); + openRichTextModal(ed, component); + }, + }); + editor.Commands.add('bridge-table:edit', { + __bridgeTableStub: true, + run(ed, sender, opts = {}) { + if (sender && sender.set) sender.set('active', 0); + }, + }); }; - ensurePlaceholderCommandStub(ed); + ensureCommandStubs(ed); try { const textTags = ['p','span','div','br','b','strong','i','em','u','a','ul','ol','li'];