@atlaskit/editor-core
Version:
A package contains Atlassian editor core functionality
296 lines • 12 kB
JavaScript
import { Plugin, PluginKey, } from '../../prosemirror';
import * as commands from '../../commands';
import keymapHandler from './keymap';
import inputRulePlugin from './input-rule';
import { transformToCodeAction } from './transform-to-code';
var TextFormattingState = (function () {
function TextFormattingState(state) {
this.changeHandlers = [];
// public state
this.emActive = false;
this.emDisabled = false;
this.emHidden = false;
this.codeActive = false;
this.codeDisabled = false;
this.codeHidden = false;
this.underlineActive = false;
this.underlineDisabled = false;
this.underlineHidden = false;
this.strikeActive = false;
this.strikeDisabled = false;
this.strikeHidden = false;
this.strongActive = false;
this.strongDisabled = false;
this.strongHidden = false;
this.superscriptActive = false;
this.superscriptDisabled = false;
this.superscriptHidden = false;
this.subscriptActive = false;
this.subscriptDisabled = false;
this.subscriptHidden = false;
this.state = state;
this.emHidden = !state.schema.marks.em;
this.strongHidden = !state.schema.marks.strong;
this.underlineHidden = !state.schema.marks.underline;
this.codeHidden = !state.schema.marks.code;
this.superscriptHidden = !state.schema.marks.subsup;
this.subscriptHidden = !state.schema.marks.subsup;
this.strikeHidden = !state.schema.marks.strike;
this.update(state);
}
TextFormattingState.prototype.toggleEm = function (view) {
var em = this.state.schema.marks.em;
if (em) {
return this.toggleMark(view, em);
}
return false;
};
TextFormattingState.prototype.toggleCode = function (view) {
var code = this.state.schema.marks.code;
var _a = this.state.selection, from = _a.from, to = _a.to;
if (code) {
if (!this.codeActive) {
view.dispatch(transformToCodeAction(view.state, from, to));
return true;
}
return commands.toggleMark(code)(view.state, view.dispatch);
}
return false;
};
TextFormattingState.prototype.toggleStrike = function (view) {
var strike = this.state.schema.marks.strike;
if (strike) {
return this.toggleMark(view, strike);
}
return false;
};
TextFormattingState.prototype.toggleStrong = function (view) {
var strong = this.state.schema.marks.strong;
if (strong) {
return this.toggleMark(view, strong);
}
return false;
};
TextFormattingState.prototype.toggleSuperscript = function (view) {
var subsup = this.state.schema.marks.subsup;
if (subsup) {
if (this.subscriptActive) {
// If subscript is enabled, turn it off first.
return this.toggleMark(view, subsup);
}
return this.toggleMark(view, subsup, { type: 'sup' });
}
return false;
};
TextFormattingState.prototype.toggleSubscript = function (view) {
var subsup = this.state.schema.marks.subsup;
if (subsup) {
if (this.superscriptActive) {
// If superscript is enabled, turn it off first.
return this.toggleMark(view, subsup);
}
return this.toggleMark(view, subsup, { type: 'sub' });
}
return false;
};
TextFormattingState.prototype.toggleUnderline = function (view) {
var underline = this.state.schema.marks.underline;
if (underline) {
return this.toggleMark(view, underline);
}
return false;
};
TextFormattingState.prototype.subscribe = function (cb) {
this.changeHandlers.push(cb);
cb(this);
};
TextFormattingState.prototype.unsubscribe = function (cb) {
this.changeHandlers = this.changeHandlers.filter(function (ch) { return ch !== cb; });
};
TextFormattingState.prototype.update = function (newEditorState) {
this.state = newEditorState;
var state = this.state;
var _a = state.schema.marks, em = _a.em, code = _a.code, strike = _a.strike, strong = _a.strong, subsup = _a.subsup, underline = _a.underline;
var dirty = false;
if (code) {
var newCodeActive = this.markActive(code.create());
if (newCodeActive !== this.codeActive) {
this.codeActive = newCodeActive;
dirty = true;
}
var newCodeDisabled = !commands.toggleMark(code)(this.state);
if (newCodeDisabled !== this.codeDisabled) {
this.codeDisabled = newCodeDisabled;
dirty = true;
}
}
if (em) {
var newEmActive = this.anyMarkActive(em);
if (newEmActive !== this.emActive) {
this.emActive = newEmActive;
dirty = true;
}
var newEmDisabled = !commands.toggleMark(em)(this.state);
if (this.codeActive || newEmDisabled !== this.emDisabled) {
this.emDisabled = this.codeActive ? true : newEmDisabled;
dirty = true;
}
}
if (strike) {
var newStrikeActive = this.anyMarkActive(strike);
if (newStrikeActive !== this.strikeActive) {
this.strikeActive = newStrikeActive;
dirty = true;
}
var newStrikeDisabled = !commands.toggleMark(strike)(this.state);
if (this.codeActive || newStrikeDisabled !== this.strikeDisabled) {
this.strikeDisabled = this.codeActive ? true : newStrikeDisabled;
dirty = true;
}
}
if (strong) {
var newStrongActive = this.anyMarkActive(strong);
if (newStrongActive !== this.strongActive) {
this.strongActive = newStrongActive;
dirty = true;
}
var newStrongDisabled = !commands.toggleMark(strong)(this.state);
if (this.codeActive || newStrongDisabled !== this.strongDisabled) {
this.strongDisabled = this.codeActive ? true : newStrongDisabled;
dirty = true;
}
}
if (subsup) {
var subMark = subsup.create({ type: 'sub' });
var supMark = subsup.create({ type: 'sup' });
var newSubscriptActive = this.markActive(subMark);
if (newSubscriptActive !== this.subscriptActive) {
this.subscriptActive = newSubscriptActive;
dirty = true;
}
var newSubscriptDisabled = !commands.toggleMark(subsup, { type: 'sub' })(this.state);
if (this.codeActive || newSubscriptDisabled !== this.subscriptDisabled) {
this.subscriptDisabled = this.codeActive ? true : newSubscriptDisabled;
dirty = true;
}
var newSuperscriptActive = this.markActive(supMark);
if (newSuperscriptActive !== this.superscriptActive) {
this.superscriptActive = newSuperscriptActive;
dirty = true;
}
var newSuperscriptDisabled = !commands.toggleMark(subsup, { type: 'sup' })(this.state);
if (this.codeActive || newSuperscriptDisabled !== this.superscriptDisabled) {
this.superscriptDisabled = this.codeActive ? true : newSuperscriptDisabled;
dirty = true;
}
}
if (underline) {
var newUnderlineActive = this.anyMarkActive(underline);
if (newUnderlineActive !== this.underlineActive) {
this.underlineActive = newUnderlineActive;
dirty = true;
}
var newUnderlineDisabled = !commands.toggleMark(underline)(this.state);
if (this.codeActive || newUnderlineDisabled !== this.underlineDisabled) {
this.underlineDisabled = this.codeActive ? true : newUnderlineDisabled;
dirty = true;
}
}
if (dirty) {
this.triggerOnChange();
}
};
/**
* Determine if a mark (with specific attribute values) exists anywhere in the selection.
*/
TextFormattingState.prototype.markActive = function (mark) {
var state = this.state;
var _a = state.selection, from = _a.from, to = _a.to, empty = _a.empty;
var foundMark = false;
if (this.marksToRemove) {
this.marksToRemove.forEach(function (markToRemove) {
if (markToRemove.type.name === mark.type.name) {
foundMark = true;
}
});
}
var currentMarkBefore = state.doc.rangeHasMark(from - 1, to, mark.type);
var currentMarkAfter = state.doc.rangeHasMark(from, to, mark.type);
if (foundMark && (!currentMarkBefore || (!mark.type.spec.inclusive && !currentMarkAfter))) {
return false;
}
// When the selection is empty, only the active marks apply.
if (empty) {
return !!mark.isInSet(state.tr.storedMarks || state.selection.$from.marks());
}
// For a non-collapsed selection, the marks on the nodes matter.
var found = false;
state.doc.nodesBetween(from, to, function (node) {
found = found || mark.isInSet(node.marks);
});
return found;
};
TextFormattingState.prototype.triggerOnChange = function () {
var _this = this;
this.changeHandlers.forEach(function (cb) { return cb(_this); });
};
/**
* Determine if a mark of a specific type exists anywhere in the selection.
*/
TextFormattingState.prototype.anyMarkActive = function (markType) {
var state = this.state;
var _a = state.selection, from = _a.from, to = _a.to, empty = _a.empty;
var found = false;
if (this.marksToRemove) {
this.marksToRemove.forEach(function (mark) {
if (mark.type.name === markType.name) {
found = true;
}
});
}
if (found && !state.doc.rangeHasMark(from - 1, to, markType)) {
return false;
}
if (empty) {
return !!markType.isInSet(state.tr.storedMarks || state.selection.$from.marks());
}
return state.doc.rangeHasMark(from, to, markType);
};
TextFormattingState.prototype.toggleMark = function (view, markType, attrs) {
// Disable text-formatting inside code
if (this.codeActive ? this.codeDisabled : true) {
return commands.toggleMark(markType, attrs)(view.state, view.dispatch);
}
return false;
};
return TextFormattingState;
}());
export { TextFormattingState };
export var stateKey = new PluginKey('textFormatting');
export var plugin = new Plugin({
state: {
init: function (config, state) {
return new TextFormattingState(state);
},
apply: function (tr, pluginState, oldState, newState) {
pluginState.update(newState);
return pluginState;
}
},
key: stateKey,
view: function (view) {
var pluginState = stateKey.getState(view.state);
pluginState.keymapHandler = keymapHandler(view, pluginState);
return {};
},
props: {
handleKeyDown: function (view, event) {
return stateKey.getState(view.state).keymapHandler(view, event);
}
}
});
var plugins = function (schema) {
return [plugin, inputRulePlugin(schema)].filter(function (plugin) { return !!plugin; });
};
export default plugins;
//# sourceMappingURL=index.js.map