@atlaskit/editor-plugin-annotation
Version:
Annotation plugin for @atlaskit/editor-core
523 lines (511 loc) • 28.8 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.inlineCommentPlugin = void 0;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _adfSchema = require("@atlaskit/adf-schema");
var _analytics = require("@atlaskit/editor-common/analytics");
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
var _utils = require("@atlaskit/editor-common/utils");
var _view = require("@atlaskit/editor-prosemirror/view");
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
var _editorCommands = require("../editor-commands");
var _utils2 = require("../editor-commands/utils");
var _nodeviews = require("../nodeviews");
var _annotationManagerHooks = require("./annotation-manager-hooks");
var _pluginFactory = require("./plugin-factory");
var _toolbar = require("./toolbar");
var _utils3 = require("./utils");
var fetchProviderStates = /*#__PURE__*/function () {
var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(provider, annotationIds) {
var data, result;
return _regenerator.default.wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
if (!(!provider || !provider.getState)) {
_context.next = 2;
break;
}
return _context.abrupt("return", {});
case 2:
_context.next = 4;
return provider.getState(annotationIds);
case 4:
data = _context.sent;
result = {};
data.forEach(function (annotation) {
if (annotation.annotationType === _adfSchema.AnnotationTypes.INLINE_COMMENT) {
result[annotation.id] = annotation.state.resolved;
}
});
return _context.abrupt("return", result);
case 8:
case "end":
return _context.stop();
}
}, _callee);
}));
return function fetchProviderStates(_x, _x2) {
return _ref.apply(this, arguments);
};
}();
// fetchState is unable to return a command as it's runs async and may dispatch at a later time
// Requires `editorView` instead of the decomposition as the async means state may end up stale
var fetchState = /*#__PURE__*/function () {
var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(provider, annotationIds, editorView, editorAnalyticsAPI) {
var inlineCommentStates, _ref3, annotationsLoaded;
return _regenerator.default.wrap(function _callee2$(_context2) {
while (1) switch (_context2.prev = _context2.next) {
case 0:
_context2.next = 2;
return fetchProviderStates(provider, annotationIds);
case 2:
inlineCommentStates = _context2.sent;
if (!(Object.keys(inlineCommentStates).length === 0)) {
_context2.next = 7;
break;
}
_ref3 = (0, _utils3.getPluginState)(editorView.state) || {}, annotationsLoaded = _ref3.annotationsLoaded;
if (!annotationsLoaded && (0, _platformFeatureFlags.fg)('confluence_frontend_new_dangling_comments_ux')) {
(0, _editorCommands.setInlineCommentsFetched)()(editorView.state, editorView.dispatch);
}
return _context2.abrupt("return");
case 7:
if (editorView.dispatch) {
(0, _editorCommands.updateInlineCommentResolvedState)(editorAnalyticsAPI)(inlineCommentStates)(editorView.state, editorView.dispatch);
}
case 8:
case "end":
return _context2.stop();
}
}, _callee2);
}));
return function fetchState(_x3, _x4, _x5, _x6) {
return _ref2.apply(this, arguments);
};
}();
var initialState = function initialState() {
var disallowOnWhitespace = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var featureFlagsPluginState = arguments.length > 1 ? arguments[1] : undefined;
var isAnnotationManagerEnabled = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
return {
annotationsLoaded: false,
annotations: {},
selectedAnnotations: [],
hoveredAnnotations: [],
mouseData: {
isSelecting: false
},
disallowOnWhitespace: disallowOnWhitespace,
isInlineCommentViewClosed: false,
isVisible: true,
skipSelectionHandling: false,
featureFlagsPluginState: featureFlagsPluginState,
isDrafting: false,
pendingSelectedAnnotations: [],
pendingSelectedAnnotationsUpdateCount: 0,
isAnnotationManagerEnabled: isAnnotationManagerEnabled
};
};
var hideToolbar = function hideToolbar(state, dispatch) {
return function () {
(0, _editorCommands.updateMouseState)({
isSelecting: true
})(state, dispatch);
};
};
// Subscribe to updates from consumer
var onResolve = function onResolve(editorAnalyticsAPI) {
return function (state, dispatch) {
return function (annotationId) {
(0, _editorCommands.updateInlineCommentResolvedState)(editorAnalyticsAPI)((0, _defineProperty2.default)({}, annotationId, true), _analytics.RESOLVE_METHOD.CONSUMER)(state, dispatch);
};
};
};
var onUnResolve = function onUnResolve(editorAnalyticsAPI) {
return function (state, dispatch) {
return function (annotationId) {
(0, _editorCommands.updateInlineCommentResolvedState)(editorAnalyticsAPI)((0, _defineProperty2.default)({}, annotationId, false))(state, dispatch);
};
};
};
var onMouseUp = function onMouseUp(state, dispatch) {
return function (e) {
var _ref4 = (0, _utils3.getPluginState)(state) || {},
mouseData = _ref4.mouseData;
if (mouseData !== null && mouseData !== void 0 && mouseData.isSelecting) {
(0, _editorCommands.updateMouseState)({
isSelecting: false
})(state, dispatch);
}
};
};
var onSetVisibility = function onSetVisibility(view) {
return function (isVisible) {
var state = view.state,
dispatch = view.dispatch;
(0, _editorCommands.setInlineCommentsVisibility)(isVisible)(state, dispatch);
if (isVisible) {
// PM retains focus when we click away from the editor.
// This will restore the visual aspect of the selection,
// otherwise it will seem a floating toolbar will appear
// for no reason.
view.focus();
}
};
};
var inlineCommentPlugin = exports.inlineCommentPlugin = function inlineCommentPlugin(options) {
var provider = options.provider,
featureFlagsPluginState = options.featureFlagsPluginState,
annotationManager = options.annotationManager;
return new _safePlugin.SafePlugin({
key: _utils3.inlineCommentPluginKey,
state: (0, _pluginFactory.createPluginState)(options.dispatch, initialState(provider.disallowOnWhitespace, featureFlagsPluginState, !!annotationManager)),
view: function view(editorView) {
var allowAnnotationFn;
var startDraftFn;
var clearDraftFn;
var applyDraftFn;
var getDraftFn;
var setIsAnnotationSelectedFn;
var setIsAnnotationHoveredFn;
var clearAnnotationFn;
if (annotationManager) {
allowAnnotationFn = (0, _annotationManagerHooks.allowAnnotation)(editorView, options);
startDraftFn = (0, _annotationManagerHooks.startDraft)(editorView, options);
clearDraftFn = (0, _annotationManagerHooks.clearDraft)(editorView, options);
applyDraftFn = (0, _annotationManagerHooks.applyDraft)(editorView, options);
getDraftFn = (0, _annotationManagerHooks.getDraft)(editorView, options);
setIsAnnotationSelectedFn = (0, _annotationManagerHooks.setIsAnnotationSelected)(editorView, options);
setIsAnnotationHoveredFn = (0, _annotationManagerHooks.setIsAnnotationHovered)(editorView, options);
clearAnnotationFn = (0, _annotationManagerHooks.clearAnnotation)(editorView, options);
annotationManager.hook('allowAnnotation', allowAnnotationFn);
annotationManager.hook('startDraft', startDraftFn);
annotationManager.hook('clearDraft', clearDraftFn);
annotationManager.hook('applyDraft', applyDraftFn);
annotationManager.hook('getDraft', getDraftFn);
annotationManager.hook('setIsAnnotationSelected', setIsAnnotationSelectedFn);
annotationManager.hook('setIsAnnotationHovered', setIsAnnotationHoveredFn);
annotationManager.hook('clearAnnotation', clearAnnotationFn);
}
// Get initial state
// Need to pass `editorView` to mitigate editor state going stale
fetchState(provider, (0, _utils3.getAllAnnotations)(editorView.state.doc), editorView, options.editorAnalyticsAPI);
var resolve = function resolve(annotationId) {
return onResolve(options.editorAnalyticsAPI)(editorView.state, editorView.dispatch)(annotationId);
};
var unResolve = function unResolve(annotationId) {
return onUnResolve(options.editorAnalyticsAPI)(editorView.state, editorView.dispatch)(annotationId);
};
var mouseUp = function mouseUp(event) {
return onMouseUp(editorView.state, editorView.dispatch)(event);
};
var setVisibility = function setVisibility(isVisible) {
return onSetVisibility(editorView)(isVisible);
};
var setSelectedAnnotationFn = function setSelectedAnnotationFn(annotationId) {
if (!annotationId) {
(0, _editorCommands.closeComponent)()(editorView.state, editorView.dispatch);
} else {
(0, _editorCommands.setSelectedAnnotation)(annotationId)(editorView.state, editorView.dispatch);
}
};
var setHoveredAnnotationFn = function setHoveredAnnotationFn(annotationId) {
if (!annotationId) {
(0, _editorCommands.closeComponent)()(editorView.state, editorView.dispatch);
} else {
(0, _editorCommands.setHoveredAnnotation)(annotationId)(editorView.state, editorView.dispatch);
}
};
var removeHoveredannotationFn = function removeHoveredannotationFn() {
(0, _editorCommands.setHoveredAnnotation)('')(editorView.state, editorView.dispatch);
};
var closeInlineCommentFn = function closeInlineCommentFn() {
(0, _editorCommands.closeComponent)()(editorView.state, editorView.dispatch);
};
var updateSubscriber = provider.updateSubscriber;
if (updateSubscriber) {
updateSubscriber.on('resolve', resolve).on('delete', resolve).on('unresolve', unResolve).on('create', unResolve).on('setvisibility', setVisibility).on('setselectedannotation', setSelectedAnnotationFn).on('sethoveredannotation', setHoveredAnnotationFn).on('removehoveredannotation', removeHoveredannotationFn).on('closeinlinecomment', closeInlineCommentFn);
}
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
editorView.root.addEventListener('mouseup', mouseUp);
/**
* This flag is used to prevent the preemptive gate from being called multiple times while a check is in-flight.
* If a check is still pending then it's most likely because the product is busy and trying to block the
* selection of an annotation.
*/
var isPreemptiveGateActive = false;
return {
update: function update(view, _prevState) {
var _prevSelectedAnnotati;
var _ref5 = (0, _utils3.getPluginState)(view.state) || {},
selectedAnnotations = _ref5.selectedAnnotations,
annotations = _ref5.annotations,
isDrafting = _ref5.isDrafting,
bookmark = _ref5.bookmark;
var _ref6 = (0, _utils3.getPluginState)(_prevState) || {},
prevSelectedAnnotations = _ref6.selectedAnnotations;
var selectedAnnotationId = selectedAnnotations && selectedAnnotations.length !== 0 && selectedAnnotations[0].id ? selectedAnnotations[0].id : undefined;
// If the new state has an unresolved selected annotation, and it's different from
// the previous one then...
if (
//This checks the selected annotation is different from the previous one
selectedAnnotationId && selectedAnnotationId !== (prevSelectedAnnotations === null || prevSelectedAnnotations === void 0 || (_prevSelectedAnnotati = prevSelectedAnnotations[0]) === null || _prevSelectedAnnotati === void 0 ? void 0 : _prevSelectedAnnotati.id) &&
// This ensures that the selected annotation is unresolved
annotations && annotations[selectedAnnotationId] === false) {
var _options$selectCommen, _options$viewInlineCo;
// ...we mark the select annotation experience as complete.
// The selectComponentExperience is using a simplified object, which is why it's type asserted.
(_options$selectCommen = options.selectCommentExperience) === null || _options$selectCommen === void 0 || _options$selectCommen.selectAnnotation.complete(selectedAnnotationId);
// ...and start a new UFO press trace since the selected comment is changing
(_options$viewInlineCo = options.viewInlineCommentTraceUFOPress) === null || _options$viewInlineCo === void 0 || _options$viewInlineCo.call(options);
}
var api = options.api;
if (isDrafting && !view.state.selection.eq(_prevState.selection) && Boolean(api === null || api === void 0 ? void 0 : api.toolbar)) {
// It is possible that user update selection while having a active draft,
// so we need to reset the user intent to allow inline text toolbar to be visible
api === null || api === void 0 || api.core.actions.execute(function (_ref7) {
var tr = _ref7.tr;
if ((0, _toolbar.shouldSuppressFloatingToolbar)({
state: view.state,
bookmark: bookmark
})) {
(0, _utils2.setUserIntent)(api, tr);
} else {
(0, _utils2.resetUserIntent)(api, tr);
}
return tr;
});
}
if (annotationManager) {
// In the Editor, Annotations can be selected in three ways:
// 1. By clicking on the annotation in the editor
// 2. By using the annotation manager to select the annotation
// 3. By moving the cursor to the annotation and using the keyboard to select it
// Item 1 & 3 need to be protected by the preemptive gate. This is because these actions could be performed by a user
// at a time when changing the selection could cause data loss.
// The following preemptive check is designed to cover these items.
var _ref8 = (0, _utils3.getPluginState)(view.state) || {},
pendingSelectedAnnotations = _ref8.pendingSelectedAnnotations,
pendingSelectedAnnotationsUpdateCount = _ref8.pendingSelectedAnnotationsUpdateCount;
var _ref9 = (0, _utils3.getPluginState)(_prevState) || {},
prevPendingSelectedAnnotationsUpdateCount = _ref9.pendingSelectedAnnotationsUpdateCount;
if (!isPreemptiveGateActive && pendingSelectedAnnotationsUpdateCount !== prevPendingSelectedAnnotationsUpdateCount && !!(pendingSelectedAnnotations !== null && pendingSelectedAnnotations !== void 0 && pendingSelectedAnnotations.length)) {
// Need to set a lock to avoid calling gate multiple times. The lock will be released
// when the preemptive gate is complete.
isPreemptiveGateActive = true;
annotationManager.checkPreemptiveGate().then(function (canSelectAnnotation) {
var _ref0 = (0, _utils3.getPluginState)(view.state) || {},
isDrafting = _ref0.isDrafting,
latestPendingSelectedAnnotations = _ref0.pendingSelectedAnnotations,
latestSelectedAnnotations = _ref0.selectedAnnotations;
if (canSelectAnnotation) {
if (isDrafting) {
// The user must have chosen to discard there draft. So before we flush the pending selections
// we need to clear the draft if there is one.
(0, _editorCommands.setInlineCommentDraftState)(options.editorAnalyticsAPI, undefined, options.api)(false)(view.state, view.dispatch);
}
// Flush the pending selections into the selected annotations list.
(0, _editorCommands.flushPendingSelections)(options.editorAnalyticsAPI)(true)(view.state, view.dispatch);
latestSelectedAnnotations === null || latestSelectedAnnotations === void 0 || latestSelectedAnnotations.filter(function (annotation) {
return (latestPendingSelectedAnnotations === null || latestPendingSelectedAnnotations === void 0 ? void 0 : latestPendingSelectedAnnotations.findIndex(function (pendingAnnotation) {
return pendingAnnotation.id === annotation.id;
})) === -1;
}).forEach(function (annotation) {
var _getAnnotationInlineN;
annotationManager.emit({
name: 'annotationSelectionChanged',
data: {
annotationId: annotation.id,
isSelected: false,
inlineNodeTypes: (_getAnnotationInlineN = (0, _utils.getAnnotationInlineNodeTypes)(editorView.state, annotation.id)) !== null && _getAnnotationInlineN !== void 0 ? _getAnnotationInlineN : []
}
});
});
// Notify the annotation manager that the pending selection has changed.
latestPendingSelectedAnnotations === null || latestPendingSelectedAnnotations === void 0 || latestPendingSelectedAnnotations.forEach(function (_ref1) {
var _getAnnotationInlineN2;
var id = _ref1.id;
annotationManager.emit({
name: 'annotationSelectionChanged',
data: {
annotationId: id,
isSelected: true,
inlineNodeTypes: (_getAnnotationInlineN2 = (0, _utils.getAnnotationInlineNodeTypes)(view.state, id)) !== null && _getAnnotationInlineN2 !== void 0 ? _getAnnotationInlineN2 : []
}
});
});
} else {
// Clears the pending selections if the preemptive gate returns false.
// We should need to worry about dispatching change events here because the pending selections
// are being aborted and the selections will remain unchanged.
(0, _editorCommands.flushPendingSelections)(options.editorAnalyticsAPI)(false)(view.state, view.dispatch);
}
}).catch(function (error) {
// If an error has occured we will clear any pending selections to avoid accidentally setting the wrong thing.
(0, _editorCommands.flushPendingSelections)(options.editorAnalyticsAPI)(false, 'pending-selection-preemptive-gate-error')(view.state, view.dispatch);
}).finally(function () {
isPreemptiveGateActive = false;
});
}
}
var _ref10 = (0, _utils3.getPluginState)(view.state) || {},
dirtyAnnotations = _ref10.dirtyAnnotations;
if (!dirtyAnnotations) {
return;
}
(0, _editorCommands.clearDirtyMark)()(view.state, view.dispatch);
fetchState(provider, (0, _utils3.getAllAnnotations)(view.state.doc), view, options.editorAnalyticsAPI);
},
destroy: function destroy() {
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
editorView.root.removeEventListener('mouseup', mouseUp);
if (updateSubscriber) {
updateSubscriber.off('resolve', resolve).off('delete', resolve).off('unresolve', unResolve).off('create', unResolve).off('setvisibility', setVisibility).off('setselectedannotation', setSelectedAnnotationFn).off('sethoveredannotation', setHoveredAnnotationFn).off('removehoveredannotation', removeHoveredannotationFn).off('closeinlinecomment', closeInlineCommentFn);
}
if (annotationManager) {
annotationManager.unhook('allowAnnotation', allowAnnotationFn);
annotationManager.unhook('startDraft', startDraftFn);
annotationManager.unhook('clearDraft', clearDraftFn);
annotationManager.unhook('applyDraft', applyDraftFn);
annotationManager.unhook('getDraft', getDraftFn);
annotationManager.unhook('setIsAnnotationSelected', setIsAnnotationSelectedFn);
annotationManager.unhook('setIsAnnotationHovered', setIsAnnotationHoveredFn);
annotationManager.unhook('clearAnnotation', clearAnnotationFn);
}
}
};
},
props: {
handleDOMEvents: {
mousedown: function mousedown(view) {
var pluginState = (0, _utils3.getPluginState)(view.state);
if (!(pluginState !== null && pluginState !== void 0 && pluginState.mouseData.isSelecting)) {
hideToolbar(view.state, view.dispatch)();
}
return false;
},
dragstart: function dragstart(view, event) {
// Mouseup won't be triggered after dropping
// Hence, update the mouse data to cancel selecting when drag starts
return onMouseUp(view.state, view.dispatch)(event);
},
click: function click(view, event) {
var _event$target$closest, _pluginState$selected;
if (!(event.target instanceof HTMLElement)) {
return false;
}
// Find the nearest ancestor (or self) with the data-id attribute
var annotationId = (_event$target$closest = event.target.closest('[data-id]')) === null || _event$target$closest === void 0 ? void 0 : _event$target$closest.getAttribute('data-id');
if (!annotationId) {
return false;
}
var pluginState = (0, _utils3.getPluginState)(view.state);
var isSelected = pluginState === null || pluginState === void 0 || (_pluginState$selected = pluginState.selectedAnnotations) === null || _pluginState$selected === void 0 ? void 0 : _pluginState$selected.some(function (selectedAnnotation) {
return selectedAnnotation.id === annotationId;
});
// If the annotation is selected and the inline comment view is open, do nothing
// as the user is already in the comment view.
if (isSelected && !(pluginState !== null && pluginState !== void 0 && pluginState.isInlineCommentViewClosed)) {
return false;
}
var _ref11 = pluginState || {},
annotations = _ref11.annotations;
var isUnresolved = annotations && annotations[annotationId] === false;
if (!isUnresolved) {
return false;
}
if (annotationManager) {
var _pluginState$pendingS;
// The manager disable setting the selected annotation on click because in the editor this is already
// handled by the selection update handler. When the manager is enabled, and a selection changes it's pushed into
// the pendingSelectedAnnotations array. This is then used to update the selection when the preemptive gate
// is released.
var isPendingSelection = pluginState === null || pluginState === void 0 || (_pluginState$pendingS = pluginState.pendingSelectedAnnotations) === null || _pluginState$pendingS === void 0 ? void 0 : _pluginState$pendingS.some(function (selectedAnnotation) {
return selectedAnnotation.id === annotationId;
});
// If the annotation is selected and the inline comment view is open, do nothing
// as the user is already in the comment view.
if (isPendingSelection) {
return false;
}
(0, _editorCommands.setPendingSelectedAnnotation)(annotationId)(view.state, view.dispatch);
} else {
(0, _editorCommands.setSelectedAnnotation)(annotationId)(view.state, view.dispatch);
}
return true;
}
},
decorations: function decorations(state) {
// highlight comments, depending on state
var _ref12 = (0, _utils3.getPluginState)(state) || {},
draftDecorationSet = _ref12.draftDecorationSet,
annotations = _ref12.annotations,
selectedAnnotations = _ref12.selectedAnnotations,
isVisible = _ref12.isVisible,
isInlineCommentViewClosed = _ref12.isInlineCommentViewClosed,
hoveredAnnotations = _ref12.hoveredAnnotations;
var decorations = draftDecorationSet !== null && draftDecorationSet !== void 0 ? draftDecorationSet : _view.DecorationSet.empty;
var focusDecorations = [];
// TODO: EDITOR-760 - This needs to be optimised, it's not a good idea to scan the entire document
// everytime we need to update the decorations. This handler will be called alot. We should be caching
// the decorations in plugin state and only updating them when required.
state.doc.descendants(function (node, pos) {
var _provider$supportedBl;
// Inline comment on mediaInline is not supported as part of comments on media project
// Thus, we skip the decoration for mediaInline node
if (node.type.name === 'mediaInline') {
return false;
}
var isSupportedBlockNode = node.isBlock && ((_provider$supportedBl = provider.supportedBlockNodes) === null || _provider$supportedBl === void 0 ? void 0 : _provider$supportedBl.includes(node.type.name));
node.marks.filter(function (mark) {
return mark.type === state.schema.marks.annotation;
}).forEach(function (mark) {
if (isVisible) {
var isUnresolved = !!annotations && annotations[mark.attrs.id] === false;
var isSelected = !isInlineCommentViewClosed && !!(selectedAnnotations !== null && selectedAnnotations !== void 0 && selectedAnnotations.some(function (selectedAnnotation) {
return selectedAnnotation.id === mark.attrs.id;
}));
var isHovered = !isInlineCommentViewClosed && !!(hoveredAnnotations !== null && hoveredAnnotations !== void 0 && hoveredAnnotations.some(function (hoveredAnnotation) {
return hoveredAnnotation.id === mark.attrs.id;
}));
if (isSupportedBlockNode) {
focusDecorations.push(_view.Decoration.node(pos, pos + node.nodeSize, {
class: "".concat((0, _nodeviews.getBlockAnnotationViewClassname)(isUnresolved, isSelected), " ").concat(isUnresolved)
}, {
key: _utils3.decorationKey.block
}));
} else {
if ((0, _platformFeatureFlags.fg)('editor_inline_comments_on_inline_nodes')) {
if (node.isText) {
focusDecorations.push(_view.Decoration.inline(pos, pos + node.nodeSize, {
class: "".concat((0, _nodeviews.getAnnotationViewClassname)(isUnresolved, isSelected, isHovered), " ").concat(isUnresolved),
nodeName: 'span'
}));
} else {
focusDecorations.push(_view.Decoration.node(pos, pos + node.nodeSize, {
class: "".concat((0, _nodeviews.getAnnotationViewClassname)(isUnresolved, isSelected, isHovered), " ").concat(isUnresolved)
}, {
key: _utils3.decorationKey.block
}));
}
} else {
focusDecorations.push(_view.Decoration.inline(pos, pos + node.nodeSize, {
class: "".concat((0, _nodeviews.getAnnotationViewClassname)(isUnresolved, isSelected, isHovered), " ").concat(isUnresolved),
nodeName: 'span'
}));
}
}
}
});
});
decorations = decorations.add(state.doc, focusDecorations);
return decorations;
}
}
});
};