@atlaskit/editor-plugin-limited-mode
Version:
LimitedMode plugin for @atlaskit/editor-core
77 lines (71 loc) • 2.98 kB
JavaScript
import { LIMITED_MODE_DEFAULT_DOC_SIZE_THRESHOLD, LIMITED_MODE_DEFAULT_NODE_COUNT_THRESHOLD } from '@atlaskit/editor-common/limited-mode-document-thresholds';
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
export var limitedModePluginKey = new PluginKey('limitedModePlugin');
/**
* Determines whether limited mode should be enabled for a document.
* If this logic changes, update the duplicate in `editor-common/src/node-anchor/node-anchor-provider.ts` to avoid drift.
*
* Limited mode is activated when ANY of the following conditions are met:
* 1. Document size exceeds `LIMITED_MODE_DEFAULT_DOC_SIZE_THRESHOLD`
* 2. Node count exceeds `LIMITED_MODE_DEFAULT_NODE_COUNT_THRESHOLD`
* 3. Document contains a legacy-content macro (LCM)
*
* Performance optimisations:
* - Doc size is checked first (O(1)) - if it exceeds threshold, we skip traversal entirely.
* - If we find an LCM during traversal, we exit early since limited mode will be enabled.
*/
var shouldEnableLimitedModeForDocument = function shouldEnableLimitedModeForDocument(doc) {
var nodeCountThreshold = LIMITED_MODE_DEFAULT_NODE_COUNT_THRESHOLD;
var docSizeThreshold = LIMITED_MODE_DEFAULT_DOC_SIZE_THRESHOLD;
// Early exit: doc size exceeds threshold - O(1), no traversal needed
if (doc.nodeSize > docSizeThreshold) {
return true;
}
// Single traversal for node count and LCM detection
var nodeCount = 0;
var hasLcm = false;
doc.descendants(function (node) {
var _node$attrs;
nodeCount += 1;
if (((_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.extensionKey) === 'legacy-content') {
hasLcm = true;
// Early exit: LCM found — limited mode will be enabled
return false;
}
});
// LCM condition takes precedence (if we early exited traversal, this is why)
if (hasLcm) {
return true;
}
// Check node count threshold
if (nodeCount > nodeCountThreshold) {
return true;
}
return false;
};
export var createPlugin = function createPlugin() {
return new SafePlugin({
key: limitedModePluginKey,
view: function view(_view) {
return {};
},
state: {
init: function init(_config, editorState) {
return {
documentSizeBreachesThreshold: shouldEnableLimitedModeForDocument(editorState.doc)
};
},
apply: function apply(tr, currentPluginState, _oldState, _newState) {
// Don't check the document size if we're already in limited mode.
// We ALWAYS want to re-check the document size if we're replacing the document (e.g. live-to-live page navigation).
if (currentPluginState.documentSizeBreachesThreshold && !tr.getMeta('replaceDocument')) {
return currentPluginState;
}
return {
documentSizeBreachesThreshold: shouldEnableLimitedModeForDocument(tr.doc)
};
}
}
});
};