@atlaskit/editor-plugin-synced-block
Version:
SyncedBlock plugin for @atlaskit/editor-core
144 lines (136 loc) • 4.54 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.trackSyncBlocks = exports.hasEditInSyncBlock = void 0;
var _transform = require("@atlaskit/editor-prosemirror/transform");
var _utils = require("@atlaskit/editor-prosemirror/utils");
/**
* Tracks changes to sync blocks in a transaction.
* @param predicate - A function that returns true if a node is a sync block (source or reference or both).
* @param tr - The transaction to track changes in.
* @param state - The editor state.
* @returns An object containing the removed and added sync blocks.
*/
var trackSyncBlocks = exports.trackSyncBlocks = function trackSyncBlocks(predicate, tr, state) {
var removed = {};
var added = {};
if (!tr.docChanged) {
return {
removed: [],
added: []
};
}
// and cast to specific step types
var replaceSteps = tr.steps.filter(function (step) {
return step instanceof _transform.ReplaceStep || step instanceof _transform.ReplaceAroundStep;
});
// this is a quick check to see if any insertion/deletion of sync block happened
var hasSyncBlockChanges = replaceSteps.some(function (step) {
var from = step.from,
to = step.to;
var docAtStep = tr.docs[tr.steps.indexOf(step)];
var hasChange = false;
if (from !== to) {
step.getMap().forEach(function (oldStart, oldEnd) {
if (oldStart !== oldEnd && !hasChange) {
var deletedSlice = docAtStep.slice(Math.max(0, oldStart), Math.min(docAtStep.content.size, oldEnd));
deletedSlice.content.forEach(function (node) {
if (hasChange) {
return;
}
// for top level nodes
if (predicate(node)) {
hasChange = true;
}
});
}
});
}
// no need to check insertions if we already found deletions
if (step.slice.content.size > 0 && !hasChange) {
step.slice.content.forEach(function (node) {
if (predicate(node) && !hasChange) {
hasChange = true;
}
});
}
return hasChange;
});
if (hasSyncBlockChanges) {
var oldDoc = state.doc;
var newDoc = tr.doc;
var syncBlockMapOld = {};
var syncBlockMapNew = {};
oldDoc.content.forEach(function (node) {
if (predicate(node)) {
var syncBlockAttr = node.attrs;
syncBlockMapOld[syncBlockAttr.localId] = {
attrs: syncBlockAttr
};
}
});
newDoc.content.forEach(function (node, offset) {
if (predicate(node)) {
var syncBlockAttr = node.attrs;
syncBlockMapNew[syncBlockAttr.localId] = {
attrs: syncBlockAttr,
node: node,
from: offset,
to: offset + node.nodeSize
};
}
});
// Find removed sync blocks
for (var localId in syncBlockMapOld) {
if (!syncBlockMapNew[localId]) {
removed[localId] = syncBlockMapOld[localId];
}
}
// Find added sync blocks
for (var _localId in syncBlockMapNew) {
if (!syncBlockMapOld[_localId]) {
added[_localId] = syncBlockMapNew[_localId];
}
}
}
return {
removed: Object.values(removed),
added: Object.values(added)
};
};
/**
*
* @returns true if steps modifies children node within bodiedSyncBlock
*/
var hasEditInSyncBlock = exports.hasEditInSyncBlock = function hasEditInSyncBlock(tr, state) {
var bodiedSyncBlock = state.schema.nodes.bodiedSyncBlock;
for (var i = 0; i < tr.steps.length; i++) {
var _tr$docs;
var step = tr.steps[i];
var map = step.getMap();
var docAfterStep = (_tr$docs = tr.docs[i + 1]) !== null && _tr$docs !== void 0 ? _tr$docs : tr.doc;
var positions = [];
// Extract positions from steps dynamically based on applicable properties
if ('from' in step && typeof step.from === 'number' && 'to' in step && typeof step.to === 'number') {
var _ref = step,
from = _ref.from,
to = _ref.to;
positions.push(from, to);
} else if ('pos' in step && typeof step.pos === 'number') {
var _ref2 = step,
pos = _ref2.pos;
positions.push(pos);
}
for (var _i = 0, _positions = positions; _i < _positions.length; _i++) {
var _pos = _positions[_i];
var newPos = map.map(_pos);
if (newPos >= 0 && newPos <= docAfterStep.content.size) {
if ((0, _utils.findParentNodeOfTypeClosestToPos)(docAfterStep.resolve(newPos), bodiedSyncBlock)) {
return true;
}
}
}
}
return false;
};