roosterjs-content-model-plugins 9.26.0 → 9.27.0

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 (139) hide show
  1. package/lib/autoFormat/AutoFormatPlugin.d.ts +4 -1
  2. package/lib/autoFormat/AutoFormatPlugin.js +94 -96
  3. package/lib/autoFormat/AutoFormatPlugin.js.map +1 -1
  4. package/lib/autoFormat/horizontalLine/checkAndInsertHorizontalLine.d.ts +3 -3
  5. package/lib/autoFormat/horizontalLine/checkAndInsertHorizontalLine.js +14 -21
  6. package/lib/autoFormat/horizontalLine/checkAndInsertHorizontalLine.js.map +1 -1
  7. package/lib/edit/EditPlugin.d.ts +9 -0
  8. package/lib/edit/EditPlugin.js +19 -3
  9. package/lib/edit/EditPlugin.js.map +1 -1
  10. package/lib/edit/utils/splitParagraph.d.ts +3 -2
  11. package/lib/edit/utils/splitParagraph.js +41 -2
  12. package/lib/edit/utils/splitParagraph.js.map +1 -1
  13. package/lib/imageEdit/ImageEditPlugin.js +9 -9
  14. package/lib/imageEdit/ImageEditPlugin.js.map +1 -1
  15. package/lib/imageEdit/utils/findEditingImage.d.ts +4 -0
  16. package/lib/imageEdit/utils/findEditingImage.js +7 -2
  17. package/lib/imageEdit/utils/findEditingImage.js.map +1 -1
  18. package/lib/paste/PastePlugin.js +3 -3
  19. package/lib/paste/PastePlugin.js.map +1 -1
  20. package/lib/paste/PowerPoint/processPastedContentFromPowerPoint.js +132 -1
  21. package/lib/paste/PowerPoint/processPastedContentFromPowerPoint.js.map +1 -1
  22. package/lib/paste/WordDesktop/getStyleMetadata.d.ts +2 -2
  23. package/lib/paste/WordDesktop/getStyleMetadata.js +22 -5
  24. package/lib/paste/WordDesktop/getStyleMetadata.js.map +1 -1
  25. package/lib/paste/WordDesktop/processPastedContentFromWordDesktop.d.ts +2 -2
  26. package/lib/paste/WordDesktop/processPastedContentFromWordDesktop.js +5 -5
  27. package/lib/paste/WordDesktop/processPastedContentFromWordDesktop.js.map +1 -1
  28. package/lib/paste/WordDesktop/processWordLists.js +25 -60
  29. package/lib/paste/WordDesktop/processWordLists.js.map +1 -1
  30. package/lib/paste/parsers/deprecatedColorParser.js.map +1 -0
  31. package/lib/paste/parsers/linkParser.js.map +1 -0
  32. package/lib/paste/{WordDesktop → parsers}/removeNegativeTextIndentParser.js +1 -1
  33. package/lib/paste/parsers/removeNegativeTextIndentParser.js.map +1 -0
  34. package/lib/paste/utils/customListUtils.d.ts +9 -0
  35. package/lib/paste/utils/customListUtils.js +63 -0
  36. package/lib/paste/utils/customListUtils.js.map +1 -0
  37. package/lib/watermark/WatermarkPlugin.js +1 -1
  38. package/lib/watermark/WatermarkPlugin.js.map +1 -1
  39. package/lib-amd/autoFormat/AutoFormatPlugin.d.ts +4 -1
  40. package/lib-amd/autoFormat/AutoFormatPlugin.js +94 -96
  41. package/lib-amd/autoFormat/AutoFormatPlugin.js.map +1 -1
  42. package/lib-amd/autoFormat/horizontalLine/checkAndInsertHorizontalLine.d.ts +3 -3
  43. package/lib-amd/autoFormat/horizontalLine/checkAndInsertHorizontalLine.js +15 -21
  44. package/lib-amd/autoFormat/horizontalLine/checkAndInsertHorizontalLine.js.map +1 -1
  45. package/lib-amd/edit/EditPlugin.d.ts +9 -0
  46. package/lib-amd/edit/EditPlugin.js +19 -3
  47. package/lib-amd/edit/EditPlugin.js.map +1 -1
  48. package/lib-amd/edit/utils/splitParagraph.d.ts +3 -2
  49. package/lib-amd/edit/utils/splitParagraph.js +41 -2
  50. package/lib-amd/edit/utils/splitParagraph.js.map +1 -1
  51. package/lib-amd/imageEdit/ImageEditPlugin.js +9 -9
  52. package/lib-amd/imageEdit/ImageEditPlugin.js.map +1 -1
  53. package/lib-amd/imageEdit/utils/findEditingImage.d.ts +4 -0
  54. package/lib-amd/imageEdit/utils/findEditingImage.js +7 -2
  55. package/lib-amd/imageEdit/utils/findEditingImage.js.map +1 -1
  56. package/lib-amd/paste/PastePlugin.js +2 -2
  57. package/lib-amd/paste/PastePlugin.js.map +1 -1
  58. package/lib-amd/paste/PowerPoint/processPastedContentFromPowerPoint.js +128 -2
  59. package/lib-amd/paste/PowerPoint/processPastedContentFromPowerPoint.js.map +1 -1
  60. package/lib-amd/paste/WordDesktop/getStyleMetadata.d.ts +2 -2
  61. package/lib-amd/paste/WordDesktop/getStyleMetadata.js +22 -5
  62. package/lib-amd/paste/WordDesktop/getStyleMetadata.js.map +1 -1
  63. package/lib-amd/paste/WordDesktop/processPastedContentFromWordDesktop.d.ts +2 -2
  64. package/lib-amd/paste/WordDesktop/processPastedContentFromWordDesktop.js +5 -5
  65. package/lib-amd/paste/WordDesktop/processPastedContentFromWordDesktop.js.map +1 -1
  66. package/lib-amd/paste/WordDesktop/processWordLists.js +25 -60
  67. package/lib-amd/paste/WordDesktop/processWordLists.js.map +1 -1
  68. package/lib-amd/paste/parsers/deprecatedColorParser.js.map +1 -0
  69. package/lib-amd/paste/parsers/linkParser.js.map +1 -0
  70. package/lib-amd/paste/{WordDesktop → parsers}/removeNegativeTextIndentParser.js +1 -1
  71. package/lib-amd/paste/parsers/removeNegativeTextIndentParser.js.map +1 -0
  72. package/lib-amd/paste/utils/customListUtils.d.ts +9 -0
  73. package/lib-amd/paste/utils/customListUtils.js +63 -0
  74. package/lib-amd/paste/utils/customListUtils.js.map +1 -0
  75. package/lib-amd/watermark/WatermarkPlugin.js +1 -1
  76. package/lib-amd/watermark/WatermarkPlugin.js.map +1 -1
  77. package/lib-mjs/autoFormat/AutoFormatPlugin.d.ts +4 -1
  78. package/lib-mjs/autoFormat/AutoFormatPlugin.js +95 -97
  79. package/lib-mjs/autoFormat/AutoFormatPlugin.js.map +1 -1
  80. package/lib-mjs/autoFormat/horizontalLine/checkAndInsertHorizontalLine.d.ts +3 -3
  81. package/lib-mjs/autoFormat/horizontalLine/checkAndInsertHorizontalLine.js +15 -22
  82. package/lib-mjs/autoFormat/horizontalLine/checkAndInsertHorizontalLine.js.map +1 -1
  83. package/lib-mjs/edit/EditPlugin.d.ts +9 -0
  84. package/lib-mjs/edit/EditPlugin.js +19 -3
  85. package/lib-mjs/edit/EditPlugin.js.map +1 -1
  86. package/lib-mjs/edit/utils/splitParagraph.d.ts +3 -2
  87. package/lib-mjs/edit/utils/splitParagraph.js +42 -3
  88. package/lib-mjs/edit/utils/splitParagraph.js.map +1 -1
  89. package/lib-mjs/imageEdit/ImageEditPlugin.js +11 -11
  90. package/lib-mjs/imageEdit/ImageEditPlugin.js.map +1 -1
  91. package/lib-mjs/imageEdit/utils/findEditingImage.d.ts +4 -0
  92. package/lib-mjs/imageEdit/utils/findEditingImage.js +6 -1
  93. package/lib-mjs/imageEdit/utils/findEditingImage.js.map +1 -1
  94. package/lib-mjs/paste/PastePlugin.js +3 -3
  95. package/lib-mjs/paste/PastePlugin.js.map +1 -1
  96. package/lib-mjs/paste/PowerPoint/processPastedContentFromPowerPoint.js +133 -2
  97. package/lib-mjs/paste/PowerPoint/processPastedContentFromPowerPoint.js.map +1 -1
  98. package/lib-mjs/paste/WordDesktop/getStyleMetadata.d.ts +2 -2
  99. package/lib-mjs/paste/WordDesktop/getStyleMetadata.js +22 -5
  100. package/lib-mjs/paste/WordDesktop/getStyleMetadata.js.map +1 -1
  101. package/lib-mjs/paste/WordDesktop/processPastedContentFromWordDesktop.d.ts +2 -2
  102. package/lib-mjs/paste/WordDesktop/processPastedContentFromWordDesktop.js +5 -5
  103. package/lib-mjs/paste/WordDesktop/processPastedContentFromWordDesktop.js.map +1 -1
  104. package/lib-mjs/paste/WordDesktop/processWordLists.js +26 -61
  105. package/lib-mjs/paste/WordDesktop/processWordLists.js.map +1 -1
  106. package/lib-mjs/paste/parsers/deprecatedColorParser.js.map +1 -0
  107. package/lib-mjs/paste/parsers/linkParser.js.map +1 -0
  108. package/lib-mjs/paste/{WordDesktop → parsers}/removeNegativeTextIndentParser.js +1 -1
  109. package/lib-mjs/paste/parsers/removeNegativeTextIndentParser.js.map +1 -0
  110. package/lib-mjs/paste/utils/customListUtils.d.ts +9 -0
  111. package/lib-mjs/paste/utils/customListUtils.js +58 -0
  112. package/lib-mjs/paste/utils/customListUtils.js.map +1 -0
  113. package/lib-mjs/watermark/WatermarkPlugin.js +1 -1
  114. package/lib-mjs/watermark/WatermarkPlugin.js.map +1 -1
  115. package/package.json +5 -5
  116. package/lib/paste/WordDesktop/removeNegativeTextIndentParser.js.map +0 -1
  117. package/lib/paste/utils/deprecatedColorParser.js.map +0 -1
  118. package/lib/paste/utils/linkParser.js.map +0 -1
  119. package/lib-amd/paste/WordDesktop/removeNegativeTextIndentParser.js.map +0 -1
  120. package/lib-amd/paste/utils/deprecatedColorParser.js.map +0 -1
  121. package/lib-amd/paste/utils/linkParser.js.map +0 -1
  122. package/lib-mjs/paste/WordDesktop/removeNegativeTextIndentParser.js.map +0 -1
  123. package/lib-mjs/paste/utils/deprecatedColorParser.js.map +0 -1
  124. package/lib-mjs/paste/utils/linkParser.js.map +0 -1
  125. /package/lib/paste/{utils → parsers}/deprecatedColorParser.d.ts +0 -0
  126. /package/lib/paste/{utils → parsers}/deprecatedColorParser.js +0 -0
  127. /package/lib/paste/{utils → parsers}/linkParser.d.ts +0 -0
  128. /package/lib/paste/{utils → parsers}/linkParser.js +0 -0
  129. /package/lib/paste/{WordDesktop → parsers}/removeNegativeTextIndentParser.d.ts +0 -0
  130. /package/lib-amd/paste/{utils → parsers}/deprecatedColorParser.d.ts +0 -0
  131. /package/lib-amd/paste/{utils → parsers}/deprecatedColorParser.js +0 -0
  132. /package/lib-amd/paste/{utils → parsers}/linkParser.d.ts +0 -0
  133. /package/lib-amd/paste/{utils → parsers}/linkParser.js +0 -0
  134. /package/lib-amd/paste/{WordDesktop → parsers}/removeNegativeTextIndentParser.d.ts +0 -0
  135. /package/lib-mjs/paste/{utils → parsers}/deprecatedColorParser.d.ts +0 -0
  136. /package/lib-mjs/paste/{utils → parsers}/deprecatedColorParser.js +0 -0
  137. /package/lib-mjs/paste/{utils → parsers}/linkParser.d.ts +0 -0
  138. /package/lib-mjs/paste/{utils → parsers}/linkParser.js +0 -0
  139. /package/lib-mjs/paste/{WordDesktop → parsers}/removeNegativeTextIndentParser.d.ts +0 -0
