UNPKG

@atlaskit/editor-plugin-show-diff

Version:

ShowDiff plugin for @atlaskit/editor-core

84 lines (82 loc) • 3.42 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createEditorProxy = createEditorProxy; var _selection = require("@atlaskit/editor-common/selection/gap-cursor/selection"); /** * A preview is rendered by the live view's own node views, which read `getPos()` against * `view.state.doc` for both layout (`isTableNested`) and writes (`scaleTable` builds attribute * steps at `getPos() + 1`). Handing them live positions makes the layout correct but points the * writes at unrelated live nodes, so give them a view whose document *is* the preview instead. * * With `$sourcePos` (the node's position in the doc it came from) the node is swapped into a copy * of its real top-level ancestor, so a table inside an expand still resolves as nested. * * Returns `null` when the node cannot be a top-level child (e.g. a bare `tableCell`), in which * case the caller falls back to the live view and the previous stubbed positions. */ function createEditorProxy(liveView, rootNode, $sourcePos) { var liveState = liveView.state; var createDoc = function createDoc(topLevel) { return liveState.schema.topNodeType.createChecked(null, topLevel); }; var previewDoc; var rootPos = 0; try { var _$sourcePos$nodeAfter; if ($sourcePos && $sourcePos.depth > 0 && ((_$sourcePos$nodeAfter = $sourcePos.nodeAfter) === null || _$sourcePos$nodeAfter === void 0 ? void 0 : _$sourcePos$nodeAfter.type) === rootNode.type) { var topLevel = rootNode; for (var depth = $sourcePos.depth; depth > 0; depth--) { var ancestor = $sourcePos.node(depth); topLevel = ancestor.copy(ancestor.content.replaceChild($sourcePos.index(depth), topLevel)); } previewDoc = createDoc(topLevel); rootPos = $sourcePos.pos - $sourcePos.before(1); } else { previewDoc = createDoc(rootNode); } } catch (_unused) { return null; } // A gap cursor just before the node selects nothing, so the table's node view doesn't render // as selected or show its controls. var previewSelection = new _selection.GapCursorSelection(previewDoc.resolve(rootPos), _selection.Side.LEFT); // Proxy rather than `EditorState.create` so plugin state is shared as-is: re-initialising // every plugin per preview would be costly and re-runs their side effects. var stateProxy = new Proxy(liveState, { get: function get(target, prop, receiver) { if (prop === 'doc') { return previewDoc; } if (prop === 'selection') { return previewSelection; } return Reflect.get(target, prop, receiver); } }); var editorProxy = new Proxy(liveView, { get: function get(target, prop, receiver) { if (prop === 'state') { return stateProxy; } if (prop === 'dispatch') { // Keep the transaction inside the preview. It was built against `previewDoc`, so // applying it to the live state would corrupt the real document. return function (tr) { try { stateProxy = stateProxy.apply(tr); } catch (_unused2) { // A preview is throwaway; a failed self-update is not worth surfacing. } }; } var value = Reflect.get(target, prop, receiver); return typeof value === 'function' ? value.bind(target) : value; } }); return { editorProxy: editorProxy, rootPos: rootPos }; }