roosterjs 8.9.0 → 8.10.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.
@@ -3105,7 +3105,7 @@ exports.default = setDirection;
3105
3105
  "use strict";
3106
3106
 
3107
3107
  Object.defineProperty(exports, "__esModule", { value: true });
3108
- var applyInlineStyle_1 = __webpack_require__(/*! ../utils/applyInlineStyle */ "./packages/roosterjs-editor-api/lib/utils/applyInlineStyle.ts");
3108
+ var applyListItemWrap_1 = __webpack_require__(/*! ../utils/applyListItemWrap */ "./packages/roosterjs-editor-api/lib/utils/applyListItemWrap.ts");
3109
3109
  /**
3110
3110
  * Set font name at selection
3111
3111
  * @param editor The editor instance
@@ -3113,11 +3113,9 @@ var applyInlineStyle_1 = __webpack_require__(/*! ../utils/applyInlineStyle */ ".
3113
3113
  * Currently there's no validation to the string, if the passed string is invalid, it won't take affect
3114
3114
  */
3115
3115
  function setFontName(editor, fontName) {
3116
- fontName = fontName.trim();
3117
3116
  // The browser provided execCommand creates a HTML <font> tag with face attribute. <font> is not HTML5 standard
3118
- // (http://www.w3schools.com/tags/tag_font.asp). Use applyInlineStyle which gives flexibility on applying inline style
3119
- // for here, we use CSS font-family style
3120
- applyInlineStyle_1.default(editor, function (element, isInnerNode) {
3117
+ // (http://www.w3schools.com/tags/tag_font.asp).
3118
+ applyListItemWrap_1.default(editor, 'font-family', function (element, isInnerNode) {
3121
3119
  element.style.fontFamily = isInnerNode ? '' : fontName;
3122
3120
  });
3123
3121
  }
@@ -3136,7 +3134,7 @@ exports.default = setFontName;
3136
3134
  "use strict";
3137
3135
 
3138
3136
  Object.defineProperty(exports, "__esModule", { value: true });
3139
- var applyInlineStyle_1 = __webpack_require__(/*! ../utils/applyInlineStyle */ "./packages/roosterjs-editor-api/lib/utils/applyInlineStyle.ts");
3137
+ var applyListItemWrap_1 = __webpack_require__(/*! ../utils/applyListItemWrap */ "./packages/roosterjs-editor-api/lib/utils/applyListItemWrap.ts");
3140
3138
  var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
3141
3139
  /**
3142
3140
  * Set font size at selection
@@ -3145,11 +3143,9 @@ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./
3145
3143
  * Currently there's no validation to the string, if the passed string is invalid, it won't take affect
3146
3144
  */
3147
3145
  function setFontSize(editor, fontSize) {
3148
- fontSize = fontSize.trim();
3149
3146
  // The browser provided execCommand only accepts 1-7 point value. In addition, it uses HTML <font> tag with size attribute.
3150
- // <font> is not HTML5 standard (http://www.w3schools.com/tags/tag_font.asp). Use applyInlineStyle which gives flexibility on applying inline style
3151
- // for here, we use CSS font-size style
3152
- applyInlineStyle_1.default(editor, function (element, isInnerNode) {
3147
+ // <font> is not HTML5 standard (http://www.w3schools.com/tags/tag_font.asp).
3148
+ applyListItemWrap_1.default(editor, 'font-size', function (element, isInnerNode) {
3153
3149
  element.style.fontSize = isInnerNode ? '' : fontSize;
3154
3150
  var lineHeight = roosterjs_editor_dom_1.getComputedStyle(element, 'line-height');
3155
3151
  if (lineHeight != 'normal') {
@@ -3309,7 +3305,7 @@ exports.default = setOrderedListNumbering;
3309
3305
  "use strict";
3310
3306
 
3311
3307
  Object.defineProperty(exports, "__esModule", { value: true });
3312
- var applyInlineStyle_1 = __webpack_require__(/*! ../utils/applyInlineStyle */ "./packages/roosterjs-editor-api/lib/utils/applyInlineStyle.ts");
3308
+ var applyListItemWrap_1 = __webpack_require__(/*! ../utils/applyListItemWrap */ "./packages/roosterjs-editor-api/lib/utils/applyListItemWrap.ts");
3313
3309
  var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
3314
3310
  /**
3315
3311
  * Set text color at selection
@@ -3323,7 +3319,7 @@ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./
3323
3319
  * @param shouldApplyInlineStyle Optional callback function to be invoked to verify if the current element should have the inline Style applied
3324
3320
  */
3325
3321
  function setTextColor(editor, color, shouldApplyInlineStyle) {
3326
- applyInlineStyle_1.default(editor, function (element, isInnerNode) {
3322
+ applyListItemWrap_1.default(editor, 'color', function (element, isInnerNode) {
3327
3323
  if (!shouldApplyInlineStyle || shouldApplyInlineStyle(element)) {
3328
3324
  roosterjs_editor_dom_1.setColor(element, isInnerNode ? '' : color, false /*isBackground*/, editor.isDarkMode());
3329
3325
  }
@@ -4011,6 +4007,54 @@ function applyInlineStyle(editor, callback) {
4011
4007
  exports.default = applyInlineStyle;
4012
4008
 
4013
4009
 
4010
+ /***/ }),
4011
+
4012
+ /***/ "./packages/roosterjs-editor-api/lib/utils/applyListItemWrap.ts":
4013
+ /*!**********************************************************************!*\
4014
+ !*** ./packages/roosterjs-editor-api/lib/utils/applyListItemWrap.ts ***!
4015
+ \**********************************************************************/
4016
+ /*! no static exports found */
4017
+ /***/ (function(module, exports, __webpack_require__) {
4018
+
4019
+ "use strict";
4020
+
4021
+ Object.defineProperty(exports, "__esModule", { value: true });
4022
+ var applyInlineStyle_1 = __webpack_require__(/*! ../utils/applyInlineStyle */ "./packages/roosterjs-editor-api/lib/utils/applyInlineStyle.ts");
4023
+ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
4024
+ /**
4025
+ * @internal
4026
+ * Set the List Item Style when all inner inline element have the same style
4027
+ * @param editor The editor instance
4028
+ * @param styleName Name of the style to apply to the list item
4029
+ * @param formatCallback callback to apply the style to each element
4030
+ */
4031
+ function applyListItemStyleWrap(editor, styleName, formatCallback) {
4032
+ var parentNodes = [];
4033
+ applyInlineStyle_1.default(editor, function (element, isInnerNode) {
4034
+ formatCallback(element, isInnerNode);
4035
+ var parent = editor.getElementAtCursor('LI', element);
4036
+ if (parent && parentNodes.indexOf(parent) === -1) {
4037
+ parentNodes.push(parent);
4038
+ }
4039
+ });
4040
+ applyStyleToListItems(parentNodes, [styleName]);
4041
+ }
4042
+ exports.default = applyListItemStyleWrap;
4043
+ /**
4044
+ * @internal
4045
+ * Checks if the parent element is a List Item, if it is, apply the style elements to the list item
4046
+ * @param parentNodes parentNodes to apply the style
4047
+ * @param styles styles to apply to the List Item Element
4048
+ */
4049
+ function applyStyleToListItems(parentNodes, styles) {
4050
+ parentNodes.forEach(function (node) {
4051
+ if (roosterjs_editor_dom_1.safeInstanceOf(node, 'HTMLLIElement')) {
4052
+ roosterjs_editor_dom_1.setListItemStyle(node, styles);
4053
+ }
4054
+ });
4055
+ }
4056
+
4057
+
4014
4058
  /***/ }),
4015
4059
 
4016
4060
  /***/ "./packages/roosterjs-editor-api/lib/utils/blockFormat.ts":
@@ -5871,6 +5915,12 @@ var ALLOWED_CSS_CLASSES = [
5871
5915
  ENTITY_TYPE_CSS_REGEX,
5872
5916
  ENTITY_READONLY_CSS_REGEX,
5873
5917
  ];
5918
+ var REMOVE_ENTITY_OPERATIONS = [
5919
+ 6 /* Overwrite */,
5920
+ 7 /* PartialOverwrite */,
5921
+ 4 /* RemoveFromStart */,
5922
+ 5 /* RemoveFromEnd */,
5923
+ ];
5874
5924
  /**
5875
5925
  * @internal
5876
5926
  * Entity Plugin helps handle all operations related to an entity and generate entity specified events
@@ -5887,9 +5937,28 @@ var EntityPlugin = /** @class */ (function () {
5887
5937
  _this.checkRemoveEntityForRange(event);
5888
5938
  }
5889
5939
  };
5940
+ this.workaroundShadowDOMIssueForChrome = function () {
5941
+ var cache = {};
5942
+ _this.cacheShadowEntities(cache);
5943
+ _this.editor.runAsync(function () {
5944
+ Object.keys(cache).forEach(function (id) {
5945
+ var entity = roosterjs_editor_dom_1.getEntityFromElement(cache[id]);
5946
+ var newWrapper = _this.editor.queryElements(roosterjs_editor_dom_1.getEntitySelector(entity.type, entity.id))[0];
5947
+ if (newWrapper != entity.wrapper) {
5948
+ _this.triggerEvent(entity.wrapper, 10 /* RemoveShadowRoot */);
5949
+ _this.setIsEntityKnown(entity.wrapper, false /*isKnown*/);
5950
+ if (newWrapper) {
5951
+ roosterjs_editor_dom_1.moveChildNodes(newWrapper, entity.wrapper);
5952
+ _this.createShadowRoot(newWrapper, entity.wrapper.shadowRoot);
5953
+ _this.setIsEntityKnown(newWrapper, true /*isKnown*/);
5954
+ }
5955
+ }
5956
+ });
5957
+ });
5958
+ };
5890
5959
  this.state = {
5891
- clickingPoint: null,
5892
5960
  knownEntityElements: [],
5961
+ shadowEntityCache: {},
5893
5962
  };
5894
5963
  }
5895
5964
  /**
@@ -5904,6 +5973,27 @@ var EntityPlugin = /** @class */ (function () {
5904
5973
  */
5905
5974
  EntityPlugin.prototype.initialize = function (editor) {
5906
5975
  this.editor = editor;
5976
+ // Workaround an issue for Chrome that when Delete or Backsapce, shadow DOM may be lost in editor
5977
+ if (roosterjs_editor_dom_1.Browser.isChrome || roosterjs_editor_dom_1.Browser.isSafari) {
5978
+ this.editor.addContentEditFeature({
5979
+ keys: [8 /* BACKSPACE */, 46 /* DELETE */],
5980
+ shouldHandleEvent: function () { return true; },
5981
+ handleEvent: this.workaroundShadowDOMIssueForChrome,
5982
+ });
5983
+ }
5984
+ };
5985
+ /**
5986
+ * Check if the plugin should handle the given event exclusively.
5987
+ * Handle an event exclusively means other plugin will not receive this event in
5988
+ * onPluginEvent method.
5989
+ * If two plugins will return true in willHandleEventExclusively() for the same event,
5990
+ * the final result depends on the order of the plugins are added into editor
5991
+ * @param event The event to check
5992
+ */
5993
+ EntityPlugin.prototype.willHandleEventExclusively = function (event) {
5994
+ var _a;
5995
+ return (event.eventType == 1 /* KeyPress */ &&
5996
+ !!((_a = event.rawEvent.target) === null || _a === void 0 ? void 0 : _a.shadowRoot));
5907
5997
  };
5908
5998
  /**
5909
5999
  * Dispose this plugin
@@ -5911,7 +6001,6 @@ var EntityPlugin = /** @class */ (function () {
5911
6001
  EntityPlugin.prototype.dispose = function () {
5912
6002
  this.editor = null;
5913
6003
  this.state.knownEntityElements = [];
5914
- this.state.clickingPoint = null;
5915
6004
  };
5916
6005
  /**
5917
6006
  * Get plugin state object
@@ -5925,11 +6014,8 @@ var EntityPlugin = /** @class */ (function () {
5925
6014
  */
5926
6015
  EntityPlugin.prototype.onPluginEvent = function (event) {
5927
6016
  switch (event.eventType) {
5928
- case 5 /* MouseDown */:
5929
- this.handleMouseDownEvent(event.rawEvent);
5930
- break;
5931
6017
  case 6 /* MouseUp */:
5932
- this.handleMouseUpEvent(event.rawEvent);
6018
+ this.handleMouseUpEvent(event);
5933
6019
  break;
5934
6020
  case 0 /* KeyDown */:
5935
6021
  this.handleKeyDownEvent(event.rawEvent);
@@ -5940,13 +6026,13 @@ var EntityPlugin = /** @class */ (function () {
5940
6026
  }
5941
6027
  break;
5942
6028
  case 10 /* BeforePaste */:
5943
- this.handleBeforePasteEvent(event.fragment, event.sanitizingOption);
6029
+ this.handleBeforePasteEvent(event.sanitizingOption);
5944
6030
  break;
5945
6031
  case 7 /* ContentChanged */:
5946
- this.handleContentChangedEvent(event.source == "SetContent" /* SetContent */);
6032
+ this.handleContentChangedEvent(event);
5947
6033
  break;
5948
6034
  case 11 /* EditorReady */:
5949
- this.handleContentChangedEvent(true /*resetAll*/);
6035
+ this.handleContentChangedEvent();
5950
6036
  break;
5951
6037
  case 8 /* ExtractContentWithDom */:
5952
6038
  this.handleExtractContentWithDomEvent(event.clonedRoot);
@@ -5954,6 +6040,12 @@ var EntityPlugin = /** @class */ (function () {
5954
6040
  case 16 /* ContextMenu */:
5955
6041
  this.handleContextMenuEvent(event.rawEvent);
5956
6042
  break;
6043
+ case 20 /* BeforeSetContent */:
6044
+ this.handleBeforeSetContentEvent();
6045
+ break;
6046
+ case 15 /* EntityOperation */:
6047
+ this.handleEntityOperationEvent(event);
6048
+ break;
5957
6049
  }
5958
6050
  };
5959
6051
  EntityPlugin.prototype.handleContextMenuEvent = function (event) {
@@ -5964,63 +6056,83 @@ var EntityPlugin = /** @class */ (function () {
5964
6056
  this.triggerEvent(entityElement, 2 /* ContextMenu */, event);
5965
6057
  }
5966
6058
  };
5967
- EntityPlugin.prototype.handleMouseDownEvent = function (event) {
5968
- var target = event.target, pageX = event.pageX, pageY = event.pageY;
5969
- var node = target;
5970
- var entityElement = node && this.editor.getElementAtCursor(roosterjs_editor_dom_1.getEntitySelector(), node);
5971
- if (entityElement && !entityElement.isContentEditable) {
5972
- event.preventDefault();
5973
- this.state.clickingPoint = { pageX: pageX, pageY: pageY };
5974
- }
5975
- };
5976
6059
  EntityPlugin.prototype.handleMouseUpEvent = function (event) {
5977
- var target = event.target, pageX = event.pageX, pageY = event.pageY;
5978
- var node = target;
6060
+ var rawEvent = event.rawEvent, isClicking = event.isClicking;
6061
+ var node = rawEvent.target;
5979
6062
  var entityElement;
5980
- if (this.state.clickingPoint &&
5981
- this.state.clickingPoint.pageX == pageX &&
5982
- this.state.clickingPoint.pageY == pageY &&
6063
+ if (isClicking &&
5983
6064
  node &&
5984
6065
  !!(entityElement = this.editor.getElementAtCursor(roosterjs_editor_dom_1.getEntitySelector(), node))) {
5985
- event.preventDefault();
5986
- this.triggerEvent(entityElement, 1 /* Click */, event);
6066
+ this.triggerEvent(entityElement, 1 /* Click */, rawEvent);
5987
6067
  workaroundSelectionIssueForIE(this.editor);
5988
6068
  }
5989
- this.state.clickingPoint = null;
5990
6069
  };
5991
6070
  EntityPlugin.prototype.handleKeyDownEvent = function (event) {
5992
6071
  if (roosterjs_editor_dom_1.isCharacterValue(event) ||
5993
6072
  event.which == 8 /* BACKSPACE */ ||
5994
- event.which == 46 /* DELETE */) {
6073
+ event.which == 46 /* DELETE */ ||
6074
+ event.which == 13 /* ENTER */) {
5995
6075
  var range = this.editor.getSelectionRange();
5996
6076
  if (range && !range.collapsed) {
5997
6077
  this.checkRemoveEntityForRange(event);
5998
6078
  }
5999
6079
  }
6000
6080
  };
6001
- EntityPlugin.prototype.handleBeforePasteEvent = function (fragment, sanitizingOption) {
6081
+ EntityPlugin.prototype.handleBeforePasteEvent = function (sanitizingOption) {
6002
6082
  var range = this.editor.getSelectionRange();
6003
6083
  if (!range.collapsed) {
6004
6084
  this.checkRemoveEntityForRange(null /*rawEvent*/);
6005
6085
  }
6006
6086
  roosterjs_editor_dom_1.arrayPush(sanitizingOption.additionalAllowedCssClasses, ALLOWED_CSS_CLASSES);
6007
6087
  };
6008
- EntityPlugin.prototype.handleContentChangedEvent = function (resetAll) {
6088
+ EntityPlugin.prototype.handleBeforeSetContentEvent = function () {
6089
+ this.cacheShadowEntities(this.state.shadowEntityCache);
6090
+ };
6091
+ EntityPlugin.prototype.handleContentChangedEvent = function (event) {
6009
6092
  var _this = this;
6010
- this.state.knownEntityElements = resetAll
6011
- ? []
6012
- : this.state.knownEntityElements.filter(function (node) { return _this.editor.contains(node); });
6013
- var allId = this.state.knownEntityElements
6093
+ // 1. find removed entities
6094
+ for (var i = this.state.knownEntityElements.length - 1; i >= 0; i--) {
6095
+ var element = this.state.knownEntityElements[i];
6096
+ if (!this.editor.contains(element)) {
6097
+ this.setIsEntityKnown(element, false /*isKnown*/);
6098
+ if (element.shadowRoot) {
6099
+ this.triggerEvent(element, 10 /* RemoveShadowRoot */);
6100
+ }
6101
+ }
6102
+ }
6103
+ // 2. collect all new entities
6104
+ var knownIds = this.state.knownEntityElements
6014
6105
  .map(function (e) { var _a; return (_a = roosterjs_editor_dom_1.getEntityFromElement(e)) === null || _a === void 0 ? void 0 : _a.id; })
6015
6106
  .filter(function (x) { return !!x; });
6016
- this.editor.queryElements(roosterjs_editor_dom_1.getEntitySelector(), function (element) {
6017
- if (_this.state.knownEntityElements.indexOf(element) < 0) {
6018
- _this.state.knownEntityElements.push(element);
6019
- var entity = roosterjs_editor_dom_1.getEntityFromElement(element);
6020
- _this.hydrateEntity(entity, allId);
6021
- }
6107
+ var newEntities = (event === null || event === void 0 ? void 0 : event.source) == "InsertEntity" /* InsertEntity */ && event.data
6108
+ ? [event.data]
6109
+ : this.getExistingEntities().filter(function (_a) {
6110
+ var wrapper = _a.wrapper;
6111
+ return !_this.isEntityKnown(wrapper);
6112
+ });
6113
+ // 3. Add new entities to known entity list, and hydrate
6114
+ newEntities.forEach(function (entity) {
6115
+ var wrapper = entity.wrapper, type = entity.type, id = entity.id, isReadonly = entity.isReadonly;
6116
+ entity.id = _this.ensureUniqueId(type, id, knownIds);
6117
+ roosterjs_editor_dom_1.commitEntity(wrapper, type, isReadonly, entity.id); // Use entity.id here because it is newly updated
6118
+ _this.handleNewEntity(entity);
6119
+ });
6120
+ Object.keys(this.state.shadowEntityCache).forEach(function (id) {
6121
+ _this.triggerEvent(_this.state.shadowEntityCache[id], 6 /* Overwrite */);
6122
+ delete _this.state.shadowEntityCache[id];
6022
6123
  });
6023
6124
  };
6125
+ EntityPlugin.prototype.handleEntityOperationEvent = function (event) {
6126
+ var _this = this;
6127
+ var _a;
6128
+ if (REMOVE_ENTITY_OPERATIONS.indexOf(event.operation) >= 0) {
6129
+ (_a = this.cancelAsyncRun) === null || _a === void 0 ? void 0 : _a.call(this);
6130
+ this.cancelAsyncRun = this.editor.runAsync(function () {
6131
+ _this.cancelAsyncRun = null;
6132
+ _this.handleContentChangedEvent();
6133
+ });
6134
+ }
6135
+ };
6024
6136
  EntityPlugin.prototype.handleExtractContentWithDomEvent = function (root) {
6025
6137
  var _this = this;
6026
6138
  roosterjs_editor_dom_1.toArray(root.querySelectorAll(roosterjs_editor_dom_1.getEntitySelector())).forEach(function (element) {
@@ -6050,8 +6162,71 @@ var EntityPlugin = /** @class */ (function () {
6050
6162
  });
6051
6163
  }
6052
6164
  };
6053
- EntityPlugin.prototype.hydrateEntity = function (entity, knownIds) {
6054
- var id = entity.id, type = entity.type, wrapper = entity.wrapper, isReadonly = entity.isReadonly;
6165
+ EntityPlugin.prototype.triggerEvent = function (element, operation, rawEvent, contentForShadowEntity) {
6166
+ var entity = element && roosterjs_editor_dom_1.getEntityFromElement(element);
6167
+ if (entity) {
6168
+ this.editor.triggerPluginEvent(15 /* EntityOperation */, {
6169
+ operation: operation,
6170
+ rawEvent: rawEvent,
6171
+ entity: entity,
6172
+ contentForShadowEntity: contentForShadowEntity,
6173
+ });
6174
+ }
6175
+ };
6176
+ EntityPlugin.prototype.handleNewEntity = function (entity) {
6177
+ var wrapper = entity.wrapper;
6178
+ var fragment = this.editor.getDocument().createDocumentFragment();
6179
+ var cache = this.state.shadowEntityCache[entity.id];
6180
+ delete this.state.shadowEntityCache[entity.id];
6181
+ if (cache === null || cache === void 0 ? void 0 : cache.shadowRoot) {
6182
+ roosterjs_editor_dom_1.moveChildNodes(fragment, cache.shadowRoot);
6183
+ }
6184
+ this.triggerEvent(wrapper, 0 /* NewEntity */, undefined /*rawEvent*/, fragment);
6185
+ // If there is element to hydrate for shadow entity, craete shadow root and mount these elements to shadow root
6186
+ // Then trigger AddShadowRoot so that plugins can do further actions
6187
+ if (fragment.firstChild) {
6188
+ if (wrapper.shadowRoot) {
6189
+ roosterjs_editor_dom_1.moveChildNodes(wrapper.shadowRoot, fragment);
6190
+ }
6191
+ else {
6192
+ this.createShadowRoot(wrapper, fragment);
6193
+ }
6194
+ }
6195
+ else if (wrapper.shadowRoot) {
6196
+ // If no elements to hydrate, remove existing shadow root by cloning a new node
6197
+ this.triggerEvent(wrapper, 10 /* RemoveShadowRoot */);
6198
+ var newWrapper = wrapper.cloneNode();
6199
+ roosterjs_editor_dom_1.moveChildNodes(newWrapper, wrapper);
6200
+ this.editor.replaceNode(wrapper, newWrapper);
6201
+ entity.wrapper = newWrapper;
6202
+ }
6203
+ this.setIsEntityKnown(entity.wrapper, true /*isKnown*/);
6204
+ };
6205
+ EntityPlugin.prototype.getExistingEntities = function (shadowEntityOnly) {
6206
+ return this.editor
6207
+ .queryElements(roosterjs_editor_dom_1.getEntitySelector())
6208
+ .map(roosterjs_editor_dom_1.getEntityFromElement)
6209
+ .filter(function (x) { return !!x && (!shadowEntityOnly || !!x.wrapper.shadowRoot); });
6210
+ };
6211
+ EntityPlugin.prototype.createShadowRoot = function (wrapper, shadowContentContainer) {
6212
+ if (wrapper.attachShadow) {
6213
+ var shadowRoot = wrapper.attachShadow({
6214
+ mode: 'open',
6215
+ delegatesFocus: true,
6216
+ });
6217
+ wrapper.contentEditable = 'false';
6218
+ this.triggerEvent(wrapper, 9 /* AddShadowRoot */);
6219
+ roosterjs_editor_dom_1.moveChildNodes(shadowRoot, shadowContentContainer);
6220
+ return shadowRoot;
6221
+ }
6222
+ };
6223
+ EntityPlugin.prototype.cacheShadowEntities = function (cache) {
6224
+ this.getExistingEntities(true /*shadowEntityOnly*/).forEach(function (_a) {
6225
+ var wrapper = _a.wrapper, id = _a.id;
6226
+ cache[id] = wrapper;
6227
+ });
6228
+ };
6229
+ EntityPlugin.prototype.ensureUniqueId = function (type, id, knownIds) {
6055
6230
  var match = ENTITY_ID_REGEX.exec(id);
6056
6231
  var baseId = (match ? id.substr(0, id.length - match[0].length) : id) || type;
6057
6232
  // Make sure entity id is unique
@@ -6063,19 +6238,20 @@ var EntityPlugin = /** @class */ (function () {
6063
6238
  break;
6064
6239
  }
6065
6240
  }
6066
- roosterjs_editor_dom_1.commitEntity(wrapper, type, isReadonly, newId);
6067
- this.triggerEvent(wrapper, 0 /* NewEntity */);
6241
+ return newId;
6068
6242
  };
6069
- EntityPlugin.prototype.triggerEvent = function (element, operation, rawEvent) {
6070
- var entity = element && roosterjs_editor_dom_1.getEntityFromElement(element);
6071
- if (entity) {
6072
- this.editor.triggerPluginEvent(15 /* EntityOperation */, {
6073
- operation: operation,
6074
- rawEvent: rawEvent,
6075
- entity: entity,
6076
- });
6243
+ EntityPlugin.prototype.setIsEntityKnown = function (wrapper, isKnown) {
6244
+ var index = this.state.knownEntityElements.indexOf(wrapper);
6245
+ if (isKnown && index < 0) {
6246
+ this.state.knownEntityElements.push(wrapper);
6247
+ }
6248
+ else if (!isKnown && index >= 0) {
6249
+ this.state.knownEntityElements.splice(index, 1);
6077
6250
  }
6078
6251
  };
6252
+ EntityPlugin.prototype.isEntityKnown = function (wrapper) {
6253
+ return this.state.knownEntityElements.indexOf(wrapper) >= 0;
6254
+ };
6079
6255
  return EntityPlugin;
6080
6256
  }());
6081
6257
  exports.default = EntityPlugin;
@@ -6087,13 +6263,10 @@ var workaroundSelectionIssueForIE = roosterjs_editor_dom_1.Browser.isIE
6087
6263
  ? function (editor) {
6088
6264
  editor.runAsync(function (editor) {
6089
6265
  var workaroundButton = editor.getCustomData('ENTITY_IE_FOCUS_BUTTON', function () {
6090
- var button = editor.getDocument().createElement('button');
6091
- button.style.overflow = 'hidden';
6092
- button.style.position = 'fixed';
6093
- button.style.width = '0';
6094
- button.style.height = '0';
6095
- button.style.left = '0';
6096
- button.style.top = '-1000px';
6266
+ var button = roosterjs_editor_dom_1.createElement({
6267
+ tag: 'button',
6268
+ style: 'overflow:hidden;position:fixed;width:0;height:0;top:-1000px',
6269
+ }, editor.getDocument());
6097
6270
  button.onblur = function () {
6098
6271
  button.style.display = 'none';
6099
6272
  };
@@ -6103,13 +6276,7 @@ var workaroundSelectionIssueForIE = roosterjs_editor_dom_1.Browser.isIE
6103
6276
  return button;
6104
6277
  });
6105
6278
  workaroundButton.style.display = '';
6106
- var range = editor.getDocument().createRange();
6107
- range.setStart(workaroundButton, 0);
6108
- try {
6109
- window.getSelection().removeAllRanges();
6110
- window.getSelection().addRange(range);
6111
- }
6112
- catch (_a) { }
6279
+ roosterjs_editor_dom_1.addRangeToSelection(roosterjs_editor_dom_1.createRange(workaroundButton, 0));
6113
6280
  });
6114
6281
  }
6115
6282
  : function () { };
@@ -7312,15 +7479,19 @@ var Editor = /** @class */ (function () {
7312
7479
  /**
7313
7480
  * Run a callback function asynchronously
7314
7481
  * @param callback The callback function to run
7482
+ * @returns a function to cancel this async run
7315
7483
  */
7316
7484
  Editor.prototype.runAsync = function (callback) {
7317
7485
  var _this = this;
7318
7486
  var win = this.core.contentDiv.ownerDocument.defaultView || window;
7319
- win.requestAnimationFrame(function () {
7487
+ var handle = win.requestAnimationFrame(function () {
7320
7488
  if (!_this.isDisposed() && callback) {
7321
7489
  callback(_this);
7322
7490
  }
7323
7491
  });
7492
+ return function () {
7493
+ win.cancelAnimationFrame(handle);
7494
+ };
7324
7495
  };
7325
7496
  /**
7326
7497
  * Set DOM attribute of editor content DIV
@@ -9882,6 +10053,8 @@ exports.createElement = createElement_1.default;
9882
10053
  exports.KnownCreateElementData = createElement_1.KnownCreateElementData;
9883
10054
  var moveChildNodes_1 = __webpack_require__(/*! ./utils/moveChildNodes */ "./packages/roosterjs-editor-dom/lib/utils/moveChildNodes.ts");
9884
10055
  exports.moveChildNodes = moveChildNodes_1.default;
10056
+ var setListItemStyle_1 = __webpack_require__(/*! ./utils/setListItemStyle */ "./packages/roosterjs-editor-dom/lib/utils/setListItemStyle.ts");
10057
+ exports.setListItemStyle = setListItemStyle_1.default;
9885
10058
  var VTable_1 = __webpack_require__(/*! ./table/VTable */ "./packages/roosterjs-editor-dom/lib/table/VTable.ts");
9886
10059
  exports.VTable = VTable_1.default;
9887
10060
  var VList_1 = __webpack_require__(/*! ./list/VList */ "./packages/roosterjs-editor-dom/lib/list/VList.ts");
@@ -11053,6 +11226,7 @@ var getTagOfNode_1 = __webpack_require__(/*! ../utils/getTagOfNode */ "./package
11053
11226
  var isBlockElement_1 = __webpack_require__(/*! ../utils/isBlockElement */ "./packages/roosterjs-editor-dom/lib/utils/isBlockElement.ts");
11054
11227
  var moveChildNodes_1 = __webpack_require__(/*! ../utils/moveChildNodes */ "./packages/roosterjs-editor-dom/lib/utils/moveChildNodes.ts");
11055
11228
  var safeInstanceOf_1 = __webpack_require__(/*! ../utils/safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts");
11229
+ var setListItemStyle_1 = __webpack_require__(/*! ../utils/setListItemStyle */ "./packages/roosterjs-editor-dom/lib/utils/setListItemStyle.ts");
11056
11230
  var toArray_1 = __webpack_require__(/*! ../utils/toArray */ "./packages/roosterjs-editor-dom/lib/utils/toArray.ts");
11057
11231
  var unwrap_1 = __webpack_require__(/*! ../utils/unwrap */ "./packages/roosterjs-editor-dom/lib/utils/unwrap.ts");
11058
11232
  var wrap_1 = __webpack_require__(/*! ../utils/wrap */ "./packages/roosterjs-editor-dom/lib/utils/wrap.ts");
@@ -11230,7 +11404,14 @@ var VListItem = /** @class */ (function () {
11230
11404
  // 3. Add current node into deepest list element
11231
11405
  listStack[listStack.length - 1].appendChild(this.node);
11232
11406
  this.node.style.display = this.dummy ? 'block' : null;
11233
- // 4. If this is not a list item now, need to unwrap the LI node and do proper handling
11407
+ // 4. Inherit styles of the childelement to the li, so we are able to apply the styles to the ::marker
11408
+ if (this.listTypes.length > 1) {
11409
+ if (!(this.node.style.fontSize || this.node.style.color || this.node.style.fontFamily)) {
11410
+ var stylesToInherit = ['font-size', 'font-family', 'color'];
11411
+ setListItemStyle_1.default(this.node, stylesToInherit);
11412
+ }
11413
+ }
11414
+ // 5. If this is not a list item now, need to unwrap the LI node and do proper handling
11234
11415
  if (this.listTypes.length <= 1) {
11235
11416
  wrapIfNotBlockNode(getTagOfNode_1.default(this.node) == 'LI' ? getChildrenAndUnwrap(this.node) : [this.node], true /*checkFirst*/, true /*checkLast*/);
11236
11417
  }
@@ -14990,6 +15171,65 @@ function setColor(element, color, isBackgroundColor, isDarkMode) {
14990
15171
  exports.default = setColor;
14991
15172
 
14992
15173
 
15174
+ /***/ }),
15175
+
15176
+ /***/ "./packages/roosterjs-editor-dom/lib/utils/setListItemStyle.ts":
15177
+ /*!*********************************************************************!*\
15178
+ !*** ./packages/roosterjs-editor-dom/lib/utils/setListItemStyle.ts ***!
15179
+ \*********************************************************************/
15180
+ /*! no static exports found */
15181
+ /***/ (function(module, exports, __webpack_require__) {
15182
+
15183
+ "use strict";
15184
+
15185
+ Object.defineProperty(exports, "__esModule", { value: true });
15186
+ var ContentTraverser_1 = __webpack_require__(/*! ../contentTraverser/ContentTraverser */ "./packages/roosterjs-editor-dom/lib/contentTraverser/ContentTraverser.ts");
15187
+ var findClosestElementAncestor_1 = __webpack_require__(/*! ./findClosestElementAncestor */ "./packages/roosterjs-editor-dom/lib/utils/findClosestElementAncestor.ts");
15188
+ var getStyles_1 = __webpack_require__(/*! ../style/getStyles */ "./packages/roosterjs-editor-dom/lib/style/getStyles.ts");
15189
+ var safeInstanceOf_1 = __webpack_require__(/*! ./safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts");
15190
+ var setStyles_1 = __webpack_require__(/*! ../style/setStyles */ "./packages/roosterjs-editor-dom/lib/style/setStyles.ts");
15191
+ /**
15192
+ * Set the Style of a List Item provided, with the styles that the inline child elements have
15193
+ * If the child inline elements have different styles, it will not modify the styles of the list item
15194
+ * @param element the LI Element to set the styles
15195
+ * @param styles The styles that should be applied to the element.
15196
+ */
15197
+ function setListItemStyle(element, styles) {
15198
+ var elementsStyles = getInlineChildElementsStyle(element);
15199
+ var stylesToApply = getStyles_1.default(element);
15200
+ styles.forEach(function (styleName) {
15201
+ var styleValues = elementsStyles.map(function (style) {
15202
+ return style[styleName] !== undefined ? style[styleName] : '';
15203
+ });
15204
+ if (styleValues &&
15205
+ (styleValues.length == 1 || new Set(styleValues).size == 1) &&
15206
+ styleValues[0]) {
15207
+ stylesToApply[styleName] = styleValues[0];
15208
+ }
15209
+ });
15210
+ setStyles_1.default(element, stylesToApply);
15211
+ }
15212
+ exports.default = setListItemStyle;
15213
+ function getInlineChildElementsStyle(element) {
15214
+ var result = [];
15215
+ var contentTraverser = ContentTraverser_1.default.createBodyTraverser(element);
15216
+ var currentInlineElement;
15217
+ while (contentTraverser.currentInlineElement != currentInlineElement) {
15218
+ currentInlineElement = contentTraverser.currentInlineElement;
15219
+ var currentNode = currentInlineElement.getContainerNode();
15220
+ currentNode = findClosestElementAncestor_1.default(currentNode);
15221
+ if (safeInstanceOf_1.default(currentNode, 'HTMLElement')) {
15222
+ var childStyle = getStyles_1.default(currentNode);
15223
+ if (childStyle) {
15224
+ result.push(childStyle);
15225
+ }
15226
+ }
15227
+ contentTraverser.getNextInlineElement();
15228
+ }
15229
+ return result;
15230
+ }
15231
+
15232
+
14993
15233
  /***/ }),
14994
15234
 
14995
15235
  /***/ "./packages/roosterjs-editor-dom/lib/utils/shouldSkipNode.ts":
@@ -15905,6 +16145,7 @@ function cacheGetNeighborEntityElement(event, editor, isNext, collapseOnly, oper
15905
16145
  if (collapseOnly && !range.collapsed) {
15906
16146
  return null;
15907
16147
  }
16148
+ range.commonAncestorContainer.normalize();
15908
16149
  var pos = roosterjs_editor_dom_1.Position.getEnd(range).normalize();
15909
16150
  var isAtBeginOrEnd = pos.offset == 0 || pos.isAtEnd;
15910
16151
  var entityNode = null;
@@ -16086,27 +16327,29 @@ var AutoBullet = {
16086
16327
  editor.insertContent('&nbsp;');
16087
16328
  event.rawEvent.preventDefault();
16088
16329
  editor.addUndoSnapshot(function () {
16330
+ var _a;
16089
16331
  var regions;
16090
16332
  var searcher = editor.getContentSearcherOfCursor();
16091
16333
  var textBeforeCursor = searcher.getSubStringBefore(4);
16092
- var rangeToDelete = searcher.getRangeFromText(textBeforeCursor, true /*exactMatch*/);
16093
- if (!rangeToDelete) {
16334
+ var textRange = searcher.getRangeFromText(textBeforeCursor, true /*exactMatch*/);
16335
+ if (!textRange) {
16094
16336
  // no op if the range can't be found
16095
16337
  }
16096
16338
  else if (textBeforeCursor.indexOf('*') == 0 ||
16097
16339
  textBeforeCursor.indexOf('-') == 0) {
16098
- prepareAutoBullet(editor, rangeToDelete);
16340
+ prepareAutoBullet(editor, textRange);
16099
16341
  roosterjs_editor_api_1.toggleBullet(editor);
16100
16342
  }
16101
16343
  else if (isAListPattern(textBeforeCursor)) {
16102
- prepareAutoBullet(editor, rangeToDelete);
16344
+ prepareAutoBullet(editor, textRange);
16103
16345
  roosterjs_editor_api_1.toggleNumbering(editor);
16104
16346
  }
16105
16347
  else if ((regions = editor.getSelectedRegions()) && regions.length == 1) {
16106
16348
  var num = parseInt(textBeforeCursor);
16107
- prepareAutoBullet(editor, rangeToDelete);
16349
+ prepareAutoBullet(editor, textRange);
16108
16350
  roosterjs_editor_api_1.toggleNumbering(editor, num);
16109
16351
  }
16352
+ (_a = searcher.getRangeFromText(textBeforeCursor, true /*exactMatch*/)) === null || _a === void 0 ? void 0 : _a.deleteContents();
16110
16353
  }, null /*changeSource*/, true /*canUndoByBackspace*/);
16111
16354
  },
16112
16355
  };
@@ -16151,7 +16394,6 @@ function getCacheNextSibiling(event, editor) {
16151
16394
  return element;
16152
16395
  }
16153
16396
  function prepareAutoBullet(editor, range) {
16154
- range.deleteContents();
16155
16397
  var block = editor.getBlockElementAtNode(range.startContainer);
16156
16398
  var endNode = block === null || block === void 0 ? void 0 : block.getEndNode();
16157
16399
  if (endNode && roosterjs_editor_dom_1.getTagOfNode(endNode) != 'BR' && (block === null || block === void 0 ? void 0 : block.getTextContent().trim()) === '') {
@@ -17425,7 +17667,6 @@ var ImageEdit = /** @class */ (function () {
17425
17667
  var img = wrapper === null || wrapper === void 0 ? void 0 : wrapper.querySelector('img');
17426
17668
  if (img && parent) {
17427
17669
  img.style.position = '';
17428
- img.style.maxWidth = '100%';
17429
17670
  img.style.margin = null;
17430
17671
  img.style.textAlign = null;
17431
17672
  parent.insertBefore(img, wrapper);
@@ -17484,6 +17725,7 @@ var ImageEdit = /** @class */ (function () {
17484
17725
  if ((context === null || context === void 0 ? void 0 : context.elementClass) == "r_resizeH" /* ResizeHandle */) {
17485
17726
  var clientWidth = wrapper.clientWidth;
17486
17727
  var clientHeight = wrapper.clientHeight;
17728
+ _this.wasResized = true;
17487
17729
  Resizer_1.doubleCheckResize(_this.editInfo, _this.options.preserveRatio, clientWidth, clientHeight);
17488
17730
  _this.updateWrapper();
17489
17731
  }
@@ -17594,7 +17836,7 @@ var ImageEdit = /** @class */ (function () {
17594
17836
  // When there is image in editing, clean up any cached objects and elements
17595
17837
  this.clearDndHelpers();
17596
17838
  // Apply the changes, and add undo snapshot if necessary
17597
- if (applyChange_1.default(this.editor, this.image, this.editInfo, this.lastSrc)) {
17839
+ if (applyChange_1.default(this.editor, this.image, this.editInfo, this.lastSrc, this.wasResized)) {
17598
17840
  this.editor.addUndoSnapshot(function () { return _this.image; }, "ImageResize" /* ImageResize */);
17599
17841
  }
17600
17842
  // Remove editing wrapper
@@ -17615,6 +17857,8 @@ var ImageEdit = /** @class */ (function () {
17615
17857
  this.image = image;
17616
17858
  // Get initial edit info
17617
17859
  this.editInfo = editInfo_1.getEditInfoFromImage(image);
17860
+ //Check if the image was resized by the user
17861
+ this.wasResized = checkIfImageWasResized(this.image);
17618
17862
  operation =
17619
17863
  (canRegenerateImage_1.default(image) ? operation : 3 /* Resize */) &
17620
17864
  this.allowedOperations;
@@ -17747,6 +17991,28 @@ function updateHandleCursor(handles, angleRad) {
17747
17991
  handle.style.cursor = rotateHandles(handle, angleRad) + "-resize";
17748
17992
  });
17749
17993
  }
17994
+ /**
17995
+ * Check if the current image was resized by the user
17996
+ * @param image the current image
17997
+ * @returns if the user resized the image, returns true, otherwise, returns false
17998
+ */
17999
+ function checkIfImageWasResized(image) {
18000
+ var width = image.width, height = image.height, style = image.style;
18001
+ if (style.maxWidth === 'initial' &&
18002
+ (isFixedNumberValue(style.height) ||
18003
+ isFixedNumberValue(style.width) ||
18004
+ isFixedNumberValue(width) ||
18005
+ isFixedNumberValue(height))) {
18006
+ return true;
18007
+ }
18008
+ else {
18009
+ return false;
18010
+ }
18011
+ }
18012
+ function isFixedNumberValue(value) {
18013
+ var numberValue = typeof value === 'string' ? parseInt(value) : value;
18014
+ return !isNaN(numberValue);
18015
+ }
17750
18016
 
17751
18017
 
17752
18018
  /***/ }),
@@ -17881,7 +18147,7 @@ function resizeByPercentage(editor, image, percentage, minWidth, minHeight) {
17881
18147
  editInfo.widthPx = Math.max(width, minWidth);
17882
18148
  editInfo.heightPx = Math.max(height, minHeight);
17883
18149
  editor.addUndoSnapshot(function () {
17884
- applyChange_1.default(editor, image, editInfo, lastSrc_1);
18150
+ applyChange_1.default(editor, image, editInfo, lastSrc_1, true /*wasResized*/);
17885
18151
  }, "ImageResize" /* ImageResize */);
17886
18152
  }
17887
18153
  });
@@ -17928,7 +18194,7 @@ var editInfo_1 = __webpack_require__(/*! ./editInfo */ "./packages/roosterjs-edi
17928
18194
  * @param previousSrc Last src value of the image before the change was made
17929
18195
  * @returns True if the image is changed, otherwise false
17930
18196
  */
17931
- function applyChange(editor, image, editInfo, previousSrc) {
18197
+ function applyChange(editor, image, editInfo, previousSrc, wasResized) {
17932
18198
  var newSrc = '';
17933
18199
  var initEditInfo = editInfo_1.getEditInfoFromImage(image);
17934
18200
  var state = checkEditInfoState_1.default(editInfo, initEditInfo);
@@ -17972,15 +18238,32 @@ function applyChange(editor, image, editInfo, previousSrc) {
17972
18238
  // Write back the change to image, and set its new size
17973
18239
  var _a = getGeneratedImageSize_1.default(editInfo), targetWidth = _a.targetWidth, targetHeight = _a.targetHeight;
17974
18240
  image.src = newSrc;
17975
- image.style.width = targetWidth + 'px';
17976
- image.style.height = targetHeight + 'px';
17977
- image.width = targetWidth;
17978
- image.height = targetHeight;
18241
+ setImageSize(image, wasResized, targetWidth, targetHeight);
17979
18242
  return (srcChanged ||
17980
18243
  editInfo.widthPx != initEditInfo.widthPx ||
17981
18244
  editInfo.heightPx != initEditInfo.heightPx);
17982
18245
  }
17983
18246
  exports.default = applyChange;
18247
+ /**
18248
+ * @param img The current image.
18249
+ * @param wasResized the current resize state of the image
18250
+ */
18251
+ function setImageSize(image, wasResized, targetWidth, targetHeight) {
18252
+ if (wasResized) {
18253
+ image.style.maxWidth = 'initial';
18254
+ image.width = targetWidth;
18255
+ image.height = targetHeight;
18256
+ image.style.width = targetWidth + 'px';
18257
+ image.style.height = targetHeight + 'px';
18258
+ }
18259
+ else {
18260
+ image.style.maxWidth = '100%';
18261
+ image.style.height = 'initial';
18262
+ image.style.width = 'initial';
18263
+ image.removeAttribute('height');
18264
+ image.removeAttribute('width');
18265
+ }
18266
+ }
17984
18267
 
17985
18268
 
17986
18269
  /***/ }),