@atlaskit/editor-plugin-base
Version:
Base plugin for @atlaskit/editor-core
182 lines (180 loc) • 7.45 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/defineProperty";
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
import { doc, paragraph, text } from '@atlaskit/adf-schema';
import { keymap } from '@atlaskit/editor-common/keymaps';
import { baseKeymap } from '@atlaskit/editor-prosemirror/commands';
import { history } from '@atlaskit/prosemirror-history';
import { setKeyboardHeight } from './editor-commands/set-keyboard-height';
import disableSpellcheckingPlugin from './pm-plugins/disable-spell-checking';
import filterStepsPlugin from './pm-plugins/filter-steps';
import frozenEditor from './pm-plugins/frozen-editor';
import inlineCursorTargetPlugin from './pm-plugins/inline-cursor-target';
import { createLazyNodeViewDecorationPlugin } from './pm-plugins/lazy-node-view-decoration';
import newlinePreserveMarksPlugin from './pm-plugins/newline-preserve-marks';
import scrollGutter from './pm-plugins/scroll-gutter/plugin';
import { getKeyboardHeight } from './pm-plugins/scroll-gutter/util/get-keyboard-height';
import { inputTracking } from './pm-plugins/utils/inputTrackingConfig';
export function resolveCallbacks(from, to, tr, callbacks) {
var doc = tr.doc;
doc.nodesBetween(from, to, function (node, pos) {
callbacks.forEach(function (cb) {
return cb({
tr: tr,
node: node,
pos: pos,
from: from,
to: to
});
});
});
}
var SMART_TO_ASCII = {
'…': '...',
'→': '->',
'←': '<-',
'–': '--',
'“': '"',
'”': '"',
'‘': "'",
'’': "'"
};
// eslint-disable-next-line require-unicode-regexp
var FIND_SMART_CHAR = new RegExp("[".concat(Object.keys(SMART_TO_ASCII).join(''), "]"), 'g');
var basePlugin = function basePlugin(_ref) {
var _api$featureFlags, _api$base;
var options = _ref.config,
api = _ref.api;
var featureFlags = (api === null || api === void 0 || (_api$featureFlags = api.featureFlags) === null || _api$featureFlags === void 0 ? void 0 : _api$featureFlags.sharedState.currentState()) || {};
var callbacks = [];
api === null || api === void 0 || (_api$base = api.base) === null || _api$base === void 0 || _api$base.actions.registerMarks(function (_ref2) {
var tr = _ref2.tr,
node = _ref2.node,
pos = _ref2.pos,
from = _ref2.from,
to = _ref2.to;
var doc = tr.doc;
var schema = doc.type.schema;
var textNodeType = schema.nodes.text;
if (node.type === textNodeType && node.text) {
// Find a valid start and end position because the text may be partially selected.
var startPositionInSelection = Math.max(pos, from);
var endPositionInSelection = Math.min(pos + node.nodeSize, to);
var textForReplacing = doc.textBetween(startPositionInSelection, endPositionInSelection);
var newText = textForReplacing.replace(FIND_SMART_CHAR, function (match) {
var _SMART_TO_ASCII$match;
return (_SMART_TO_ASCII$match = SMART_TO_ASCII[match]) !== null && _SMART_TO_ASCII$match !== void 0 ? _SMART_TO_ASCII$match : match;
});
var currentStartPos = tr.mapping.map(startPositionInSelection);
var currentEndPos = tr.mapping.map(endPositionInSelection);
tr.replaceWith(currentStartPos, currentEndPos, schema.text(newText, node.marks));
}
});
return {
name: 'base',
getSharedState: function getSharedState(editorState) {
return {
allowScrollGutter: options === null || options === void 0 ? void 0 : options.allowScrollGutter,
keyboardHeight: getKeyboardHeight(editorState)
};
},
actions: {
setKeyboardHeight: setKeyboardHeight,
resolveMarks: function resolveMarks(from, to, tr) {
return resolveCallbacks(from, to, tr, callbacks);
},
registerMarks: function registerMarks(callback) {
callbacks.push(callback);
}
},
pmPlugins: function pmPlugins() {
var plugins = [{
name: 'filterStepsPlugin',
plugin: function plugin(_ref3) {
var dispatchAnalyticsEvent = _ref3.dispatchAnalyticsEvent;
return filterStepsPlugin(dispatchAnalyticsEvent);
}
}];
plugins.push({
name: 'lazyNodeViewDecorationsPlugin',
plugin: function plugin() {
return createLazyNodeViewDecorationPlugin();
}
});
// In Chrome, when the selection is placed between adjacent nodes which are not contenteditatble
// the cursor appears at the right most point of the parent container.
//
// In Firefox, when the selection is placed between adjacent nodes which are not contenteditatble
// no cursor is presented to users.
//
// In Safari, when the selection is placed between adjacent nodes which are not contenteditatble
// it is not possible to navigate with arrow keys.
//
// This plugin works around the issues by inserting decorations between
// inline nodes which are set as contenteditable, and have a zero width space.
plugins.push({
name: 'inlineCursorTargetPlugin',
plugin: function plugin() {
return options && options.allowInlineCursorTarget ? inlineCursorTargetPlugin() : undefined;
}
});
plugins.push({
name: 'newlinePreserveMarksPlugin',
plugin: newlinePreserveMarksPlugin
}, {
name: 'frozenEditor',
plugin: function plugin(_ref4) {
var dispatchAnalyticsEvent = _ref4.dispatchAnalyticsEvent;
return frozenEditor(api === null || api === void 0 ? void 0 : api.contextIdentifier)(dispatchAnalyticsEvent, inputTracking, undefined);
}
}, {
name: 'history',
plugin: function plugin() {
return history();
}
},
// should be last :(
{
name: 'codeBlockIndent',
plugin: function plugin() {
return keymap(_objectSpread(_objectSpread({}, baseKeymap), {}, {
'Mod-[': function Mod() {
return true;
},
'Mod-]': function Mod() {
return true;
}
}));
}
});
if (options && options.allowScrollGutter) {
plugins.push({
name: 'scrollGutterPlugin',
plugin: function plugin() {
return scrollGutter(options.allowScrollGutter);
}
});
}
plugins.push({
name: 'disableSpellcheckingPlugin',
plugin: function plugin() {
return disableSpellcheckingPlugin(featureFlags);
}
});
return plugins;
},
nodes: function nodes() {
return [{
name: 'doc',
node: doc
}, {
name: 'paragraph',
node: paragraph
}, {
name: 'text',
node: text
}];
}
};
};
export default basePlugin;