@atlaskit/editor-plugin-text-formatting
Version:
Text-formatting plugin for @atlaskit/editor-core
175 lines (174 loc) • 9.92 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.plugin = void 0;
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _keymaps = require("@atlaskit/editor-common/keymaps");
var _mark = require("@atlaskit/editor-common/mark");
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
var _utils = require("@atlaskit/editor-common/utils");
var _commands = require("@atlaskit/editor-prosemirror/commands");
var _model = require("@atlaskit/editor-prosemirror/model");
var _state = require("@atlaskit/editor-prosemirror/state");
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
var _textFormatting = _interopRequireWildcard(require("../editor-commands/text-formatting"));
var commands = _textFormatting;
var _pluginKey = require("./plugin-key");
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } // TODO: ED-26962 - Ideally this should use the custom toggleMark function from @atlaskit/editor-common so we also disable the options when selecting inline nodes but it disables the marks when the selection is empty at this point in time which is undesirable
// import { toggleMark } from '@atlaskit/editor-common/mark';
// Ignored via go/ees005
// eslint-disable-next-line import/no-namespace
var isSelectionInlineCursor = function isSelectionInlineCursor(selection) {
if (selection instanceof _state.NodeSelection) {
return true;
}
return false;
};
var checkNodeSelection = function checkNodeSelection(mark, editorState, type) {
var selection = editorState.selection;
if (isSelectionInlineCursor(selection)) {
return false;
}
return (0, _commands.toggleMark)(mark, {
type: type
})(editorState);
};
var getTextFormattingState = function getTextFormattingState(editorState, _editorAnalyticsAPI) {
var _editorState$schema$m = editorState.schema.marks,
em = _editorState$schema$m.em,
code = _editorState$schema$m.code,
strike = _editorState$schema$m.strike,
strong = _editorState$schema$m.strong,
subsup = _editorState$schema$m.subsup,
underline = _editorState$schema$m.underline;
var state = {
isInitialised: true
};
var showOnlyCommonMarks = (0, _expValEquals.expValEquals)('platform_editor_controls', 'cohort', 'variant1');
if (showOnlyCommonMarks) {
// Code marks will disable all other formatting options when they are included in a
// selection but (for now) we do not want to make it behave differently in regards to which
// toolbar items are highlighted on selection. We need to track code in selection seperately
// to ensure all other formatting options are disabled appropriately.
if (code) {
state.codeInSelection = (0, _mark.anyMarkActive)(editorState, code.create());
}
var marks = [[code, 'code'], [em, 'em'], [strike, 'strike'], [strong, 'strong'], [underline, 'underline'], [subsup === null || subsup === void 0 ? void 0 : subsup.create({
type: 'sub'
}), 'subscript'], [subsup === null || subsup === void 0 ? void 0 : subsup.create({
type: 'sup'
}), 'superscript']].filter(function (_ref) {
var _ref2 = (0, _slicedToArray2.default)(_ref, 1),
mark = _ref2[0];
return mark;
});
var marksToName = new Map(marks);
var activeMarks = (0, _mark.wholeSelectionHasMarks)(editorState, Array.from(marksToName.keys()));
var _iterator = _createForOfIteratorHelper(marks),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var _step$value = (0, _slicedToArray2.default)(_step.value, 2),
mark = _step$value[0],
markName = _step$value[1];
var active = activeMarks.get(mark);
if (active !== undefined) {
state["".concat(markName, "Active")] = active;
}
state["".concat(markName, "Disabled")] =
// Disable when code is active, except for code itself which should not be disabled
// when code is in selection 😅
state.codeInSelection && markName !== 'code' ? true : !checkNodeSelection(mark instanceof _model.MarkType ? mark : mark.type, editorState);
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
return state;
}
if (code) {
state.codeActive = (0, _mark.anyMarkActive)(editorState, code.create());
state.codeDisabled = !checkNodeSelection(code, editorState);
}
if (em) {
state.emActive = (0, _mark.anyMarkActive)(editorState, em);
state.emDisabled = state.codeActive ? true : !checkNodeSelection(em, editorState);
}
if (strike) {
state.strikeActive = (0, _mark.anyMarkActive)(editorState, strike);
state.strikeDisabled = state.codeActive ? true : !checkNodeSelection(strike, editorState);
}
if (strong) {
state.strongActive = (0, _mark.anyMarkActive)(editorState, strong);
state.strongDisabled = state.codeActive ? true : !checkNodeSelection(strong, editorState);
}
if (subsup) {
var subMark = subsup.create({
type: 'sub'
});
var supMark = subsup.create({
type: 'sup'
});
state.subscriptActive = (0, _mark.anyMarkActive)(editorState, subMark);
state.superscriptActive = (0, _mark.anyMarkActive)(editorState, supMark);
state.subscriptDisabled = state.codeActive ? true : !checkNodeSelection(subsup, editorState, 'sub');
state.superscriptDisabled = state.codeActive ? true : !checkNodeSelection(subsup, editorState, 'sup');
}
if (underline) {
state.underlineActive = (0, _mark.anyMarkActive)(editorState, underline);
state.underlineDisabled = state.codeActive ? true : !checkNodeSelection(underline, editorState);
}
return state;
};
var plugin = exports.plugin = function plugin(dispatch, editorAnalyticsAPI) {
return new _safePlugin.SafePlugin({
state: {
init: function init(_config, state) {
return getTextFormattingState(state, editorAnalyticsAPI);
},
apply: function apply(_tr, pluginState, _oldState, newState) {
var state = getTextFormattingState(newState, editorAnalyticsAPI);
if (!(0, _utils.shallowEqual)(pluginState, state)) {
dispatch(_pluginKey.pluginKey, state);
return state;
}
return pluginState;
}
},
key: _pluginKey.pluginKey,
props: {
handleKeyDown: function handleKeyDown(view, event) {
var _pluginKey$getState;
var state = view.state,
dispatch = view.dispatch;
if (event.key === _keymaps.moveRight.common && !event.metaKey) {
return commands.moveRight()(state, dispatch);
} else if (event.key === _keymaps.moveLeft.common && !event.metaKey) {
return commands.moveLeft()(state, dispatch);
} else if (event.key === 'u' && event.metaKey && (_pluginKey$getState = _pluginKey.pluginKey.getState(state)) !== null && _pluginKey$getState !== void 0 && _pluginKey$getState.underlineDisabled && (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1')) {
// This is a workaround for browser behaviour with cmd+u (in Chrome only) where the underline mark being applied around the selection
event.preventDefault();
}
return false;
},
handleTextInput: function handleTextInput(view, from, to, text) {
var state = view.state,
dispatch = view.dispatch;
var schema = state.schema,
parentNodeType = state.selection.$from.parent.type;
if (parentNodeType.allowsMarkType(schema.marks.code)) {
return (0, _textFormatting.createInlineCodeFromTextInputWithAnalytics)(editorAnalyticsAPI)(from, to, text)(state, dispatch);
}
return false;
}
}
});
};