diff --git a/config/current.ver b/config/current.ver index 0663412..4e16b4e 100644 --- a/config/current.ver +++ b/config/current.ver @@ -1 +1 @@ -1.1.43 \ No newline at end of file +1.1.44 \ No newline at end of file diff --git a/public/editor/bridge-core.js b/public/editor/bridge-core.js index a288e94..86c83de 100644 --- a/public/editor/bridge-core.js +++ b/public/editor/bridge-core.js @@ -556,6 +556,15 @@ if (!body || body.__bridgeBlurLoggerBound) return; body.__bridgeBlurLoggerBound = true; const focusSnapshots = new WeakMap(); + const syncing = new WeakSet(); + const normalizeViewHtml = (html) => { + return String(html || '') + .replace(/]*>/gi, '
') + .replace(/\sdata-gjs-type="[^"]*"/gi, '') + .replace(/\sdraggable="[^"]*"/gi, '') + .replace(/\scontenteditable="[^"]*"/gi, '') + .trim(); + }; const buildSnapshot = (target, selected, selectedEl, editorHtml) => { let modelContent = ''; try { @@ -616,9 +625,41 @@ focusSnapshots.set(target, buildSnapshot(target, selected, selectedEl, editorHtml)); } catch {} }; + const syncFromDomInput = (evt) => { + const target = evt && evt.target; + if (!target) return; + if (window.__bridgeRteOpen) return; + const isEditable = !!(target.isContentEditable || (target.getAttribute && target.getAttribute('contenteditable') === 'true')); + if (!isEditable) return; + const selected = editor.getSelected && editor.getSelected(); + const selectedEl = selected && selected.view && selected.view.el; + if (!selected || !selectedEl) return; + if (!(selectedEl === target || selectedEl.contains(target))) return; + if (syncing.has(selected)) return; + try { + const viewHtml = normalizeViewHtml(target.innerHTML || ''); + if (!viewHtml) return; + syncing.add(selected); + if (selected.components) { + try { selected.components(viewHtml); } catch {} + } + if (selected.set) selected.set('content', viewHtml); + selected.trigger && selected.trigger('change:content'); + if (selected.view && typeof selected.view.render === 'function') { + selected.view.render(); + } + if (editor && typeof editor.trigger === 'function') { + editor.trigger('component:update', selected); + } + } catch {} finally { + syncing.delete(selected); + } + }; body.addEventListener('focusin', logFocus, true); body.addEventListener('blur', logBlur, true); body.addEventListener('focusout', logBlur, true); + body.addEventListener('input', syncFromDomInput, true); + body.addEventListener('keyup', syncFromDomInput, true); }); };