@@ -46,9 +46,12 @@ export declare class AutoFormatPlugin implements EditorPlugin {
46
46
  * @param event The event to handle:
47
47
  */
48
48
  onPluginEvent(event: PluginEvent): void;
49
+ private autoLink;
50
+ private tabFeatures;
49
51
  private features;
52
+ private enterFeatures;
53
+ private handleKeyboardEvents;
50
54
  private handleEditorInputEvent;
51
55
  private handleKeyDownEvent;
52
- private handleEnterKey;
53
56
  private handleContentChangedEvent;
54
57
  }
@@ -49,52 +49,71 @@ var AutoFormatPlugin = /** @class */ (function () {
49
49
  if (options === void 0) { options = DefaultOptions; }
50
50
  this.options = options;
51
51
  this.editor = null;
52
- this.features = [
52
+ this.autoLink = {
53
+ enabled: !!(this.options.autoLink || this.options.autoTel || this.options.autoMailto),
54
+ transformFunction: function (_model, previousSegment, paragraph, context) {
55
+ var _a;
56
+ var _b = _this.options, autoLink = _b.autoLink, autoTel = _b.autoTel, autoMailto = _b.autoMailto;
57
+ var linkSegment = (0, roosterjs_content_model_api_1.promoteLink)(previousSegment, paragraph, {
58
+ autoLink: autoLink,
59
+ autoTel: autoTel,
60
+ autoMailto: autoMailto,
61
+ });
62
+ if (linkSegment) {
63
+ return createAnchor(((_a = linkSegment.link) === null || _a === void 0 ? void 0 : _a.format.href) || '', linkSegment.text);
64
+ }
65
+ return false;
66
+ },
67
+ apiName: 'autoLink',
68
+ changeSource: roosterjs_content_model_dom_1.ChangeSource.AutoLink,
69
+ };
70
+ this.tabFeatures = [
53
71
  {
54
- autoFormat: 'list',
55
72
  enabled: !!(this.options.autoBullet || this.options.autoNumbering),
56
73
  transformFunction: function (model, _previousSegment, paragraph, context) {
57
74
  return (0, keyboardListTrigger_1.keyboardListTrigger)(model, paragraph, context, _this.options.autoBullet, _this.options.autoNumbering, _this.options.removeListMargins);
58
75
  },
76
+ apiName: 'autoToggleList',
77
+ changeSource: roosterjs_content_model_dom_1.ChangeSource.AutoFormat,
59
78
  },
79
+ this.autoLink,
80
+ ];
81
+ this.features = (0, tslib_1.__spreadArray)((0, tslib_1.__spreadArray)([], (0, tslib_1.__read)(this.tabFeatures), false), [
60
82
  {
61
- autoFormat: 'link',
62
- enabled: !!(this.options.autoLink || this.options.autoTel || this.options.autoMailto),
63
- transformFunction: function (_model, previousSegment, paragraph, context) {
64
- var _a;
65
- var _b = _this.options, autoLink = _b.autoLink, autoTel = _b.autoTel, autoMailto = _b.autoMailto;
66
- var linkSegment = (0, roosterjs_content_model_api_1.promoteLink)(previousSegment, paragraph, {
67
- autoLink: autoLink,
68
- autoTel: autoTel,
69
- autoMailto: autoMailto,
70
- });
71
- if (linkSegment) {
72
- return createAnchor(((_a = linkSegment.link) === null || _a === void 0 ? void 0 : _a.format.href) || '', linkSegment.text);
73
- }
74
- return false;
75
- },
76
- },
77
- {
78
- autoFormat: 'hyphen',
79
83
  enabled: !!this.options.autoHyphen,
84
+ apiName: 'autoHyphen',
85
+ changeSource: roosterjs_content_model_dom_1.ChangeSource.Format,
80
86
  transformFunction: function (_model, previousSegment, paragraph, context) {
81
87
  return (0, transformHyphen_1.transformHyphen)(previousSegment, paragraph, context);
82
88
  },
83
89
  },
84
90
  {
85
- autoFormat: 'fraction',
86
91
  enabled: !!this.options.autoFraction,
92
+ apiName: 'autoFraction',
93
+ changeSource: roosterjs_content_model_dom_1.ChangeSource.Format,
87
94
  transformFunction: function (_model, previousSegment, paragraph, context) {
88
95
  return (0, transformFraction_1.transformFraction)(previousSegment, paragraph, context);
89
96
  },
90
97
  },
91
98
  {
92
- autoFormat: 'ordinal',
93
99
  enabled: !!this.options.autoOrdinals,
100
+ apiName: 'autoOrdinal',
101
+ changeSource: roosterjs_content_model_dom_1.ChangeSource.Format,
94
102
  transformFunction: function (_model, previousSegment, paragraph, context) {
95
103
  return (0, transformOrdinals_1.transformOrdinals)(previousSegment, paragraph, context);
96
104
  },
97
105
  },
106
+ ], false);
107
+ this.enterFeatures = [
108
+ {
109
+ enabled: !!this.options.autoHorizontalLine,
110
+ transformFunction: function (model, _previousSegment, paragraph, context) {
111
+ return (0, checkAndInsertHorizontalLine_1.checkAndInsertHorizontalLine)(model, paragraph, context);
112
+ },
113
+ apiName: 'autoHorizontalLine',
114
+ changeSource: roosterjs_content_model_dom_1.ChangeSource.AutoFormat,
115
+ },
116
+ this.autoLink,
98
117
  ];
99
118
  }
100
119
  /**
@@ -141,8 +160,51 @@ var AutoFormatPlugin = /** @class */ (function () {
141
160
  }
142
161
  }
143
162
  };
163
+ AutoFormatPlugin.prototype.handleKeyboardEvents = function (editor, features) {
164
+ var formatOptions = {
165
+ changeSource: '',
166
+ apiName: '',
167
+ getChangeData: undefined,
168
+ };
169
+ (0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(editor, function (model, previousSegment, paragraph, _markerFormat, context) {
170
+ var e_1, _a;
171
+ var featureApplied = undefined;
172
+ var _loop_1 = function (feature) {
173
+ if (feature.enabled) {
174
+ var result_1 = feature.transformFunction(model, previousSegment, paragraph, context);
175
+ if (result_1) {
176
+ if (typeof result_1 !== 'boolean') {
177
+ formatOptions.getChangeData = function () { return result_1; };
178
+ }
179
+ featureApplied = feature;
180
+ return "break";
181
+ }
182
+ }
183
+ };
184
+ try {
185
+ for (var features_1 = (0, tslib_1.__values)(features), features_1_1 = features_1.next(); !features_1_1.done; features_1_1 = features_1.next()) {
186
+ var feature = features_1_1.value;
187
+ var state_1 = _loop_1(feature);
188
+ if (state_1 === "break")
189
+ break;
190
+ }
191
+ }
192
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
193
+ finally {
194
+ try {
195
+ if (features_1_1 && !features_1_1.done && (_a = features_1.return)) _a.call(features_1);
196
+ }
197
+ finally { if (e_1) throw e_1.error; }
198
+ }
199
+ if (featureApplied) {
200
+ formatOptions.changeSource = featureApplied.changeSource;
201
+ formatOptions.apiName = featureApplied.apiName;
202
+ }
203
+ return !!featureApplied;
204
+ }, formatOptions);
205
+ return formatOptions;
206
+ };
144
207
  AutoFormatPlugin.prototype.handleEditorInputEvent = function (editor, event) {
145
- var _this = this;
146
208
  var rawEvent = event.rawEvent;
147
209
  var selection = editor.getDOMSelection();
148
210
  if (rawEvent.inputType === 'insertText' &&
@@ -151,53 +213,12 @@ var AutoFormatPlugin = /** @class */ (function () {
151
213
  selection.range.collapsed) {
152
214
  switch (rawEvent.data) {
153
215
  case ' ':
154
- var formatOptions_1 = {
155
- changeSource: '',
156
- apiName: '',
157
- getChangeData: undefined,
158
- };
159
- (0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(editor, function (model, previousSegment, paragraph, _markerFormat, context) {
160
- var e_1, _a;
161
- var formatApplied = undefined;
162
- var _loop_1 = function (feature) {
163
- if (feature.enabled) {
164
- var result_1 = feature.transformFunction(model, previousSegment, paragraph, context);
165
- if (result_1) {
166
- if (typeof result_1 !== 'boolean') {
167
- formatOptions_1.getChangeData = function () { return result_1; };
168
- }
169
- formatApplied = feature.autoFormat;
170
- return "break";
171
- }
172
- }
173
- };
174
- try {
175
- for (var _b = (0, tslib_1.__values)(_this.features), _c = _b.next(); !_c.done; _c = _b.next()) {
176
- var feature = _c.value;
177
- var state_1 = _loop_1(feature);
178
- if (state_1 === "break")
179
- break;
180
- }
181
- }
182
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
183
- finally {
184
- try {
185
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
186
- }
187
- finally { if (e_1) throw e_1.error; }
188
- }
189
- if (formatApplied) {
190
- formatOptions_1.changeSource = getChangeSource(formatApplied);
191
- formatOptions_1.apiName = getApiName(formatApplied);
192
- }
193
- return !!formatApplied;
194
- }, formatOptions_1);
216
+ this.handleKeyboardEvents(editor, this.features);
195
217
  break;
196
218
  }
197
219
  }
198
220
  };
199
221
  AutoFormatPlugin.prototype.handleKeyDownEvent = function (editor, event) {
200
- var _this = this;
201
222
  var rawEvent = event.rawEvent;
202
223
  if (!rawEvent.defaultPrevented && !event.handledByEditFeature) {
203
224
  switch (rawEvent.key) {
@@ -208,34 +229,21 @@ var AutoFormatPlugin = /** @class */ (function () {
208
229
  break;
209
230
  case 'Tab':
210
231
  if (!rawEvent.shiftKey) {
211
- (0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(editor, function (model, _previousSegment, paragraph, _markerFormat, context) {
212
- var _a = _this.options, autoBullet = _a.autoBullet, autoNumbering = _a.autoNumbering, removeListMargins = _a.removeListMargins;
213
- var shouldList = false;
214
- if (autoBullet || autoNumbering) {
215
- shouldList = (0, keyboardListTrigger_1.keyboardListTrigger)(model, paragraph, context, autoBullet, autoNumbering, removeListMargins);
216
- context.canUndoByBackspace = shouldList;
217
- }
218
- if (shouldList) {
219
- event.rawEvent.preventDefault();
220
- }
221
- return shouldList;
222
- }, {
223
- changeSource: roosterjs_content_model_dom_1.ChangeSource.AutoFormat,
224
- apiName: 'autoToggleList',
225
- });
232
+ var eventHandled_1 = this.handleKeyboardEvents(editor, this.tabFeatures);
233
+ if (eventHandled_1.apiName == 'autoToggleList') {
234
+ event.rawEvent.preventDefault();
235
+ }
226
236
  }
227
237
  break;
228
238
  case 'Enter':
229
- this.handleEnterKey(editor, event);
239
+ var eventHandled = this.handleKeyboardEvents(editor, this.enterFeatures);
240
+ if (eventHandled.apiName == 'autoHorizontalLine') {
241
+ event.rawEvent.preventDefault();
242
+ }
230
243
  break;
231
244
  }
232
245
  }
233
246
  };
234
- AutoFormatPlugin.prototype.handleEnterKey = function (editor, event) {
235
- if (this.options.autoHorizontalLine) {
236
- (0, checkAndInsertHorizontalLine_1.checkAndInsertHorizontalLine)(editor, event);
237
- }
238
- };
239
247
  AutoFormatPlugin.prototype.handleContentChangedEvent = function (editor, event) {
240
248
  var _a = this.options, autoLink = _a.autoLink, autoTel = _a.autoTel, autoMailto = _a.autoMailto;
241
249
  if (event.source == 'Paste' && (autoLink || autoTel || autoMailto)) {
@@ -249,16 +257,6 @@ var AutoFormatPlugin = /** @class */ (function () {
249
257
  return AutoFormatPlugin;
250
258
  }());
251
259
  exports.AutoFormatPlugin = AutoFormatPlugin;
252
- var getApiName = function (autoFormat) {
253
- return autoFormat == 'list' ? 'autoToggleList' : autoFormat == 'hyphen' ? 'autoHyphen' : '';
254
- };
255
- var getChangeSource = function (autoFormat) {
256
- return autoFormat == 'list' || autoFormat == 'hyphen'
257
- ? roosterjs_content_model_dom_1.ChangeSource.AutoFormat
258
- : autoFormat == 'link'
259
- ? roosterjs_content_model_dom_1.ChangeSource.AutoLink
260
- : '';
261
- };
262
260
  var createAnchor = function (url, text) {
263
261
  var anchor = document.createElement('a');
264
262
  anchor.href = url;
@@ -1 +1 @@
1
- {"version":3,"file":"AutoFormatPlugin.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-plugins/lib/autoFormat/AutoFormatPlugin.ts"],"names":[],"mappings":";;;;AAAA,2EAA2D;AAC3D,8FAA6F;AAC7F,gDAA+C;AAC/C,2EAAkG;AAClG,kEAAiE;AACjE,iEAAgE;AAChE,4DAA2D;AAC3D,iEAAgE;AAChE,wCAAuC;AAmCvC;;GAEG;AACH,IAAM,cAAc,GAA+B;IAC/C,UAAU,EAAE,KAAK;IACjB,aAAa,EAAE,KAAK;IACpB,UAAU,EAAE,KAAK;IACjB,QAAQ,EAAE,KAAK;IACf,UAAU,EAAE,KAAK;IACjB,YAAY,EAAE,KAAK;IACnB,YAAY,EAAE,KAAK;IACnB,iBAAiB,EAAE,KAAK;IACxB,kBAAkB,EAAE,KAAK;CAC5B,CAAC;AAEF;;;GAGG;AACH;IAEI;;;;;;;;;;;;;OAaG;IACH,0BAAoB,OAA2C;QAA/D,iBAAmE;QAA/C,wBAAA,EAAA,wBAA2C;QAA3C,YAAO,GAAP,OAAO,CAAoC;QAfvD,WAAM,GAAmB,IAAI,CAAC;QAiE9B,aAAQ,GAAc;YAC1B;gBACI,UAAU,EAAE,MAAM;gBAClB,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC;gBAClE,iBAAiB,EAAE,UAAC,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,OAAO;oBAC3D,OAAA,IAAA,yCAAmB,EACf,KAAK,EACL,SAAS,EACT,OAAO,EACP,KAAI,CAAC,OAAO,CAAC,UAAU,EACvB,KAAI,CAAC,OAAO,CAAC,aAAa,EAC1B,KAAI,CAAC,OAAO,CAAC,iBAAiB,CACjC;gBAPD,CAOC;aACR;YACD;gBACI,UAAU,EAAE,MAAM;gBAClB,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;gBACrF,iBAAiB,EAAE,UAAC,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,OAAO;;oBACrD,IAAA,KAAoC,KAAI,CAAC,OAAO,EAA9C,QAAQ,cAAA,EAAE,OAAO,aAAA,EAAE,UAAU,gBAAiB,CAAC;oBACvD,IAAM,WAAW,GAAG,IAAA,yCAAW,EAAC,eAAe,EAAE,SAAS,EAAE;wBACxD,QAAQ,UAAA;wBACR,OAAO,SAAA;wBACP,UAAU,YAAA;qBACb,CAAC,CAAC;oBAEH,IAAI,WAAW,EAAE;wBACb,OAAO,YAAY,CAAC,CAAA,MAAA,WAAW,CAAC,IAAI,0CAAE,MAAM,CAAC,IAAI,KAAI,EAAE,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC;qBAC9E;oBACD,OAAO,KAAK,CAAC;gBACjB,CAAC;aACJ;YACD;gBACI,UAAU,EAAE,QAAQ;gBACpB,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU;gBAClC,iBAAiB,EAAE,UAAC,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,OAAO;oBAC3D,OAAA,IAAA,iCAAe,EAAC,eAAe,EAAE,SAAS,EAAE,OAAO,CAAC;gBAApD,CAAoD;aAC3D;YACD;gBACI,UAAU,EAAE,UAAU;gBACtB,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY;gBACpC,iBAAiB,EAAE,UAAC,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,OAAO;oBAC3D,OAAA,IAAA,qCAAiB,EAAC,eAAe,EAAE,SAAS,EAAE,OAAO,CAAC;gBAAtD,CAAsD;aAC7D;YACD;gBACI,UAAU,EAAE,SAAS;gBACrB,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY;gBACpC,iBAAiB,EAAE,UAAC,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,OAAO;oBAC3D,OAAA,IAAA,qCAAiB,EAAC,eAAe,EAAE,SAAS,EAAE,OAAO,CAAC;gBAAtD,CAAsD;aAC7D;SACJ,CAAC;IAnGgE,CAAC;IAEnE;;OAEG;IACH,kCAAO,GAAP;QACI,OAAO,YAAY,CAAC;IACxB,CAAC;IAED;;;;;OAKG;IACH,qCAAU,GAAV,UAAW,MAAe;QACtB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACzB,CAAC;IAED;;;;OAIG;IACH,kCAAO,GAAP;QACI,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACvB,CAAC;IAED;;;;;OAKG;IACH,wCAAa,GAAb,UAAc,KAAkB;QAC5B,IAAI,IAAI,CAAC,MAAM,EAAE;YACb,QAAQ,KAAK,CAAC,SAAS,EAAE;gBACrB,KAAK,OAAO;oBACR,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;oBAChD,MAAM;gBACV,KAAK,SAAS;oBACV,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;oBAC5C,MAAM;gBACV,KAAK,gBAAgB;oBACjB,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;oBACnD,MAAM;aACb;SACJ;IACL,CAAC;IAqDO,iDAAsB,GAA9B,UAA+B,MAAe,EAAE,KAAuB;QAAvE,iBAoDC;QAnDG,IAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAChC,IAAM,SAAS,GAAG,MAAM,CAAC,eAAe,EAAE,CAAC;QAC3C,IACI,QAAQ,CAAC,SAAS,KAAK,YAAY;YACnC,SAAS;YACT,SAAS,CAAC,IAAI,KAAK,OAAO;YAC1B,SAAS,CAAC,KAAK,CAAC,SAAS,EAC3B;YACE,QAAQ,QAAQ,CAAC,IAAI,EAAE;gBACnB,KAAK,GAAG;oBACJ,IAAM,eAAa,GAA8B;wBAC7C,YAAY,EAAE,EAAE;wBAChB,OAAO,EAAE,EAAE;wBACX,aAAa,EAAE,SAAS;qBAC3B,CAAC;oBACF,IAAA,oEAAsC,EAClC,MAAM,EACN,UAAC,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO;;wBACtD,IAAI,aAAa,GAAkC,SAAS,CAAC;gDAElD,OAAO;4BACd,IAAI,OAAO,CAAC,OAAO,EAAE;gCACjB,IAAM,QAAM,GAAG,OAAO,CAAC,iBAAiB,CACpC,KAAK,EACL,eAAe,EACf,SAAS,EACT,OAAO,CACV,CAAC;gCACF,IAAI,QAAM,EAAE;oCACR,IAAI,OAAO,QAAM,KAAK,SAAS,EAAE;wCAC7B,eAAa,CAAC,aAAa,GAAG,cAAM,OAAA,QAAM,EAAN,CAAM,CAAC;qCAC9C;oCACD,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC;;iCAEtC;6BACJ;;;4BAfL,KAAsB,IAAA,KAAA,sBAAA,KAAI,CAAC,QAAQ,CAAA,gBAAA;gCAA9B,IAAM,OAAO,WAAA;sDAAP,OAAO;;;6BAgBjB;;;;;;;;;wBAED,IAAI,aAAa,EAAE;4BACf,eAAa,CAAC,YAAY,GAAG,eAAe,CAAC,aAAa,CAAC,CAAC;4BAC5D,eAAa,CAAC,OAAO,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC;yBACrD;wBAED,OAAO,CAAC,CAAC,aAAa,CAAC;oBAC3B,CAAC,EACD,eAAa,CAChB,CAAC;oBAEF,MAAM;aACb;SACJ;IACL,CAAC;IAEO,6CAAkB,GAA1B,UAA2B,MAAe,EAAE,KAAmB;QAA/D,iBAgDC;QA/CG,IAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAChC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,IAAI,CAAC,KAAK,CAAC,oBAAoB,EAAE;YAC3D,QAAQ,QAAQ,CAAC,GAAG,EAAE;gBAClB,KAAK,WAAW;oBACZ,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE;wBACzB,IAAA,eAAM,EAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;qBAC5B;oBACD,MAAM;gBACV,KAAK,KAAK;oBACN,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE;wBACpB,IAAA,oEAAsC,EAClC,MAAM,EACN,UAAC,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO;4BACjD,IAAA,KAIF,KAAI,CAAC,OAAO,EAHZ,UAAU,gBAAA,EACV,aAAa,mBAAA,EACb,iBAAiB,uBACL,CAAC;4BACjB,IAAI,UAAU,GAAG,KAAK,CAAC;4BACvB,IAAI,UAAU,IAAI,aAAa,EAAE;gCAC7B,UAAU,GAAG,IAAA,yCAAmB,EAC5B,KAAK,EACL,SAAS,EACT,OAAO,EACP,UAAU,EACV,aAAa,EACb,iBAAiB,CACpB,CAAC;gCACF,OAAO,CAAC,kBAAkB,GAAG,UAAU,CAAC;6BAC3C;4BACD,IAAI,UAAU,EAAE;gCACZ,KAAK,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC;6BACnC;4BACD,OAAO,UAAU,CAAC;wBACtB,CAAC,EACD;4BACI,YAAY,EAAE,0CAAY,CAAC,UAAU;4BACrC,OAAO,EAAE,gBAAgB;yBAC5B,CACJ,CAAC;qBACL;oBACD,MAAM;gBACV,KAAK,OAAO;oBACR,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;oBACnC,MAAM;aACb;SACJ;IACL,CAAC;IAEO,yCAAc,GAAtB,UAAuB,MAAe,EAAE,KAAmB;QACvD,IAAI,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE;YACjC,IAAA,2DAA4B,EAAC,MAAM,EAAE,KAAK,CAAC,CAAC;SAC/C;IACL,CAAC;IAEO,oDAAyB,GAAjC,UAAkC,MAAe,EAAE,KAA0B;QACnE,IAAA,KAAoC,IAAI,CAAC,OAAO,EAA9C,QAAQ,cAAA,EAAE,OAAO,aAAA,EAAE,UAAU,gBAAiB,CAAC;QACvD,IAAI,KAAK,CAAC,MAAM,IAAI,OAAO,IAAI,CAAC,QAAQ,IAAI,OAAO,IAAI,UAAU,CAAC,EAAE;YAChE,IAAA,uBAAU,EAAC,MAAM,EAAE;gBACf,QAAQ,UAAA;gBACR,OAAO,SAAA;gBACP,UAAU,YAAA;aACb,CAAC,CAAC;SACN;IACL,CAAC;IACL,uBAAC;AAAD,CAAC,AA7OD,IA6OC;AA7OY,4CAAgB;AA+O7B,IAAM,UAAU,GAAG,UAAC,UAA6B;IAC7C,OAAO,UAAU,IAAI,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,UAAU,IAAI,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;AAChG,CAAC,CAAC;AAEF,IAAM,eAAe,GAAG,UAAC,UAA6B;IAClD,OAAO,UAAU,IAAI,MAAM,IAAI,UAAU,IAAI,QAAQ;QACjD,CAAC,CAAC,0CAAY,CAAC,UAAU;QACzB,CAAC,CAAC,UAAU,IAAI,MAAM;YACtB,CAAC,CAAC,0CAAY,CAAC,QAAQ;YACvB,CAAC,CAAC,EAAE,CAAC;AACb,CAAC,CAAC;AAEF,IAAM,YAAY,GAAG,UAAC,GAAW,EAAE,IAAY;IAC3C,IAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,CAAC,IAAI,GAAG,GAAG,CAAC;IAClB,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC;IAC1B,OAAO,MAAM,CAAC;AAClB,CAAC,CAAC","sourcesContent":["import { ChangeSource } from 'roosterjs-content-model-dom';\nimport { checkAndInsertHorizontalLine } from './horizontalLine/checkAndInsertHorizontalLine';\nimport { createLink } from './link/createLink';\nimport { formatTextSegmentBeforeSelectionMarker, promoteLink } from 'roosterjs-content-model-api';\nimport { keyboardListTrigger } from './list/keyboardListTrigger';\nimport { transformFraction } from './numbers/transformFraction';\nimport { transformHyphen } from './hyphen/transformHyphen';\nimport { transformOrdinals } from './numbers/transformOrdinals';\nimport { unlink } from './link/unlink';\nimport type { AutoFormatOptions } from './interface/AutoFormatOptions';\nimport type {\n ContentChangedEvent,\n ContentModelText,\n EditorInputEvent,\n EditorPlugin,\n FormatContentModelContext,\n FormatContentModelOptions,\n IEditor,\n KeyDownEvent,\n PluginEvent,\n ReadonlyContentModelDocument,\n ShallowMutableContentModelParagraph,\n} from 'roosterjs-content-model-types';\n\n/**\n * @internal\n */\ntype AutoFormatFeature = 'list' | 'link' | 'hyphen' | 'fraction' | 'ordinal';\n\n/**\n * @internal\n */\ninterface Feature {\n autoFormat: AutoFormatFeature;\n enabled: boolean;\n transformFunction: (\n model: ReadonlyContentModelDocument,\n previousSegment: ContentModelText,\n paragraph: ShallowMutableContentModelParagraph,\n context: FormatContentModelContext\n ) => boolean | HTMLElement;\n}\n\n/**\n * @internal\n */\nconst DefaultOptions: Partial<AutoFormatOptions> = {\n autoBullet: false,\n autoNumbering: false,\n autoUnlink: false,\n autoLink: false,\n autoHyphen: false,\n autoFraction: false,\n autoOrdinals: false,\n removeListMargins: false,\n autoHorizontalLine: false,\n};\n\n/**\n * Auto Format plugin handles auto formatting, such as transforming * characters into a bullet list.\n * It can be customized with options to enable or disable auto list features.\n */\nexport class AutoFormatPlugin implements EditorPlugin {\n private editor: IEditor | null = null;\n /**\n * @param options An optional parameter that takes in an object of type AutoFormatOptions, which includes the following properties:\n * - autoBullet: A boolean that enables or disables automatic bullet list formatting. Defaults to false.\n * - autoNumbering: A boolean that enables or disables automatic numbering formatting. Defaults to false.\n * - removeListMargins: A boolean to remove list margins when it is automatically triggered. Defaults to false.\n * - autoHyphen: A boolean that enables or disables automatic hyphen transformation. Defaults to false.\n * - autoFraction: A boolean that enables or disables automatic fraction transformation. Defaults to false.\n * - autoOrdinals: A boolean that enables or disables automatic ordinal number transformation. Defaults to false.\n * - autoLink: A boolean that enables or disables automatic hyperlink url address creation when pasting or typing content. Defaults to false.\n * - autoUnlink: A boolean that enables or disables automatic hyperlink removal when pressing backspace. Defaults to false.\n * - autoTel: A boolean that enables or disables automatic hyperlink telephone numbers transformation. Defaults to false.\n * - autoMailto: A boolean that enables or disables automatic hyperlink email address transformation. Defaults to false.\n * - autoHorizontalLine: A boolean that enables or disables automatic horizontal line creation. Defaults to false.\n */\n constructor(private options: AutoFormatOptions = DefaultOptions) {}\n\n /**\n * Get name of this plugin\n */\n getName() {\n return 'AutoFormat';\n }\n\n /**\n * The first method that editor will call to a plugin when editor is initializing.\n * It will pass in the editor instance, plugin should take this chance to save the\n * editor reference so that it can call to any editor method or format API later.\n * @param editor The editor object\n */\n initialize(editor: IEditor) {\n this.editor = editor;\n }\n\n /**\n * The last method that editor will call to a plugin before it is disposed.\n * Plugin can take this chance to clear the reference to editor. After this method is\n * called, plugin should not call to any editor method since it will result in error.\n */\n dispose() {\n this.editor = null;\n }\n\n /**\n * Core method for a plugin. Once an event happens in editor, editor will call this\n * method of each plugin to handle the event as long as the event is not handled\n * exclusively by another plugin.\n * @param event The event to handle:\n */\n onPluginEvent(event: PluginEvent) {\n if (this.editor) {\n switch (event.eventType) {\n case 'input':\n this.handleEditorInputEvent(this.editor, event);\n break;\n case 'keyDown':\n this.handleKeyDownEvent(this.editor, event);\n break;\n case 'contentChanged':\n this.handleContentChangedEvent(this.editor, event);\n break;\n }\n }\n }\n\n private features: Feature[] = [\n {\n autoFormat: 'list',\n enabled: !!(this.options.autoBullet || this.options.autoNumbering),\n transformFunction: (model, _previousSegment, paragraph, context) =>\n keyboardListTrigger(\n model,\n paragraph,\n context,\n this.options.autoBullet,\n this.options.autoNumbering,\n this.options.removeListMargins\n ),\n },\n {\n autoFormat: 'link',\n enabled: !!(this.options.autoLink || this.options.autoTel || this.options.autoMailto),\n transformFunction: (_model, previousSegment, paragraph, context) => {\n const { autoLink, autoTel, autoMailto } = this.options;\n const linkSegment = promoteLink(previousSegment, paragraph, {\n autoLink,\n autoTel,\n autoMailto,\n });\n\n if (linkSegment) {\n return createAnchor(linkSegment.link?.format.href || '', linkSegment.text);\n }\n return false;\n },\n },\n {\n autoFormat: 'hyphen',\n enabled: !!this.options.autoHyphen,\n transformFunction: (_model, previousSegment, paragraph, context) =>\n transformHyphen(previousSegment, paragraph, context),\n },\n {\n autoFormat: 'fraction',\n enabled: !!this.options.autoFraction,\n transformFunction: (_model, previousSegment, paragraph, context) =>\n transformFraction(previousSegment, paragraph, context),\n },\n {\n autoFormat: 'ordinal',\n enabled: !!this.options.autoOrdinals,\n transformFunction: (_model, previousSegment, paragraph, context) =>\n transformOrdinals(previousSegment, paragraph, context),\n },\n ];\n\n private handleEditorInputEvent(editor: IEditor, event: EditorInputEvent) {\n const rawEvent = event.rawEvent;\n const selection = editor.getDOMSelection();\n if (\n rawEvent.inputType === 'insertText' &&\n selection &&\n selection.type === 'range' &&\n selection.range.collapsed\n ) {\n switch (rawEvent.data) {\n case ' ':\n const formatOptions: FormatContentModelOptions = {\n changeSource: '',\n apiName: '',\n getChangeData: undefined,\n };\n formatTextSegmentBeforeSelectionMarker(\n editor,\n (model, previousSegment, paragraph, _markerFormat, context) => {\n let formatApplied: AutoFormatFeature | undefined = undefined;\n\n for (const feature of this.features) {\n if (feature.enabled) {\n const result = feature.transformFunction(\n model,\n previousSegment,\n paragraph,\n context\n );\n if (result) {\n if (typeof result !== 'boolean') {\n formatOptions.getChangeData = () => result;\n }\n formatApplied = feature.autoFormat;\n break;\n }\n }\n }\n\n if (formatApplied) {\n formatOptions.changeSource = getChangeSource(formatApplied);\n formatOptions.apiName = getApiName(formatApplied);\n }\n\n return !!formatApplied;\n },\n formatOptions\n );\n\n break;\n }\n }\n }\n\n private handleKeyDownEvent(editor: IEditor, event: KeyDownEvent) {\n const rawEvent = event.rawEvent;\n if (!rawEvent.defaultPrevented && !event.handledByEditFeature) {\n switch (rawEvent.key) {\n case 'Backspace':\n if (this.options.autoUnlink) {\n unlink(editor, rawEvent);\n }\n break;\n case 'Tab':\n if (!rawEvent.shiftKey) {\n formatTextSegmentBeforeSelectionMarker(\n editor,\n (model, _previousSegment, paragraph, _markerFormat, context) => {\n const {\n autoBullet,\n autoNumbering,\n removeListMargins,\n } = this.options;\n let shouldList = false;\n if (autoBullet || autoNumbering) {\n shouldList = keyboardListTrigger(\n model,\n paragraph,\n context,\n autoBullet,\n autoNumbering,\n removeListMargins\n );\n context.canUndoByBackspace = shouldList;\n }\n if (shouldList) {\n event.rawEvent.preventDefault();\n }\n return shouldList;\n },\n {\n changeSource: ChangeSource.AutoFormat,\n apiName: 'autoToggleList',\n }\n );\n }\n break;\n case 'Enter':\n this.handleEnterKey(editor, event);\n break;\n }\n }\n }\n\n private handleEnterKey(editor: IEditor, event: KeyDownEvent) {\n if (this.options.autoHorizontalLine) {\n checkAndInsertHorizontalLine(editor, event);\n }\n }\n\n private handleContentChangedEvent(editor: IEditor, event: ContentChangedEvent) {\n const { autoLink, autoTel, autoMailto } = this.options;\n if (event.source == 'Paste' && (autoLink || autoTel || autoMailto)) {\n createLink(editor, {\n autoLink,\n autoTel,\n autoMailto,\n });\n }\n }\n}\n\nconst getApiName = (autoFormat: AutoFormatFeature) => {\n return autoFormat == 'list' ? 'autoToggleList' : autoFormat == 'hyphen' ? 'autoHyphen' : '';\n};\n\nconst getChangeSource = (autoFormat: AutoFormatFeature) => {\n return autoFormat == 'list' || autoFormat == 'hyphen'\n ? ChangeSource.AutoFormat\n : autoFormat == 'link'\n ? ChangeSource.AutoLink\n : '';\n};\n\nconst createAnchor = (url: string, text: string) => {\n const anchor = document.createElement('a');\n anchor.href = url;\n anchor.textContent = text;\n return anchor;\n};\n"]}
1
+ {"version":3,"file":"AutoFormatPlugin.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-plugins/lib/autoFormat/AutoFormatPlugin.ts"],"names":[],"mappings":";;;;AAAA,2EAA2D;AAC3D,8FAA6F;AAC7F,gDAA+C;AAC/C,2EAAkG;AAClG,kEAAiE;AACjE,iEAAgE;AAChE,4DAA2D;AAC3D,iEAAgE;AAChE,wCAAuC;AA+BvC;;GAEG;AACH,IAAM,cAAc,GAA+B;IAC/C,UAAU,EAAE,KAAK;IACjB,aAAa,EAAE,KAAK;IACpB,UAAU,EAAE,KAAK;IACjB,QAAQ,EAAE,KAAK;IACf,UAAU,EAAE,KAAK;IACjB,YAAY,EAAE,KAAK;IACnB,YAAY,EAAE,KAAK;IACnB,iBAAiB,EAAE,KAAK;IACxB,kBAAkB,EAAE,KAAK;CAC5B,CAAC;AAEF;;;GAGG;AACH;IAEI;;;;;;;;;;;;;OAaG;IACH,0BAAoB,OAA2C;QAA/D,iBAAmE;QAA/C,wBAAA,EAAA,wBAA2C;QAA3C,YAAO,GAAP,OAAO,CAAoC;QAfvD,WAAM,GAAmB,IAAI,CAAC;QAiE9B,aAAQ,GAAY;YACxB,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;YACrF,iBAAiB,EAAE,UAAC,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,OAAO;;gBACrD,IAAA,KAAoC,KAAI,CAAC,OAAO,EAA9C,QAAQ,cAAA,EAAE,OAAO,aAAA,EAAE,UAAU,gBAAiB,CAAC;gBACvD,IAAM,WAAW,GAAG,IAAA,yCAAW,EAAC,eAAe,EAAE,SAAS,EAAE;oBACxD,QAAQ,UAAA;oBACR,OAAO,SAAA;oBACP,UAAU,YAAA;iBACb,CAAC,CAAC;gBAEH,IAAI,WAAW,EAAE;oBACb,OAAO,YAAY,CAAC,CAAA,MAAA,WAAW,CAAC,IAAI,0CAAE,MAAM,CAAC,IAAI,KAAI,EAAE,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC;iBAC9E;gBACD,OAAO,KAAK,CAAC;YACjB,CAAC;YACD,OAAO,EAAE,UAAU;YACnB,YAAY,EAAE,0CAAY,CAAC,QAAQ;SACtC,CAAC;QAEM,gBAAW,GAAc;YAC7B;gBACI,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC;gBAClE,iBAAiB,EAAE,UAAC,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,OAAO;oBAC3D,OAAA,IAAA,yCAAmB,EACf,KAAK,EACL,SAAS,EACT,OAAO,EACP,KAAI,CAAC,OAAO,CAAC,UAAU,EACvB,KAAI,CAAC,OAAO,CAAC,aAAa,EAC1B,KAAI,CAAC,OAAO,CAAC,iBAAiB,CACjC;gBAPD,CAOC;gBACL,OAAO,EAAE,gBAAgB;gBACzB,YAAY,EAAE,0CAAY,CAAC,UAAU;aACxC;YACD,IAAI,CAAC,QAAQ;SAChB,CAAC;QAEM,aAAQ,iFACT,IAAI,CAAC,WAAW;YACnB;gBACI,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU;gBAClC,OAAO,EAAE,YAAY;gBACrB,YAAY,EAAE,0CAAY,CAAC,MAAM;gBACjC,iBAAiB,EAAE,UAAC,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,OAAO;oBAC3D,OAAA,IAAA,iCAAe,EAAC,eAAe,EAAE,SAAS,EAAE,OAAO,CAAC;gBAApD,CAAoD;aAC3D;YACD;gBACI,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY;gBACpC,OAAO,EAAE,cAAc;gBACvB,YAAY,EAAE,0CAAY,CAAC,MAAM;gBACjC,iBAAiB,EAAE,UAAC,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,OAAO;oBAC3D,OAAA,IAAA,qCAAiB,EAAC,eAAe,EAAE,SAAS,EAAE,OAAO,CAAC;gBAAtD,CAAsD;aAC7D;YACD;gBACI,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY;gBACpC,OAAO,EAAE,aAAa;gBACtB,YAAY,EAAE,0CAAY,CAAC,MAAM;gBACjC,iBAAiB,EAAE,UAAC,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,OAAO;oBAC3D,OAAA,IAAA,qCAAiB,EAAC,eAAe,EAAE,SAAS,EAAE,OAAO,CAAC;gBAAtD,CAAsD;aAC7D;kBACH;QAEM,kBAAa,GAAc;YAC/B;gBACI,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,kBAAkB;gBAC1C,iBAAiB,EAAE,UAAC,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,OAAO;oBAC3D,OAAA,IAAA,2DAA4B,EAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC;gBAAvD,CAAuD;gBAC3D,OAAO,EAAE,oBAAoB;gBAC7B,YAAY,EAAE,0CAAY,CAAC,UAAU;aACxC;YACD,IAAI,CAAC,QAAQ;SAChB,CAAC;IAzHgE,CAAC;IAEnE;;OAEG;IACH,kCAAO,GAAP;QACI,OAAO,YAAY,CAAC;IACxB,CAAC;IAED;;;;;OAKG;IACH,qCAAU,GAAV,UAAW,MAAe;QACtB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACzB,CAAC;IAED;;;;OAIG;IACH,kCAAO,GAAP;QACI,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACvB,CAAC;IAED;;;;;OAKG;IACH,wCAAa,GAAb,UAAc,KAAkB;QAC5B,IAAI,IAAI,CAAC,MAAM,EAAE;YACb,QAAQ,KAAK,CAAC,SAAS,EAAE;gBACrB,KAAK,OAAO;oBACR,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;oBAChD,MAAM;gBACV,KAAK,SAAS;oBACV,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;oBAC5C,MAAM;gBACV,KAAK,gBAAgB;oBACjB,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;oBACnD,MAAM;aACb;SACJ;IACL,CAAC;IA2EO,+CAAoB,GAA5B,UAA6B,MAAe,EAAE,QAAmB;QAC7D,IAAM,aAAa,GAA8B;YAC7C,YAAY,EAAE,EAAE;YAChB,OAAO,EAAE,EAAE;YACX,aAAa,EAAE,SAAS;SAC3B,CAAC;QAEF,IAAA,oEAAsC,EAClC,MAAM,EACN,UAAC,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO;;YACtD,IAAI,cAAc,GAAwB,SAAS,CAAC;oCACzC,OAAO;gBACd,IAAI,OAAO,CAAC,OAAO,EAAE;oBACjB,IAAM,QAAM,GAAG,OAAO,CAAC,iBAAiB,CACpC,KAAK,EACL,eAAe,EACf,SAAS,EACT,OAAO,CACV,CAAC;oBACF,IAAI,QAAM,EAAE;wBACR,IAAI,OAAO,QAAM,KAAK,SAAS,EAAE;4BAC7B,aAAa,CAAC,aAAa,GAAG,cAAM,OAAA,QAAM,EAAN,CAAM,CAAC;yBAC9C;wBACD,cAAc,GAAG,OAAO,CAAC;;qBAE5B;iBACJ;;;gBAfL,KAAsB,IAAA,aAAA,sBAAA,QAAQ,CAAA,kCAAA;oBAAzB,IAAM,OAAO,qBAAA;0CAAP,OAAO;;;iBAgBjB;;;;;;;;;YAED,IAAI,cAAc,EAAE;gBAChB,aAAa,CAAC,YAAY,GAAG,cAAc,CAAC,YAAY,CAAC;gBACzD,aAAa,CAAC,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC;aAClD;YAED,OAAO,CAAC,CAAC,cAAc,CAAC;QAC5B,CAAC,EACD,aAAa,CAChB,CAAC;QACF,OAAO,aAAa,CAAC;IACzB,CAAC;IAEO,iDAAsB,GAA9B,UAA+B,MAAe,EAAE,KAAuB;QACnE,IAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAChC,IAAM,SAAS,GAAG,MAAM,CAAC,eAAe,EAAE,CAAC;QAC3C,IACI,QAAQ,CAAC,SAAS,KAAK,YAAY;YACnC,SAAS;YACT,SAAS,CAAC,IAAI,KAAK,OAAO;YAC1B,SAAS,CAAC,KAAK,CAAC,SAAS,EAC3B;YACE,QAAQ,QAAQ,CAAC,IAAI,EAAE;gBACnB,KAAK,GAAG;oBACJ,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;oBACjD,MAAM;aACb;SACJ;IACL,CAAC;IAEO,6CAAkB,GAA1B,UAA2B,MAAe,EAAE,KAAmB;QAC3D,IAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAChC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,IAAI,CAAC,KAAK,CAAC,oBAAoB,EAAE;YAC3D,QAAQ,QAAQ,CAAC,GAAG,EAAE;gBAClB,KAAK,WAAW;oBACZ,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE;wBACzB,IAAA,eAAM,EAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;qBAC5B;oBACD,MAAM;gBACV,KAAK,KAAK;oBACN,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE;wBACpB,IAAM,cAAY,GAAG,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;wBACzE,IAAI,cAAY,CAAC,OAAO,IAAI,gBAAgB,EAAE;4BAC1C,KAAK,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC;yBACnC;qBACJ;oBACD,MAAM;gBACV,KAAK,OAAO;oBACR,IAAM,YAAY,GAAG,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;oBAC3E,IAAI,YAAY,CAAC,OAAO,IAAI,oBAAoB,EAAE;wBAC9C,KAAK,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC;qBACnC;oBACD,MAAM;aACb;SACJ;IACL,CAAC;IAEO,oDAAyB,GAAjC,UAAkC,MAAe,EAAE,KAA0B;QACnE,IAAA,KAAoC,IAAI,CAAC,OAAO,EAA9C,QAAQ,cAAA,EAAE,OAAO,aAAA,EAAE,UAAU,gBAAiB,CAAC;QACvD,IAAI,KAAK,CAAC,MAAM,IAAI,OAAO,IAAI,CAAC,QAAQ,IAAI,OAAO,IAAI,UAAU,CAAC,EAAE;YAChE,IAAA,uBAAU,EAAC,MAAM,EAAE;gBACf,QAAQ,UAAA;gBACR,OAAO,SAAA;gBACP,UAAU,YAAA;aACb,CAAC,CAAC;SACN;IACL,CAAC;IACL,uBAAC;AAAD,CAAC,AA1OD,IA0OC;AA1OY,4CAAgB;AA4O7B,IAAM,YAAY,GAAG,UAAC,GAAW,EAAE,IAAY;IAC3C,IAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,CAAC,IAAI,GAAG,GAAG,CAAC;IAClB,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC;IAC1B,OAAO,MAAM,CAAC;AAClB,CAAC,CAAC","sourcesContent":["import { ChangeSource } from 'roosterjs-content-model-dom';\nimport { checkAndInsertHorizontalLine } from './horizontalLine/checkAndInsertHorizontalLine';\nimport { createLink } from './link/createLink';\nimport { formatTextSegmentBeforeSelectionMarker, promoteLink } from 'roosterjs-content-model-api';\nimport { keyboardListTrigger } from './list/keyboardListTrigger';\nimport { transformFraction } from './numbers/transformFraction';\nimport { transformHyphen } from './hyphen/transformHyphen';\nimport { transformOrdinals } from './numbers/transformOrdinals';\nimport { unlink } from './link/unlink';\nimport type { AutoFormatOptions } from './interface/AutoFormatOptions';\nimport type {\n ContentChangedEvent,\n ContentModelText,\n EditorInputEvent,\n EditorPlugin,\n FormatContentModelContext,\n FormatContentModelOptions,\n IEditor,\n KeyDownEvent,\n PluginEvent,\n ReadonlyContentModelDocument,\n ShallowMutableContentModelParagraph,\n} from 'roosterjs-content-model-types';\n\n/**\n * @internal\n */\ninterface Feature {\n enabled: boolean;\n transformFunction: (\n model: ReadonlyContentModelDocument,\n previousSegment: ContentModelText,\n paragraph: ShallowMutableContentModelParagraph,\n context: FormatContentModelContext\n ) => boolean | HTMLElement;\n changeSource: string;\n apiName: string;\n}\n\n/**\n * @internal\n */\nconst DefaultOptions: Partial<AutoFormatOptions> = {\n autoBullet: false,\n autoNumbering: false,\n autoUnlink: false,\n autoLink: false,\n autoHyphen: false,\n autoFraction: false,\n autoOrdinals: false,\n removeListMargins: false,\n autoHorizontalLine: false,\n};\n\n/**\n * Auto Format plugin handles auto formatting, such as transforming * characters into a bullet list.\n * It can be customized with options to enable or disable auto list features.\n */\nexport class AutoFormatPlugin implements EditorPlugin {\n private editor: IEditor | null = null;\n /**\n * @param options An optional parameter that takes in an object of type AutoFormatOptions, which includes the following properties:\n * - autoBullet: A boolean that enables or disables automatic bullet list formatting. Defaults to false.\n * - autoNumbering: A boolean that enables or disables automatic numbering formatting. Defaults to false.\n * - removeListMargins: A boolean to remove list margins when it is automatically triggered. Defaults to false.\n * - autoHyphen: A boolean that enables or disables automatic hyphen transformation. Defaults to false.\n * - autoFraction: A boolean that enables or disables automatic fraction transformation. Defaults to false.\n * - autoOrdinals: A boolean that enables or disables automatic ordinal number transformation. Defaults to false.\n * - autoLink: A boolean that enables or disables automatic hyperlink url address creation when pasting or typing content. Defaults to false.\n * - autoUnlink: A boolean that enables or disables automatic hyperlink removal when pressing backspace. Defaults to false.\n * - autoTel: A boolean that enables or disables automatic hyperlink telephone numbers transformation. Defaults to false.\n * - autoMailto: A boolean that enables or disables automatic hyperlink email address transformation. Defaults to false.\n * - autoHorizontalLine: A boolean that enables or disables automatic horizontal line creation. Defaults to false.\n */\n constructor(private options: AutoFormatOptions = DefaultOptions) {}\n\n /**\n * Get name of this plugin\n */\n getName() {\n return 'AutoFormat';\n }\n\n /**\n * The first method that editor will call to a plugin when editor is initializing.\n * It will pass in the editor instance, plugin should take this chance to save the\n * editor reference so that it can call to any editor method or format API later.\n * @param editor The editor object\n */\n initialize(editor: IEditor) {\n this.editor = editor;\n }\n\n /**\n * The last method that editor will call to a plugin before it is disposed.\n * Plugin can take this chance to clear the reference to editor. After this method is\n * called, plugin should not call to any editor method since it will result in error.\n */\n dispose() {\n this.editor = null;\n }\n\n /**\n * Core method for a plugin. Once an event happens in editor, editor will call this\n * method of each plugin to handle the event as long as the event is not handled\n * exclusively by another plugin.\n * @param event The event to handle:\n */\n onPluginEvent(event: PluginEvent) {\n if (this.editor) {\n switch (event.eventType) {\n case 'input':\n this.handleEditorInputEvent(this.editor, event);\n break;\n case 'keyDown':\n this.handleKeyDownEvent(this.editor, event);\n break;\n case 'contentChanged':\n this.handleContentChangedEvent(this.editor, event);\n break;\n }\n }\n }\n\n private autoLink: Feature = {\n enabled: !!(this.options.autoLink || this.options.autoTel || this.options.autoMailto),\n transformFunction: (_model, previousSegment, paragraph, context) => {\n const { autoLink, autoTel, autoMailto } = this.options;\n const linkSegment = promoteLink(previousSegment, paragraph, {\n autoLink,\n autoTel,\n autoMailto,\n });\n\n if (linkSegment) {\n return createAnchor(linkSegment.link?.format.href || '', linkSegment.text);\n }\n return false;\n },\n apiName: 'autoLink',\n changeSource: ChangeSource.AutoLink,\n };\n\n private tabFeatures: Feature[] = [\n {\n enabled: !!(this.options.autoBullet || this.options.autoNumbering),\n transformFunction: (model, _previousSegment, paragraph, context) =>\n keyboardListTrigger(\n model,\n paragraph,\n context,\n this.options.autoBullet,\n this.options.autoNumbering,\n this.options.removeListMargins\n ),\n apiName: 'autoToggleList',\n changeSource: ChangeSource.AutoFormat,\n },\n this.autoLink,\n ];\n\n private features: Feature[] = [\n ...this.tabFeatures,\n {\n enabled: !!this.options.autoHyphen,\n apiName: 'autoHyphen',\n changeSource: ChangeSource.Format,\n transformFunction: (_model, previousSegment, paragraph, context) =>\n transformHyphen(previousSegment, paragraph, context),\n },\n {\n enabled: !!this.options.autoFraction,\n apiName: 'autoFraction',\n changeSource: ChangeSource.Format,\n transformFunction: (_model, previousSegment, paragraph, context) =>\n transformFraction(previousSegment, paragraph, context),\n },\n {\n enabled: !!this.options.autoOrdinals,\n apiName: 'autoOrdinal',\n changeSource: ChangeSource.Format,\n transformFunction: (_model, previousSegment, paragraph, context) =>\n transformOrdinals(previousSegment, paragraph, context),\n },\n ];\n\n private enterFeatures: Feature[] = [\n {\n enabled: !!this.options.autoHorizontalLine,\n transformFunction: (model, _previousSegment, paragraph, context) =>\n checkAndInsertHorizontalLine(model, paragraph, context),\n apiName: 'autoHorizontalLine',\n changeSource: ChangeSource.AutoFormat,\n },\n this.autoLink,\n ];\n\n private handleKeyboardEvents(editor: IEditor, features: Feature[]): FormatContentModelOptions {\n const formatOptions: FormatContentModelOptions = {\n changeSource: '',\n apiName: '',\n getChangeData: undefined,\n };\n\n formatTextSegmentBeforeSelectionMarker(\n editor,\n (model, previousSegment, paragraph, _markerFormat, context) => {\n let featureApplied: Feature | undefined = undefined;\n for (const feature of features) {\n if (feature.enabled) {\n const result = feature.transformFunction(\n model,\n previousSegment,\n paragraph,\n context\n );\n if (result) {\n if (typeof result !== 'boolean') {\n formatOptions.getChangeData = () => result;\n }\n featureApplied = feature;\n break;\n }\n }\n }\n\n if (featureApplied) {\n formatOptions.changeSource = featureApplied.changeSource;\n formatOptions.apiName = featureApplied.apiName;\n }\n\n return !!featureApplied;\n },\n formatOptions\n );\n return formatOptions;\n }\n\n private handleEditorInputEvent(editor: IEditor, event: EditorInputEvent) {\n const rawEvent = event.rawEvent;\n const selection = editor.getDOMSelection();\n if (\n rawEvent.inputType === 'insertText' &&\n selection &&\n selection.type === 'range' &&\n selection.range.collapsed\n ) {\n switch (rawEvent.data) {\n case ' ':\n this.handleKeyboardEvents(editor, this.features);\n break;\n }\n }\n }\n\n private handleKeyDownEvent(editor: IEditor, event: KeyDownEvent) {\n const rawEvent = event.rawEvent;\n if (!rawEvent.defaultPrevented && !event.handledByEditFeature) {\n switch (rawEvent.key) {\n case 'Backspace':\n if (this.options.autoUnlink) {\n unlink(editor, rawEvent);\n }\n break;\n case 'Tab':\n if (!rawEvent.shiftKey) {\n const eventHandled = this.handleKeyboardEvents(editor, this.tabFeatures);\n if (eventHandled.apiName == 'autoToggleList') {\n event.rawEvent.preventDefault();\n }\n }\n break;\n case 'Enter':\n const eventHandled = this.handleKeyboardEvents(editor, this.enterFeatures);\n if (eventHandled.apiName == 'autoHorizontalLine') {\n event.rawEvent.preventDefault();\n }\n break;\n }\n }\n }\n\n private handleContentChangedEvent(editor: IEditor, event: ContentChangedEvent) {\n const { autoLink, autoTel, autoMailto } = this.options;\n if (event.source == 'Paste' && (autoLink || autoTel || autoMailto)) {\n createLink(editor, {\n autoLink,\n autoTel,\n autoMailto,\n });\n }\n }\n}\n\nconst createAnchor = (url: string, text: string) => {\n const anchor = document.createElement('a');\n anchor.href = url;\n anchor.textContent = text;\n return anchor;\n};\n"]}
@@ -1,4 +1,4 @@
1
- import type { FormatContentModelContext, IEditor, KeyDownEvent, ShallowMutableContentModelDocument } from 'roosterjs-content-model-types';
1
+ import type { FormatContentModelContext, ReadonlyContentModelDocument, ShallowMutableContentModelParagraph } from 'roosterjs-content-model-types';
2
2
  /**
3
3
  * @internal
4
4
  */
@@ -11,7 +11,7 @@ export declare type HorizontalLineTriggerCharacter = '-' | '=' | '_' | '*' | '~'
11
11
  * @param model the model to insert horizontal line into
12
12
  * @param context the formatting context
13
13
  */
14
- export declare function insertHorizontalLineIntoModel(model: ShallowMutableContentModelDocument, context: FormatContentModelContext, triggerChar: HorizontalLineTriggerCharacter): void;
14
+ export declare function insertHorizontalLineIntoModel(model: ReadonlyContentModelDocument, context: FormatContentModelContext, triggerChar: HorizontalLineTriggerCharacter): void;
15
15
  /**
16
16
  * @internal
17
17
  *
@@ -21,4 +21,4 @@ export declare function insertHorizontalLineIntoModel(model: ShallowMutableConte
21
21
  * @param event The keydown event
22
22
  * @returns True if horizontal line is inserted, otherwise false
23
23
  */
24
- export declare function checkAndInsertHorizontalLine(editor: IEditor, event: KeyDownEvent): boolean;
24
+ export declare const checkAndInsertHorizontalLine: (model: ReadonlyContentModelDocument, paragraph: ShallowMutableContentModelParagraph, context: FormatContentModelContext) => boolean;
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.checkAndInsertHorizontalLine = exports.insertHorizontalLineIntoModel = void 0;
4
4
  var tslib_1 = require("tslib");
5
- var roosterjs_content_model_api_1 = require("roosterjs-content-model-api");
6
5
  var roosterjs_content_model_dom_1 = require("roosterjs-content-model-dom");
7
6
  var HorizontalLineTriggerCharacters = [
8
7
  '-',
@@ -66,27 +65,21 @@ exports.insertHorizontalLineIntoModel = insertHorizontalLineIntoModel;
66
65
  * @param event The keydown event
67
66
  * @returns True if horizontal line is inserted, otherwise false
68
67
  */
69
- function checkAndInsertHorizontalLine(editor, event) {
70
- return (0, roosterjs_content_model_api_1.formatTextSegmentBeforeSelectionMarker)(editor, function (model, _, para, __, context) {
71
- var allText = para.segments.reduce(function (acc, segment) { return (segment.segmentType === 'Text' ? acc + segment.text : acc); }, '');
72
- // At least 3 characters are needed to trigger horizontal line
73
- if (allText.length < 3) {
74
- return false;
68
+ var checkAndInsertHorizontalLine = function (model, paragraph, context) {
69
+ var allText = paragraph.segments.reduce(function (acc, segment) { return (segment.segmentType === 'Text' ? acc + segment.text : acc); }, '');
70
+ // At least 3 characters are needed to trigger horizontal line
71
+ if (allText.length < 3) {
72
+ return false;
73
+ }
74
+ return HorizontalLineTriggerCharacters.some(function (triggerCharacter) {
75
+ var shouldFormat = allText.split('').every(function (char) { return char === triggerCharacter; });
76
+ if (shouldFormat) {
77
+ paragraph.segments = paragraph.segments.filter(function (s) { return s.segmentType != 'Text'; });
78
+ insertHorizontalLineIntoModel(model, context, triggerCharacter);
79
+ context.canUndoByBackspace = true;
75
80
  }
76
- return HorizontalLineTriggerCharacters.some(function (triggerCharacter) {
77
- var shouldFormat = allText.split('').every(function (char) { return char === triggerCharacter; });
78
- if (shouldFormat) {
79
- para.segments = para.segments.filter(function (s) { return s.segmentType != 'Text'; });
80
- insertHorizontalLineIntoModel(model, context, triggerCharacter);
81
- event.rawEvent.preventDefault();
82
- context.canUndoByBackspace = true;
83
- }
84
- return shouldFormat;
85
- });
86
- }, {
87
- changeSource: roosterjs_content_model_dom_1.ChangeSource.AutoFormat,
88
- apiName: 'autoHorizontalLine',
81
+ return shouldFormat;
89
82
  });
90
- }
83
+ };
91
84
  exports.checkAndInsertHorizontalLine = checkAndInsertHorizontalLine;
92
85
  //# sourceMappingURL=checkAndInsertHorizontalLine.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"checkAndInsertHorizontalLine.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-plugins/lib/autoFormat/horizontalLine/checkAndInsertHorizontalLine.ts"],"names":[],"mappings":"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","sourcesContent":["import { formatTextSegmentBeforeSelectionMarker } from 'roosterjs-content-model-api';\nimport type {\n ContentModelDividerFormat,\n FormatContentModelContext,\n IEditor,\n KeyDownEvent,\n ShallowMutableContentModelDocument,\n} from 'roosterjs-content-model-types';\nimport {\n addBlock,\n ChangeSource,\n createContentModelDocument,\n createDivider,\n mergeModel,\n} from 'roosterjs-content-model-dom';\n\n/**\n * @internal\n */\nexport type HorizontalLineTriggerCharacter = '-' | '=' | '_' | '*' | '~' | '#';\nconst HorizontalLineTriggerCharacters: HorizontalLineTriggerCharacter[] = [\n '-',\n '=',\n '_',\n '*',\n '~',\n '#',\n];\n\nconst commonStyles: ContentModelDividerFormat = {\n width: '98%',\n display: 'inline-block',\n};\n\nconst HorizontalLineStyles: Map<\n HorizontalLineTriggerCharacter,\n ContentModelDividerFormat\n> = new Map([\n [\n '-',\n {\n borderTop: '1px none',\n borderRight: '1px none',\n borderBottom: '1px solid',\n borderLeft: '1px none',\n ...commonStyles,\n },\n ],\n [\n '=',\n {\n borderTop: '3pt double',\n borderRight: '3pt none',\n borderBottom: '3pt none',\n borderLeft: '3pt none',\n ...commonStyles,\n },\n ],\n [\n '_',\n {\n borderTop: '1px solid',\n borderRight: '1px none',\n borderBottom: '1px solid',\n borderLeft: '1px none',\n ...commonStyles,\n },\n ],\n [\n '*',\n {\n borderTop: '1px none',\n borderRight: '1px none',\n borderBottom: '3px dotted',\n borderLeft: '1px none',\n ...commonStyles,\n },\n ],\n [\n '~',\n {\n borderTop: '1px none',\n borderRight: '1px none',\n borderBottom: '1px solid',\n borderLeft: '1px none',\n ...commonStyles,\n },\n ],\n [\n '#',\n {\n borderTop: '3pt double',\n borderRight: '3pt none',\n borderBottom: '3pt double',\n borderLeft: '3pt none',\n ...commonStyles,\n },\n ],\n]);\n\n/**\n * @internal exported only for unit test\n *\n * Create a horizontal line and insert it into the model\n *\n * @param model the model to insert horizontal line into\n * @param context the formatting context\n */\nexport function insertHorizontalLineIntoModel(\n model: ShallowMutableContentModelDocument,\n context: FormatContentModelContext,\n triggerChar: HorizontalLineTriggerCharacter\n) {\n const hr = createDivider('hr', HorizontalLineStyles.get(triggerChar));\n const doc = createContentModelDocument();\n addBlock(doc, hr);\n\n mergeModel(model, doc, context);\n}\n\n/**\n * @internal\n *\n * Check if the current line should be formatted as horizontal line, and insert horizontal line if needed\n *\n * @param editor The editor to check and insert horizontal line\n * @param event The keydown event\n * @returns True if horizontal line is inserted, otherwise false\n */\nexport function checkAndInsertHorizontalLine(editor: IEditor, event: KeyDownEvent) {\n return formatTextSegmentBeforeSelectionMarker(\n editor,\n (model, _, para, __, context) => {\n const allText = para.segments.reduce(\n (acc, segment) => (segment.segmentType === 'Text' ? acc + segment.text : acc),\n ''\n );\n // At least 3 characters are needed to trigger horizontal line\n if (allText.length < 3) {\n return false;\n }\n\n return HorizontalLineTriggerCharacters.some(triggerCharacter => {\n const shouldFormat = allText.split('').every(char => char === triggerCharacter);\n if (shouldFormat) {\n para.segments = para.segments.filter(s => s.segmentType != 'Text');\n insertHorizontalLineIntoModel(model, context, triggerCharacter);\n event.rawEvent.preventDefault();\n context.canUndoByBackspace = true;\n }\n return shouldFormat;\n });\n },\n {\n changeSource: ChangeSource.AutoFormat,\n apiName: 'autoHorizontalLine',\n }\n );\n}\n"]}
1
+ {"version":3,"file":"checkAndInsertHorizontalLine.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-plugins/lib/autoFormat/horizontalLine/checkAndInsertHorizontalLine.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ContentModelDividerFormat,\n FormatContentModelContext,\n ReadonlyContentModelDocument,\n ShallowMutableContentModelParagraph,\n} from 'roosterjs-content-model-types';\nimport {\n addBlock,\n createContentModelDocument,\n createDivider,\n mergeModel,\n} from 'roosterjs-content-model-dom';\n\n/**\n * @internal\n */\nexport type HorizontalLineTriggerCharacter = '-' | '=' | '_' | '*' | '~' | '#';\nconst HorizontalLineTriggerCharacters: HorizontalLineTriggerCharacter[] = [\n '-',\n '=',\n '_',\n '*',\n '~',\n '#',\n];\n\nconst commonStyles: ContentModelDividerFormat = {\n width: '98%',\n display: 'inline-block',\n};\n\nconst HorizontalLineStyles: Map<\n HorizontalLineTriggerCharacter,\n ContentModelDividerFormat\n> = new Map([\n [\n '-',\n {\n borderTop: '1px none',\n borderRight: '1px none',\n borderBottom: '1px solid',\n borderLeft: '1px none',\n ...commonStyles,\n },\n ],\n [\n '=',\n {\n borderTop: '3pt double',\n borderRight: '3pt none',\n borderBottom: '3pt none',\n borderLeft: '3pt none',\n ...commonStyles,\n },\n ],\n [\n '_',\n {\n borderTop: '1px solid',\n borderRight: '1px none',\n borderBottom: '1px solid',\n borderLeft: '1px none',\n ...commonStyles,\n },\n ],\n [\n '*',\n {\n borderTop: '1px none',\n borderRight: '1px none',\n borderBottom: '3px dotted',\n borderLeft: '1px none',\n ...commonStyles,\n },\n ],\n [\n '~',\n {\n borderTop: '1px none',\n borderRight: '1px none',\n borderBottom: '1px solid',\n borderLeft: '1px none',\n ...commonStyles,\n },\n ],\n [\n '#',\n {\n borderTop: '3pt double',\n borderRight: '3pt none',\n borderBottom: '3pt double',\n borderLeft: '3pt none',\n ...commonStyles,\n },\n ],\n]);\n\n/**\n * @internal exported only for unit test\n *\n * Create a horizontal line and insert it into the model\n *\n * @param model the model to insert horizontal line into\n * @param context the formatting context\n */\nexport function insertHorizontalLineIntoModel(\n model: ReadonlyContentModelDocument,\n context: FormatContentModelContext,\n triggerChar: HorizontalLineTriggerCharacter\n) {\n const hr = createDivider('hr', HorizontalLineStyles.get(triggerChar));\n const doc = createContentModelDocument();\n addBlock(doc, hr);\n mergeModel(model, doc, context);\n}\n\n/**\n * @internal\n *\n * Check if the current line should be formatted as horizontal line, and insert horizontal line if needed\n *\n * @param editor The editor to check and insert horizontal line\n * @param event The keydown event\n * @returns True if horizontal line is inserted, otherwise false\n */\nexport const checkAndInsertHorizontalLine = (\n model: ReadonlyContentModelDocument,\n paragraph: ShallowMutableContentModelParagraph,\n context: FormatContentModelContext\n) => {\n const allText = paragraph.segments.reduce(\n (acc, segment) => (segment.segmentType === 'Text' ? acc + segment.text : acc),\n ''\n );\n // At least 3 characters are needed to trigger horizontal line\n if (allText.length < 3) {\n return false;\n }\n\n return HorizontalLineTriggerCharacters.some(triggerCharacter => {\n const shouldFormat = allText.split('').every(char => char === triggerCharacter);\n if (shouldFormat) {\n paragraph.segments = paragraph.segments.filter(s => s.segmentType != 'Text');\n insertHorizontalLineIntoModel(model, context, triggerCharacter);\n context.canUndoByBackspace = true;\n }\n return shouldFormat;\n });\n};\n"]}
@@ -12,6 +12,13 @@ export declare type EditOptions = {
12
12
  * @default true
13
13
  */
14
14
  handleExpandedSelectionOnDelete?: boolean;
15
+ /**
16
+ * Callback function to determine whether the Rooster should handle the Enter key press.
17
+ * If the function returns true, the Rooster will handle the Enter key press instead of the browser.
18
+ * @param editor - The editor instance.
19
+ * @returns A boolean
20
+ */
21
+ shouldHandleEnterKey?: ((editor: IEditor) => boolean) | boolean;
15
22
  };
16
23
  /**
17
24
  * Edit plugins helps editor to do editing operation on top of content model.
@@ -32,6 +39,8 @@ export declare class EditPlugin implements EditorPlugin {
32
39
  * handleTabKey: A boolean that enables or disables Tab key handling. Defaults to true.
33
40
  */
34
41
  constructor(options?: EditOptions);
42
+ private createNormalEnterChecker;
43
+ private getHandleNormalEnter;
35
44
  /**
36
45
  * Get name of this plugin
37
46
  */
@@ -38,8 +38,24 @@ var EditPlugin = /** @class */ (function () {
38
38
  this.disposer = null;
39
39
  this.shouldHandleNextInputEvent = false;
40
40
  this.selectionAfterDelete = null;
41
- this.handleNormalEnter = false;
41
+ this.handleNormalEnter = function (editor) { return false; };
42
42
  }
43
+ EditPlugin.prototype.createNormalEnterChecker = function (result) {
44
+ return result ? function () { return true; } : function () { return false; };
45
+ };
46
+ EditPlugin.prototype.getHandleNormalEnter = function (editor) {
47
+ switch (typeof this.options.shouldHandleEnterKey) {
48
+ case 'function':
49
+ return this.options.shouldHandleEnterKey;
50
+ break;
51
+ case 'boolean':
52
+ return this.createNormalEnterChecker(this.options.shouldHandleEnterKey);
53
+ break;
54
+ default:
55
+ return this.createNormalEnterChecker(editor.isExperimentalFeatureEnabled('HandleEnterKey'));
56
+ break;
57
+ }
58
+ };
43
59
  /**
44
60
  * Get name of this plugin
45
61
  */
@@ -55,7 +71,7 @@ var EditPlugin = /** @class */ (function () {
55
71
  EditPlugin.prototype.initialize = function (editor) {
56
72
  var _this = this;
57
73
  this.editor = editor;
58
- this.handleNormalEnter = this.editor.isExperimentalFeatureEnabled('HandleEnterKey');
74
+ this.handleNormalEnter = this.getHandleNormalEnter(editor);
59
75
  if (editor.getEnvironment().isAndroid) {
60
76
  this.disposer = this.editor.attachDomEvent({
61
77
  beforeinput: {
@@ -162,7 +178,7 @@ var EditPlugin = /** @class */ (function () {
162
178
  if (!hasCtrlOrMetaKey &&
163
179
  !event.rawEvent.isComposing &&
164
180
  event.rawEvent.keyCode !== DEAD_KEY) {
165
- (0, keyboardEnter_1.keyboardEnter)(editor, rawEvent, this.handleNormalEnter);
181
+ (0, keyboardEnter_1.keyboardEnter)(editor, rawEvent, this.handleNormalEnter(editor));
166
182
  }
167
183
  break;
168
184
  default:
@@ -1 +1 @@
1
- {"version":3,"file":"EditPlugin.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-plugins/lib/edit/EditPlugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { keyboardDelete } from './keyboardDelete';\nimport { keyboardEnter } from './keyboardEnter';\nimport { keyboardInput } from './keyboardInput';\nimport { keyboardTab } from './keyboardTab';\nimport { parseTableCells } from 'roosterjs-content-model-dom';\nimport type {\n DOMSelection,\n EditorPlugin,\n IEditor,\n KeyDownEvent,\n PluginEvent,\n} from 'roosterjs-content-model-types';\n\n/**\n * Options to customize the keyboard handling behavior of Edit plugin\n */\nexport type EditOptions = {\n /**\n * Whether to handle Tab key in keyboard. @default true\n */\n handleTabKey?: boolean;\n\n /**\n * Whether expanded selection within a text node should be handled by CM when pressing Backspace/Delete key.\n * @default true\n */\n handleExpandedSelectionOnDelete?: boolean;\n};\n\nconst BACKSPACE_KEY = 8;\nconst DELETE_KEY = 46;\n/**\n * According to https://lists.w3.org/Archives/Public/www-dom/2010JulSep/att-0182/keyCode-spec.html\n * 229 can be sent in variants generated when Long press (iOS) or using IM.\n *\n * Other cases: https://stackoverflow.com/questions/25043934/is-it-ok-to-ignore-keydown-events-with-keycode-229\n */\nconst DEAD_KEY = 229;\n\nconst DefaultOptions: Partial<EditOptions> = {\n handleTabKey: true,\n handleExpandedSelectionOnDelete: true,\n};\n\n/**\n * Edit plugins helps editor to do editing operation on top of content model.\n * This includes:\n * 1. Delete Key\n * 2. Backspace Key\n * 3. Tab Key\n */\nexport class EditPlugin implements EditorPlugin {\n private editor: IEditor | null = null;\n private disposer: (() => void) | null = null;\n private shouldHandleNextInputEvent = false;\n private selectionAfterDelete: DOMSelection | null = null;\n private handleNormalEnter = false;\n\n /**\n * @param options An optional parameter that takes in an object of type EditOptions, which includes the following properties:\n * handleTabKey: A boolean that enables or disables Tab key handling. Defaults to true.\n */\n constructor(private options: EditOptions = DefaultOptions) {}\n\n /**\n * Get name of this plugin\n */\n getName() {\n return 'Edit';\n }\n\n /**\n * The first method that editor will call to a plugin when editor is initializing.\n * It will pass in the editor instance, plugin should take this chance to save the\n * editor reference so that it can call to any editor method or format API later.\n * @param editor The editor object\n */\n initialize(editor: IEditor) {\n this.editor = editor;\n this.handleNormalEnter = this.editor.isExperimentalFeatureEnabled('HandleEnterKey');\n\n if (editor.getEnvironment().isAndroid) {\n this.disposer = this.editor.attachDomEvent({\n beforeinput: {\n beforeDispatch: e => this.handleBeforeInputEvent(editor, e),\n },\n });\n }\n }\n\n /**\n * The last method that editor will call to a plugin before it is disposed.\n * Plugin can take this chance to clear the reference to editor. After this method is\n * called, plugin should not call to any editor method since it will result in error.\n */\n dispose() {\n this.editor = null;\n this.disposer?.();\n this.disposer = null;\n }\n\n /**\n * Core method for a plugin. Once an event happens in editor, editor will call this\n * method of each plugin to handle the event as long as the event is not handled\n * exclusively by another plugin.\n * @param event The event to handle:\n */\n onPluginEvent(event: PluginEvent) {\n if (this.editor) {\n switch (event.eventType) {\n case 'keyDown':\n this.handleKeyDownEvent(this.editor, event);\n break;\n case 'keyUp':\n if (this.selectionAfterDelete) {\n this.editor.setDOMSelection(this.selectionAfterDelete);\n this.selectionAfterDelete = null;\n }\n break;\n }\n }\n }\n\n /**\n * Check if the plugin should handle the given event exclusively.\n * Handle an event exclusively means other plugin will not receive this event in\n * onPluginEvent method.\n * If two plugins will return true in willHandleEventExclusively() for the same event,\n * the final result depends on the order of the plugins are added into editor\n * @param event The event to check:\n */\n willHandleEventExclusively(event: PluginEvent) {\n if (\n this.editor &&\n this.options.handleTabKey &&\n event.eventType == 'keyDown' &&\n event.rawEvent.key == 'Tab' &&\n !event.rawEvent.shiftKey\n ) {\n const selection = this.editor.getDOMSelection();\n const startContainer =\n selection?.type == 'range' && selection.range.collapsed\n ? selection.range.startContainer\n : null;\n const table = startContainer\n ? this.editor.getDOMHelper().findClosestElementAncestor(startContainer, 'table')\n : null;\n const parsedTable = table && parseTableCells(table);\n\n if (parsedTable) {\n const lastRow = parsedTable[parsedTable.length - 1];\n const lastCell = lastRow && lastRow[lastRow.length - 1];\n\n if (typeof lastCell == 'object' && lastCell.contains(startContainer)) {\n // When TAB in the last cell of a table, we will generate new table row, so prevent other plugins handling this event\n // e.g. SelectionPlugin will move the focus out of table, which is conflict with this behavior\n return true;\n }\n }\n }\n\n return false;\n }\n\n private handleKeyDownEvent(editor: IEditor, event: KeyDownEvent) {\n const rawEvent = event.rawEvent;\n const hasCtrlOrMetaKey = rawEvent.ctrlKey || rawEvent.metaKey;\n\n if (!rawEvent.defaultPrevented && !event.handledByEditFeature) {\n switch (rawEvent.key) {\n case 'Backspace':\n // Use our API to handle BACKSPACE/DELETE key.\n // No need to clear cache here since if we rely on browser's behavior, there will be Input event and its handler will reconcile cache\n keyboardDelete(editor, rawEvent, this.options.handleExpandedSelectionOnDelete);\n break;\n\n case 'Delete':\n // Use our API to handle BACKSPACE/DELETE key.\n // No need to clear cache here since if we rely on browser's behavior, there will be Input event and its handler will reconcile cache\n // And leave it to browser when shift key is pressed so that browser will trigger cut event\n if (!event.rawEvent.shiftKey) {\n keyboardDelete(\n editor,\n rawEvent,\n this.options.handleExpandedSelectionOnDelete\n );\n }\n break;\n\n case 'Tab':\n if (this.options.handleTabKey && !hasCtrlOrMetaKey) {\n keyboardTab(editor, rawEvent);\n }\n break;\n case 'Unidentified':\n if (editor.getEnvironment().isAndroid) {\n this.shouldHandleNextInputEvent = true;\n }\n break;\n\n case 'Enter':\n if (\n !hasCtrlOrMetaKey &&\n !event.rawEvent.isComposing &&\n event.rawEvent.keyCode !== DEAD_KEY\n ) {\n keyboardEnter(editor, rawEvent, this.handleNormalEnter);\n }\n break;\n\n default:\n keyboardInput(editor, rawEvent);\n break;\n }\n }\n }\n\n private handleBeforeInputEvent(editor: IEditor, rawEvent: Event) {\n // Some Android IMEs doesn't fire correct keydown event for BACKSPACE/DELETE key\n // Here we translate input event to BACKSPACE/DELETE keydown event to be compatible with existing logic\n if (\n !this.shouldHandleNextInputEvent ||\n !(rawEvent instanceof InputEvent) ||\n rawEvent.defaultPrevented\n ) {\n return;\n }\n this.shouldHandleNextInputEvent = false;\n\n let handled = false;\n switch (rawEvent.inputType) {\n case 'deleteContentBackward':\n handled = keyboardDelete(\n editor,\n new KeyboardEvent('keydown', {\n key: 'Backspace',\n keyCode: BACKSPACE_KEY,\n which: BACKSPACE_KEY,\n }),\n this.options.handleExpandedSelectionOnDelete\n );\n break;\n case 'deleteContentForward':\n handled = keyboardDelete(\n editor,\n new KeyboardEvent('keydown', {\n key: 'Delete',\n keyCode: DELETE_KEY,\n which: DELETE_KEY,\n }),\n this.options.handleExpandedSelectionOnDelete\n );\n break;\n }\n\n if (handled) {\n rawEvent.preventDefault();\n\n // Restore the selection on keyup event to avoid the cursor jump issue\n // See: https://issues.chromium.org/issues/330596261\n this.selectionAfterDelete = editor.getDOMSelection();\n }\n }\n}\n"]}
1
+ {"version":3,"file":"EditPlugin.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-plugins/lib/edit/EditPlugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { keyboardDelete } from './keyboardDelete';\nimport { keyboardEnter } from './keyboardEnter';\nimport { keyboardInput } from './keyboardInput';\nimport { keyboardTab } from './keyboardTab';\nimport { parseTableCells } from 'roosterjs-content-model-dom';\nimport type {\n DOMSelection,\n EditorPlugin,\n IEditor,\n KeyDownEvent,\n PluginEvent,\n} from 'roosterjs-content-model-types';\n\n/**\n * Options to customize the keyboard handling behavior of Edit plugin\n */\nexport type EditOptions = {\n /**\n * Whether to handle Tab key in keyboard. @default true\n */\n handleTabKey?: boolean;\n\n /**\n * Whether expanded selection within a text node should be handled by CM when pressing Backspace/Delete key.\n * @default true\n */\n handleExpandedSelectionOnDelete?: boolean;\n\n /**\n * Callback function to determine whether the Rooster should handle the Enter key press.\n * If the function returns true, the Rooster will handle the Enter key press instead of the browser.\n * @param editor - The editor instance.\n * @returns A boolean\n */\n shouldHandleEnterKey?: ((editor: IEditor) => boolean) | boolean;\n};\n\nconst BACKSPACE_KEY = 8;\nconst DELETE_KEY = 46;\n/**\n * According to https://lists.w3.org/Archives/Public/www-dom/2010JulSep/att-0182/keyCode-spec.html\n * 229 can be sent in variants generated when Long press (iOS) or using IM.\n *\n * Other cases: https://stackoverflow.com/questions/25043934/is-it-ok-to-ignore-keydown-events-with-keycode-229\n */\nconst DEAD_KEY = 229;\n\nconst DefaultOptions: Partial<EditOptions> = {\n handleTabKey: true,\n handleExpandedSelectionOnDelete: true,\n};\n\n/**\n * Edit plugins helps editor to do editing operation on top of content model.\n * This includes:\n * 1. Delete Key\n * 2. Backspace Key\n * 3. Tab Key\n */\nexport class EditPlugin implements EditorPlugin {\n private editor: IEditor | null = null;\n private disposer: (() => void) | null = null;\n private shouldHandleNextInputEvent = false;\n private selectionAfterDelete: DOMSelection | null = null;\n private handleNormalEnter: (editor: IEditor) => boolean = (editor: IEditor) => false;\n\n /**\n * @param options An optional parameter that takes in an object of type EditOptions, which includes the following properties:\n * handleTabKey: A boolean that enables or disables Tab key handling. Defaults to true.\n */\n constructor(private options: EditOptions = DefaultOptions) {}\n\n private createNormalEnterChecker(result: boolean) {\n return result ? () => true : () => false;\n }\n\n private getHandleNormalEnter(editor: IEditor) {\n switch (typeof this.options.shouldHandleEnterKey) {\n case 'function':\n return this.options.shouldHandleEnterKey;\n break;\n case 'boolean':\n return this.createNormalEnterChecker(this.options.shouldHandleEnterKey);\n break;\n default:\n return this.createNormalEnterChecker(\n editor.isExperimentalFeatureEnabled('HandleEnterKey')\n );\n break;\n }\n }\n\n /**\n * Get name of this plugin\n */\n getName() {\n return 'Edit';\n }\n\n /**\n * The first method that editor will call to a plugin when editor is initializing.\n * It will pass in the editor instance, plugin should take this chance to save the\n * editor reference so that it can call to any editor method or format API later.\n * @param editor The editor object\n */\n initialize(editor: IEditor) {\n this.editor = editor;\n this.handleNormalEnter = this.getHandleNormalEnter(editor);\n\n if (editor.getEnvironment().isAndroid) {\n this.disposer = this.editor.attachDomEvent({\n beforeinput: {\n beforeDispatch: e => this.handleBeforeInputEvent(editor, e),\n },\n });\n }\n }\n\n /**\n * The last method that editor will call to a plugin before it is disposed.\n * Plugin can take this chance to clear the reference to editor. After this method is\n * called, plugin should not call to any editor method since it will result in error.\n */\n dispose() {\n this.editor = null;\n this.disposer?.();\n this.disposer = null;\n }\n\n /**\n * Core method for a plugin. Once an event happens in editor, editor will call this\n * method of each plugin to handle the event as long as the event is not handled\n * exclusively by another plugin.\n * @param event The event to handle:\n */\n onPluginEvent(event: PluginEvent) {\n if (this.editor) {\n switch (event.eventType) {\n case 'keyDown':\n this.handleKeyDownEvent(this.editor, event);\n break;\n case 'keyUp':\n if (this.selectionAfterDelete) {\n this.editor.setDOMSelection(this.selectionAfterDelete);\n this.selectionAfterDelete = null;\n }\n break;\n }\n }\n }\n\n /**\n * Check if the plugin should handle the given event exclusively.\n * Handle an event exclusively means other plugin will not receive this event in\n * onPluginEvent method.\n * If two plugins will return true in willHandleEventExclusively() for the same event,\n * the final result depends on the order of the plugins are added into editor\n * @param event The event to check:\n */\n willHandleEventExclusively(event: PluginEvent) {\n if (\n this.editor &&\n this.options.handleTabKey &&\n event.eventType == 'keyDown' &&\n event.rawEvent.key == 'Tab' &&\n !event.rawEvent.shiftKey\n ) {\n const selection = this.editor.getDOMSelection();\n const startContainer =\n selection?.type == 'range' && selection.range.collapsed\n ? selection.range.startContainer\n : null;\n const table = startContainer\n ? this.editor.getDOMHelper().findClosestElementAncestor(startContainer, 'table')\n : null;\n const parsedTable = table && parseTableCells(table);\n\n if (parsedTable) {\n const lastRow = parsedTable[parsedTable.length - 1];\n const lastCell = lastRow && lastRow[lastRow.length - 1];\n\n if (typeof lastCell == 'object' && lastCell.contains(startContainer)) {\n // When TAB in the last cell of a table, we will generate new table row, so prevent other plugins handling this event\n // e.g. SelectionPlugin will move the focus out of table, which is conflict with this behavior\n return true;\n }\n }\n }\n\n return false;\n }\n\n private handleKeyDownEvent(editor: IEditor, event: KeyDownEvent) {\n const rawEvent = event.rawEvent;\n const hasCtrlOrMetaKey = rawEvent.ctrlKey || rawEvent.metaKey;\n\n if (!rawEvent.defaultPrevented && !event.handledByEditFeature) {\n switch (rawEvent.key) {\n case 'Backspace':\n // Use our API to handle BACKSPACE/DELETE key.\n // No need to clear cache here since if we rely on browser's behavior, there will be Input event and its handler will reconcile cache\n keyboardDelete(editor, rawEvent, this.options.handleExpandedSelectionOnDelete);\n break;\n\n case 'Delete':\n // Use our API to handle BACKSPACE/DELETE key.\n // No need to clear cache here since if we rely on browser's behavior, there will be Input event and its handler will reconcile cache\n // And leave it to browser when shift key is pressed so that browser will trigger cut event\n if (!event.rawEvent.shiftKey) {\n keyboardDelete(\n editor,\n rawEvent,\n this.options.handleExpandedSelectionOnDelete\n );\n }\n break;\n\n case 'Tab':\n if (this.options.handleTabKey && !hasCtrlOrMetaKey) {\n keyboardTab(editor, rawEvent);\n }\n break;\n case 'Unidentified':\n if (editor.getEnvironment().isAndroid) {\n this.shouldHandleNextInputEvent = true;\n }\n break;\n\n case 'Enter':\n if (\n !hasCtrlOrMetaKey &&\n !event.rawEvent.isComposing &&\n event.rawEvent.keyCode !== DEAD_KEY\n ) {\n keyboardEnter(editor, rawEvent, this.handleNormalEnter(editor));\n }\n break;\n\n default:\n keyboardInput(editor, rawEvent);\n break;\n }\n }\n }\n\n private handleBeforeInputEvent(editor: IEditor, rawEvent: Event) {\n // Some Android IMEs doesn't fire correct keydown event for BACKSPACE/DELETE key\n // Here we translate input event to BACKSPACE/DELETE keydown event to be compatible with existing logic\n if (\n !this.shouldHandleNextInputEvent ||\n !(rawEvent instanceof InputEvent) ||\n rawEvent.defaultPrevented\n ) {\n return;\n }\n this.shouldHandleNextInputEvent = false;\n\n let handled = false;\n switch (rawEvent.inputType) {\n case 'deleteContentBackward':\n handled = keyboardDelete(\n editor,\n new KeyboardEvent('keydown', {\n key: 'Backspace',\n keyCode: BACKSPACE_KEY,\n which: BACKSPACE_KEY,\n }),\n this.options.handleExpandedSelectionOnDelete\n );\n break;\n case 'deleteContentForward':\n handled = keyboardDelete(\n editor,\n new KeyboardEvent('keydown', {\n key: 'Delete',\n keyCode: DELETE_KEY,\n which: DELETE_KEY,\n }),\n this.options.handleExpandedSelectionOnDelete\n );\n break;\n }\n\n if (handled) {\n rawEvent.preventDefault();\n\n // Restore the selection on keyup event to avoid the cursor jump issue\n // See: https://issues.chromium.org/issues/330596261\n this.selectionAfterDelete = editor.getDOMSelection();\n }\n }\n}\n"]}