@harbour-enterprises/superdoc 0.8.10 → 0.8.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/chunks/{super-editor.es-CnpejCPC.js → super-editor.es-D8IC7SPE.js} +719 -375
  2. package/dist/chunks/super-editor.es-D8IC7SPE.js.map +1 -0
  3. package/dist/super-editor/chunks/{converter-B5SRaBp5.js → converter-vMwuPcFT.js} +28 -27
  4. package/dist/super-editor/chunks/converter-vMwuPcFT.js.map +1 -0
  5. package/dist/super-editor/chunks/{docx-zipper-fdMcchlI.js → docx-zipper-CNguQWs9.js} +2 -2
  6. package/dist/super-editor/chunks/{docx-zipper-fdMcchlI.js.map → docx-zipper-CNguQWs9.js.map} +1 -1
  7. package/dist/super-editor/chunks/{editor-nlt5JeOJ.js → editor-aREw3zbp.js} +764 -420
  8. package/dist/super-editor/chunks/editor-aREw3zbp.js.map +1 -0
  9. package/dist/super-editor/chunks/{toolbar-COfngBDY.js → toolbar-BQJNZhd8.js} +3 -3
  10. package/dist/super-editor/chunks/{toolbar-COfngBDY.js.map → toolbar-BQJNZhd8.js.map} +1 -1
  11. package/dist/super-editor/converter.es.js +2 -2
  12. package/dist/super-editor/core/Editor.d.ts +1 -0
  13. package/dist/super-editor/core/Editor.d.ts.map +1 -1
  14. package/dist/super-editor/core/ExtensionService.d.ts.map +1 -1
  15. package/dist/super-editor/core/InputRule.d.ts +11 -0
  16. package/dist/super-editor/core/InputRule.d.ts.map +1 -0
  17. package/dist/super-editor/core/commands/index.d.ts +1 -0
  18. package/dist/super-editor/core/commands/undoInputRule.d.ts +5 -0
  19. package/dist/super-editor/core/commands/undoInputRule.d.ts.map +1 -0
  20. package/dist/super-editor/core/extensions/keymap.d.ts.map +1 -1
  21. package/dist/super-editor/core/helpers/getHTMLFromFragment.d.ts +2 -0
  22. package/dist/super-editor/core/helpers/getHTMLFromFragment.d.ts.map +1 -0
  23. package/dist/super-editor/core/helpers/getTextContentFromNodes.d.ts +2 -0
  24. package/dist/super-editor/core/helpers/getTextContentFromNodes.d.ts.map +1 -0
  25. package/dist/super-editor/core/helpers/isExtentionRulesEnabled.d.ts +2 -0
  26. package/dist/super-editor/core/helpers/isExtentionRulesEnabled.d.ts.map +1 -0
  27. package/dist/super-editor/core/inputRules/wrappingInputRule.d.ts +9 -0
  28. package/dist/super-editor/core/inputRules/wrappingInputRule.d.ts.map +1 -0
  29. package/dist/super-editor/core/utilities/isRegExp.d.ts +2 -0
  30. package/dist/super-editor/core/utilities/isRegExp.d.ts.map +1 -0
  31. package/dist/super-editor/core/utilities/objectIncludes.d.ts.map +1 -1
  32. package/dist/super-editor/docx-zipper.es.js +2 -2
  33. package/dist/super-editor/editor.es.js +3 -3
  34. package/dist/super-editor/extensions/bullet-list/bullet-list.d.ts.map +1 -1
  35. package/dist/super-editor/extensions/comment/comments-plugin.d.ts.map +1 -1
  36. package/dist/super-editor/extensions/ordered-list/ordered-list.d.ts.map +1 -1
  37. package/dist/super-editor/extensions/track-changes/trackChangesHelpers/addMarkStep.d.ts.map +1 -1
  38. package/dist/super-editor/extensions/track-changes/trackChangesHelpers/removeMarkStep.d.ts.map +1 -1
  39. package/dist/super-editor/extensions/track-changes/trackChangesHelpers/replaceStep.d.ts.map +1 -1
  40. package/dist/super-editor/file-zipper.es.js +1 -1
  41. package/dist/super-editor/super-editor.es.js +7 -7
  42. package/dist/super-editor/toolbar.es.js +2 -2
  43. package/dist/super-editor.es.js +1 -1
  44. package/dist/superdoc.es.js +3 -3
  45. package/dist/superdoc.umd.js +730 -386
  46. package/dist/superdoc.umd.js.map +1 -1
  47. package/package.json +1 -1
  48. package/dist/chunks/super-editor.es-CnpejCPC.js.map +0 -1
  49. package/dist/super-editor/chunks/converter-B5SRaBp5.js.map +0 -1
  50. package/dist/super-editor/chunks/editor-nlt5JeOJ.js.map +0 -1
@@ -12,9 +12,9 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
12
12
  var _events, _Attribute_static, getGlobalAttributes_fn, getNodeAndMarksAttributes_fn, _Schema_static, createNodesSchema_fn, createMarksSchema_fn, _ExtensionService_instances, setupExtensions_fn, attachEditorEvents_fn, _commandService, _css, _Editor_instances, init_fn, initRichText_fn, onFocus_fn, checkHeadless_fn, insertNewFileData_fn, registerPluginByNameIfNotExists_fn, createExtensionService_fn, createCommandService_fn, createConverter_fn, initMedia_fn, createSchema_fn, generatePmData_fn, createView_fn, onCollaborationReady_fn, initComments_fn, initPagination_fn, dispatchTransaction_fn, prepareDocumentForImport_fn, prepareDocumentForExport_fn, endCollaboration_fn, _FieldAnnotationView_instances, createAnnotation_fn;
13
13
  import * as Y from "yjs";
14
14
  import { UndoManager, Item as Item$1, ContentType, Text as Text$1, XmlElement } from "yjs";
15
- import { P as PluginKey, a as Plugin, M as Mapping, N as NodeSelection, S as Selection, T as TextSelection, b as Slice, D as DOMSerializer, F as Fragment, c as DOMParser$1, d as Mark$1, e as dropPoint, A as AllSelection, p as process$1, f as Schema$1, g as canSplit, l as liftTarget, h as canJoin, j as joinPoint, r as replaceStep$1, R as ReplaceAroundStep, o as objectIncludes, i as ReplaceStep, k as NodeRange, m as findWrapping, n as TrackDeleteMarkName, q as TrackInsertMarkName, v as v4, s as generateDocxRandomId, t as generateRandom32BitHex, u as TrackFormatMarkName, w as comments_module_events, x as AddMarkStep, y as RemoveMarkStep, z as twipsToLines, B as pixelsToTwips, C as SuperConverter, E as EditorState, G as toKebabCase, H as kebabCase, I as SelectionRange, J as Transform } from "./converter-B5SRaBp5.js";
15
+ import { P as PluginKey, a as Plugin, M as Mapping, N as NodeSelection, S as Selection, T as TextSelection, b as Slice, D as DOMSerializer, F as Fragment, c as DOMParser$1, d as Mark$1, e as dropPoint, A as AllSelection, p as process$1, f as Schema$1, i as isRegExp, g as canSplit, l as liftTarget, h as canJoin, j as joinPoint, r as replaceStep$1, R as ReplaceAroundStep, o as objectIncludes, k as ReplaceStep, m as NodeRange, n as findWrapping, q as TrackDeleteMarkName, s as TrackInsertMarkName, v as v4, t as generateDocxRandomId, u as generateRandom32BitHex, w as TrackFormatMarkName, x as comments_module_events, y as AddMarkStep, z as RemoveMarkStep, B as twipsToLines, C as pixelsToTwips, E as SuperConverter, G as EditorState, H as toKebabCase, I as kebabCase, J as SelectionRange, K as Transform } from "./converter-vMwuPcFT.js";
16
16
  import { ref, computed, createElementBlock, openBlock, withModifiers, Fragment as Fragment$1, renderList, normalizeClass, createCommentVNode, toDisplayString, createElementVNode, createApp } from "vue";
