tiptap-extensions
Version:
Extensions for tiptap
1,683 lines (1,474 loc) • 84.5 kB
JavaScript
/*!
* tiptap-extensions v1.32.1
* (c) 2020 überdosis GbR (limited liability)
* @license MIT
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('tiptap'), require('tiptap-commands'), require('lowlight/lib/core'), require('prosemirror-view'), require('prosemirror-utils'), require('prosemirror-state'), require('regenerator-runtime/runtime'), require('prosemirror-tables'), require('tiptap-utils'), require('prosemirror-transform'), require('prosemirror-collab'), require('prosemirror-history')) :
typeof define === 'function' && define.amd ? define(['exports', 'tiptap', 'tiptap-commands', 'lowlight/lib/core', 'prosemirror-view', 'prosemirror-utils', 'prosemirror-state', 'regenerator-runtime/runtime', 'prosemirror-tables', 'tiptap-utils', 'prosemirror-transform', 'prosemirror-collab', 'prosemirror-history'], factory) :
(global = global || self, factory(global.tiptapExtensions = {}, global.tiptap, global.tiptapCommands, global.low, global.prosemirrorView, global.prosemirrorUtils, global.prosemirrorState, null, global.prosemirrorTables, global.tiptapUtils, global.prosemirrorTransform, global.prosemirrorCollab, global.prosemirrorHistory));
}(this, (function (exports, tiptap, tiptapCommands, low, prosemirrorView, prosemirrorUtils, prosemirrorState, runtime, prosemirrorTables, tiptapUtils, prosemirrorTransform, prosemirrorCollab, prosemirrorHistory) { 'use strict';
low = low && Object.prototype.hasOwnProperty.call(low, 'default') ? low['default'] : low;
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
try {
var info = gen[key](arg);
var value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
Promise.resolve(value).then(_next, _throw);
}
}
function _asyncToGenerator(fn) {
return function () {
var self = this,
args = arguments;
return new Promise(function (resolve, reject) {
var gen = fn.apply(self, args);
function _next(value) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
}
function _throw(err) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
}
_next(undefined);
});
};
}
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function ownKeys(object, enumerableOnly) {
var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(object);
if (enumerableOnly) symbols = symbols.filter(function (sym) {
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
});
keys.push.apply(keys, symbols);
}
return keys;
}
function _objectSpread2(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i] != null ? arguments[i] : {};
if (i % 2) {
ownKeys(Object(source), true).forEach(function (key) {
_defineProperty(target, key, source[key]);
});
} else if (Object.getOwnPropertyDescriptors) {
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
} else {
ownKeys(Object(source)).forEach(function (key) {
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
});
}
}
return target;
}
function _inherits(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf(subClass, superClass);
}
function _getPrototypeOf(o) {
_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf(o);
}
function _setPrototypeOf(o, p) {
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf(o, p);
}
function _isNativeReflectConstruct() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _assertThisInitialized(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _possibleConstructorReturn(self, call) {
if (call && (typeof call === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized(self);
}
function _createSuper(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct();
return function _createSuperInternal() {
var Super = _getPrototypeOf(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn(this, result);
};
}
function _slicedToArray(arr, i) {
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
}
function _toConsumableArray(arr) {
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
}
function _arrayWithoutHoles(arr) {
if (Array.isArray(arr)) return _arrayLikeToArray(arr);
}
function _arrayWithHoles(arr) {
if (Array.isArray(arr)) return arr;
}
function _iterableToArray(iter) {
if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
}
function _iterableToArrayLimit(arr, i) {
if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
var _arr = [];
var _n = true;
var _d = false;
var _e = undefined;
try {
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"] != null) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
var Blockquote = /*#__PURE__*/function (_Node) {
_inherits(Blockquote, _Node);
var _super = _createSuper(Blockquote);
function Blockquote() {
_classCallCheck(this, Blockquote);
return _super.apply(this, arguments);
}
_createClass(Blockquote, [{
key: "commands",
value: function commands(_ref) {
var type = _ref.type,
schema = _ref.schema;
return function () {
return tiptapCommands.toggleWrap(type, schema.nodes.paragraph);
};
}
}, {
key: "keys",
value: function keys(_ref2) {
var type = _ref2.type;
return {
'Ctrl->': tiptapCommands.toggleWrap(type)
};
}
}, {
key: "inputRules",
value: function inputRules(_ref3) {
var type = _ref3.type;
return [tiptapCommands.wrappingInputRule(/^\s*>\s$/, type)];
}
}, {
key: "name",
get: function get() {
return 'blockquote';
}
}, {
key: "schema",
get: function get() {
return {
content: 'block*',
group: 'block',
defining: true,
draggable: false,
parseDOM: [{
tag: 'blockquote'
}],
toDOM: function toDOM() {
return ['blockquote', 0];
}
};
}
}]);
return Blockquote;
}(tiptap.Node);
var BulletList = /*#__PURE__*/function (_Node) {
_inherits(BulletList, _Node);
var _super = _createSuper(BulletList);
function BulletList() {
_classCallCheck(this, BulletList);
return _super.apply(this, arguments);
}
_createClass(BulletList, [{
key: "commands",
value: function commands(_ref) {
var type = _ref.type,
schema = _ref.schema;
return function () {
return tiptapCommands.toggleList(type, schema.nodes.list_item);
};
}
}, {
key: "keys",
value: function keys(_ref2) {
var type = _ref2.type,
schema = _ref2.schema;
return {
'Shift-Ctrl-8': tiptapCommands.toggleList(type, schema.nodes.list_item)
};
}
}, {
key: "inputRules",
value: function inputRules(_ref3) {
var type = _ref3.type;
return [tiptapCommands.wrappingInputRule(/^\s*([-+*])\s$/, type)];
}
}, {
key: "name",
get: function get() {
return 'bullet_list';
}
}, {
key: "schema",
get: function get() {
return {
content: 'list_item+',
group: 'block',
parseDOM: [{
tag: 'ul'
}],
toDOM: function toDOM() {
return ['ul', 0];
}
};
}
}]);
return BulletList;
}(tiptap.Node);
var CodeBlock = /*#__PURE__*/function (_Node) {
_inherits(CodeBlock, _Node);
var _super = _createSuper(CodeBlock);
function CodeBlock() {
_classCallCheck(this, CodeBlock);
return _super.apply(this, arguments);
}
_createClass(CodeBlock, [{
key: "commands",
value: function commands(_ref) {
var type = _ref.type,
schema = _ref.schema;
return function () {
return tiptapCommands.toggleBlockType(type, schema.nodes.paragraph);
};
}
}, {
key: "keys",
value: function keys(_ref2) {
var type = _ref2.type;
return {
'Shift-Ctrl-\\': tiptapCommands.setBlockType(type)
};
}
}, {
key: "inputRules",
value: function inputRules(_ref3) {
var type = _ref3.type;
return [tiptapCommands.textblockTypeInputRule(/^```$/, type)];
}
}, {
key: "name",
get: function get() {
return 'code_block';
}
}, {
key: "schema",
get: function get() {
return {
content: 'text*',
marks: '',
group: 'block',
code: true,
defining: true,
draggable: false,
parseDOM: [{
tag: 'pre',
preserveWhitespace: 'full'
}],
toDOM: function toDOM() {
return ['pre', ['code', 0]];
}
};
}
}]);
return CodeBlock;
}(tiptap.Node);
function getDecorations(_ref) {
var doc = _ref.doc,
name = _ref.name;
var decorations = [];
var blocks = prosemirrorUtils.findBlockNodes(doc).filter(function (item) {
return item.node.type.name === name;
});
var flatten = function flatten(list) {
return list.reduce(function (a, b) {
return a.concat(Array.isArray(b) ? flatten(b) : b);
}, []);
};
function parseNodes(nodes) {
var className = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
return nodes.map(function (node) {
var classes = [].concat(_toConsumableArray(className), _toConsumableArray(node.properties ? node.properties.className : []));
if (node.children) {
return parseNodes(node.children, classes);
}
return {
text: node.value,
classes: classes
};
});
}
blocks.forEach(function (block) {
var startPos = block.pos + 1;
var nodes = low.highlightAuto(block.node.textContent).value;
flatten(parseNodes(nodes)).map(function (node) {
var from = startPos;
var to = from + node.text.length;
startPos = to;
return _objectSpread2(_objectSpread2({}, node), {}, {
from: from,
to: to
});
}).forEach(function (node) {
var decoration = prosemirrorView.Decoration.inline(node.from, node.to, {
class: node.classes.join(' ')
});
decorations.push(decoration);
});
});
return prosemirrorView.DecorationSet.create(doc, decorations);
}
function HighlightPlugin(_ref2) {
var name = _ref2.name;
return new tiptap.Plugin({
name: new tiptap.PluginKey('highlight'),
state: {
init: function init(_, _ref3) {
var doc = _ref3.doc;
return getDecorations({
doc: doc,
name: name
});
},
apply: function apply(transaction, decorationSet, oldState, newState) {
// TODO: find way to cache decorations
// https://discuss.prosemirror.net/t/how-to-update-multiple-inline-decorations-on-node-change/1493
var oldNodeName = oldState.selection.$head.parent.type.name;
var newNodeName = newState.selection.$head.parent.type.name;
var oldNodes = prosemirrorUtils.findBlockNodes(oldState.doc).filter(function (item) {
return item.node.type.name === name;
});
var newNodes = prosemirrorUtils.findBlockNodes(newState.doc).filter(function (item) {
return item.node.type.name === name;
}); // Apply decorations if selection includes named node, or transaction changes named node.
if (transaction.docChanged && ([oldNodeName, newNodeName].includes(name) || newNodes.length !== oldNodes.length)) {
return getDecorations({
doc: transaction.doc,
name: name
});
}
return decorationSet.map(transaction.mapping, transaction.doc);
}
},
props: {
decorations: function decorations(state) {
return this.getState(state);
}
}
});
}
var CodeBlockHighlight = /*#__PURE__*/function (_Node) {
_inherits(CodeBlockHighlight, _Node);
var _super = _createSuper(CodeBlockHighlight);
function CodeBlockHighlight() {
var _this;
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_classCallCheck(this, CodeBlockHighlight);
_this = _super.call(this, options);
try {
Object.entries(_this.options.languages).forEach(function (_ref) {
var _ref2 = _slicedToArray(_ref, 2),
name = _ref2[0],
mapping = _ref2[1];
low.registerLanguage(name, mapping);
});
} catch (err) {
throw new Error('Invalid syntax highlight definitions: define at least one highlight.js language mapping');
}
return _this;
}
_createClass(CodeBlockHighlight, [{
key: "commands",
value: function commands(_ref3) {
var type = _ref3.type,
schema = _ref3.schema;
return function () {
return tiptapCommands.toggleBlockType(type, schema.nodes.paragraph);
};
}
}, {
key: "keys",
value: function keys(_ref4) {
var type = _ref4.type;
return {
'Shift-Ctrl-\\': tiptapCommands.setBlockType(type)
};
}
}, {
key: "inputRules",
value: function inputRules(_ref5) {
var type = _ref5.type;
return [tiptapCommands.textblockTypeInputRule(/^```$/, type)];
}
}, {
key: "name",
get: function get() {
return 'code_block';
}
}, {
key: "defaultOptions",
get: function get() {
return {
languages: {}
};
}
}, {
key: "schema",
get: function get() {
return {
content: 'text*',
marks: '',
group: 'block',
code: true,
defining: true,
draggable: false,
parseDOM: [{
tag: 'pre',
preserveWhitespace: 'full'
}],
toDOM: function toDOM() {
return ['pre', ['code', 0]];
}
};
}
}, {
key: "plugins",
get: function get() {
return [HighlightPlugin({
name: this.name
})];
}
}]);
return CodeBlockHighlight;
}(tiptap.Node);
var HardBreak = /*#__PURE__*/function (_Node) {
_inherits(HardBreak, _Node);
var _super = _createSuper(HardBreak);
function HardBreak() {
_classCallCheck(this, HardBreak);
return _super.apply(this, arguments);
}
_createClass(HardBreak, [{
key: "keys",
value: function keys(_ref) {
var type = _ref.type;
var command = tiptapCommands.chainCommands(tiptapCommands.exitCode, function (state, dispatch) {
dispatch(state.tr.replaceSelectionWith(type.create()).scrollIntoView());
return true;
});
return {
'Mod-Enter': command,
'Shift-Enter': command
};
}
}, {
key: "name",
get: function get() {
return 'hard_break';
}
}, {
key: "schema",
get: function get() {
return {
inline: true,
group: 'inline',
selectable: false,
parseDOM: [{
tag: 'br'
}],
toDOM: function toDOM() {
return ['br'];
}
};
}
}]);
return HardBreak;
}(tiptap.Node);
var Heading = /*#__PURE__*/function (_Node) {
_inherits(Heading, _Node);
var _super = _createSuper(Heading);
function Heading() {
_classCallCheck(this, Heading);
return _super.apply(this, arguments);
}
_createClass(Heading, [{
key: "commands",
value: function commands(_ref) {
var type = _ref.type,
schema = _ref.schema;
return function (attrs) {
return tiptapCommands.toggleBlockType(type, schema.nodes.paragraph, attrs);
};
}
}, {
key: "keys",
value: function keys(_ref2) {
var type = _ref2.type;
return this.options.levels.reduce(function (items, level) {
return _objectSpread2(_objectSpread2({}, items), _defineProperty({}, "Shift-Ctrl-".concat(level), tiptapCommands.setBlockType(type, {
level: level
})));
}, {});
}
}, {
key: "inputRules",
value: function inputRules(_ref3) {
var type = _ref3.type;
return this.options.levels.map(function (level) {
return tiptapCommands.textblockTypeInputRule(new RegExp("^(#{1,".concat(level, "})\\s$")), type, function () {
return {
level: level
};
});
});
}
}, {
key: "name",
get: function get() {
return 'heading';
}
}, {
key: "defaultOptions",
get: function get() {
return {
levels: [1, 2, 3, 4, 5, 6]
};
}
}, {
key: "schema",
get: function get() {
return {
attrs: {
level: {
default: 1
}
},
content: 'inline*',
group: 'block',
defining: true,
draggable: false,
parseDOM: this.options.levels.map(function (level) {
return {
tag: "h".concat(level),
attrs: {
level: level
}
};
}),
toDOM: function toDOM(node) {
return ["h".concat(node.attrs.level), 0];
}
};
}
}]);
return Heading;
}(tiptap.Node);
var HorizontalRule = /*#__PURE__*/function (_Node) {
_inherits(HorizontalRule, _Node);
var _super = _createSuper(HorizontalRule);
function HorizontalRule() {
_classCallCheck(this, HorizontalRule);
return _super.apply(this, arguments);
}
_createClass(HorizontalRule, [{
key: "commands",
value: function commands(_ref) {
var type = _ref.type;
return function () {
return function (state, dispatch) {
return dispatch(state.tr.replaceSelectionWith(type.create()));
};
};
}
}, {
key: "inputRules",
value: function inputRules(_ref2) {
var type = _ref2.type;
return [tiptapCommands.nodeInputRule(/^(?:---|___\s|\*\*\*\s)$/, type)];
}
}, {
key: "name",
get: function get() {
return 'horizontal_rule';
}
}, {
key: "schema",
get: function get() {
return {
group: 'block',
parseDOM: [{
tag: 'hr'
}],
toDOM: function toDOM() {
return ['hr'];
}
};
}
}]);
return HorizontalRule;
}(tiptap.Node);
/**
* Matches following attributes in Markdown-typed image: [, alt, src, title]
*
* Example:
*  -> [, "Lorem", "image.jpg"]
*  -> [, "", "image.jpg", "Ipsum"]
*  -> [, "Lorem", "image.jpg", "Ipsum"]
*/
var IMAGE_INPUT_REGEX = /!\[(.+|:?)]\((\S+)(?:(?:\s+)["'](\S+)["'])?\)/;
var Image = /*#__PURE__*/function (_Node) {
_inherits(Image, _Node);
var _super = _createSuper(Image);
function Image() {
_classCallCheck(this, Image);
return _super.apply(this, arguments);
}
_createClass(Image, [{
key: "commands",
value: function commands(_ref) {
var type = _ref.type;
return function (attrs) {
return function (state, dispatch) {
var selection = state.selection;
var position = selection.$cursor ? selection.$cursor.pos : selection.$to.pos;
var node = type.create(attrs);
var transaction = state.tr.insert(position, node);
dispatch(transaction);
};
};
}
}, {
key: "inputRules",
value: function inputRules(_ref2) {
var type = _ref2.type;
return [tiptapCommands.nodeInputRule(IMAGE_INPUT_REGEX, type, function (match) {
var _match = _slicedToArray(match, 4),
alt = _match[1],
src = _match[2],
title = _match[3];
return {
src: src,
alt: alt,
title: title
};
})];
}
}, {
key: "name",
get: function get() {
return 'image';
}
}, {
key: "schema",
get: function get() {
return {
inline: true,
attrs: {
src: {},
alt: {
default: null
},
title: {
default: null
}
},
group: 'inline',
draggable: true,
parseDOM: [{
tag: 'img[src]',
getAttrs: function getAttrs(dom) {
return {
src: dom.getAttribute('src'),
title: dom.getAttribute('title'),
alt: dom.getAttribute('alt')
};
}
}],
toDOM: function toDOM(node) {
return ['img', node.attrs];
}
};
}
}, {
key: "plugins",
get: function get() {
return [new tiptap.Plugin({
props: {
handleDOMEvents: {
drop: function drop(view, event) {
var hasFiles = event.dataTransfer && event.dataTransfer.files && event.dataTransfer.files.length;
if (!hasFiles) {
return;
}
var images = Array.from(event.dataTransfer.files).filter(function (file) {
return /image/i.test(file.type);
});
if (images.length === 0) {
return;
}
event.preventDefault();
var schema = view.state.schema;
var coordinates = view.posAtCoords({
left: event.clientX,
top: event.clientY
});
images.forEach(function (image) {
var reader = new FileReader();
reader.onload = function (readerEvent) {
var node = schema.nodes.image.create({
src: readerEvent.target.result
});
var transaction = view.state.tr.insert(coordinates.pos, node);
view.dispatch(transaction);
};
reader.readAsDataURL(image);
});
}
}
}
})];
}
}]);
return Image;
}(tiptap.Node);
var ListItem = /*#__PURE__*/function (_Node) {
_inherits(ListItem, _Node);
var _super = _createSuper(ListItem);
function ListItem() {
_classCallCheck(this, ListItem);
return _super.apply(this, arguments);
}
_createClass(ListItem, [{
key: "keys",
value: function keys(_ref) {
var type = _ref.type;
return {
Enter: tiptapCommands.splitListItem(type),
Tab: tiptapCommands.sinkListItem(type),
'Shift-Tab': tiptapCommands.liftListItem(type)
};
}
}, {
key: "name",
get: function get() {
return 'list_item';
}
}, {
key: "schema",
get: function get() {
return {
content: 'paragraph block*',
defining: true,
draggable: false,
parseDOM: [{
tag: 'li'
}],
toDOM: function toDOM() {
return ['li', 0];
}
};
}
}]);
return ListItem;
}(tiptap.Node);
function triggerCharacter(_ref) {
var _ref$char = _ref.char,
char = _ref$char === void 0 ? '@' : _ref$char,
_ref$allowSpaces = _ref.allowSpaces,
allowSpaces = _ref$allowSpaces === void 0 ? false : _ref$allowSpaces,
_ref$startOfLine = _ref.startOfLine,
startOfLine = _ref$startOfLine === void 0 ? false : _ref$startOfLine;
return function ($position) {
// cancel if top level node
if ($position.depth <= 0) {
return false;
} // Matching expressions used for later
var escapedChar = "\\".concat(char);
var suffix = new RegExp("\\s".concat(escapedChar, "$"));
var prefix = startOfLine ? '^' : '';
var regexp = allowSpaces ? new RegExp("".concat(prefix).concat(escapedChar, ".*?(?=\\s").concat(escapedChar, "|$)"), 'gm') : new RegExp("".concat(prefix, "(?:^)?").concat(escapedChar, "[^\\s").concat(escapedChar, "]*"), 'gm'); // Lookup the boundaries of the current node
var textFrom = $position.before();
var textTo = $position.end();
var text = $position.doc.textBetween(textFrom, textTo, '\0', '\0');
var match = regexp.exec(text);
var position;
while (match !== null) {
// JavaScript doesn't have lookbehinds; this hacks a check that first character is " "
// or the line beginning
var matchPrefix = match.input.slice(Math.max(0, match.index - 1), match.index);
if (/^[\s\0]?$/.test(matchPrefix)) {
// The absolute position of the match in the document
var from = match.index + $position.start();
var to = from + match[0].length; // Edge case handling; if spaces are allowed and we're directly in between
// two triggers
if (allowSpaces && suffix.test(text.slice(to - 1, to + 1))) {
match[0] += ' ';
to += 1;
} // If the $position is located within the matched substring, return that range
if (from < $position.pos && to >= $position.pos) {
position = {
range: {
from: from,
to: to
},
query: match[0].slice(char.length),
text: match[0]
};
}
}
match = regexp.exec(text);
}
return position;
};
}
function SuggestionsPlugin(_ref2) {
var _ref2$matcher = _ref2.matcher,
matcher = _ref2$matcher === void 0 ? {
char: '@',
allowSpaces: false,
startOfLine: false
} : _ref2$matcher,
_ref2$appendText = _ref2.appendText,
appendText = _ref2$appendText === void 0 ? null : _ref2$appendText,
_ref2$suggestionClass = _ref2.suggestionClass,
suggestionClass = _ref2$suggestionClass === void 0 ? 'suggestion' : _ref2$suggestionClass,
_ref2$command = _ref2.command,
_command = _ref2$command === void 0 ? function () {
return false;
} : _ref2$command,
_ref2$items = _ref2.items,
items = _ref2$items === void 0 ? [] : _ref2$items,
_ref2$onEnter = _ref2.onEnter,
onEnter = _ref2$onEnter === void 0 ? function () {
return false;
} : _ref2$onEnter,
_ref2$onChange = _ref2.onChange,
onChange = _ref2$onChange === void 0 ? function () {
return false;
} : _ref2$onChange,
_ref2$onExit = _ref2.onExit,
onExit = _ref2$onExit === void 0 ? function () {
return false;
} : _ref2$onExit,
_ref2$onKeyDown = _ref2.onKeyDown,
onKeyDown = _ref2$onKeyDown === void 0 ? function () {
return false;
} : _ref2$onKeyDown,
_ref2$onFilter = _ref2.onFilter,
onFilter = _ref2$onFilter === void 0 ? function (searchItems, query) {
if (!query) {
return searchItems;
}
return searchItems.filter(function (item) {
return JSON.stringify(item).toLowerCase().includes(query.toLowerCase());
});
} : _ref2$onFilter;
return new prosemirrorState.Plugin({
key: new prosemirrorState.PluginKey('suggestions'),
view: function view() {
var _this = this;
return {
update: function () {
var _update = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(view, prevState) {
var prev, next, moved, started, stopped, changed, handleStart, handleChange, handleExit, state, decorationNode, virtualNode, props;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
prev = _this.key.getState(prevState);
next = _this.key.getState(view.state); // See how the state changed
moved = prev.active && next.active && prev.range.from !== next.range.from;
started = !prev.active && next.active;
stopped = prev.active && !next.active;
changed = !started && !stopped && prev.query !== next.query;
handleStart = started || moved;
handleChange = changed && !moved;
handleExit = stopped || moved; // Cancel when suggestion isn't active
if (!(!handleStart && !handleChange && !handleExit)) {
_context.next = 11;
break;
}
return _context.abrupt("return");
case 11:
state = handleExit ? prev : next;
decorationNode = document.querySelector("[data-decoration-id=\"".concat(state.decorationId, "\"]")); // build a virtual node for popper.js or tippy.js
// this can be used for building popups without a DOM node
virtualNode = decorationNode ? {
getBoundingClientRect: function getBoundingClientRect() {
return decorationNode.getBoundingClientRect();
},
clientWidth: decorationNode.clientWidth,
clientHeight: decorationNode.clientHeight
} : null;
_context.t0 = view;
_context.t1 = state.range;
_context.t2 = state.query;
_context.t3 = state.text;
_context.t4 = decorationNode;
_context.t5 = virtualNode;
if (!(handleChange || handleStart)) {
_context.next = 36;
break;
}
_context.t7 = onFilter;
if (!Array.isArray(items)) {
_context.next = 26;
break;
}
_context.t8 = items;
_context.next = 29;
break;
case 26:
_context.next = 28;
return items();
case 28:
_context.t8 = _context.sent;
case 29:
_context.t9 = _context.t8;
_context.t10 = state.query;
_context.next = 33;
return (0, _context.t7)(_context.t9, _context.t10);
case 33:
_context.t6 = _context.sent;
_context.next = 37;
break;
case 36:
_context.t6 = [];
case 37:
_context.t11 = _context.t6;
_context.t12 = function command(_ref3) {
var range = _ref3.range,
attrs = _ref3.attrs;
_command({
range: range,
attrs: attrs,
schema: view.state.schema
})(view.state, view.dispatch, view);
if (appendText) {
tiptapCommands.insertText(appendText)(view.state, view.dispatch, view);
}
};
props = {
view: _context.t0,
range: _context.t1,
query: _context.t2,
text: _context.t3,
decorationNode: _context.t4,
virtualNode: _context.t5,
items: _context.t11,
command: _context.t12
};
// Trigger the hooks when necessary
if (handleExit) {
onExit(props);
}
if (handleChange) {
onChange(props);
}
if (handleStart) {
onEnter(props);
}
case 43:
case "end":
return _context.stop();
}
}
}, _callee);
}));
function update(_x, _x2) {
return _update.apply(this, arguments);
}
return update;
}()
};
},
state: {
// Initialize the plugin's internal state.
init: function init() {
return {
active: false,
range: {},
query: null,
text: null
};
},
// Apply changes to the plugin state from a view transaction.
apply: function apply(tr, prev) {
var selection = tr.selection;
var next = _objectSpread2({}, prev); // We can only be suggesting if there is no selection
if (selection.from === selection.to) {
// Reset active state if we just left the previous suggestion range
if (selection.from < prev.range.from || selection.from > prev.range.to) {
next.active = false;
} // Try to match against where our cursor currently is
var $position = selection.$from;
var match = triggerCharacter(matcher)($position);
var decorationId = (Math.random() + 1).toString(36).substr(2, 5); // If we found a match, update the current state to show it
if (match) {
next.active = true;
next.decorationId = prev.decorationId ? prev.decorationId : decorationId;
next.range = match.range;
next.query = match.query;
next.text = match.text;
} else {
next.active = false;
}
} else {
next.active = false;
} // Make sure to empty the range if suggestion is inactive
if (!next.active) {
next.decorationId = null;
next.range = {};
next.query = null;
next.text = null;
}
return next;
}
},
props: {
// Call the keydown hook if suggestion is active.
handleKeyDown: function handleKeyDown(view, event) {
var _this$getState = this.getState(view.state),
active = _this$getState.active,
range = _this$getState.range;
if (!active) return false;
return onKeyDown({
view: view,
event: event,
range: range
});
},
// Setup decorator on the currently active suggestion.
decorations: function decorations(editorState) {
var _this$getState2 = this.getState(editorState),
active = _this$getState2.active,
range = _this$getState2.range,
decorationId = _this$getState2.decorationId;
if (!active) return null;
return prosemirrorView.DecorationSet.create(editorState.doc, [prosemirrorView.Decoration.inline(range.from, range.to, {
nodeName: 'span',
class: suggestionClass,
'data-decoration-id': decorationId
})]);
}
}
});
}
var Mention = /*#__PURE__*/function (_Node) {
_inherits(Mention, _Node);
var _super = _createSuper(Mention);
function Mention() {
_classCallCheck(this, Mention);
return _super.apply(this, arguments);
}
_createClass(Mention, [{
key: "commands",
value: function commands(_ref) {
var _this = this;
var schema = _ref.schema;
return function (attrs) {
return tiptapCommands.replaceText(null, schema.nodes[_this.name], attrs);
};
}
}, {
key: "name",
get: function get() {
return 'mention';
}
}, {
key: "defaultOptions",
get: function get() {
return {
matcher: {
char: '@',
allowSpaces: false,
startOfLine: false
},
mentionClass: 'mention',
suggestionClass: 'mention-suggestion'
};
}
}, {
key: "schema",
get: function get() {
var _this2 = this;
return {
attrs: {
id: {},
label: {}
},
group: 'inline',
inline: true,
selectable: false,
atom: true,
toDOM: function toDOM(node) {
return ['span', {
class: _this2.options.mentionClass,
'data-mention-id': node.attrs.id
}, "".concat(_this2.options.matcher.char).concat(node.attrs.label)];
},
parseDOM: [{
tag: 'span[data-mention-id]',
getAttrs: function getAttrs(dom) {
var id = dom.getAttribute('data-mention-id');
var label = dom.innerText.split(_this2.options.matcher.char).join('');
return {
id: id,
label: label
};
}
}]
};
}
}, {
key: "plugins",
get: function get() {
var _this3 = this;
return [SuggestionsPlugin({
command: function command(_ref2) {
var range = _ref2.range,
attrs = _ref2.attrs,
schema = _ref2.schema;
return tiptapCommands.replaceText(range, schema.nodes[_this3.name], attrs);
},
appendText: ' ',
matcher: this.options.matcher,
items: this.options.items,
onEnter: this.options.onEnter,
onChange: this.options.onChange,
onExit: this.options.onExit,
onKeyDown: this.options.onKeyDown,
onFilter: this.options.onFilter,
suggestionClass: this.options.suggestionClass
})];
}
}]);
return Mention;
}(tiptap.Node);
var OrderedList = /*#__PURE__*/function (_Node) {
_inherits(OrderedList, _Node);
var _super = _createSuper(OrderedList);
function OrderedList() {
_classCallCheck(this, OrderedList);
return _super.apply(this, arguments);
}
_createClass(OrderedList, [{
key: "commands",
value: function commands(_ref) {
var type = _ref.type,
schema = _ref.schema;
return function () {
return tiptapCommands.toggleList(type, schema.nodes.list_item);
};
}
}, {
key: "keys",
value: function keys(_ref2) {
var type = _ref2.type,
schema = _ref2.schema;
return {
'Shift-Ctrl-9': tiptapCommands.toggleList(type, schema.nodes.list_item)
};
}
}, {
key: "inputRules",
value: function inputRules(_ref3) {
var type = _ref3.type;
return [tiptapCommands.wrappingInputRule(/^(\d+)\.\s$/, type, function (match) {
return {
order: +match[1]
};
}, function (match, node) {
return node.childCount + node.attrs.order === +match[1];
})];
}
}, {
key: "name",
get: function get() {
return 'ordered_list';
}
}, {
key: "schema",
get: function get() {
return {
attrs: {
order: {
default: 1
}
},
content: 'list_item+',
group: 'block',
parseDOM: [{
tag: 'ol',
getAttrs: function getAttrs(dom) {
return {
order: dom.hasAttribute('start') ? +dom.getAttribute('start') : 1
};
}
}],
toDOM: function toDOM(node) {
return node.attrs.order === 1 ? ['ol', 0] : ['ol', {
start: node.attrs.order
}, 0];
}
};
}
}]);
return OrderedList;
}(tiptap.Node);
var TableNodes = prosemirrorTables.tableNodes({
tableGroup: 'block',
cellContent: 'block+',
cellAttributes: {
background: {
default: null,
getFromDOM: function getFromDOM(dom) {
return dom.style.backgroundColor || null;
},
setDOMAttr: function setDOMAttr(value, attrs) {
if (value) {
var style = {
style: "".concat(attrs.style || '', "background-color: ").concat(value, ";")
};
Object.assign(attrs, style);
}
}
}
}
});
var Table = /*#__PURE__*/function (_Node) {
_inherits(Table, _Node);
var _super = _createSuper(Table);
function Table() {
_classCallCheck(this, Table);
return _super.apply(this, arguments);
}
_createClass(Table, [{
key: "commands",
value: function commands(_ref) {
var schema = _ref.schema;
return {
createTable: function createTable(_ref2) {
var rowsCount = _ref2.rowsCount,
colsCount = _ref2.colsCount,
withHeaderRow = _ref2.withHeaderRow;
return function (state, dispatch) {
var offset = state.tr.selection.anchor + 1;
var nodes = prosemirrorUtils.createTable(schema, rowsCount, colsCount, withHeaderRow);
var tr = state.tr.replaceSelectionWith(nodes).scrollIntoView();
var resolvedPos = tr.doc.resolve(offset);
tr.setSelection(prosemirrorState.TextSelection.near(resolvedPos));
dispatch(tr);
};
},
addColumnBefore: function addColumnBefore() {
return prosemirrorTables.addColumnBefore;
},
addColumnAfter: function addColumnAfter() {
return prosemirrorTables.addColumnAfter;
},
deleteColumn: function deleteColumn() {
return prosemirrorTables.deleteColumn;
},
addRowBefore: function addRowBefore() {
return prosemirrorTables.addRowBefore;
},
addRowAfter: function addRowAfter() {
return prosemirrorTables.addRowAfter;
},
deleteRow: function deleteRow() {
return prosemirrorTables.deleteRow;
},
deleteTable: function deleteTable() {
return prosemirrorTables.deleteTable;
},
toggleCellMerge: function toggleCellMerge() {
return function (state, dispatch) {
if (prosemirrorTables.mergeCells(state, dispatch)) {
return;
}
prosemirrorTables.splitCell(state, dispatch);
};
},
mergeCells: function mergeCells() {
return prosemirrorTables.mergeCells;
},
splitCell: function splitCell() {
return prosemirrorTables.splitCell;
},
toggleHeaderColumn: function toggleHeaderColumn() {
return prosemirrorTables.toggleHeaderColumn;
},
toggleHeaderRow: function toggleHeaderRow() {
return prosemirrorTables.toggleHeaderRow;
},
toggleHeaderCell: function toggleHeaderCell() {
return prosemirrorTables.toggleHeaderCell;
},
setCellAttr: function setCellAttr() {
return prosemirrorTables.setCellAttr;
},
fixTables: function fixTables() {
return prosemirrorTables.fixTables;
}
};
}
}, {
key: "keys",
value: function keys() {
return {
Tab: prosemirrorTables.goToNextCell(1),
'Shift-Tab': prosemirrorTables.goToNextCell(-1)
};
}
}, {
key: "name",
get: function get() {
return 'table';
}
}, {
key: "defaultOptions",
get: function get() {
return {
resizable: false
};
}
}, {
key: "schema",
get: function get() {
return TableNodes.table;
}
}, {
key: "plugins",
get: function get() {
return [].concat(_toConsumableArray(this.options.resizable ? [prosemirrorTables.columnResizing()] : []), [prosemirrorTables.tableEditing()]);
}
}]);
return Table;
}(tiptap.Node);
var TableHeader = /*#__PURE__*/function (_Node) {
_inherits(TableHeader, _Node);
var _super = _createSuper(TableHeader);
function TableHeader() {
_classCallCheck(this, TableHeader);
return _super.apply(this, arguments);
}
_createClass(TableHeader, [{
key: "name",
get: function get() {
return 'table_header';
}
}, {
key: "schema",
get: function get() {
ret