17
- import { D as DocxZipper } from "./docx-zipper-fdMcchlI.js";
17
+ import { D as DocxZipper } from "./docx-zipper-CNguQWs9.js";
18
18
  function getMarksFromSelection(state) {
19
19
  const { from: from2, to, empty: empty2 } = state.selection;
20
20
  const marks = [];
@@ -7961,206 +7961,15 @@ let Schema = _Schema;
7961
7961
  function getSchemaTypeByName(name, schema) {
7962
7962
  return schema.nodes[name] || schema.marks[name] || null;
7963
7963
  }
7964
- const _ExtensionService = class _ExtensionService {
7965
- constructor(extensions, userExtensions, editor) {
7966
- __privateAdd(this, _ExtensionService_instances);
7967
- __publicField(this, "editor");
7968
- __publicField(this, "schema");
7969
- __publicField(this, "extensions");
7970
- __publicField(this, "externalExtensions", []);
7971
- __publicField(this, "splittableMarks", []);
7972
- this.editor = editor;
7973
- this.externalExtensions = userExtensions || [];
7974
- this.extensions = _ExtensionService.getResolvedExtensions([...extensions, ...this.externalExtensions]);
7975
- this.schema = Schema.createSchemaByExtensions(this.extensions, editor);
7976
- __privateMethod(this, _ExtensionService_instances, setupExtensions_fn).call(this);
7977
- }
7978
- /**
7979
- * Static method for creating ExtensionService.
7980
- * @param args Arguments for the constructor.
7981
- */
7982
- static create(...args) {
7983
- return new _ExtensionService(...args);
7984
- }
7985
- /**
7986
- * Get an array of resolved extensions (e.g. sorted by priority).
7987
- * @param extensions Array of extensions.
7988
- * @returns Array of resolved extensions.
7989
- */
7990
- static getResolvedExtensions(extensions) {
7991
- const resolvedExtensions = _ExtensionService.sortByPriority(extensions);
7992
- return resolvedExtensions;
7993
- }
7994
- /**
7995
- * Sort extensions by priority.
7996
- * @param extensions Array of extensions.
7997
- * @returns Array of sorted extensions by priority.
7998
- */
7999
- static sortByPriority(extensions) {
8000
- const defaultValue = 100;
8001
- return extensions.sort((a, b) => {
8002
- const priorityA = getExtensionConfigField(a, "priority") || defaultValue;
8003
- const priorityB = getExtensionConfigField(b, "priority") || defaultValue;
8004
- if (priorityA > priorityB) return -1;
8005
- if (priorityA < priorityB) return 1;
8006
- return 0;
8007
- });
8008
- }
8009
- /**
8010
- * Get all attributes defined in the extensions.
8011
- * @returns Array of attributes.
8012
- */
8013
- get attributes() {
8014
- return Attribute.getAttributesFromExtensions(this.extensions);
8015
- }
8016
- /**
8017
- * Get all commands defined in the extensions.
8018
- * @returns Object with commands (key - command name, value - function).
8019
- */
8020
- get commands() {
8021
- let commandsObject = {};
8022
- for (const extension of this.extensions) {
8023
- const context = {
8024
- name: extension.name,
8025
- options: extension.options,
8026
- storage: extension.storage,
8027
- editor: this.editor,
8028
- type: getSchemaTypeByName(extension.name, this.schema)
8029
- };
8030
- const addCommands = getExtensionConfigField(extension, "addCommands", context);
8031
- if (addCommands) {
8032
- commandsObject = {
8033
- ...commandsObject,
8034
- ...addCommands()
8035
- };
8036
- }
8037
- }
8038
- return commandsObject;
8039
- }
8040
- /**
8041
- * Get all PM plugins defined in the extensions.
8042
- * And also keyboard shortcuts.
8043
- * @returns Array of PM plugins.
8044
- */
8045
- get plugins() {
8046
- const editor = this.editor;
8047
- const extensions = _ExtensionService.sortByPriority([...this.extensions].reverse());
8048
- const allPlugins = extensions.map((extension) => {
8049
- const context = {
8050
- name: extension.name,
8051
- options: extension.options,
8052
- storage: extension.storage,
8053
- editor,
8054
- type: getSchemaTypeByName(extension.name, this.schema)
8055
- };
8056
- const plugins = [];
8057
- const addShortcuts = getExtensionConfigField(extension, "addShortcuts", context);
8058
- let bindingsObject = {};
8059
- if (addShortcuts) {
8060
- const entries = Object.entries(addShortcuts()).map(([shortcut, method]) => {
8061
- return [shortcut, (...args) => method({ editor, keymapArgs: args })];
8062
- });
8063
- bindingsObject = { ...Object.fromEntries(entries) };
8064
- }
8065
- plugins.push(keymap(bindingsObject));
8066
- const addPmPlugins = getExtensionConfigField(extension, "addPmPlugins", context);
8067
- if (addPmPlugins) {
8068
- const pmPlugins = addPmPlugins();
8069
- plugins.push(...pmPlugins);
8070
- }
8071
- return plugins;
8072
- }).flat();
8073
- return [...allPlugins];
8074
- }
8075
- /**
8076
- * Get all node views from the extensions.
8077
- * @returns An object with all node views.
8078
- */
8079
- get nodeViews() {
8080
- const { editor } = this;
8081
- const nodeExtensions = this.extensions.filter((e) => e.type === "node");
8082
- const entries = nodeExtensions.filter((extension) => !!getExtensionConfigField(extension, "addNodeView")).map((extension) => {
8083
- const extensionAttrs = this.attributes.filter((a) => a.type === extension.name);
8084
- const context = {
8085
- name: extension.name,
8086
- options: extension.options,
8087
- storage: extension.storage,
8088
- editor,
8089
- type: getNodeType(extension.name, this.schema)
8090
- };
8091
- const addNodeView = getExtensionConfigField(extension, "addNodeView", context);
8092
- if (!addNodeView) return [];
8093
- const nodeview = (node, _view, getPos, decorations) => {
8094
- const htmlAttributes = Attribute.getAttributesToRender(node, extensionAttrs);
8095
- return addNodeView()({
8096
- editor,
8097
- node,
8098
- getPos,
8099
- decorations,
8100
- htmlAttributes,
8101
- extension
8102
- });
8103
- };
8104
- return [extension.name, nodeview];
7964
+ function isExtensionRulesEnabled(extension, enabled) {
7965
+ if (Array.isArray(enabled)) {
7966
+ return enabled.some((enabledExtension) => {
7967
+ const name = typeof enabledExtension === "string" ? enabledExtension : enabledExtension.name;
7968
+ return name === extension.name;
8105
7969
  });
8106
- return Object.fromEntries(entries);
8107
- }
8108
- };
8109
- _ExtensionService_instances = new WeakSet();
8110
- /**
8111
- * Install all extensions.
8112
- * Create extension storage in the editor, attach editor events.
8113
- */
8114
- setupExtensions_fn = function() {
8115
- for (const extension of this.extensions) {
8116
- this.editor.extensionStorage[extension.name] = extension.storage;
8117
- const context = {
8118
- name: extension.name,
8119
- options: extension.options,
8120
- storage: extension.storage,
8121
- editor: this.editor,
8122
- type: getSchemaTypeByName(extension.name, this.schema)
8123
- };
8124
- if (extension.type === "mark") {
8125
- const keepOnSplit = callOrGet(getExtensionConfigField(extension, "keepOnSplit", context)) ?? true;
8126
- if (keepOnSplit) {
8127
- this.splittableMarks.push(extension.name);
8128
- }
8129
- }
8130
- __privateMethod(this, _ExtensionService_instances, attachEditorEvents_fn).call(this, extension);
8131
7970
  }
8132
- };
8133
- /**
8134
- * Attach editor events to extension
8135
- * if callbacks are defined in the extension config.
8136
- * @param extension Extension.
8137
- */
8138
- attachEditorEvents_fn = function(extension) {
8139
- const context = {
8140
- name: extension.name,
8141
- options: extension.options,
8142
- storage: extension.storage,
8143
- editor: this.editor,
8144
- type: getSchemaTypeByName(extension.name, this.schema)
8145
- };
8146
- const onBeforeCreate = getExtensionConfigField(extension, "onBeforeCreate", context);
8147
- const onCreate2 = getExtensionConfigField(extension, "onCreate", context);
8148
- const onUpdate = getExtensionConfigField(extension, "onUpdate", context);
8149
- const onSelectionUpdate = getExtensionConfigField(extension, "onSelectionUpdate", context);
8150
- const onTransaction = getExtensionConfigField(extension, "onTransaction", context);
8151
- const onFocus = getExtensionConfigField(extension, "onFocus", context);
8152
- const onBlur = getExtensionConfigField(extension, "onBlur", context);
8153
- const onDestroy2 = getExtensionConfigField(extension, "onDestroy", context);
8154
- if (onBeforeCreate) this.editor.on("beforeCreate", onBeforeCreate);
8155
- if (onCreate2) this.editor.on("create", onCreate2);
8156
- if (onUpdate) this.editor.on("update", onUpdate);
8157
- if (onSelectionUpdate) this.editor.on("selectionUpdate", onSelectionUpdate);
8158
- if (onTransaction) this.editor.on("transaction", onTransaction);
8159
- if (onFocus) this.editor.on("focus", onFocus);
8160
- if (onBlur) this.editor.on("blur", onBlur);
8161
- if (onDestroy2) this.editor.on("destroy", onDestroy2);
8162
- };
8163
- let ExtensionService = _ExtensionService;
7971
+ return enabled;
7972
+ }
8164
7973
  function chainableEditorState(transaction, state) {
8165
7974
  let { selection, doc: doc2, storedMarks } = transaction;
8166
7975
  return {
@@ -8251,7 +8060,7 @@ class CommandService {
8251
8060
  const callbacks = [];
8252
8061
  const hasStartTr = !!startTr;
8253
8062
  const tr = startTr || state.tr;
8254
- const run = () => {
8063
+ const run2 = () => {
8255
8064
  if (!hasStartTr && shouldDispatch && !tr.getMeta("preventDispatch")) {
8256
8065
  view.dispatch(tr);
8257
8066
  }
@@ -8268,7 +8077,7 @@ class CommandService {
8268
8077
  });
8269
8078
  const chain = {
8270
8079
  ...Object.fromEntries(entries),
8271
- run
8080
+ run: run2
8272
8081
  };
8273
8082
  return chain;
8274
8083
  }
@@ -8316,9 +8125,404 @@ class CommandService {
8316
8125
  );
8317
8126
  }
8318
8127
  };
8319
- return props;
8128
+ return props;
8129
+ }
8130
+ }
8131
+ function getHTMLFromFragment(fragment, schema) {
8132
+ const documentFragment = DOMSerializer.fromSchema(schema).serializeFragment(fragment);
8133
+ const temporaryDocument = document.implementation.createHTMLDocument();
8134
+ const container = temporaryDocument.createElement("div");
8135
+ container.appendChild(documentFragment);
8136
+ return container.innerHTML;
8137
+ }
8138
+ const getTextContentFromNodes = ($from, maxMatch = 500) => {
8139
+ let textBefore = "";
8140
+ const sliceEndPos = $from.parentOffset;
8141
+ $from.parent.nodesBetween(
8142
+ Math.max(0, sliceEndPos - maxMatch),
8143
+ sliceEndPos,
8144
+ (node, pos, parent, index2) => {
8145
+ const chunk = node.type.spec.toText?.({
8146
+ node,
8147
+ pos,
8148
+ parent,
8149
+ index: index2
8150
+ }) || node.textContent || "%leaf%";
8151
+ textBefore += node.isAtom && !node.isText ? chunk : chunk.slice(0, Math.max(0, sliceEndPos - pos));
8152
+ }
8153
+ );
8154
+ return textBefore;
8155
+ };
8156
+ class InputRule {
8157
+ constructor(config) {
8158
+ __publicField(this, "match");
8159
+ __publicField(this, "handler");
8160
+ this.match = config.match;
8161
+ this.handler = config.handler;
8162
+ }
8163
+ }
8164
+ const inputRuleMatcherHandler = (text, match) => {
8165
+ if (isRegExp(match)) {
8166
+ return match.exec(text);
8167
+ }
8168
+ const inputRuleMatch = match(text);
8169
+ if (!inputRuleMatch) {
8170
+ return null;
8171
+ }
8172
+ const result = [inputRuleMatch.text];
8173
+ result.index = inputRuleMatch.index;
8174
+ result.input = text;
8175
+ result.data = inputRuleMatch.data;
8176
+ if (inputRuleMatch.replaceWith) {
8177
+ if (!inputRuleMatch.text.includes(inputRuleMatch.replaceWith)) {
8178
+ console.warn(
8179
+ '[super-editor warn]: "inputRuleMatch.replaceWith" must be part of "inputRuleMatch.text".'
8180
+ );
8181
+ }
8182
+ result.push(inputRuleMatch.replaceWith);
8183
+ }
8184
+ return result;
8185
+ };
8186
+ const run = (config) => {
8187
+ const {
8188
+ editor,
8189
+ from: from2,
8190
+ to,
8191
+ text,
8192
+ rules,
8193
+ plugin
8194
+ } = config;
8195
+ const { view } = editor;
8196
+ if (view.composing) {
8197
+ return false;
8198
+ }
8199
+ const $from = view.state.doc.resolve(from2);
8200
+ if ($from.parent.type.spec.code || !!($from.nodeBefore || $from.nodeAfter)?.marks.find((mark) => mark.type.spec.code)) {
8201
+ return false;
8202
+ }
8203
+ let matched = false;
8204
+ const textBefore = getTextContentFromNodes($from) + text;
8205
+ rules.forEach((rule) => {
8206
+ if (matched) {
8207
+ return;
8208
+ }
8209
+ const match = inputRuleMatcherHandler(textBefore, rule.match);
8210
+ if (!match) {
8211
+ return;
8212
+ }
8213
+ const tr = view.state.tr;
8214
+ const state = chainableEditorState(tr, view.state);
8215
+ const range = {
8216
+ from: from2 - (match[0].length - text.length),
8217
+ to
8218
+ };
8219
+ const { commands: commands2, chain, can } = new CommandService({
8220
+ editor,
8221
+ state
8222
+ });
8223
+ const handler = rule.handler({
8224
+ state,
8225
+ range,
8226
+ match,
8227
+ commands: commands2,
8228
+ chain,
8229
+ can
8230
+ });
8231
+ if (handler === null || !tr.steps.length) {
8232
+ return;
8233
+ }
8234
+ tr.setMeta(plugin, {
8235
+ transform: tr,
8236
+ from: from2,
8237
+ to,
8238
+ text
8239
+ });
8240
+ view.dispatch(tr);
8241
+ matched = true;
8242
+ });
8243
+ return matched;
8244
+ };
8245
+ const inputRulesPlugin = ({ editor, rules }) => {
8246
+ const plugin = new Plugin({
8247
+ key: new PluginKey("inputRulesPlugin"),
8248
+ state: {
8249
+ init() {
8250
+ return null;
8251
+ },
8252
+ apply(tr, prev, state) {
8253
+ const stored = tr.getMeta(plugin);
8254
+ if (stored) {
8255
+ return stored;
8256
+ }
8257
+ const simulatedInputMeta = tr.getMeta("applyInputRules");
8258
+ const isSimulatedInput = !!simulatedInputMeta;
8259
+ if (isSimulatedInput) {
8260
+ setTimeout(() => {
8261
+ let { text } = simulatedInputMeta;
8262
+ if (typeof text !== "string") {
8263
+ text = getHTMLFromFragment(Fragment.from(text), state.schema);
8264
+ }
8265
+ const { from: from2 } = simulatedInputMeta;
8266
+ const to = from2 + text.length;
8267
+ run({
8268
+ editor,
8269
+ from: from2,
8270
+ to,
8271
+ text,
8272
+ rules,
8273
+ plugin
8274
+ });
8275
+ });
8276
+ }
8277
+ return tr.selectionSet || tr.docChanged ? null : prev;
8278
+ }
8279
+ },
8280
+ props: {
8281
+ handleTextInput(view, from2, to, text) {
8282
+ return run({
8283
+ editor,
8284
+ from: from2,
8285
+ to,
8286
+ text,
8287
+ rules,
8288
+ plugin
8289
+ });
8290
+ },
8291
+ // add support for input rules to trigger on enter
8292
+ // this is useful for example for code blocks
8293
+ handleKeyDown(view, event) {
8294
+ if (event.key !== "Enter") {
8295
+ return false;
8296
+ }
8297
+ const { $cursor } = view.state.selection;
8298
+ if ($cursor) {
8299
+ return run({
8300
+ editor,
8301
+ from: $cursor.pos,
8302
+ to: $cursor.pos,
8303
+ text: "\n",
8304
+ rules,
8305
+ plugin
8306
+ });
8307
+ }
8308
+ return false;
8309
+ }
8310
+ },
8311
+ isInputRules: true
8312
+ });
8313
+ return plugin;
8314
+ };
8315
+ const _ExtensionService = class _ExtensionService {
8316
+ constructor(extensions, userExtensions, editor) {
8317
+ __privateAdd(this, _ExtensionService_instances);
8318
+ __publicField(this, "editor");
8319
+ __publicField(this, "schema");
8320
+ __publicField(this, "extensions");
8321
+ __publicField(this, "externalExtensions", []);
8322
+ __publicField(this, "splittableMarks", []);
8323
+ this.editor = editor;
8324
+ this.externalExtensions = userExtensions || [];
8325
+ this.extensions = _ExtensionService.getResolvedExtensions([...extensions, ...this.externalExtensions]);
8326
+ this.schema = Schema.createSchemaByExtensions(this.extensions, editor);
8327
+ __privateMethod(this, _ExtensionService_instances, setupExtensions_fn).call(this);
8328
+ }
8329
+ /**
8330
+ * Static method for creating ExtensionService.
8331
+ * @param args Arguments for the constructor.
8332
+ */
8333
+ static create(...args) {
8334
+ return new _ExtensionService(...args);
8335
+ }
8336
+ /**
8337
+ * Get an array of resolved extensions (e.g. sorted by priority).
8338
+ * @param extensions Array of extensions.
8339
+ * @returns Array of resolved extensions.
8340
+ */
8341
+ static getResolvedExtensions(extensions) {
8342
+ const resolvedExtensions = _ExtensionService.sortByPriority(extensions);
8343
+ return resolvedExtensions;
8344
+ }
8345
+ /**
8346
+ * Sort extensions by priority.
8347
+ * @param extensions Array of extensions.
8348
+ * @returns Array of sorted extensions by priority.
8349
+ */
8350
+ static sortByPriority(extensions) {
8351
+ const defaultValue = 100;
8352
+ return extensions.sort((a, b) => {
8353
+ const priorityA = getExtensionConfigField(a, "priority") || defaultValue;
8354
+ const priorityB = getExtensionConfigField(b, "priority") || defaultValue;
8355
+ if (priorityA > priorityB) return -1;
8356
+ if (priorityA < priorityB) return 1;
8357
+ return 0;
8358
+ });
8359
+ }
8360
+ /**
8361
+ * Get all attributes defined in the extensions.
8362
+ * @returns Array of attributes.
8363
+ */
8364
+ get attributes() {
8365
+ return Attribute.getAttributesFromExtensions(this.extensions);
8366
+ }
8367
+ /**
8368
+ * Get all commands defined in the extensions.
8369
+ * @returns Object with commands (key - command name, value - function).
8370
+ */
8371
+ get commands() {
8372
+ let commandsObject = {};
8373
+ for (const extension of this.extensions) {
8374
+ const context = {
8375
+ name: extension.name,
8376
+ options: extension.options,
8377
+ storage: extension.storage,
8378
+ editor: this.editor,
8379
+ type: getSchemaTypeByName(extension.name, this.schema)
8380
+ };
8381
+ const addCommands = getExtensionConfigField(extension, "addCommands", context);
8382
+ if (addCommands) {
8383
+ commandsObject = {
8384
+ ...commandsObject,
8385
+ ...addCommands()
8386
+ };
8387
+ }
8388
+ }
8389
+ return commandsObject;
8390
+ }
8391
+ /**
8392
+ * Get all PM plugins defined in the extensions.
8393
+ * And also keyboard shortcuts.
8394
+ * @returns Array of PM plugins.
8395
+ */
8396
+ get plugins() {
8397
+ const editor = this.editor;
8398
+ const extensions = _ExtensionService.sortByPriority([...this.extensions].reverse());
8399
+ const inputRules = [];
8400
+ const allPlugins = extensions.map((extension) => {
8401
+ const context = {
8402
+ name: extension.name,
8403
+ options: extension.options,
8404
+ storage: extension.storage,
8405
+ editor,
8406
+ type: getSchemaTypeByName(extension.name, this.schema)
8407
+ };
8408
+ const plugins = [];
8409
+ const addShortcuts = getExtensionConfigField(extension, "addShortcuts", context);
8410
+ let bindingsObject = {};
8411
+ if (addShortcuts) {
8412
+ const entries = Object.entries(addShortcuts()).map(([shortcut, method]) => {
8413
+ return [shortcut, (...args) => method({ editor, keymapArgs: args })];
8414
+ });
8415
+ bindingsObject = { ...Object.fromEntries(entries) };
8416
+ }
8417
+ plugins.push(keymap(bindingsObject));
8418
+ const addInputRules = getExtensionConfigField(extension, "addInputRules", context);
8419
+ if (isExtensionRulesEnabled(extension, editor.options.enableInputRules) && addInputRules) {
8420
+ inputRules.push(...addInputRules());
8421
+ }
8422
+ const addPmPlugins = getExtensionConfigField(extension, "addPmPlugins", context);
8423
+ if (addPmPlugins) {
8424
+ const pmPlugins = addPmPlugins();
8425
+ plugins.push(...pmPlugins);
8426
+ }
8427
+ return plugins;
8428
+ }).flat();
8429
+ return [
8430
+ inputRulesPlugin({
8431
+ editor,
8432
+ rules: inputRules
8433
+ }),
8434
+ ...allPlugins
8435
+ ];
8436
+ }
8437
+ /**
8438
+ * Get all node views from the extensions.
8439
+ * @returns An object with all node views.
8440
+ */
8441
+ get nodeViews() {
8442
+ const { editor } = this;
8443
+ const nodeExtensions = this.extensions.filter((e) => e.type === "node");
8444
+ const entries = nodeExtensions.filter((extension) => !!getExtensionConfigField(extension, "addNodeView")).map((extension) => {
8445
+ const extensionAttrs = this.attributes.filter((a) => a.type === extension.name);
8446
+ const context = {
8447
+ name: extension.name,
8448
+ options: extension.options,
8449
+ storage: extension.storage,
8450
+ editor,
8451
+ type: getNodeType(extension.name, this.schema)
8452
+ };
8453
+ const addNodeView = getExtensionConfigField(extension, "addNodeView", context);
8454
+ if (!addNodeView) return [];
8455
+ const nodeview = (node, _view, getPos, decorations) => {
8456
+ const htmlAttributes = Attribute.getAttributesToRender(node, extensionAttrs);
8457
+ return addNodeView()({
8458
+ editor,
8459
+ node,
8460
+ getPos,
8461
+ decorations,
8462
+ htmlAttributes,
8463
+ extension
8464
+ });
8465
+ };
8466
+ return [extension.name, nodeview];
8467
+ });
8468
+ return Object.fromEntries(entries);
8469
+ }
8470
+ };
8471
+ _ExtensionService_instances = new WeakSet();
8472
+ /**
8473
+ * Install all extensions.
8474
+ * Create extension storage in the editor, attach editor events.
8475
+ */
8476
+ setupExtensions_fn = function() {
8477
+ for (const extension of this.extensions) {
8478
+ this.editor.extensionStorage[extension.name] = extension.storage;
8479
+ const context = {
8480
+ name: extension.name,
8481
+ options: extension.options,
8482
+ storage: extension.storage,
8483
+ editor: this.editor,
8484
+ type: getSchemaTypeByName(extension.name, this.schema)
8485
+ };
8486
+ if (extension.type === "mark") {
8487
+ const keepOnSplit = callOrGet(getExtensionConfigField(extension, "keepOnSplit", context)) ?? true;
8488
+ if (keepOnSplit) {
8489
+ this.splittableMarks.push(extension.name);
8490
+ }
8491
+ }
8492
+ __privateMethod(this, _ExtensionService_instances, attachEditorEvents_fn).call(this, extension);
8320
8493
  }
8321
- }
8494
+ };
8495
+ /**
8496
+ * Attach editor events to extension
8497
+ * if callbacks are defined in the extension config.
8498
+ * @param extension Extension.
8499
+ */
8500
+ attachEditorEvents_fn = function(extension) {
8501
+ const context = {
8502
+ name: extension.name,
8503
+ options: extension.options,
8504
+ storage: extension.storage,
8505
+ editor: this.editor,
8506
+ type: getSchemaTypeByName(extension.name, this.schema)
8507
+ };
8508
+ const onBeforeCreate = getExtensionConfigField(extension, "onBeforeCreate", context);
8509
+ const onCreate2 = getExtensionConfigField(extension, "onCreate", context);
8510
+ const onUpdate = getExtensionConfigField(extension, "onUpdate", context);
8511
+ const onSelectionUpdate = getExtensionConfigField(extension, "onSelectionUpdate", context);
8512
+ const onTransaction = getExtensionConfigField(extension, "onTransaction", context);
8513
+ const onFocus = getExtensionConfigField(extension, "onFocus", context);
8514
+ const onBlur = getExtensionConfigField(extension, "onBlur", context);
8515
+ const onDestroy2 = getExtensionConfigField(extension, "onDestroy", context);
8516
+ if (onBeforeCreate) this.editor.on("beforeCreate", onBeforeCreate);
8517
+ if (onCreate2) this.editor.on("create", onCreate2);
8518
+ if (onUpdate) this.editor.on("update", onUpdate);
8519
+ if (onSelectionUpdate) this.editor.on("selectionUpdate", onSelectionUpdate);
8520
+ if (onTransaction) this.editor.on("transaction", onTransaction);
8521
+ if (onFocus) this.editor.on("focus", onFocus);
8522
+ if (onBlur) this.editor.on("blur", onBlur);
8523
+ if (onDestroy2) this.editor.on("destroy", onDestroy2);
8524
+ };
8525
+ let ExtensionService = _ExtensionService;
8322
8526
  const first = (commands2) => (props) => {
8323
8527
  const items = typeof commands2 === "function" ? commands2(props) : commands2;
8324
8528
  for (let i = 0; i < items.length; i += 1) {
@@ -9355,6 +9559,30 @@ const insertContentAt = (position, value, options) => ({ tr, dispatch, editor })
9355
9559
  }
9356
9560
  return true;
9357
9561
  };
9562
+ const undoInputRule = () => ({ state, dispatch }) => {
9563
+ const plugins = state.plugins;
9564
+ for (let i = 0; i < plugins.length; i += 1) {
9565
+ const plugin = plugins[i];
9566
+ let undoable;
9567
+ if (plugin.spec.isInputRules && (undoable = plugin.getState(state))) {
9568
+ if (dispatch) {
9569
+ const tr = state.tr;
9570
+ const toUndo = undoable.transform;
9571
+ for (let j = toUndo.steps.length - 1; j >= 0; j -= 1) {
9572
+ tr.step(toUndo.steps[j].invert(toUndo.docs[j]));
9573
+ }
9574
+ if (undoable.text) {
9575
+ const marks = tr.doc.resolve(undoable.from).marks();
9576
+ tr.replaceWith(undoable.from, undoable.to, state.schema.text(undoable.text, marks));
9577
+ } else {
9578
+ tr.delete(undoable.from, undoable.to);
9579
+ }
9580
+ }
9581
+ return true;
9582
+ }
9583
+ }
9584
+ return false;
9585
+ };
9358
9586
  function wrapInList$1(listType, attrs = null) {
9359
9587
  return function(state, dispatch) {
9360
9588
  let { $from, $to } = state.selection;
@@ -9684,6 +9912,7 @@ const commands = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProp
9684
9912
  toggleList,
9685
9913
  toggleMark,
9686
9914
  toggleNode,
9915
+ undoInputRule,
9687
9916
  unsetAllMarks,
9688
9917
  unsetMark,
9689
9918
  updateAttributes,
@@ -9713,6 +9942,7 @@ const Keymap = Extension.create({
9713
9942
  () => commands2.splitBlock()
9714
9943
  ]);
9715
9944
  const handleBackspace = () => this.editor.commands.first(({ commands: commands2, tr }) => [
9945
+ () => commands2.undoInputRule(),
9716
9946
  () => {
9717
9947
  tr.setMeta("inputType", "deleteContentBackward");
9718
9948
  return false;
@@ -10318,208 +10548,15 @@ const getTrackChangesDecorations = (state, onlyOriginalShown, onlyModifiedShown)
10318
10548
  class: "track-format-dec normal"
10319
10549
  });
10320
10550
  decorations.push(decoration);
10321
- } else {
10322
- const decoration = Decoration.inline(from2, to, {
10323
- class: "track-format-dec highlighted"
10324
- });
10325
- decorations.push(decoration);
10326
- }
10327
- }
10328
- });
10329
- return DecorationSet.create(state.doc, decorations);
10330
- };
10331
- const replaceStep = ({ state, tr, step, newTr, map: map2, doc: doc2, user, date, originalStep, originalStepIndex }) => {
10332
- const deletionMarkSchema = state.schema.marks[TrackDeleteMarkName];
10333
- const deletionMark = findMark(state, deletionMarkSchema, false);
10334
- const positionTo = deletionMark ? deletionMark.to : step.to;
10335
- const newStep = new ReplaceStep(
10336
- positionTo,
10337
- // We insert all the same steps, but with "from"/"to" both set to "to" in order not to delete content. Mapped as needed.
10338
- positionTo,
10339
- step.slice,
10340
- step.structure
10341
- );
10342
- const invertStep = originalStep.invert(tr.docs[originalStepIndex]).map(map2);
10343
- map2.appendMap(invertStep.getMap());
10344
- const meta = {};
10345
- if (newStep) {
10346
- const trTemp = state.apply(newTr).tr;
10347
- if (trTemp.maybeStep(newStep).failed) {
10348
- return;
10349
- }
10350
- const mappedNewStepTo = newStep.getMap().map(newStep.to);
10351
- const insertedMark = markInsertion({
10352
- tr: trTemp,
10353
- from: newStep.from,
10354
- to: mappedNewStepTo,
10355
- user,
10356
- date
10357
- });
10358
- const condensedStep = new ReplaceStep(newStep.from, newStep.to, trTemp.doc.slice(newStep.from, mappedNewStepTo));
10359
- newTr.step(condensedStep);
10360
- const mirrorIndex = map2.maps.length - 1;
10361
- map2.appendMap(condensedStep.getMap(), mirrorIndex);
10362
- if (newStep.from !== mappedNewStepTo) {
10363
- meta.insertedMark = insertedMark;
10364
- meta.step = condensedStep;
10365
- }
10366
- if (!newTr.selection.eq(trTemp.selection)) {
10367
- newTr.setSelection(trTemp.selection);
10368
- }
10369
- }
10370
- if (step.from !== step.to) {
10371
- const { deletionMark: deletionMark2, deletionMap, nodes: deletionNodes } = markDeletion({
10372
- tr: newTr,
10373
- from: step.from,
10374
- to: step.to,
10375
- user,
10376
- date
10377
- });
10378
- meta.deletionNodes = deletionNodes;
10379
- meta.deletionMark = deletionMark2;
10380
- map2.appendMapping(deletionMap);
10381
- }
10382
- newTr.setMeta(TrackChangesBasePluginKey, meta);
10383
- };
10384
- const markWrapping = () => {
10385
- };
10386
- const replaceAroundStep = () => {
10387
- };
10388
- const addMarkStep = ({ state, tr, step, newTr, map: map2, doc: doc2, user, date }) => {
10389
- const meta = {};
10390
- doc2.nodesBetween(step.from, step.to, (node, pos) => {
10391
- if (!node.isInline) {
10392
- return;
10393
- }
10394
- if (node.marks.find((mark) => mark.type.name === TrackDeleteMarkName)) {
10395
- return false;
10396
- }
10397
- const existingChangeMark = node.marks.find((mark) => [TrackDeleteMarkName, TrackFormatMarkName].includes(mark.type.name));
10398
- const wid = existingChangeMark ? existingChangeMark.attrs.id : v4();
10399
- newTr.addMark(Math.max(step.from, pos), Math.min(step.to, pos + node.nodeSize), step.mark);
10400
- const allowedMarks = ["bold", "italic", "strike", "underline", "textStyle"];
10401
- if (allowedMarks.includes(step.mark.type.name) && !node.marks.find((mark) => mark.type === step.mark.type)) {
10402
- const formatChangeMark = node.marks.find((mark) => mark.type.name === TrackFormatMarkName);
10403
- let after = [];
10404
- let before = [];
10405
- if (formatChangeMark) {
10406
- let foundBefore = formatChangeMark.attrs.before.find((mark) => {
10407
- if (mark.type === "textStyle") {
10408
- return mark.type === step.mark.type.name && objectIncludes(mark.attrs, step.mark.attrs);
10409
- }
10410
- return mark.type === step.mark.type.name;
10411
- });
10412
- if (foundBefore) {
10413
- before = [...formatChangeMark.attrs.before.filter((mark) => mark.type !== step.mark.type.name)];
10414
- after = [...formatChangeMark.attrs.after];
10415
- } else {
10416
- before = [...formatChangeMark.attrs.before];
10417
- after = [
10418
- ...formatChangeMark.attrs.after,
10419
- {
10420
- type: step.mark.type.name,
10421
- attrs: { ...step.mark.attrs }
10422
- }
10423
- ];
10424
- }
10425
- } else {
10426
- before = node.marks.map((mark) => ({
10427
- type: mark.type.name,
10428
- attrs: { ...mark.attrs }
10429
- }));
10430
- after = [
10431
- {
10432
- type: step.mark.type.name,
10433
- attrs: { ...step.mark.attrs }
10434
- }
10435
- ];
10436
- }
10437
- if (after.length || before.length) {
10438
- const newFormatMark = state.schema.marks[TrackFormatMarkName].create({
10439
- id: wid,
10440
- author: user.name,
10441
- authorEmail: user.email,
10442
- date,
10443
- before,
10444
- after
10445
- });
10446
- newTr.addMark(
10447
- step.from,
10448
- // Math.max(step.from, pos)
10449
- step.to,
10450
- // Math.min(step.to, pos + node.nodeSize),
10451
- newFormatMark
10452
- );
10453
- meta.formatMark = newFormatMark;
10454
- meta.step = step;
10455
- newTr.setMeta(TrackChangesBasePluginKey, meta);
10456
- } else if (formatChangeMark) {
10457
- newTr.removeMark(Math.max(step.from, pos), Math.min(step.to, pos + node.nodeSize), formatChangeMark);
10458
- }
10459
- }
10460
- });
10461
- };
10462
- const removeMarkStep = ({ state, tr, step, newTr, map: map2, doc: doc2, user, date }) => {
10463
- const meta = {};
10464
- doc2.nodesBetween(step.from, step.to, (node, pos) => {
10465
- if (!node.isInline) {
10466
- return true;
10467
- }
10468
- if (node.marks.find((mark) => mark.type.name === TrackDeleteMarkName)) {
10469
- return false;
10470
- }
10471
- newTr.removeMark(Math.max(step.from, pos), Math.min(step.to, pos + node.nodeSize), step.mark);
10472
- const allowedMarks = ["bold", "italic", "strike", "underline", "textStyle"];
10473
- if (allowedMarks.includes(step.mark.type.name) && node.marks.find((mark) => mark.type === step.mark.type)) {
10474
- const formatChangeMark = node.marks.find((mark) => mark.type.name === TrackFormatMarkName);
10475
- let after = [];
10476
- let before = [];
10477
- if (formatChangeMark) {
10478
- let foundAfter = formatChangeMark.attrs.after.find((mark) => mark.type === step.mark.type.name);
10479
- if (foundAfter) {
10480
- after = [...formatChangeMark.attrs.after.filter((mark) => mark.type !== step.mark.type.name)];
10481
- before = [...formatChangeMark.attrs.before];
10482
- } else {
10483
- after = [...formatChangeMark.attrs.after];
10484
- before = [
10485
- ...formatChangeMark.attrs.before,
10486
- {
10487
- type: step.mark.type.name,
10488
- attrs: { ...step.mark.attrs }
10489
- }
10490
- ];
10491
- }
10492
- } else {
10493
- after = [];
10494
- before = [
10495
- {
10496
- type: step.mark.type.name,
10497
- attrs: { ...step.mark.attrs }
10498
- }
10499
- ];
10500
- }
10501
- if (after.length || before.length) {
10502
- const newFormatMark = state.schema.marks[TrackFormatMarkName].create({
10503
- id: v4(),
10504
- author: user.name,
10505
- authorEmail: user.email,
10506
- date,
10507
- before,
10508
- after
10551
+ } else {
10552
+ const decoration = Decoration.inline(from2, to, {
10553
+ class: "track-format-dec highlighted"
10509
10554
  });
10510
- newTr.addMark(
10511
- Math.max(step.from, pos),
10512
- Math.min(step.to, pos + node.nodeSize),
10513
- newFormatMark
10514
- );
10515
- meta.formatMark = newFormatMark;
10516
- meta.step = step;
10517
- newTr.setMeta(TrackChangesBasePluginKey, meta);
10518
- } else if (formatChangeMark) {
10519
- newTr.removeMark(Math.max(step.from, pos), Math.min(step.to, pos + node.nodeSize), formatChangeMark);
10555
+ decorations.push(decoration);
10520
10556
  }
10521
10557
  }
10522
10558
  });
10559
+ return DecorationSet.create(state.doc, decorations);
10523
10560
  };
10524
10561
  const CommentMarkName = "commentMark";
10525
10562
  const removeCommentsById = ({ commentId, state, tr, dispatch }) => {
@@ -10927,7 +10964,7 @@ const CommentsPlugin = Extension.create({
10927
10964
  update(view, prevState) {
10928
10965
  const { state } = view;
10929
10966
  const { doc: doc2, tr } = state;
10930
- if (prevDoc && prevDoc.eq(doc2)) shouldUpdate = true;
10967
+ if (prevDoc && !prevDoc.eq(doc2)) shouldUpdate = true;
10931
10968
  if (!shouldUpdate) return;
10932
10969
  prevDoc = doc2;
10933
10970
  shouldUpdate = false;
@@ -10961,10 +10998,14 @@ const CommentsPlugin = Extension.create({
10961
10998
  if (hasActive && activeThreadId !== threadId) return;
10962
10999
  decorations.push(deco);
10963
11000
  });
10964
- const trackedChangeNode = getTrackedChangeNode(node);
10965
- if (trackedChangeNode) {
11001
+ const trackedChangeMark = findTrackedMark({
11002
+ doc: doc2,
11003
+ from: pos,
11004
+ to: pos + node.nodeSize
11005
+ });
11006
+ if (trackedChangeMark) {
10966
11007
  const currentBounds = view.coordsAtPos(pos);
10967
- const { id } = trackedChangeNode.attrs;
11008
+ const { id } = trackedChangeMark.mark.attrs;
10968
11009
  updatePosition({
10969
11010
  allCommentPositions,
10970
11011
  threadId: id,
@@ -11032,9 +11073,13 @@ const getActiveCommentId = (doc2, selection) => {
11032
11073
  if ($from.pos !== $to.pos) return;
11033
11074
  const nodeAtPos = doc2.nodeAt($from.pos);
11034
11075
  if (!nodeAtPos) return;
11035
- const trackedChangeNode = getTrackedChangeNode(nodeAtPos);
11036
- if (trackedChangeNode) {
11037
- return trackedChangeNode.attrs.id;
11076
+ const trackedChangeMark = findTrackedMark({
11077
+ doc: doc2,
11078
+ from: $from.pos,
11079
+ to: $to.pos
11080
+ });
11081
+ if (trackedChangeMark) {
11082
+ return trackedChangeMark.mark.attrs.id;
11038
11083
  }
11039
11084
  const overlaps = [];
11040
11085
  let found = false;
@@ -11071,13 +11116,30 @@ const getActiveCommentId = (doc2, selection) => {
11071
11116
  const closestCommentMark = closestMarks.find((mark) => mark.type.name === CommentMarkName);
11072
11117
  return closestCommentMark?.attrs?.commentId || closestCommentMark?.attrs?.importedId;
11073
11118
  };
11074
- const getTrackedChangeNode = (node) => {
11075
- if (!node) return;
11076
- const nodeMarks = node.marks;
11077
- const trackedInsertMark = nodeMarks?.find((mark) => mark.type.name === TrackInsertMarkName);
11078
- const trackedDeleteMark = nodeMarks?.find((mark) => mark.type.name === TrackDeleteMarkName);
11079
- const trackedFormatMark = nodeMarks?.find((mark) => mark.type.name === TrackFormatMarkName);
11080
- return trackedInsertMark || trackedDeleteMark || trackedFormatMark;
11119
+ const findTrackedMark = ({
11120
+ doc: doc2,
11121
+ from: from2,
11122
+ to,
11123
+ offset: offset2 = 1
11124
+ // To get non-inclusive marks.
11125
+ }) => {
11126
+ const startPos = Math.max(from2 - offset2, 0);
11127
+ const endPos = Math.min(to + offset2, doc2.content.size);
11128
+ let markFound;
11129
+ doc2.nodesBetween(startPos, endPos, (node, pos) => {
11130
+ if (!node || node?.nodeSize === void 0) {
11131
+ return;
11132
+ }
11133
+ const mark = node.marks.find((mark2) => TRACK_CHANGE_MARKS.includes(mark2.type.name));
11134
+ if (mark && !markFound) {
11135
+ markFound = {
11136
+ from: pos,
11137
+ to: pos + node.nodeSize,
11138
+ mark
11139
+ };
11140
+ }
11141
+ });
11142
+ return markFound;
11081
11143
  };
11082
11144
  const handleTrackedChangeTransaction = (trackedChangeMeta, trackedChanges, newEditorState, editor) => {
11083
11145
  const {
@@ -11217,6 +11279,202 @@ function findNode$1(node, predicate) {
11217
11279
  });
11218
11280
  return found;
11219
11281
  }
11282
+ const replaceStep = ({ state, tr, step, newTr, map: map2, doc: doc2, user, date, originalStep, originalStepIndex }) => {
11283
+ const deletionMarkSchema = state.schema.marks[TrackDeleteMarkName];
11284
+ const deletionMark = findMark(state, deletionMarkSchema, false);
11285
+ const positionTo = deletionMark ? deletionMark.to : step.to;
11286
+ const newStep = new ReplaceStep(
11287
+ positionTo,
11288
+ // We insert all the same steps, but with "from"/"to" both set to "to" in order not to delete content. Mapped as needed.
11289
+ positionTo,
11290
+ step.slice,
11291
+ step.structure
11292
+ );
11293
+ const invertStep = originalStep.invert(tr.docs[originalStepIndex]).map(map2);
11294
+ map2.appendMap(invertStep.getMap());
11295
+ const meta = {};
11296
+ if (newStep) {
11297
+ const trTemp = state.apply(newTr).tr;
11298
+ if (trTemp.maybeStep(newStep).failed) {
11299
+ return;
11300
+ }
11301
+ const mappedNewStepTo = newStep.getMap().map(newStep.to);
11302
+ const insertedMark = markInsertion({
11303
+ tr: trTemp,
11304
+ from: newStep.from,
11305
+ to: mappedNewStepTo,
11306
+ user,
11307
+ date
11308
+ });
11309
+ const condensedStep = new ReplaceStep(newStep.from, newStep.to, trTemp.doc.slice(newStep.from, mappedNewStepTo));
11310
+ newTr.step(condensedStep);
11311
+ const mirrorIndex = map2.maps.length - 1;
11312
+ map2.appendMap(condensedStep.getMap(), mirrorIndex);
11313
+ if (newStep.from !== mappedNewStepTo) {
11314
+ meta.insertedMark = insertedMark;
11315
+ meta.step = condensedStep;
11316
+ }
11317
+ if (!newTr.selection.eq(trTemp.selection)) {
11318
+ newTr.setSelection(trTemp.selection);
11319
+ }
11320
+ }
11321
+ if (step.from !== step.to) {
11322
+ const { deletionMark: deletionMark2, deletionMap, nodes: deletionNodes } = markDeletion({
11323
+ tr: newTr,
11324
+ from: step.from,
11325
+ to: step.to,
11326
+ user,
11327
+ date
11328
+ });
11329
+ meta.deletionNodes = deletionNodes;
11330
+ meta.deletionMark = deletionMark2;
11331
+ map2.appendMapping(deletionMap);
11332
+ }
11333
+ newTr.setMeta(TrackChangesBasePluginKey, meta);
11334
+ newTr.setMeta(CommentsPluginKey, { type: "force" });
11335
+ };
11336
+ const markWrapping = () => {
11337
+ };
11338
+ const replaceAroundStep = () => {
11339
+ };
11340
+ const addMarkStep = ({ state, tr, step, newTr, map: map2, doc: doc2, user, date }) => {
11341
+ const meta = {};
11342
+ doc2.nodesBetween(step.from, step.to, (node, pos) => {
11343
+ if (!node.isInline) {
11344
+ return;
11345
+ }
11346
+ if (node.marks.find((mark) => mark.type.name === TrackDeleteMarkName)) {
11347
+ return false;
11348
+ }
11349
+ const existingChangeMark = node.marks.find((mark) => [TrackDeleteMarkName, TrackFormatMarkName].includes(mark.type.name));
11350
+ const wid = existingChangeMark ? existingChangeMark.attrs.id : v4();
11351
+ newTr.addMark(Math.max(step.from, pos), Math.min(step.to, pos + node.nodeSize), step.mark);
11352
+ const allowedMarks = ["bold", "italic", "strike", "underline", "textStyle"];
11353
+ if (allowedMarks.includes(step.mark.type.name) && !node.marks.find((mark) => mark.type === step.mark.type)) {
11354
+ const formatChangeMark = node.marks.find((mark) => mark.type.name === TrackFormatMarkName);
11355
+ let after = [];
11356
+ let before = [];
11357
+ if (formatChangeMark) {
11358
+ let foundBefore = formatChangeMark.attrs.before.find((mark) => {
11359
+ if (mark.type === "textStyle") {
11360
+ return mark.type === step.mark.type.name && objectIncludes(mark.attrs, step.mark.attrs);
11361
+ }
11362
+ return mark.type === step.mark.type.name;
11363
+ });
11364
+ if (foundBefore) {
11365
+ before = [...formatChangeMark.attrs.before.filter((mark) => mark.type !== step.mark.type.name)];
11366
+ after = [...formatChangeMark.attrs.after];
11367
+ } else {
11368
+ before = [...formatChangeMark.attrs.before];
11369
+ after = [
11370
+ ...formatChangeMark.attrs.after,
11371
+ {
11372
+ type: step.mark.type.name,
11373
+ attrs: { ...step.mark.attrs }
11374
+ }
11375
+ ];
11376
+ }
11377
+ } else {
11378
+ before = node.marks.map((mark) => ({
11379
+ type: mark.type.name,
11380
+ attrs: { ...mark.attrs }
11381
+ }));
11382
+ after = [
11383
+ {
11384
+ type: step.mark.type.name,
11385
+ attrs: { ...step.mark.attrs }
11386
+ }
11387
+ ];
11388
+ }
11389
+ if (after.length || before.length) {
11390
+ const newFormatMark = state.schema.marks[TrackFormatMarkName].create({
11391
+ id: wid,
11392
+ author: user.name,
11393
+ authorEmail: user.email,
11394
+ date,
11395
+ before,
11396
+ after
11397
+ });
11398
+ newTr.addMark(
11399
+ step.from,
11400
+ // Math.max(step.from, pos)
11401
+ step.to,
11402
+ // Math.min(step.to, pos + node.nodeSize),
11403
+ newFormatMark
11404
+ );
11405
+ meta.formatMark = newFormatMark;
11406
+ meta.step = step;
11407
+ newTr.setMeta(TrackChangesBasePluginKey, meta);
11408
+ newTr.setMeta(CommentsPluginKey, { type: "force" });
11409
+ } else if (formatChangeMark) {
11410
+ newTr.removeMark(Math.max(step.from, pos), Math.min(step.to, pos + node.nodeSize), formatChangeMark);
11411
+ }
11412
+ }
11413
+ });
11414
+ };
11415
+ const removeMarkStep = ({ state, tr, step, newTr, map: map2, doc: doc2, user, date }) => {
11416
+ const meta = {};
11417
+ doc2.nodesBetween(step.from, step.to, (node, pos) => {
11418
+ if (!node.isInline) {
11419
+ return true;
11420
+ }
11421
+ if (node.marks.find((mark) => mark.type.name === TrackDeleteMarkName)) {
11422
+ return false;
11423
+ }
11424
+ newTr.removeMark(Math.max(step.from, pos), Math.min(step.to, pos + node.nodeSize), step.mark);
11425
+ const allowedMarks = ["bold", "italic", "strike", "underline", "textStyle"];
11426
+ if (allowedMarks.includes(step.mark.type.name) && node.marks.find((mark) => mark.type === step.mark.type)) {
11427
+ const formatChangeMark = node.marks.find((mark) => mark.type.name === TrackFormatMarkName);
11428
+ let after = [];
11429
+ let before = [];
11430
+ if (formatChangeMark) {
11431
+ let foundAfter = formatChangeMark.attrs.after.find((mark) => mark.type === step.mark.type.name);
11432
+ if (foundAfter) {
11433
+ after = [...formatChangeMark.attrs.after.filter((mark) => mark.type !== step.mark.type.name)];
11434
+ before = [...formatChangeMark.attrs.before];
11435
+ } else {
11436
+ after = [...formatChangeMark.attrs.after];
11437
+ before = [
11438
+ ...formatChangeMark.attrs.before,
11439
+ {
11440
+ type: step.mark.type.name,
11441
+ attrs: { ...step.mark.attrs }
11442
+ }
11443
+ ];
11444
+ }
11445
+ } else {
11446
+ after = [];
11447
+ before = [
11448
+ {
11449
+ type: step.mark.type.name,
11450
+ attrs: { ...step.mark.attrs }
11451
+ }
11452
+ ];
11453
+ }
11454
+ if (after.length || before.length) {
11455
+ const newFormatMark = state.schema.marks[TrackFormatMarkName].create({
11456
+ id: v4(),
11457
+ author: user.name,
11458
+ authorEmail: user.email,
11459
+ date,
11460
+ before,
11461
+ after
11462
+ });
11463
+ newTr.addMark(
11464
+ Math.max(step.from, pos),
11465
+ Math.min(step.to, pos + node.nodeSize),
11466
+ newFormatMark
11467
+ );
11468
+ meta.formatMark = newFormatMark;
11469
+ meta.step = step;
11470
+ newTr.setMeta(TrackChangesBasePluginKey, meta);
11471
+ newTr.setMeta(CommentsPluginKey, { type: "force" });
11472
+ } else if (formatChangeMark) {
11473
+ newTr.removeMark(Math.max(step.from, pos), Math.min(step.to, pos + node.nodeSize), formatChangeMark);
11474
+ }
11475
+ }
11476
+ });
11477
+ };
11220
11478
  const trackedTransaction = ({ tr, state, user }) => {
11221
11479
  const onlyInputTypeMeta = ["inputType", "uiEvent", "paste", "pointer"];
11222
11480
  const notAllowedMeta = ["historyUndo", "historyRedo", "acceptReject"];
@@ -11375,6 +11633,7 @@ const _Editor = class _Editor extends EventEmitter {
11375
11633
  editorProps: {},
11376
11634
  parseOptions: {},
11377
11635
  coreExtensionOptions: {},
11636
+ enableInputRules: true,
11378
11637
  isCommentsEnabled: false,
11379
11638
  isNewFile: false,
11380
11639
  scale: 1,
@@ -11813,7 +12072,7 @@ const _Editor = class _Editor extends EventEmitter {
11813
12072
  * @returns {Y.Doc | undefined} Updated Y.Doc if any, otherwise undefined
11814
12073
  */
11815
12074
  processCollaborationMigrations() {
11816
- console.debug("[checkVersionMigrations] Current editor version", "0.8.10");
12075
+ console.debug("[checkVersionMigrations] Current editor version", "0.8.12");
11817
12076
  if (!this.options.ydoc) return;
11818
12077
  const metaMap = this.options.ydoc.getMap("meta");
11819
12078
  let docVersion = metaMap.get("version");
@@ -13206,6 +13465,45 @@ const RunItem = Node.create({
13206
13465
  };
13207
13466
  }
13208
13467
  });
13468
+ function wrappingInputRule(config) {
13469
+ return new InputRule({
13470
+ match: config.match,
13471
+ handler: ({
13472
+ state,
13473
+ range,
13474
+ match,
13475
+ chain
13476
+ }) => {
13477
+ const attributes = callOrGet(config.getAttributes, null, match) || {};
13478
+ const tr = state.tr.delete(range.from, range.to);
13479
+ const $start = tr.doc.resolve(range.from);
13480
+ const blockRange = $start.blockRange();
13481
+ const wrapping = blockRange && findWrapping(blockRange, config.type, attributes);
13482
+ if (!wrapping) {
13483
+ return null;
13484
+ }
13485
+ tr.wrap(blockRange, wrapping);
13486
+ if (config.keepMarks && config.editor) {
13487
+ const { selection, storedMarks } = state;
13488
+ const { splittableMarks } = config.editor.extensionService;
13489
+ const marks = storedMarks || selection.$to.parentOffset && selection.$from.marks();
13490
+ if (marks) {
13491
+ const filteredMarks = marks.filter((mark) => splittableMarks.includes(mark.type.name));
13492
+ tr.ensureMarks(filteredMarks);
13493
+ }
13494
+ }
13495
+ if (config.keepAttributes) {
13496
+ const nodeType = config.type.name === "bulletList" || config.type.name === "orderedList" ? "listItem" : config.type.name;
13497
+ chain().updateAttributes(nodeType, attributes).run();
13498
+ }
13499
+ const before = tr.doc.resolve(range.from - 1).nodeBefore;
13500
+ if (before && before.type === config.type && canJoin(tr.doc, range.from - 1) && (!config.joinPredicate || config.joinPredicate(match, before))) {
13501
+ tr.join(range.from - 1);
13502
+ }
13503
+ }
13504
+ });
13505
+ }
13506
+ const inputRegex$1 = /^\s*([-+*])\s$/;
13209
13507
  const BulletList = Node.create({
13210
13508
  name: "bulletList",
13211
13509
  group: "block list",
@@ -13216,7 +13514,8 @@ const BulletList = Node.create({
13216
13514
  return {
13217
13515
  itemTypeName: "listItem",
13218
13516
  htmlAttributes: {},
13219
- keepMarks: true
13517
+ keepMarks: true,
13518
+ keepAttributes: false
13220
13519
  };
13221
13520
  },
13222
13521
  parseDOM() {
@@ -13254,8 +13553,29 @@ const BulletList = Node.create({
13254
13553
  return this.editor.commands.toggleBulletList();
13255
13554
  }
13256
13555
  };
13257
- }
13556
+ },
13258
13557
  // Input rules.
13558
+ addInputRules() {
13559
+ let inputRule = wrappingInputRule({
13560
+ match: inputRegex$1,
13561
+ type: this.type
13562
+ });
13563
+ if (this.options.keepMarks || this.options.keepAttributes) {
13564
+ inputRule = wrappingInputRule({
13565
+ match: inputRegex$1,
13566
+ type: this.type,
13567
+ keepMarks: this.options.keepMarks,
13568
+ keepAttributes: this.options.keepAttributes,
13569
+ getAttributes: () => {
13570
+ return this.editor.getAttributes("textStyle");
13571
+ },
13572
+ editor: this.editor
13573
+ });
13574
+ }
13575
+ return [
13576
+ inputRule
13577
+ ];
13578
+ }
13259
13579
  });
13260
13580
  function orderedListSync(options = {}) {
13261
13581
  return new Plugin({
@@ -13466,6 +13786,7 @@ function buildFirstListItemAttrs({ state, listItems }) {
13466
13786
  listNumberingType
13467
13787
  };
13468
13788
  }
13789
+ const inputRegex = /^(\d+)\.\s$/;
13469
13790
  const OrderedList = Node.create({
13470
13791
  name: "orderedList",
13471
13792
  group: "block list",
@@ -13477,6 +13798,7 @@ const OrderedList = Node.create({
13477
13798
  itemTypeName: "listItem",
13478
13799
  htmlAttributes: {},
13479
13800
  keepMarks: true,
13801
+ keepAttributes: false,
13480
13802
  listStyleTypes: ["decimal", "lowerAlpha", "lowerRoman"]
13481
13803
  };
13482
13804
  },
@@ -13634,6 +13956,28 @@ const OrderedList = Node.create({
13634
13956
  },
13635
13957
  addPmPlugins() {
13636
13958
  return [orderedListMarker(), orderedListSync()];
13959
+ },
13960
+ addInputRules() {
13961
+ let inputRule = wrappingInputRule({
13962
+ match: inputRegex,
13963
+ type: this.type,
13964
+ getAttributes: (match) => ({ start: +match[1] }),
13965
+ joinPredicate: (match, node) => node.childCount + node.attrs.start === +match[1]
13966
+ });
13967
+ if (this.options.keepMarks || this.options.keepAttributes) {
13968
+ inputRule = wrappingInputRule({
13969
+ match: inputRegex,
13970
+ type: this.type,
13971
+ keepMarks: this.options.keepMarks,
13972
+ keepAttributes: this.options.keepAttributes,
13973
+ getAttributes: (match) => ({ start: +match[1], ...this.editor.getAttributes("textStyle") }),
13974
+ joinPredicate: (match, node) => node.childCount + node.attrs.start === +match[1],
13975
+ editor: this.editor
13976
+ });
13977
+ }
13978
+ return [
13979
+ inputRule
13980
+ ];
13637
13981
  }
13638
13982
  });
13639
13983
  function randomId() {
@@ -22752,4 +23096,4 @@ export {
22752
23096
  redoDepth as r,
22753
23097
  undoDepth as u
22754
23098
  };
22755
- //# sourceMappingURL=editor-nlt5JeOJ.js.map
23099
+ //# sourceMappingURL=editor-aREw3zbp.js.map