roosterjs 8.6.1 → 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.
package/dist/rooster.js CHANGED
@@ -2311,6 +2311,13 @@ function changeFontSize(editor, change, fontSizes) {
2311
2311
  });
2312
2312
  }
2313
2313
  exports.default = changeFontSize;
2314
+ /**
2315
+ * @internal
2316
+ * Get new font size after increase/decrease. This is exported for test only
2317
+ * @param pt Original font size, in Point
2318
+ * @param changeBase Changed value, 1 means increase, -1 means decrease
2319
+ * @param fontSizes Known font size array
2320
+ */
2314
2321
  function getNewFontSize(pt, changeBase, fontSizes) {
2315
2322
  pt = changeBase == 1 ? Math.floor(pt) : Math.ceil(pt);
2316
2323
  var last = fontSizes[fontSizes.length - 1];
@@ -2354,37 +2361,58 @@ exports.getNewFontSize = getNewFontSize;
2354
2361
 
2355
2362
  "use strict";
2356
2363
 
2364
+ Object.defineProperty(exports, "__esModule", { value: true });
2365
+ var clearFormat_1 = __webpack_require__(/*! ./clearFormat */ "./packages/roosterjs-editor-api/lib/format/clearFormat.ts");
2366
+ /**
2367
+ * @deprecated Use clearFormat instead and pass the ClearFormatMode.Block as parameter
2368
+ * @param editor The editor instance
2369
+ */
2370
+ function clearBlockFormat(editor) {
2371
+ clearFormat_1.default(editor, 1 /* Block */);
2372
+ }
2373
+ exports.default = clearBlockFormat;
2374
+
2375
+
2376
+ /***/ }),
2377
+
2378
+ /***/ "./packages/roosterjs-editor-api/lib/format/clearFormat.ts":
2379
+ /*!*****************************************************************!*\
2380
+ !*** ./packages/roosterjs-editor-api/lib/format/clearFormat.ts ***!
2381
+ \*****************************************************************/
2382
+ /*! no static exports found */
2383
+ /***/ (function(module, exports, __webpack_require__) {
2384
+
2385
+ "use strict";
2386
+
2357
2387
  Object.defineProperty(exports, "__esModule", { value: true });
2358
2388
  var blockFormat_1 = __webpack_require__(/*! ../utils/blockFormat */ "./packages/roosterjs-editor-api/lib/utils/blockFormat.ts");
2389
+ var execCommand_1 = __webpack_require__(/*! ../utils/execCommand */ "./packages/roosterjs-editor-api/lib/utils/execCommand.ts");
2390
+ var setBackgroundColor_1 = __webpack_require__(/*! ./setBackgroundColor */ "./packages/roosterjs-editor-api/lib/format/setBackgroundColor.ts");
2391
+ var setFontName_1 = __webpack_require__(/*! ./setFontName */ "./packages/roosterjs-editor-api/lib/format/setFontName.ts");
2392
+ var setFontSize_1 = __webpack_require__(/*! ./setFontSize */ "./packages/roosterjs-editor-api/lib/format/setFontSize.ts");
2393
+ var setTextColor_1 = __webpack_require__(/*! ./setTextColor */ "./packages/roosterjs-editor-api/lib/format/setTextColor.ts");
2394
+ var toggleBold_1 = __webpack_require__(/*! ./toggleBold */ "./packages/roosterjs-editor-api/lib/format/toggleBold.ts");
2395
+ var toggleItalic_1 = __webpack_require__(/*! ./toggleItalic */ "./packages/roosterjs-editor-api/lib/format/toggleItalic.ts");
2396
+ var toggleUnderline_1 = __webpack_require__(/*! ./toggleUnderline */ "./packages/roosterjs-editor-api/lib/format/toggleUnderline.ts");
2359
2397
  var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
2398
+ var STYLES_TO_REMOVE = ['font', 'text-decoration', 'color', 'background'];
2360
2399
  var TAGS_TO_UNWRAP = 'B,I,U,STRONG,EM,SUB,SUP,STRIKE,FONT,CENTER,H1,H2,H3,H4,H5,H6,UL,OL,LI,SPAN,P,BLOCKQUOTE,CODE,S,PRE'.split(',');
2361
2400
  var ATTRIBUTES_TO_PRESERVE = ['href', 'src'];
2362
2401
  var TAGS_TO_STOP_UNWRAP = ['TD', 'TH', 'TR', 'TABLE', 'TBODY', 'THEAD'];
2363
2402
  /**
2364
- * Clear all formats of selected blocks.
2365
- * When selection is collapsed, only clear format of current block.
2366
2403
  * @param editor The editor instance
2404
+ * @returns if the current selection is composed of two or more block elements
2367
2405
  */
2368
- function clearBlockFormat(editor) {
2369
- blockFormat_1.default(editor, function (region) {
2370
- var blocks = roosterjs_editor_dom_1.getSelectedBlockElementsInRegion(region);
2371
- var nodes = roosterjs_editor_dom_1.collapseNodesInRegion(region, blocks);
2372
- if (editor.contains(region.rootNode)) {
2373
- // If there are styles on table cell, wrap all its children and move down all non-border styles.
2374
- // So that we can preserve styles for unselected blocks as well as border styles for table
2375
- var nonborderStyles = removeNonBorderStyles(region.rootNode);
2376
- if (Object.keys(nonborderStyles).length > 0) {
2377
- var wrapper = roosterjs_editor_dom_1.wrap(roosterjs_editor_dom_1.toArray(region.rootNode.childNodes));
2378
- roosterjs_editor_dom_1.setStyles(wrapper, nonborderStyles);
2379
- }
2380
- }
2381
- while (nodes.length > 0 && roosterjs_editor_dom_1.isNodeInRegion(region, nodes[0].parentNode)) {
2382
- nodes = [roosterjs_editor_dom_1.splitBalancedNodeRange(nodes)];
2383
- }
2384
- nodes.forEach(clearNodeFormat);
2385
- });
2406
+ function isMultiBlockSelection(editor) {
2407
+ var transverser = editor.getSelectionTraverser();
2408
+ var blockElement = transverser.currentBlockElement;
2409
+ if (!blockElement) {
2410
+ return false;
2411
+ }
2412
+ var nextBlockElement = transverser.getNextBlockElement();
2413
+ //At least two blocks are selected
2414
+ return !!nextBlockElement;
2386
2415
  }
2387
- exports.default = clearBlockFormat;
2388
2416
  function clearNodeFormat(node) {
2389
2417
  // 1. Recursively clear format of all its child nodes
2390
2418
  var areBlockElements = roosterjs_editor_dom_1.toArray(node.childNodes).map(clearNodeFormat);
@@ -2434,36 +2462,50 @@ function removeNonBorderStyles(element) {
2434
2462
  roosterjs_editor_dom_1.setStyles(element, styles);
2435
2463
  return result;
2436
2464
  }
2437
-
2438
-
2439
- /***/ }),
2440
-
2441
- /***/ "./packages/roosterjs-editor-api/lib/format/clearFormat.ts":
2442
- /*!*****************************************************************!*\
2443
- !*** ./packages/roosterjs-editor-api/lib/format/clearFormat.ts ***!
2444
- \*****************************************************************/
2445
- /*! no static exports found */
2446
- /***/ (function(module, exports, __webpack_require__) {
2447
-
2448
- "use strict";
2449
-
2450
- Object.defineProperty(exports, "__esModule", { value: true });
2451
- var execCommand_1 = __webpack_require__(/*! ../utils/execCommand */ "./packages/roosterjs-editor-api/lib/utils/execCommand.ts");
2452
- var setBackgroundColor_1 = __webpack_require__(/*! ./setBackgroundColor */ "./packages/roosterjs-editor-api/lib/format/setBackgroundColor.ts");
2453
- var setFontName_1 = __webpack_require__(/*! ./setFontName */ "./packages/roosterjs-editor-api/lib/format/setFontName.ts");
2454
- var setFontSize_1 = __webpack_require__(/*! ./setFontSize */ "./packages/roosterjs-editor-api/lib/format/setFontSize.ts");
2455
- var setTextColor_1 = __webpack_require__(/*! ./setTextColor */ "./packages/roosterjs-editor-api/lib/format/setTextColor.ts");
2456
- var toggleBold_1 = __webpack_require__(/*! ./toggleBold */ "./packages/roosterjs-editor-api/lib/format/toggleBold.ts");
2457
- var toggleItalic_1 = __webpack_require__(/*! ./toggleItalic */ "./packages/roosterjs-editor-api/lib/format/toggleItalic.ts");
2458
- var toggleUnderline_1 = __webpack_require__(/*! ./toggleUnderline */ "./packages/roosterjs-editor-api/lib/format/toggleUnderline.ts");
2459
- var STYLES_TO_REMOVE = ['font', 'text-decoration', 'color', 'background'];
2460
2465
  /**
2461
- * Clear the format in current selection, after cleaning, the format will be
2462
- * changed to default format. The format that get cleaned include B/I/U/font name/
2463
- * font size/text color/background color/align left/align right/align center/superscript/subscript
2466
+ * Clear the format of the selected text or list of blocks
2467
+ * If the current selection is compose of multiple block elements then remove the text and struture format for all the selected blocks
2468
+ * If the current selection is compose of a partial inline element then only the text format is removed from the current selection
2464
2469
  * @param editor The editor instance
2465
2470
  */
2466
- function clearFormat(editor) {
2471
+ function clearAutoDetectFormat(editor) {
2472
+ var isMultiBlock = isMultiBlockSelection(editor);
2473
+ if (!isMultiBlock) {
2474
+ var transverser = editor.getSelectionTraverser();
2475
+ var inlineElement = transverser.currentInlineElement;
2476
+ var isPartial = inlineElement instanceof roosterjs_editor_dom_1.PartialInlineElement;
2477
+ if (isPartial) {
2478
+ clearFormat(editor);
2479
+ return;
2480
+ }
2481
+ }
2482
+ clearBlockFormat(editor);
2483
+ }
2484
+ /**
2485
+ * Clear all formats of selected blocks.
2486
+ * When selection is collapsed, only clear format of current block.
2487
+ * @param editor The editor instance
2488
+ */
2489
+ function clearBlockFormat(editor) {
2490
+ blockFormat_1.default(editor, function (region) {
2491
+ var blocks = roosterjs_editor_dom_1.getSelectedBlockElementsInRegion(region);
2492
+ var nodes = roosterjs_editor_dom_1.collapseNodesInRegion(region, blocks);
2493
+ if (editor.contains(region.rootNode)) {
2494
+ // If there are styles on table cell, wrap all its children and move down all non-border styles.
2495
+ // So that we can preserve styles for unselected blocks as well as border styles for table
2496
+ var nonborderStyles = removeNonBorderStyles(region.rootNode);
2497
+ if (Object.keys(nonborderStyles).length > 0) {
2498
+ var wrapper = roosterjs_editor_dom_1.wrap(roosterjs_editor_dom_1.toArray(region.rootNode.childNodes));
2499
+ roosterjs_editor_dom_1.setStyles(wrapper, nonborderStyles);
2500
+ }
2501
+ }
2502
+ while (nodes.length > 0 && roosterjs_editor_dom_1.isNodeInRegion(region, nodes[0].parentNode)) {
2503
+ nodes = [roosterjs_editor_dom_1.splitBalancedNodeRange(nodes)];
2504
+ }
2505
+ nodes.forEach(clearNodeFormat);
2506
+ });
2507
+ }
2508
+ function clearInlineFormat(editor) {
2467
2509
  editor.focus();
2468
2510
  editor.addUndoSnapshot(function () {
2469
2511
  execCommand_1.default(editor, "removeFormat" /* RemoveFormat */);
@@ -2488,11 +2530,15 @@ function clearFormat(editor) {
2488
2530
  setFontSize_1.default(editor, defaultFormat.fontSize);
2489
2531
  }
2490
2532
  if (defaultFormat.textColor) {
2533
+ var setColorIgnoredElements_1 = editor.queryElements('a *, a', 1 /* OnSelection */);
2534
+ var shouldApplyInlineStyle = setColorIgnoredElements_1.length > 0
2535
+ ? function (element) { return setColorIgnoredElements_1.indexOf(element) == -1; }
2536
+ : null;
2491
2537
  if (defaultFormat.textColors) {
2492
- setTextColor_1.default(editor, defaultFormat.textColors);
2538
+ setTextColor_1.default(editor, defaultFormat.textColors, shouldApplyInlineStyle);
2493
2539
  }
2494
2540
  else {
2495
- setTextColor_1.default(editor, defaultFormat.textColor);
2541
+ setTextColor_1.default(editor, defaultFormat.textColor, shouldApplyInlineStyle);
2496
2542
  }
2497
2543
  }
2498
2544
  if (defaultFormat.backgroundColor) {
@@ -2515,6 +2561,26 @@ function clearFormat(editor) {
2515
2561
  }
2516
2562
  }, "Format" /* Format */);
2517
2563
  }
2564
+ /**
2565
+ * Clear the format in current selection, after cleaning, the format will be
2566
+ * changed to default format. The format that get cleaned include B/I/U/font name/
2567
+ * font size/text color/background color/align left/align right/align center/superscript/subscript
2568
+ * @param editor The editor instance
2569
+ * @param formatType type of format to apply
2570
+ */
2571
+ function clearFormat(editor, formatType) {
2572
+ if (formatType === void 0) { formatType = 0 /* Inline */; }
2573
+ switch (formatType) {
2574
+ case 0 /* Inline */:
2575
+ clearInlineFormat(editor);
2576
+ break;
2577
+ case 1 /* Block */:
2578
+ clearBlockFormat(editor);
2579
+ break;
2580
+ default:
2581
+ clearAutoDetectFormat(editor);
2582
+ }
2583
+ }
2518
2584
  exports.default = clearFormat;
2519
2585
 
2520
2586
 
@@ -2632,10 +2698,9 @@ function updateAnchorDisplayText(anchor, displayText) {
2632
2698
  }
2633
2699
  function checkXss(link) {
2634
2700
  var sanitizer = new roosterjs_editor_dom_1.HtmlSanitizer();
2635
- var doc = new DOMParser().parseFromString('<a></a>', 'text/html');
2636
- var a = doc.body.firstChild;
2701
+ var a = document.createElement('a');
2637
2702
  a.href = link || '';
2638
- sanitizer.sanitize(doc.body);
2703
+ sanitizer.sanitize(a);
2639
2704
  // We use getAttribute because some browsers will try to make the href property a valid link.
2640
2705
  // This has unintended side effects when the link lacks a protocol.
2641
2706
  return a.getAttribute('href');
@@ -2698,7 +2763,7 @@ exports.getElementBasedFormatState = getElementBasedFormatState;
2698
2763
  * @returns The format state at cursor
2699
2764
  */
2700
2765
  function getFormatState(editor, event) {
2701
- return __assign(__assign(__assign(__assign({}, roosterjs_editor_dom_1.getPendableFormatState(editor.getDocument())), getElementBasedFormatState(editor, event)), editor.getStyleBasedFormatState()), editor.getUndoState());
2766
+ return __assign(__assign(__assign(__assign({}, editor.getPendableFormatState(false /* forceGetStateFromDom */)), getElementBasedFormatState(editor, event)), editor.getStyleBasedFormatState()), editor.getUndoState());
2702
2767
  }
2703
2768
  exports.default = getFormatState;
2704
2769
 
@@ -3041,7 +3106,7 @@ exports.default = setDirection;
3041
3106
  "use strict";
3042
3107
 
3043
3108
  Object.defineProperty(exports, "__esModule", { value: true });
3044
- var applyInlineStyle_1 = __webpack_require__(/*! ../utils/applyInlineStyle */ "./packages/roosterjs-editor-api/lib/utils/applyInlineStyle.ts");
3109
+ var applyListItemWrap_1 = __webpack_require__(/*! ../utils/applyListItemWrap */ "./packages/roosterjs-editor-api/lib/utils/applyListItemWrap.ts");
3045
3110
  /**
3046
3111
  * Set font name at selection
3047
3112
  * @param editor The editor instance
@@ -3049,11 +3114,9 @@ var applyInlineStyle_1 = __webpack_require__(/*! ../utils/applyInlineStyle */ ".
3049
3114
  * Currently there's no validation to the string, if the passed string is invalid, it won't take affect
3050
3115
  */
3051
3116
  function setFontName(editor, fontName) {
3052
- fontName = fontName.trim();
3053
3117
  // The browser provided execCommand creates a HTML <font> tag with face attribute. <font> is not HTML5 standard
3054
- // (http://www.w3schools.com/tags/tag_font.asp). Use applyInlineStyle which gives flexibility on applying inline style
3055
- // for here, we use CSS font-family style
3056
- applyInlineStyle_1.default(editor, function (element, isInnerNode) {
3118
+ // (http://www.w3schools.com/tags/tag_font.asp).
3119
+ applyListItemWrap_1.default(editor, 'font-family', function (element, isInnerNode) {
3057
3120
  element.style.fontFamily = isInnerNode ? '' : fontName;
3058
3121
  });
3059
3122
  }
@@ -3072,7 +3135,7 @@ exports.default = setFontName;
3072
3135
  "use strict";
3073
3136
 
3074
3137
  Object.defineProperty(exports, "__esModule", { value: true });
3075
- var applyInlineStyle_1 = __webpack_require__(/*! ../utils/applyInlineStyle */ "./packages/roosterjs-editor-api/lib/utils/applyInlineStyle.ts");
3138
+ var applyListItemWrap_1 = __webpack_require__(/*! ../utils/applyListItemWrap */ "./packages/roosterjs-editor-api/lib/utils/applyListItemWrap.ts");
3076
3139
  var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
3077
3140
  /**
3078
3141
  * Set font size at selection
@@ -3081,11 +3144,9 @@ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./
3081
3144
  * Currently there's no validation to the string, if the passed string is invalid, it won't take affect
3082
3145
  */
3083
3146
  function setFontSize(editor, fontSize) {
3084
- fontSize = fontSize.trim();
3085
3147
  // The browser provided execCommand only accepts 1-7 point value. In addition, it uses HTML <font> tag with size attribute.
3086
- // <font> is not HTML5 standard (http://www.w3schools.com/tags/tag_font.asp). Use applyInlineStyle which gives flexibility on applying inline style
3087
- // for here, we use CSS font-size style
3088
- applyInlineStyle_1.default(editor, function (element, isInnerNode) {
3148
+ // <font> is not HTML5 standard (http://www.w3schools.com/tags/tag_font.asp).
3149
+ applyListItemWrap_1.default(editor, 'font-size', function (element, isInnerNode) {
3089
3150
  element.style.fontSize = isInnerNode ? '' : fontSize;
3090
3151
  var lineHeight = roosterjs_editor_dom_1.getComputedStyle(element, 'line-height');
3091
3152
  if (lineHeight != 'normal') {
@@ -3142,7 +3203,6 @@ exports.default = setImageAltText;
3142
3203
  Object.defineProperty(exports, "__esModule", { value: true });
3143
3204
  var blockFormat_1 = __webpack_require__(/*! ../utils/blockFormat */ "./packages/roosterjs-editor-api/lib/utils/blockFormat.ts");
3144
3205
  var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
3145
- var BlockWrapper = '<blockquote style="margin-top:0;margin-bottom:0"></blockquote>';
3146
3206
  /**
3147
3207
  * Set indentation at selection
3148
3208
  * If selection contains bullet/numbering list, increase/decrease indentation will
@@ -3177,7 +3237,7 @@ function setIndentation(editor, indentation) {
3177
3237
  exports.default = setIndentation;
3178
3238
  function indent(region, blocks) {
3179
3239
  var nodes = roosterjs_editor_dom_1.collapseNodesInRegion(region, blocks);
3180
- roosterjs_editor_dom_1.wrap(nodes, BlockWrapper);
3240
+ roosterjs_editor_dom_1.wrap(nodes, 2 /* BlockquoteWrapper */);
3181
3241
  }
3182
3242
  function outdent(region, blocks) {
3183
3243
  blocks.forEach(function (blockElement) {
@@ -3198,6 +3258,42 @@ function outdent(region, blocks) {
3198
3258
  }
3199
3259
 
3200
3260
 
3261
+ /***/ }),
3262
+
3263
+ /***/ "./packages/roosterjs-editor-api/lib/format/setOrderedListNumbering.ts":
3264
+ /*!*****************************************************************************!*\
3265
+ !*** ./packages/roosterjs-editor-api/lib/format/setOrderedListNumbering.ts ***!
3266
+ \*****************************************************************************/
3267
+ /*! no static exports found */
3268
+ /***/ (function(module, exports, __webpack_require__) {
3269
+
3270
+ "use strict";
3271
+
3272
+ Object.defineProperty(exports, "__esModule", { value: true });
3273
+ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
3274
+ /**
3275
+ * Resets Ordered List Numbering back to the value of the parameter startNumber
3276
+ * @param editor The editor instance
3277
+ * @param separator The HTML element that indicates when to split the VList
3278
+ * @param startNumber The number of that the splitted list should start
3279
+ */
3280
+ function setOrderedListNumbering(editor, separator, startNumber) {
3281
+ if (startNumber === void 0) { startNumber = 1; }
3282
+ editor.addUndoSnapshot(function () {
3283
+ editor.focus();
3284
+ var regions = editor.getSelectedRegions();
3285
+ if (regions[0]) {
3286
+ var vList = roosterjs_editor_dom_1.createVListFromRegion(regions[0], false /*includeSiblingLists*/, separator);
3287
+ if (vList) {
3288
+ vList.split(separator, startNumber);
3289
+ vList.writeBack();
3290
+ }
3291
+ }
3292
+ }, "Format" /* Format */);
3293
+ }
3294
+ exports.default = setOrderedListNumbering;
3295
+
3296
+
3201
3297
  /***/ }),
3202
3298
 
3203
3299
  /***/ "./packages/roosterjs-editor-api/lib/format/setTextColor.ts":
@@ -3210,7 +3306,7 @@ function outdent(region, blocks) {
3210
3306
  "use strict";
3211
3307
 
3212
3308
  Object.defineProperty(exports, "__esModule", { value: true });
3213
- var applyInlineStyle_1 = __webpack_require__(/*! ../utils/applyInlineStyle */ "./packages/roosterjs-editor-api/lib/utils/applyInlineStyle.ts");
3309
+ var applyListItemWrap_1 = __webpack_require__(/*! ../utils/applyListItemWrap */ "./packages/roosterjs-editor-api/lib/utils/applyListItemWrap.ts");
3214
3310
  var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
3215
3311
  /**
3216
3312
  * Set text color at selection
@@ -3221,10 +3317,13 @@ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./
3221
3317
  * Currently there's no validation to the string, if the passed string is invalid, it won't take affect
3222
3318
  * Alternatively, you can pass a @typedef ModeIndependentColor. If in light mode, the lightModeColor property will be used.
3223
3319
  * If in dark mode, the darkModeColor will be used and the lightModeColor will be used when converting back to light mode.
3320
+ * @param shouldApplyInlineStyle Optional callback function to be invoked to verify if the current element should have the inline Style applied
3224
3321
  */
3225
- function setTextColor(editor, color) {
3226
- applyInlineStyle_1.default(editor, function (element, isInnerNode) {
3227
- roosterjs_editor_dom_1.setColor(element, isInnerNode ? '' : color, false /*isBackground*/, editor.isDarkMode());
3322
+ function setTextColor(editor, color, shouldApplyInlineStyle) {
3323
+ applyListItemWrap_1.default(editor, 'color', function (element, isInnerNode) {
3324
+ if (!shouldApplyInlineStyle || shouldApplyInlineStyle(element)) {
3325
+ roosterjs_editor_dom_1.setColor(element, isInnerNode ? '' : color, false /*isBackground*/, editor.isDarkMode());
3326
+ }
3228
3327
  });
3229
3328
  }
3230
3329
  exports.default = setTextColor;
@@ -3392,9 +3491,7 @@ function toggleHeader(editor, level) {
3392
3491
  wrapped = true;
3393
3492
  }
3394
3493
  var div = editor.getDocument().createElement('div');
3395
- while (header.firstChild) {
3396
- div.appendChild(header.firstChild);
3397
- }
3494
+ roosterjs_editor_dom_1.moveChildNodes(div, header);
3398
3495
  editor.replaceNode(header, div);
3399
3496
  });
3400
3497
  if (level > 0) {
@@ -3650,6 +3747,8 @@ var toggleItalic_1 = __webpack_require__(/*! ./format/toggleItalic */ "./package
3650
3747
  exports.toggleItalic = toggleItalic_1.default;
3651
3748
  var toggleNumbering_1 = __webpack_require__(/*! ./format/toggleNumbering */ "./packages/roosterjs-editor-api/lib/format/toggleNumbering.ts");
3652
3749
  exports.toggleNumbering = toggleNumbering_1.default;
3750
+ var setOrderedListNumbering_1 = __webpack_require__(/*! ./format/setOrderedListNumbering */ "./packages/roosterjs-editor-api/lib/format/setOrderedListNumbering.ts");
3751
+ exports.setOrderedListNumbering = setOrderedListNumbering_1.default;
3653
3752
  var toggleBlockQuote_1 = __webpack_require__(/*! ./format/toggleBlockQuote */ "./packages/roosterjs-editor-api/lib/format/toggleBlockQuote.ts");
3654
3753
  exports.toggleBlockQuote = toggleBlockQuote_1.default;
3655
3754
  var toggleCodeBlock_1 = __webpack_require__(/*! ./format/toggleCodeBlock */ "./packages/roosterjs-editor-api/lib/format/toggleCodeBlock.ts");
@@ -3664,6 +3763,10 @@ var toggleUnderline_1 = __webpack_require__(/*! ./format/toggleUnderline */ "./p
3664
3763
  exports.toggleUnderline = toggleUnderline_1.default;
3665
3764
  var toggleHeader_1 = __webpack_require__(/*! ./format/toggleHeader */ "./packages/roosterjs-editor-api/lib/format/toggleHeader.ts");
3666
3765
  exports.toggleHeader = toggleHeader_1.default;
3766
+ var toggleListType_1 = __webpack_require__(/*! ./utils/toggleListType */ "./packages/roosterjs-editor-api/lib/utils/toggleListType.ts");
3767
+ exports.toggleListType = toggleListType_1.default;
3768
+ var blockFormat_1 = __webpack_require__(/*! ./utils/blockFormat */ "./packages/roosterjs-editor-api/lib/utils/blockFormat.ts");
3769
+ exports.blockFormat = blockFormat_1.default;
3667
3770
  var experimentCommitListChains_1 = __webpack_require__(/*! ./experiment/experimentCommitListChains */ "./packages/roosterjs-editor-api/lib/experiment/experimentCommitListChains.ts");
3668
3771
  exports.experimentCommitListChains = experimentCommitListChains_1.default;
3669
3772
 
@@ -3905,6 +4008,54 @@ function applyInlineStyle(editor, callback) {
3905
4008
  exports.default = applyInlineStyle;
3906
4009
 
3907
4010
 
4011
+ /***/ }),
4012
+
4013
+ /***/ "./packages/roosterjs-editor-api/lib/utils/applyListItemWrap.ts":
4014
+ /*!**********************************************************************!*\
4015
+ !*** ./packages/roosterjs-editor-api/lib/utils/applyListItemWrap.ts ***!
4016
+ \**********************************************************************/
4017
+ /*! no static exports found */
4018
+ /***/ (function(module, exports, __webpack_require__) {
4019
+
4020
+ "use strict";
4021
+
4022
+ Object.defineProperty(exports, "__esModule", { value: true });
4023
+ var applyInlineStyle_1 = __webpack_require__(/*! ../utils/applyInlineStyle */ "./packages/roosterjs-editor-api/lib/utils/applyInlineStyle.ts");
4024
+ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
4025
+ /**
4026
+ * @internal
4027
+ * Set the List Item Style when all inner inline element have the same style
4028
+ * @param editor The editor instance
4029
+ * @param styleName Name of the style to apply to the list item
4030
+ * @param formatCallback callback to apply the style to each element
4031
+ */
4032
+ function applyListItemStyleWrap(editor, styleName, formatCallback) {
4033
+ var parentNodes = [];
4034
+ applyInlineStyle_1.default(editor, function (element, isInnerNode) {
4035
+ formatCallback(element, isInnerNode);
4036
+ var parent = editor.getElementAtCursor('LI', element);
4037
+ if (parent && parentNodes.indexOf(parent) === -1) {
4038
+ parentNodes.push(parent);
4039
+ }
4040
+ });
4041
+ applyStyleToListItems(parentNodes, [styleName]);
4042
+ }
4043
+ exports.default = applyListItemStyleWrap;
4044
+ /**
4045
+ * @internal
4046
+ * Checks if the parent element is a List Item, if it is, apply the style elements to the list item
4047
+ * @param parentNodes parentNodes to apply the style
4048
+ * @param styles styles to apply to the List Item Element
4049
+ */
4050
+ function applyStyleToListItems(parentNodes, styles) {
4051
+ parentNodes.forEach(function (node) {
4052
+ if (roosterjs_editor_dom_1.safeInstanceOf(node, 'HTMLLIElement')) {
4053
+ roosterjs_editor_dom_1.setListItemStyle(node, styles);
4054
+ }
4055
+ });
4056
+ }
4057
+
4058
+
3908
4059
  /***/ }),
3909
4060
 
3910
4061
  /***/ "./packages/roosterjs-editor-api/lib/utils/blockFormat.ts":
@@ -3920,7 +4071,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3920
4071
  var experimentCommitListChains_1 = __webpack_require__(/*! ../experiment/experimentCommitListChains */ "./packages/roosterjs-editor-api/lib/experiment/experimentCommitListChains.ts");
3921
4072
  var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
3922
4073
  /**
3923
- * @internal
3924
4074
  * Split selection into regions, and perform a block-wise formatting action for each region.
3925
4075
  */
3926
4076
  function blockFormat(editor, callback, beforeRunCallback) {
@@ -4043,7 +4193,6 @@ function isEmptyBlockUnderTR(block) {
4043
4193
 
4044
4194
  Object.defineProperty(exports, "__esModule", { value: true });
4045
4195
  var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
4046
- var pendableFormatCommands = null;
4047
4196
  /**
4048
4197
  * @internal
4049
4198
  * Execute a document command
@@ -4060,11 +4209,13 @@ function execCommand(editor, command) {
4060
4209
  var range = editor.getSelectionRange();
4061
4210
  if (range && range.collapsed) {
4062
4211
  editor.addUndoSnapshot();
4212
+ var formatState = editor.getPendableFormatState(false /* forceGetStateFromDom */);
4063
4213
  formatter();
4064
- if (isPendableFormatCommand(command)) {
4065
- // Trigger PendingFormatStateChanged event since we changed pending format state
4214
+ var formatName = Object.keys(roosterjs_editor_dom_1.PendableFormatCommandMap).filter(function (x) { return roosterjs_editor_dom_1.PendableFormatCommandMap[x] == command; })[0];
4215
+ if (formatName) {
4216
+ formatState[formatName] = !formatState[formatName];
4066
4217
  editor.triggerPluginEvent(13 /* PendingFormatStateChanged */, {
4067
- formatState: roosterjs_editor_dom_1.getPendableFormatState(editor.getDocument()),
4218
+ formatState: formatState,
4068
4219
  });
4069
4220
  }
4070
4221
  }
@@ -4073,12 +4224,6 @@ function execCommand(editor, command) {
4073
4224
  }
4074
4225
  }
4075
4226
  exports.default = execCommand;
4076
- function isPendableFormatCommand(command) {
4077
- if (!pendableFormatCommands) {
4078
- pendableFormatCommands = Object.keys(roosterjs_editor_dom_1.PendableFormatCommandMap).map(function (key) { return roosterjs_editor_dom_1.PendableFormatCommandMap[key]; });
4079
- }
4080
- return pendableFormatCommands.indexOf(command) >= 0;
4081
- }
4082
4227
 
4083
4228
 
4084
4229
  /***/ }),
@@ -4095,13 +4240,31 @@ function isPendableFormatCommand(command) {
4095
4240
  Object.defineProperty(exports, "__esModule", { value: true });
4096
4241
  var blockFormat_1 = __webpack_require__(/*! ../utils/blockFormat */ "./packages/roosterjs-editor-api/lib/utils/blockFormat.ts");
4097
4242
  var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
4098
- function toggleListType(editor, listType, startNumber) {
4243
+ /**
4244
+ * Toggle List Type at selection
4245
+ * If ListType Provided is Ordered:
4246
+ * If selection contains numbering in deep level, toggle numbering will decrease the numbering level by one
4247
+ * If selection contains bullet list, toggle numbering will convert the bullet list into number list
4248
+ * If selection contains both bullet/numbering and normal text, the behavior is decided by corresponding
4249
+ * realization of browser execCommand API
4250
+ * If ListType Provided is Unordered:
4251
+ * If selection contains bullet in deep level, toggle bullet will decrease the bullet level by one
4252
+ * If selection contains number list, toggle bullet will convert the number list into bullet list
4253
+ * If selection contains both bullet/numbering and normal text, the behavior is decided by corresponding
4254
+ * browser execCommand API
4255
+ * @param editor The editor instance
4256
+ * @param listType The list type to toggle
4257
+ * @param startNumber (Optional) Start number of the list
4258
+ * @param includeSiblingLists Sets wether the operation should include Sibling Lists, by default true
4259
+ */
4260
+ function toggleListType(editor, listType, startNumber, includeSiblingLists) {
4261
+ if (includeSiblingLists === void 0) { includeSiblingLists = true; }
4099
4262
  blockFormat_1.default(editor, function (region, start, end, chains) {
4100
4263
  var _a;
4101
4264
  var chain = startNumber > 0 && chains.filter(function (chain) { return chain.canAppendAtCursor(startNumber); })[0];
4102
4265
  var vList = chain && start.equalTo(end)
4103
4266
  ? chain.createVListAtBlock((_a = roosterjs_editor_dom_1.getBlockElementAtNode(region.rootNode, start.node)) === null || _a === void 0 ? void 0 : _a.collapseToSingleElement(), startNumber)
4104
- : roosterjs_editor_dom_1.createVListFromRegion(region, true /*includeSiblingLists*/);
4267
+ : roosterjs_editor_dom_1.createVListFromRegion(region, includeSiblingLists);
4105
4268
  if (vList) {
4106
4269
  vList.changeListType(start, end, listType);
4107
4270
  vList.writeBack();
@@ -4255,6 +4418,7 @@ var createPasteFragment_1 = __webpack_require__(/*! ./createPasteFragment */ "./
4255
4418
  var ensureTypeInContainer_1 = __webpack_require__(/*! ./ensureTypeInContainer */ "./packages/roosterjs-editor-core/lib/coreApi/ensureTypeInContainer.ts");
4256
4419
  var focus_1 = __webpack_require__(/*! ./focus */ "./packages/roosterjs-editor-core/lib/coreApi/focus.ts");
4257
4420
  var getContent_1 = __webpack_require__(/*! ./getContent */ "./packages/roosterjs-editor-core/lib/coreApi/getContent.ts");
4421
+ var getPendableFormatState_1 = __webpack_require__(/*! ./getPendableFormatState */ "./packages/roosterjs-editor-core/lib/coreApi/getPendableFormatState.ts");
4258
4422
  var getSelectionRange_1 = __webpack_require__(/*! ./getSelectionRange */ "./packages/roosterjs-editor-core/lib/coreApi/getSelectionRange.ts");
4259
4423
  var getStyleBasedFormatState_1 = __webpack_require__(/*! ./getStyleBasedFormatState */ "./packages/roosterjs-editor-core/lib/coreApi/getStyleBasedFormatState.ts");
4260
4424
  var hasFocus_1 = __webpack_require__(/*! ./hasFocus */ "./packages/roosterjs-editor-core/lib/coreApi/hasFocus.ts");
@@ -4277,6 +4441,7 @@ exports.coreApiMap = {
4277
4441
  getContent: getContent_1.getContent,
4278
4442
  getSelectionRange: getSelectionRange_1.getSelectionRange,
4279
4443
  getStyleBasedFormatState: getStyleBasedFormatState_1.getStyleBasedFormatState,
4444
+ getPendableFormatState: getPendableFormatState_1.getPendableFormatState,
4280
4445
  hasFocus: hasFocus_1.hasFocus,
4281
4446
  insertNode: insertNode_1.insertNode,
4282
4447
  restoreUndoSnapshot: restoreUndoSnapshot_1.restoreUndoSnapshot,
@@ -4325,17 +4490,8 @@ exports.createPasteFragment = function (core, clipboardData, position, pasteAsTe
4325
4490
  var rawHtml = clipboardData.rawHtml, text = clipboardData.text, imageDataUri = clipboardData.imageDataUri;
4326
4491
  var document = core.contentDiv.ownerDocument;
4327
4492
  var doc;
4328
- // Step 2: Fill the BeforePasteEvent object, especially the fragment for paste
4329
- if (!pasteAsText && !text && imageDataUri) {
4330
- // Paste image
4331
- var img = document.createElement('img');
4332
- img.style.maxWidth = '100%';
4333
- img.src = imageDataUri;
4334
- fragment.appendChild(img);
4335
- }
4336
- else if (!pasteAsText &&
4337
- rawHtml && ((_a = (doc = new DOMParser().parseFromString(rawHtml, 'text/html'))) === null || _a === void 0 ? void 0 : _a.body)) {
4338
- // Paste HTML
4493
+ // Step 2: Retrieve Metadata from Html and the Html that was copied.
4494
+ if (rawHtml && ((_a = (doc = new DOMParser().parseFromString(core.trustedHTMLHandler(rawHtml), 'text/html'))) === null || _a === void 0 ? void 0 : _a.body)) {
4339
4495
  var attributes = (_b = doc.querySelector('html')) === null || _b === void 0 ? void 0 : _b.attributes;
4340
4496
  (attributes ? roosterjs_editor_dom_1.toArray(attributes) : []).reduce(function (attrs, attr) {
4341
4497
  attrs[attr.name] = attr.value;
@@ -4345,6 +4501,10 @@ exports.createPasteFragment = function (core, clipboardData, position, pasteAsTe
4345
4501
  attrs[meta.name] = meta.content;
4346
4502
  return attrs;
4347
4503
  }, event.htmlAttributes);
4504
+ clipboardData.htmlFirstLevelChildTags = [];
4505
+ doc === null || doc === void 0 ? void 0 : doc.body.childNodes.forEach(function (node) {
4506
+ return clipboardData.htmlFirstLevelChildTags.push(roosterjs_editor_dom_1.getTagOfNode(node));
4507
+ });
4348
4508
  // Move all STYLE nodes into header, and save them into sanitizing options.
4349
4509
  // Because if we directly move them into a fragment, all sheets under STYLE will be lost.
4350
4510
  processStyles(doc, function (style) {
@@ -4356,16 +4516,25 @@ exports.createPasteFragment = function (core, clipboardData, position, pasteAsTe
4356
4516
  if (startIndex >= 0 && endIndex >= startIndex + START_FRAGMENT.length) {
4357
4517
  event.htmlBefore = rawHtml.substr(0, startIndex);
4358
4518
  event.htmlAfter = rawHtml.substr(endIndex + END_FRAGMENT.length);
4359
- doc.body.innerHTML = clipboardData.html = rawHtml.substring(startIndex + START_FRAGMENT.length, endIndex);
4519
+ clipboardData.html = rawHtml.substring(startIndex + START_FRAGMENT.length, endIndex);
4520
+ doc.body.innerHTML = core.trustedHTMLHandler(clipboardData.html);
4360
4521
  // Remove style nodes just added by setting innerHTML of body since we already have all
4361
4522
  // style nodes in header.
4362
4523
  // Here we use doc.body instead of doc because we only want to remove STYLE nodes under BODY
4363
4524
  // and the nodes under HEAD are still used when convert global CSS to inline
4364
4525
  processStyles(doc.body, function (style) { var _a; return (_a = style.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(style); });
4365
4526
  }
4366
- while (doc.body.firstChild) {
4367
- fragment.appendChild(doc.body.firstChild);
4368
- }
4527
+ }
4528
+ // Step 3: Fill the BeforePasteEvent object, especially the fragment for paste
4529
+ if (!pasteAsText && !text && imageDataUri) {
4530
+ // Paste image
4531
+ var img = document.createElement('img');
4532
+ img.style.maxWidth = '100%';
4533
+ img.src = imageDataUri;
4534
+ fragment.appendChild(img);
4535
+ }
4536
+ else if (!pasteAsText && rawHtml && doc ? doc.body : false) {
4537
+ roosterjs_editor_dom_1.moveChildNodes(fragment, doc.body);
4369
4538
  if (applyCurrentStyle && position) {
4370
4539
  var format_1 = getCurrentFormat(core, position.node);
4371
4540
  roosterjs_editor_dom_1.applyTextStyle(fragment, function (node) { return roosterjs_editor_dom_1.applyFormat(node, format_1); });
@@ -4398,16 +4567,16 @@ exports.createPasteFragment = function (core, clipboardData, position, pasteAsTe
4398
4567
  }
4399
4568
  });
4400
4569
  }
4401
- // Step 3: Trigger BeforePasteEvent so that plugins can do proper change before paste
4570
+ // Step 4: Trigger BeforePasteEvent so that plugins can do proper change before paste
4402
4571
  core.api.triggerEvent(core, event, true /*broadcast*/);
4403
- // Step 4. Sanitize the fragment before paste to make sure the content is safe
4572
+ // Step 5. Sanitize the fragment before paste to make sure the content is safe
4404
4573
  var sanitizer = new roosterjs_editor_dom_1.HtmlSanitizer(event.sanitizingOption);
4405
4574
  sanitizer.convertGlobalCssToInlineCss(fragment);
4406
4575
  sanitizer.sanitize(fragment, position && roosterjs_editor_dom_1.getInheritableStyles(position.element));
4407
4576
  return fragment;
4408
4577
  };
4409
4578
  function getCurrentFormat(core, node) {
4410
- var pendableFormat = roosterjs_editor_dom_1.getPendableFormatState(core.contentDiv.ownerDocument);
4579
+ var pendableFormat = core.api.getPendableFormatState(core, true /** forceGetStateFromDOM*/);
4411
4580
  var styleBasedFormat = core.api.getStyleBasedFormatState(core, node);
4412
4581
  return {
4413
4582
  fontFamily: styleBasedFormat.fontName,
@@ -4472,7 +4641,7 @@ exports.ensureTypeInContainer = function (core, position, keyboardEvent) {
4472
4641
  // Only reason we don't get the selection block is that we have an empty content div
4473
4642
  // which can happen when users removes everything (i.e. select all and DEL, or backspace from very end to begin)
4474
4643
  // The fix is to add a DIV wrapping, apply default format and move cursor over
4475
- formatNode = roosterjs_editor_dom_1.fromHtml(roosterjs_editor_dom_1.Browser.isEdge ? '<div><span><br></span></div>' : '<div><br></div>', core.contentDiv.ownerDocument)[0];
4644
+ formatNode = roosterjs_editor_dom_1.createElement(1 /* EmptyLine */, core.contentDiv.ownerDocument);
4476
4645
  core.api.insertNode(core, formatNode, {
4477
4646
  position: 1 /* End */,
4478
4647
  updateCursor: false,
@@ -4620,6 +4789,98 @@ function cloneNode(node) {
4620
4789
  }
4621
4790
 
4622
4791
 
4792
+ /***/ }),
4793
+
4794
+ /***/ "./packages/roosterjs-editor-core/lib/coreApi/getPendableFormatState.ts":
4795
+ /*!******************************************************************************!*\
4796
+ !*** ./packages/roosterjs-editor-core/lib/coreApi/getPendableFormatState.ts ***!
4797
+ \******************************************************************************/
4798
+ /*! no static exports found */
4799
+ /***/ (function(module, exports, __webpack_require__) {
4800
+
4801
+ "use strict";
4802
+
4803
+ Object.defineProperty(exports, "__esModule", { value: true });
4804
+ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
4805
+ /**
4806
+ * @internal
4807
+ * @param core The EditorCore object
4808
+ * @param forceGetStateFromDOM If set to true, will force get the format state from DOM tree.
4809
+ * @returns The cached format state if it exists. If the cached postion do not exist, search for pendable elements in the DOM tree and return the pendable format state.
4810
+ */
4811
+ exports.getPendableFormatState = function (core, forceGetStateFromDOM) {
4812
+ var _a;
4813
+ var range = core.api.getSelectionRange(core, true /* tryGetFromCache*/);
4814
+ var cachedPendableFormatState = core.pendingFormatState.pendableFormatState;
4815
+ var cachedPosition = (_a = core.pendingFormatState.pendableFormatPosition) === null || _a === void 0 ? void 0 : _a.normalize();
4816
+ var currentPosition = range && roosterjs_editor_dom_1.Position.getStart(range).normalize();
4817
+ var isSamePosition = currentPosition && range.collapsed && currentPosition.equalTo(cachedPosition);
4818
+ if (range && cachedPendableFormatState && isSamePosition && !forceGetStateFromDOM) {
4819
+ return cachedPendableFormatState;
4820
+ }
4821
+ else {
4822
+ return currentPosition ? queryCommandStateFromDOM(core, currentPosition) : {};
4823
+ }
4824
+ };
4825
+ var PendableStyleCheckers = {
4826
+ isBold: function (tag, style) {
4827
+ return tag == 'B' ||
4828
+ tag == 'STRONG' ||
4829
+ parseInt(style.fontWeight) >= 700 ||
4830
+ ['bold', 'bolder'].indexOf(style.fontWeight) >= 0;
4831
+ },
4832
+ isUnderline: function (tag, style) { return tag == 'U' || style.textDecoration.indexOf('underline') >= 0; },
4833
+ isItalic: function (tag, style) { return tag == 'I' || tag == 'EM' || style.fontStyle === 'italic'; },
4834
+ isSubscript: function (tag, style) { return tag == 'SUB' || style.verticalAlign === 'sub'; },
4835
+ isSuperscript: function (tag, style) { return tag == 'SUP' || style.verticalAlign === 'super'; },
4836
+ isStrikeThrough: function (tag, style) {
4837
+ return tag == 'S' || tag == 'STRIKE' || style.textDecoration.indexOf('line-through') >= 0;
4838
+ },
4839
+ };
4840
+ /**
4841
+ * CssFalsyCheckers checks for non pendable format that might overlay a pendable format, then it can prevent getPendableFormatState return falsy pendable format states.
4842
+ */
4843
+ var CssFalsyCheckers = {
4844
+ isBold: function (style) {
4845
+ return (style.fontWeight !== '' && parseInt(style.fontWeight) < 700) ||
4846
+ style.fontWeight === 'normal';
4847
+ },
4848
+ isUnderline: function (style) {
4849
+ return style.textDecoration !== '' && style.textDecoration.indexOf('underline') < 0;
4850
+ },
4851
+ isItalic: function (style) { return style.fontStyle !== '' && style.fontStyle !== 'italic'; },
4852
+ isSubscript: function (style) { return style.verticalAlign !== '' && style.verticalAlign !== 'sub'; },
4853
+ isSuperscript: function (style) { return style.verticalAlign !== '' && style.verticalAlign !== 'super'; },
4854
+ isStrikeThrough: function (style) {
4855
+ return style.textDecoration !== '' && style.textDecoration.indexOf('line-through') < 0;
4856
+ },
4857
+ };
4858
+ function queryCommandStateFromDOM(core, currentPosition) {
4859
+ var node = currentPosition.node;
4860
+ var formatState = {};
4861
+ var pendablekeys = [];
4862
+ var _loop_1 = function () {
4863
+ var tag = roosterjs_editor_dom_1.getTagOfNode(node);
4864
+ var style = node.nodeType == 1 /* Element */ && node.style;
4865
+ if (tag && style) {
4866
+ Object.keys(PendableStyleCheckers).forEach(function (key) {
4867
+ if (!(pendablekeys.indexOf(key) >= 0)) {
4868
+ formatState[key] = formatState[key] || PendableStyleCheckers[key](tag, style);
4869
+ if (CssFalsyCheckers[key](style)) {
4870
+ pendablekeys.push(key);
4871
+ }
4872
+ }
4873
+ });
4874
+ }
4875
+ node = node.parentNode;
4876
+ };
4877
+ while (roosterjs_editor_dom_1.contains(core.contentDiv, node)) {
4878
+ _loop_1();
4879
+ }
4880
+ return formatState;
4881
+ }
4882
+
4883
+
4623
4884
  /***/ }),
4624
4885
 
4625
4886
  /***/ "./packages/roosterjs-editor-core/lib/coreApi/getSelectionRange.ts":
@@ -4758,7 +5019,6 @@ exports.hasFocus = function (core) {
4758
5019
 
4759
5020
  Object.defineProperty(exports, "__esModule", { value: true });
4760
5021
  var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
4761
- var adjustSteps = [handleHyperLink, handleStructuredNode, handleParagraph, handleVoidElement];
4762
5022
  function getInitialRange(core, option) {
4763
5023
  // Selection start replaces based on the current selection.
4764
5024
  // Range inserts based on a provided range.
@@ -4860,19 +5120,17 @@ exports.insertNode = function (core, node, option) {
4860
5120
  if (option.replaceSelection && !range.collapsed) {
4861
5121
  range.deleteContents();
4862
5122
  }
4863
- var pos_1 = roosterjs_editor_dom_1.Position.getStart(range);
5123
+ var pos = roosterjs_editor_dom_1.Position.getStart(range);
4864
5124
  var blockElement = void 0;
4865
5125
  if (option.insertOnNewLine &&
4866
- (blockElement = roosterjs_editor_dom_1.getBlockElementAtNode(contentDiv, pos_1.normalize().node))) {
4867
- pos_1 = new roosterjs_editor_dom_1.Position(blockElement.getEndNode(), -3 /* After */);
5126
+ (blockElement = roosterjs_editor_dom_1.getBlockElementAtNode(contentDiv, pos.normalize().node))) {
5127
+ pos = new roosterjs_editor_dom_1.Position(blockElement.getEndNode(), -3 /* After */);
4868
5128
  }
4869
5129
  else {
4870
- adjustSteps.forEach(function (handler) {
4871
- pos_1 = handler(contentDiv, node, pos_1);
4872
- });
5130
+ pos = roosterjs_editor_dom_1.adjustInsertPosition(contentDiv, node, pos, range);
4873
5131
  }
4874
5132
  var nodeForCursor = node.nodeType == 11 /* DocumentFragment */ ? node.lastChild : node;
4875
- range = roosterjs_editor_dom_1.createRange(pos_1);
5133
+ range = roosterjs_editor_dom_1.createRange(pos);
4876
5134
  range.insertNode(node);
4877
5135
  if (option.updateCursor && nodeForCursor) {
4878
5136
  rangeToRestore = roosterjs_editor_dom_1.createRange(new roosterjs_editor_dom_1.Position(nodeForCursor, -3 /* After */).normalize());
@@ -4883,115 +5141,6 @@ exports.insertNode = function (core, node, option) {
4883
5141
  }, 0 /* LightToDark */);
4884
5142
  return true;
4885
5143
  };
4886
- function handleHyperLink(root, nodeToInsert, position) {
4887
- var blockElement = roosterjs_editor_dom_1.getBlockElementAtNode(root, position.node);
4888
- if (blockElement) {
4889
- // Find the first <A> tag within current block which covers current selection
4890
- // If there are more than one nested, let's handle the first one only since that is not a common scenario.
4891
- var anchor = roosterjs_editor_dom_1.queryElements(root, 'a[href]', null /*forEachCallback*/, 1 /* OnSelection */, roosterjs_editor_dom_1.createRange(position)).filter(function (a) { return blockElement.contains(a); })[0];
4892
- // If this is about to insert node to an empty A tag, clear the A tag and reset position
4893
- if (anchor && roosterjs_editor_dom_1.isNodeEmpty(anchor)) {
4894
- position = new roosterjs_editor_dom_1.Position(anchor, -2 /* Before */);
4895
- safeRemove(anchor);
4896
- anchor = null;
4897
- }
4898
- // If this is about to insert nodes which contains A tag into another A tag, need to break current A tag
4899
- // otherwise we will have nested A tags which is a wrong HTML structure
4900
- if (anchor &&
4901
- nodeToInsert.querySelector &&
4902
- nodeToInsert.querySelector('a[href]')) {
4903
- var normalizedPosition = position.normalize();
4904
- var parentNode = normalizedPosition.node.parentNode;
4905
- var nextNode = normalizedPosition.node.nodeType == 3 /* Text */
4906
- ? roosterjs_editor_dom_1.splitTextNode(normalizedPosition.node, normalizedPosition.offset, false /*returnFirstPart*/)
4907
- : normalizedPosition.isAtEnd
4908
- ? normalizedPosition.node.nextSibling
4909
- : normalizedPosition.node;
4910
- var splitter = root.ownerDocument.createTextNode('');
4911
- parentNode.insertBefore(splitter, nextNode);
4912
- while (roosterjs_editor_dom_1.contains(anchor, splitter)) {
4913
- splitter = roosterjs_editor_dom_1.splitBalancedNodeRange(splitter);
4914
- }
4915
- position = new roosterjs_editor_dom_1.Position(splitter, -2 /* Before */);
4916
- safeRemove(splitter);
4917
- }
4918
- }
4919
- return position;
4920
- }
4921
- function handleStructuredNode(root, nodeToInsert, position) {
4922
- var rootNodeToInsert = nodeToInsert;
4923
- if (rootNodeToInsert.nodeType == 11 /* DocumentFragment */) {
4924
- var rootNodes = roosterjs_editor_dom_1.toArray(rootNodeToInsert.childNodes).filter(function (n) { return roosterjs_editor_dom_1.getTagOfNode(n) != 'BR'; });
4925
- rootNodeToInsert = rootNodes.length == 1 ? rootNodes[0] : null;
4926
- }
4927
- var tag = roosterjs_editor_dom_1.getTagOfNode(rootNodeToInsert);
4928
- var hasBrNextToRoot = tag && roosterjs_editor_dom_1.getTagOfNode(rootNodeToInsert.nextSibling) == 'BR';
4929
- var listItem = roosterjs_editor_dom_1.findClosestElementAncestor(position.node, root, 'LI');
4930
- var listNode = listItem && roosterjs_editor_dom_1.findClosestElementAncestor(listItem, root, 'OL,UL');
4931
- var tdNode = roosterjs_editor_dom_1.findClosestElementAncestor(position.node, root, 'TD,TH');
4932
- var trNode = tdNode && roosterjs_editor_dom_1.findClosestElementAncestor(tdNode, root, 'TR');
4933
- if (tag == 'LI') {
4934
- tag = listNode ? roosterjs_editor_dom_1.getTagOfNode(listNode) : 'UL';
4935
- rootNodeToInsert = roosterjs_editor_dom_1.wrap(rootNodeToInsert, tag);
4936
- }
4937
- if ((tag == 'OL' || tag == 'UL') && roosterjs_editor_dom_1.getTagOfNode(rootNodeToInsert.firstChild) == 'LI') {
4938
- var shouldInsertListAsText = !rootNodeToInsert.firstChild.nextSibling && !hasBrNextToRoot;
4939
- if (hasBrNextToRoot && rootNodeToInsert.parentNode) {
4940
- safeRemove(rootNodeToInsert.nextSibling);
4941
- }
4942
- if (shouldInsertListAsText) {
4943
- roosterjs_editor_dom_1.unwrap(rootNodeToInsert.firstChild);
4944
- roosterjs_editor_dom_1.unwrap(rootNodeToInsert);
4945
- }
4946
- else if (roosterjs_editor_dom_1.getTagOfNode(listNode) == tag) {
4947
- roosterjs_editor_dom_1.unwrap(rootNodeToInsert);
4948
- position = new roosterjs_editor_dom_1.Position(listItem, roosterjs_editor_dom_1.isPositionAtBeginningOf(position, listItem)
4949
- ? -2 /* Before */
4950
- : -3 /* After */);
4951
- }
4952
- }
4953
- else if (tag == 'TABLE' && trNode) {
4954
- // When inserting a table into a table, if these tables have the same column count, and
4955
- // current position is at beginning of a row, then merge these two tables
4956
- var newTable = new roosterjs_editor_dom_1.VTable(rootNodeToInsert);
4957
- var currentTable = new roosterjs_editor_dom_1.VTable(tdNode);
4958
- if (currentTable.col == 0 &&
4959
- tdNode == currentTable.getCell(currentTable.row, 0).td &&
4960
- newTable.cells[0] &&
4961
- newTable.cells[0].length == currentTable.cells[0].length &&
4962
- roosterjs_editor_dom_1.isPositionAtBeginningOf(position, tdNode)) {
4963
- if (roosterjs_editor_dom_1.getTagOfNode(rootNodeToInsert.firstChild) == 'TBODY' &&
4964
- !rootNodeToInsert.firstChild.nextSibling) {
4965
- roosterjs_editor_dom_1.unwrap(rootNodeToInsert.firstChild);
4966
- }
4967
- roosterjs_editor_dom_1.unwrap(rootNodeToInsert);
4968
- position = new roosterjs_editor_dom_1.Position(trNode, -3 /* After */);
4969
- }
4970
- }
4971
- return position;
4972
- }
4973
- function handleParagraph(root, nodeToInsert, position) {
4974
- if (roosterjs_editor_dom_1.getTagOfNode(position.node) == 'P') {
4975
- // Insert into a P tag may cause issues when the inserted content contains any block element.
4976
- // Change P tag to DIV to make sure it works well
4977
- var pos = position.normalize();
4978
- var div = roosterjs_editor_dom_1.changeElementTag(position.node, 'div');
4979
- if (pos.node != div) {
4980
- position = pos;
4981
- }
4982
- }
4983
- return position;
4984
- }
4985
- function handleVoidElement(root, nodeToInsert, position) {
4986
- if (roosterjs_editor_dom_1.isVoidHtmlElement(position.node)) {
4987
- position = new roosterjs_editor_dom_1.Position(position.node, position.isAtEnd ? -3 /* After */ : -2 /* Before */);
4988
- }
4989
- return position;
4990
- }
4991
- function safeRemove(node) {
4992
- var _a;
4993
- (_a = node === null || node === void 0 ? void 0 : node.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(node);
4994
- }
4995
5144
 
4996
5145
 
4997
5146
  /***/ }),
@@ -5112,7 +5261,11 @@ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./
5112
5261
  exports.setContent = function (core, content, triggerContentChangedEvent) {
5113
5262
  var contentChanged = false;
5114
5263
  if (core.contentDiv.innerHTML != content) {
5115
- var range = roosterjs_editor_dom_1.setHtmlWithSelectionPath(core.contentDiv, content);
5264
+ core.api.triggerEvent(core, {
5265
+ eventType: 20 /* BeforeSetContent */,
5266
+ newContent: content,
5267
+ }, true /*broadcast*/);
5268
+ var range = roosterjs_editor_dom_1.setHtmlWithSelectionPath(core.contentDiv, content, core.trustedHTMLHandler);
5116
5269
  core.api.selectRange(core, range);
5117
5270
  contentChanged = true;
5118
5271
  }
@@ -5152,9 +5305,7 @@ exports.switchShadowEdit = function (core, isOn) {
5152
5305
  var range = core.api.getSelectionRange(core, true /*tryGetFromCache*/);
5153
5306
  shadowEditSelectionPath = range && roosterjs_editor_dom_1.getSelectionPath(contentDiv, range);
5154
5307
  shadowEditFragment = core.contentDiv.ownerDocument.createDocumentFragment();
5155
- while (contentDiv.firstChild) {
5156
- shadowEditFragment.appendChild(contentDiv.firstChild);
5157
- }
5308
+ roosterjs_editor_dom_1.moveChildNodes(shadowEditFragment, contentDiv);
5158
5309
  shadowEditFragment.normalize();
5159
5310
  core.api.triggerEvent(core, {
5160
5311
  eventType: 17 /* EnteredShadowEdit */,
@@ -5164,7 +5315,7 @@ exports.switchShadowEdit = function (core, isOn) {
5164
5315
  lifecycle.shadowEditFragment = shadowEditFragment;
5165
5316
  lifecycle.shadowEditSelectionPath = shadowEditSelectionPath;
5166
5317
  }
5167
- contentDiv.innerHTML = '';
5318
+ roosterjs_editor_dom_1.moveChildNodes(contentDiv);
5168
5319
  contentDiv.appendChild(lifecycle.shadowEditFragment.cloneNode(true /*deep*/));
5169
5320
  }
5170
5321
  else {
@@ -5174,7 +5325,7 @@ exports.switchShadowEdit = function (core, isOn) {
5174
5325
  core.api.triggerEvent(core, {
5175
5326
  eventType: 18 /* LeavingShadowEdit */,
5176
5327
  }, false /*broadcast*/);
5177
- contentDiv.innerHTML = '';
5328
+ roosterjs_editor_dom_1.moveChildNodes(contentDiv);
5178
5329
  contentDiv.appendChild(shadowEditFragment);
5179
5330
  core.api.focus(core);
5180
5331
  if (shadowEditSelectionPath) {
@@ -5338,7 +5489,6 @@ function handledExclusively(event, plugin) {
5338
5489
 
5339
5490
  Object.defineProperty(exports, "__esModule", { value: true });
5340
5491
  var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
5341
- var CONTAINER_HTML = '<div contenteditable style="width: 1px; height: 1px; overflow: hidden; position: fixed; top: 0; left; 0; -webkit-user-select: text"></div>';
5342
5492
  /**
5343
5493
  * @internal
5344
5494
  * Copy and paste plugin for handling onCopy and onPaste event
@@ -5407,7 +5557,7 @@ var CopyPastePlugin = /** @class */ (function () {
5407
5557
  if (originalRange && !originalRange.collapsed) {
5408
5558
  var html = this.editor.getContent(2 /* RawHTMLWithSelection */);
5409
5559
  var tempDiv_1 = this.getTempDiv(true /*forceInLightMode*/);
5410
- var newRange = roosterjs_editor_dom_1.setHtmlWithSelectionPath(tempDiv_1, html);
5560
+ var newRange = roosterjs_editor_dom_1.setHtmlWithSelectionPath(tempDiv_1, html, this.editor.getTrustedHTMLHandler());
5411
5561
  if (newRange) {
5412
5562
  roosterjs_editor_dom_1.addRangeToSelection(newRange);
5413
5563
  }
@@ -5432,7 +5582,7 @@ var CopyPastePlugin = /** @class */ (function () {
5432
5582
  CopyPastePlugin.prototype.getTempDiv = function (forceInLightMode) {
5433
5583
  var _this = this;
5434
5584
  var div = this.editor.getCustomData('CopyPasteTempDiv', function () {
5435
- var tempDiv = roosterjs_editor_dom_1.fromHtml(CONTAINER_HTML, _this.editor.getDocument())[0];
5585
+ var tempDiv = roosterjs_editor_dom_1.createElement(3 /* CopyPasteTempDiv */, _this.editor.getDocument());
5436
5586
  _this.editor.insertNode(tempDiv, {
5437
5587
  position: 4 /* Outside */,
5438
5588
  });
@@ -5451,7 +5601,7 @@ var CopyPastePlugin = /** @class */ (function () {
5451
5601
  tempDiv.style.backgroundColor = '';
5452
5602
  tempDiv.style.color = '';
5453
5603
  tempDiv.style.display = 'none';
5454
- tempDiv.innerHTML = '';
5604
+ roosterjs_editor_dom_1.moveChildNodes(tempDiv);
5455
5605
  };
5456
5606
  return CopyPastePlugin;
5457
5607
  }());
@@ -5755,7 +5905,7 @@ exports.default = EditPlugin;
5755
5905
 
5756
5906
  Object.defineProperty(exports, "__esModule", { value: true });
5757
5907
  var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
5758
- var ENTITY_ID_REGEX = /_\d{1,8}$/;
5908
+ var ENTITY_ID_REGEX = /_(\d{1,8})$/;
5759
5909
  var ENTITY_CSS_REGEX = '^' + "_Entity" /* ENTITY_INFO_NAME */ + '$';
5760
5910
  var ENTITY_ID_CSS_REGEX = '^' + "_EId_" /* ENTITY_ID_PREFIX */;
5761
5911
  var ENTITY_TYPE_CSS_REGEX = '^' + "_EType_" /* ENTITY_TYPE_PREFIX */;
@@ -5766,6 +5916,12 @@ var ALLOWED_CSS_CLASSES = [
5766
5916
  ENTITY_TYPE_CSS_REGEX,
5767
5917
  ENTITY_READONLY_CSS_REGEX,
5768
5918
  ];
5919
+ var REMOVE_ENTITY_OPERATIONS = [
5920
+ 6 /* Overwrite */,
5921
+ 7 /* PartialOverwrite */,
5922
+ 4 /* RemoveFromStart */,
5923
+ 5 /* RemoveFromEnd */,
5924
+ ];
5769
5925
  /**
5770
5926
  * @internal
5771
5927
  * Entity Plugin helps handle all operations related to an entity and generate entity specified events
@@ -5782,9 +5938,28 @@ var EntityPlugin = /** @class */ (function () {
5782
5938
  _this.checkRemoveEntityForRange(event);
5783
5939
  }
5784
5940
  };
5941
+ this.workaroundShadowDOMIssueForChrome = function () {
5942
+ var cache = {};
5943
+ _this.cacheShadowEntities(cache);
5944
+ _this.editor.runAsync(function () {
5945
+ Object.keys(cache).forEach(function (id) {
5946
+ var entity = roosterjs_editor_dom_1.getEntityFromElement(cache[id]);
5947
+ var newWrapper = _this.editor.queryElements(roosterjs_editor_dom_1.getEntitySelector(entity.type, entity.id))[0];
5948
+ if (newWrapper != entity.wrapper) {
5949
+ _this.triggerEvent(entity.wrapper, 10 /* RemoveShadowRoot */);
5950
+ _this.setIsEntityKnown(entity.wrapper, false /*isKnown*/);
5951
+ if (newWrapper) {
5952
+ roosterjs_editor_dom_1.moveChildNodes(newWrapper, entity.wrapper);
5953
+ _this.createShadowRoot(newWrapper, entity.wrapper.shadowRoot);
5954
+ _this.setIsEntityKnown(newWrapper, true /*isKnown*/);
5955
+ }
5956
+ }
5957
+ });
5958
+ });
5959
+ };
5785
5960
  this.state = {
5786
- clickingPoint: null,
5787
5961
  knownEntityElements: [],
5962
+ shadowEntityCache: {},
5788
5963
  };
5789
5964
  }
5790
5965
  /**
@@ -5799,6 +5974,27 @@ var EntityPlugin = /** @class */ (function () {
5799
5974
  */
5800
5975
  EntityPlugin.prototype.initialize = function (editor) {
5801
5976
  this.editor = editor;
5977
+ // Workaround an issue for Chrome that when Delete or Backsapce, shadow DOM may be lost in editor
5978
+ if (roosterjs_editor_dom_1.Browser.isChrome || roosterjs_editor_dom_1.Browser.isSafari) {
5979
+ this.editor.addContentEditFeature({
5980
+ keys: [8 /* BACKSPACE */, 46 /* DELETE */],
5981
+ shouldHandleEvent: function () { return true; },
5982
+ handleEvent: this.workaroundShadowDOMIssueForChrome,
5983
+ });
5984
+ }
5985
+ };
5986
+ /**
5987
+ * Check if the plugin should handle the given event exclusively.
5988
+ * Handle an event exclusively means other plugin will not receive this event in
5989
+ * onPluginEvent method.
5990
+ * If two plugins will return true in willHandleEventExclusively() for the same event,
5991
+ * the final result depends on the order of the plugins are added into editor
5992
+ * @param event The event to check
5993
+ */
5994
+ EntityPlugin.prototype.willHandleEventExclusively = function (event) {
5995
+ var _a;
5996
+ return (event.eventType == 1 /* KeyPress */ &&
5997
+ !!((_a = event.rawEvent.target) === null || _a === void 0 ? void 0 : _a.shadowRoot));
5802
5998
  };
5803
5999
  /**
5804
6000
  * Dispose this plugin
@@ -5806,7 +6002,6 @@ var EntityPlugin = /** @class */ (function () {
5806
6002
  EntityPlugin.prototype.dispose = function () {
5807
6003
  this.editor = null;
5808
6004
  this.state.knownEntityElements = [];
5809
- this.state.clickingPoint = null;
5810
6005
  };
5811
6006
  /**
5812
6007
  * Get plugin state object
@@ -5820,11 +6015,8 @@ var EntityPlugin = /** @class */ (function () {
5820
6015
  */
5821
6016
  EntityPlugin.prototype.onPluginEvent = function (event) {
5822
6017
  switch (event.eventType) {
5823
- case 5 /* MouseDown */:
5824
- this.handleMouseDownEvent(event.rawEvent);
5825
- break;
5826
6018
  case 6 /* MouseUp */:
5827
- this.handleMouseUpEvent(event.rawEvent);
6019
+ this.handleMouseUpEvent(event);
5828
6020
  break;
5829
6021
  case 0 /* KeyDown */:
5830
6022
  this.handleKeyDownEvent(event.rawEvent);
@@ -5835,13 +6027,13 @@ var EntityPlugin = /** @class */ (function () {
5835
6027
  }
5836
6028
  break;
5837
6029
  case 10 /* BeforePaste */:
5838
- this.handleBeforePasteEvent(event.fragment, event.sanitizingOption);
6030
+ this.handleBeforePasteEvent(event.sanitizingOption);
5839
6031
  break;
5840
6032
  case 7 /* ContentChanged */:
5841
- this.handleContentChangedEvent(event.source == "SetContent" /* SetContent */);
6033
+ this.handleContentChangedEvent(event);
5842
6034
  break;
5843
6035
  case 11 /* EditorReady */:
5844
- this.handleContentChangedEvent(true /*resetAll*/);
6036
+ this.handleContentChangedEvent();
5845
6037
  break;
5846
6038
  case 8 /* ExtractContentWithDom */:
5847
6039
  this.handleExtractContentWithDomEvent(event.clonedRoot);
@@ -5849,6 +6041,12 @@ var EntityPlugin = /** @class */ (function () {
5849
6041
  case 16 /* ContextMenu */:
5850
6042
  this.handleContextMenuEvent(event.rawEvent);
5851
6043
  break;
6044
+ case 20 /* BeforeSetContent */:
6045
+ this.handleBeforeSetContentEvent();
6046
+ break;
6047
+ case 15 /* EntityOperation */:
6048
+ this.handleEntityOperationEvent(event);
6049
+ break;
5852
6050
  }
5853
6051
  };
5854
6052
  EntityPlugin.prototype.handleContextMenuEvent = function (event) {
@@ -5859,63 +6057,83 @@ var EntityPlugin = /** @class */ (function () {
5859
6057
  this.triggerEvent(entityElement, 2 /* ContextMenu */, event);
5860
6058
  }
5861
6059
  };
5862
- EntityPlugin.prototype.handleMouseDownEvent = function (event) {
5863
- var target = event.target, pageX = event.pageX, pageY = event.pageY;
5864
- var node = target;
5865
- var entityElement = node && this.editor.getElementAtCursor(roosterjs_editor_dom_1.getEntitySelector(), node);
5866
- if (entityElement && !entityElement.isContentEditable) {
5867
- event.preventDefault();
5868
- this.state.clickingPoint = { pageX: pageX, pageY: pageY };
5869
- }
5870
- };
5871
6060
  EntityPlugin.prototype.handleMouseUpEvent = function (event) {
5872
- var target = event.target, pageX = event.pageX, pageY = event.pageY;
5873
- var node = target;
6061
+ var rawEvent = event.rawEvent, isClicking = event.isClicking;
6062
+ var node = rawEvent.target;
5874
6063
  var entityElement;
5875
- if (this.state.clickingPoint &&
5876
- this.state.clickingPoint.pageX == pageX &&
5877
- this.state.clickingPoint.pageY == pageY &&
6064
+ if (isClicking &&
5878
6065
  node &&
5879
6066
  !!(entityElement = this.editor.getElementAtCursor(roosterjs_editor_dom_1.getEntitySelector(), node))) {
5880
- event.preventDefault();
5881
- this.triggerEvent(entityElement, 1 /* Click */, event);
6067
+ this.triggerEvent(entityElement, 1 /* Click */, rawEvent);
5882
6068
  workaroundSelectionIssueForIE(this.editor);
5883
6069
  }
5884
- this.state.clickingPoint = null;
5885
6070
  };
5886
6071
  EntityPlugin.prototype.handleKeyDownEvent = function (event) {
5887
6072
  if (roosterjs_editor_dom_1.isCharacterValue(event) ||
5888
6073
  event.which == 8 /* BACKSPACE */ ||
5889
- event.which == 46 /* DELETE */) {
6074
+ event.which == 46 /* DELETE */ ||
6075
+ event.which == 13 /* ENTER */) {
5890
6076
  var range = this.editor.getSelectionRange();
5891
- if (!range.collapsed) {
6077
+ if (range && !range.collapsed) {
5892
6078
  this.checkRemoveEntityForRange(event);
5893
6079
  }
5894
6080
  }
5895
6081
  };
5896
- EntityPlugin.prototype.handleBeforePasteEvent = function (fragment, sanitizingOption) {
6082
+ EntityPlugin.prototype.handleBeforePasteEvent = function (sanitizingOption) {
5897
6083
  var range = this.editor.getSelectionRange();
5898
6084
  if (!range.collapsed) {
5899
6085
  this.checkRemoveEntityForRange(null /*rawEvent*/);
5900
6086
  }
5901
6087
  roosterjs_editor_dom_1.arrayPush(sanitizingOption.additionalAllowedCssClasses, ALLOWED_CSS_CLASSES);
5902
6088
  };
5903
- EntityPlugin.prototype.handleContentChangedEvent = function (resetAll) {
6089
+ EntityPlugin.prototype.handleBeforeSetContentEvent = function () {
6090
+ this.cacheShadowEntities(this.state.shadowEntityCache);
6091
+ };
6092
+ EntityPlugin.prototype.handleContentChangedEvent = function (event) {
5904
6093
  var _this = this;
5905
- this.state.knownEntityElements = resetAll
5906
- ? []
5907
- : this.state.knownEntityElements.filter(function (node) { return _this.editor.contains(node); });
5908
- var allId = this.state.knownEntityElements
6094
+ // 1. find removed entities
6095
+ for (var i = this.state.knownEntityElements.length - 1; i >= 0; i--) {
6096
+ var element = this.state.knownEntityElements[i];
6097
+ if (!this.editor.contains(element)) {
6098
+ this.setIsEntityKnown(element, false /*isKnown*/);
6099
+ if (element.shadowRoot) {
6100
+ this.triggerEvent(element, 10 /* RemoveShadowRoot */);
6101
+ }
6102
+ }
6103
+ }
6104
+ // 2. collect all new entities
6105
+ var knownIds = this.state.knownEntityElements
5909
6106
  .map(function (e) { var _a; return (_a = roosterjs_editor_dom_1.getEntityFromElement(e)) === null || _a === void 0 ? void 0 : _a.id; })
5910
6107
  .filter(function (x) { return !!x; });
5911
- this.editor.queryElements(roosterjs_editor_dom_1.getEntitySelector(), function (element) {
5912
- if (_this.state.knownEntityElements.indexOf(element) < 0) {
5913
- _this.state.knownEntityElements.push(element);
5914
- var entity = roosterjs_editor_dom_1.getEntityFromElement(element);
5915
- _this.hydrateEntity(entity, allId);
5916
- }
6108
+ var newEntities = (event === null || event === void 0 ? void 0 : event.source) == "InsertEntity" /* InsertEntity */ && event.data
6109
+ ? [event.data]
6110
+ : this.getExistingEntities().filter(function (_a) {
6111
+ var wrapper = _a.wrapper;
6112
+ return !_this.isEntityKnown(wrapper);
6113
+ });
6114
+ // 3. Add new entities to known entity list, and hydrate
6115
+ newEntities.forEach(function (entity) {
6116
+ var wrapper = entity.wrapper, type = entity.type, id = entity.id, isReadonly = entity.isReadonly;
6117
+ entity.id = _this.ensureUniqueId(type, id, knownIds);
6118
+ roosterjs_editor_dom_1.commitEntity(wrapper, type, isReadonly, entity.id); // Use entity.id here because it is newly updated
6119
+ _this.handleNewEntity(entity);
6120
+ });
6121
+ Object.keys(this.state.shadowEntityCache).forEach(function (id) {
6122
+ _this.triggerEvent(_this.state.shadowEntityCache[id], 6 /* Overwrite */);
6123
+ delete _this.state.shadowEntityCache[id];
5917
6124
  });
5918
6125
  };
6126
+ EntityPlugin.prototype.handleEntityOperationEvent = function (event) {
6127
+ var _this = this;
6128
+ var _a;
6129
+ if (REMOVE_ENTITY_OPERATIONS.indexOf(event.operation) >= 0) {
6130
+ (_a = this.cancelAsyncRun) === null || _a === void 0 ? void 0 : _a.call(this);
6131
+ this.cancelAsyncRun = this.editor.runAsync(function () {
6132
+ _this.cancelAsyncRun = null;
6133
+ _this.handleContentChangedEvent();
6134
+ });
6135
+ }
6136
+ };
5919
6137
  EntityPlugin.prototype.handleExtractContentWithDomEvent = function (root) {
5920
6138
  var _this = this;
5921
6139
  roosterjs_editor_dom_1.toArray(root.querySelectorAll(roosterjs_editor_dom_1.getEntitySelector())).forEach(function (element) {
@@ -5945,8 +6163,71 @@ var EntityPlugin = /** @class */ (function () {
5945
6163
  });
5946
6164
  }
5947
6165
  };
5948
- EntityPlugin.prototype.hydrateEntity = function (entity, knownIds) {
5949
- var id = entity.id, type = entity.type, wrapper = entity.wrapper, isReadonly = entity.isReadonly;
6166
+ EntityPlugin.prototype.triggerEvent = function (element, operation, rawEvent, contentForShadowEntity) {
6167
+ var entity = element && roosterjs_editor_dom_1.getEntityFromElement(element);
6168
+ if (entity) {
6169
+ this.editor.triggerPluginEvent(15 /* EntityOperation */, {
6170
+ operation: operation,
6171
+ rawEvent: rawEvent,
6172
+ entity: entity,
6173
+ contentForShadowEntity: contentForShadowEntity,
6174
+ });
6175
+ }
6176
+ };
6177
+ EntityPlugin.prototype.handleNewEntity = function (entity) {
6178
+ var wrapper = entity.wrapper;
6179
+ var fragment = this.editor.getDocument().createDocumentFragment();
6180
+ var cache = this.state.shadowEntityCache[entity.id];
6181
+ delete this.state.shadowEntityCache[entity.id];
6182
+ if (cache === null || cache === void 0 ? void 0 : cache.shadowRoot) {
6183
+ roosterjs_editor_dom_1.moveChildNodes(fragment, cache.shadowRoot);
6184
+ }
6185
+ this.triggerEvent(wrapper, 0 /* NewEntity */, undefined /*rawEvent*/, fragment);
6186
+ // If there is element to hydrate for shadow entity, craete shadow root and mount these elements to shadow root
6187
+ // Then trigger AddShadowRoot so that plugins can do further actions
6188
+ if (fragment.firstChild) {
6189
+ if (wrapper.shadowRoot) {
6190
+ roosterjs_editor_dom_1.moveChildNodes(wrapper.shadowRoot, fragment);
6191
+ }
6192
+ else {
6193
+ this.createShadowRoot(wrapper, fragment);
6194
+ }
6195
+ }
6196
+ else if (wrapper.shadowRoot) {
6197
+ // If no elements to hydrate, remove existing shadow root by cloning a new node
6198
+ this.triggerEvent(wrapper, 10 /* RemoveShadowRoot */);
6199
+ var newWrapper = wrapper.cloneNode();
6200
+ roosterjs_editor_dom_1.moveChildNodes(newWrapper, wrapper);
6201
+ this.editor.replaceNode(wrapper, newWrapper);
6202
+ entity.wrapper = newWrapper;
6203
+ }
6204
+ this.setIsEntityKnown(entity.wrapper, true /*isKnown*/);
6205
+ };
6206
+ EntityPlugin.prototype.getExistingEntities = function (shadowEntityOnly) {
6207
+ return this.editor
6208
+ .queryElements(roosterjs_editor_dom_1.getEntitySelector())
6209
+ .map(roosterjs_editor_dom_1.getEntityFromElement)
6210
+ .filter(function (x) { return !!x && (!shadowEntityOnly || !!x.wrapper.shadowRoot); });
6211
+ };
6212
+ EntityPlugin.prototype.createShadowRoot = function (wrapper, shadowContentContainer) {
6213
+ if (wrapper.attachShadow) {
6214
+ var shadowRoot = wrapper.attachShadow({
6215
+ mode: 'open',
6216
+ delegatesFocus: true,
6217
+ });
6218
+ wrapper.contentEditable = 'false';
6219
+ this.triggerEvent(wrapper, 9 /* AddShadowRoot */);
6220
+ roosterjs_editor_dom_1.moveChildNodes(shadowRoot, shadowContentContainer);
6221
+ return shadowRoot;
6222
+ }
6223
+ };
6224
+ EntityPlugin.prototype.cacheShadowEntities = function (cache) {
6225
+ this.getExistingEntities(true /*shadowEntityOnly*/).forEach(function (_a) {
6226
+ var wrapper = _a.wrapper, id = _a.id;
6227
+ cache[id] = wrapper;
6228
+ });
6229
+ };
6230
+ EntityPlugin.prototype.ensureUniqueId = function (type, id, knownIds) {
5950
6231
  var match = ENTITY_ID_REGEX.exec(id);
5951
6232
  var baseId = (match ? id.substr(0, id.length - match[0].length) : id) || type;
5952
6233
  // Make sure entity id is unique
@@ -5958,18 +6239,19 @@ var EntityPlugin = /** @class */ (function () {
5958
6239
  break;
5959
6240
  }
5960
6241
  }
5961
- roosterjs_editor_dom_1.commitEntity(wrapper, type, isReadonly, newId);
5962
- this.triggerEvent(wrapper, 0 /* NewEntity */);
6242
+ return newId;
5963
6243
  };
5964
- EntityPlugin.prototype.triggerEvent = function (element, operation, rawEvent) {
5965
- var entity = element && roosterjs_editor_dom_1.getEntityFromElement(element);
5966
- if (entity) {
5967
- this.editor.triggerPluginEvent(15 /* EntityOperation */, {
5968
- operation: operation,
5969
- rawEvent: rawEvent,
5970
- entity: entity,
5971
- });
6244
+ EntityPlugin.prototype.setIsEntityKnown = function (wrapper, isKnown) {
6245
+ var index = this.state.knownEntityElements.indexOf(wrapper);
6246
+ if (isKnown && index < 0) {
6247
+ this.state.knownEntityElements.push(wrapper);
5972
6248
  }
6249
+ else if (!isKnown && index >= 0) {
6250
+ this.state.knownEntityElements.splice(index, 1);
6251
+ }
6252
+ };
6253
+ EntityPlugin.prototype.isEntityKnown = function (wrapper) {
6254
+ return this.state.knownEntityElements.indexOf(wrapper) >= 0;
5973
6255
  };
5974
6256
  return EntityPlugin;
5975
6257
  }());
@@ -5982,13 +6264,10 @@ var workaroundSelectionIssueForIE = roosterjs_editor_dom_1.Browser.isIE
5982
6264
  ? function (editor) {
5983
6265
  editor.runAsync(function (editor) {
5984
6266
  var workaroundButton = editor.getCustomData('ENTITY_IE_FOCUS_BUTTON', function () {
5985
- var button = editor.getDocument().createElement('button');
5986
- button.style.overflow = 'hidden';
5987
- button.style.position = 'fixed';
5988
- button.style.width = '0';
5989
- button.style.height = '0';
5990
- button.style.left = '0';
5991
- button.style.top = '-1000px';
6267
+ var button = roosterjs_editor_dom_1.createElement({
6268
+ tag: 'button',
6269
+ style: 'overflow:hidden;position:fixed;width:0;height:0;top:-1000px',
6270
+ }, editor.getDocument());
5992
6271
  button.onblur = function () {
5993
6272
  button.style.display = 'none';
5994
6273
  };
@@ -5998,13 +6277,7 @@ var workaroundSelectionIssueForIE = roosterjs_editor_dom_1.Browser.isIE
5998
6277
  return button;
5999
6278
  });
6000
6279
  workaroundButton.style.display = '';
6001
- var range = editor.getDocument().createRange();
6002
- range.setStart(workaroundButton, 0);
6003
- try {
6004
- window.getSelection().removeAllRanges();
6005
- window.getSelection().addRange(range);
6006
- }
6007
- catch (_a) { }
6280
+ roosterjs_editor_dom_1.addRangeToSelection(roosterjs_editor_dom_1.createRange(workaroundButton, 0));
6008
6281
  });
6009
6282
  }
6010
6283
  : function () { };
@@ -6357,102 +6630,35 @@ var PendingFormatStatePlugin = /** @class */ (function () {
6357
6630
  */
6358
6631
  PendingFormatStatePlugin.prototype.onPluginEvent = function (event) {
6359
6632
  switch (event.eventType) {
6360
- case 13 /* PendingFormatStateChanged */:
6361
- // Got PendingFormatStateChanged event, cache current position and pending format
6362
- this.state.pendableFormatPosition = this.getCurrentPosition();
6363
- this.state.pendableFormatState = event.formatState;
6364
- break;
6365
- case 0 /* KeyDown */:
6366
- case 5 /* MouseDown */:
6367
- case 7 /* ContentChanged */:
6368
- // If content or position is changed (by keyboard, mouse, or code),
6369
- // check if current position is still the same with the cached one (if exist),
6370
- // and clear cached format if position is changed since it is out-of-date now
6371
- if (this.state.pendableFormatPosition &&
6372
- !this.state.pendableFormatPosition.equalTo(this.getCurrentPosition())) {
6373
- this.clear();
6374
- }
6375
- break;
6376
- }
6377
- };
6378
- PendingFormatStatePlugin.prototype.clear = function () {
6379
- this.state.pendableFormatPosition = null;
6380
- this.state.pendableFormatState = null;
6381
- };
6382
- PendingFormatStatePlugin.prototype.getCurrentPosition = function () {
6383
- var range = this.editor.getSelectionRange();
6384
- return range && roosterjs_editor_dom_1.Position.getStart(range).normalize();
6385
- };
6386
- return PendingFormatStatePlugin;
6387
- }());
6388
- exports.default = PendingFormatStatePlugin;
6389
-
6390
-
6391
- /***/ }),
6392
-
6393
- /***/ "./packages/roosterjs-editor-core/lib/corePlugins/TypeAfterLinkPlugin.ts":
6394
- /*!*******************************************************************************!*\
6395
- !*** ./packages/roosterjs-editor-core/lib/corePlugins/TypeAfterLinkPlugin.ts ***!
6396
- \*******************************************************************************/
6397
- /*! no static exports found */
6398
- /***/ (function(module, exports, __webpack_require__) {
6399
-
6400
- "use strict";
6401
-
6402
- Object.defineProperty(exports, "__esModule", { value: true });
6403
- var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
6404
- /**
6405
- * @internal
6406
- * TypeAfterLinkPlugin Component helps handle typing event when cursor is right after a link.
6407
- * When typing/pasting after a link, browser may put the new character inside link.
6408
- * This plugin overrides this behavior to always insert outside of link.
6409
- */
6410
- var TypeAfterLinkPlugin = /** @class */ (function () {
6411
- function TypeAfterLinkPlugin() {
6412
- }
6413
- /**
6414
- * Get a friendly name of this plugin
6415
- */
6416
- TypeAfterLinkPlugin.prototype.getName = function () {
6417
- return 'TypeAfterLink';
6418
- };
6419
- /**
6420
- * Initialize this plugin. This should only be called from Editor
6421
- * @param editor Editor instance
6422
- */
6423
- TypeAfterLinkPlugin.prototype.initialize = function (editor) {
6424
- this.editor = editor;
6425
- };
6426
- /**
6427
- * Dispose this plugin
6428
- */
6429
- TypeAfterLinkPlugin.prototype.dispose = function () {
6430
- this.editor = null;
6431
- };
6432
- /**
6433
- * Handle events triggered from editor
6434
- * @param event PluginEvent object
6435
- */
6436
- TypeAfterLinkPlugin.prototype.onPluginEvent = function (event) {
6437
- if ((roosterjs_editor_dom_1.Browser.isFirefox && event.eventType == 1 /* KeyPress */) ||
6438
- event.eventType == 10 /* BeforePaste */) {
6439
- var range = this.editor.getSelectionRange();
6440
- if (range && range.collapsed && this.editor.getElementAtCursor('A[href]')) {
6441
- var searcher = this.editor.getContentSearcherOfCursor(event);
6442
- var inlineElementBefore = searcher.getInlineElementBefore();
6443
- var inlineElementAfter = searcher.getInlineElementAfter();
6444
- if (inlineElementBefore instanceof roosterjs_editor_dom_1.LinkInlineElement) {
6445
- this.editor.select(inlineElementBefore.getContainerNode(), -3 /* After */);
6446
- }
6447
- else if (inlineElementAfter instanceof roosterjs_editor_dom_1.LinkInlineElement) {
6448
- this.editor.select(inlineElementAfter.getContainerNode(), -2 /* Before */);
6633
+ case 13 /* PendingFormatStateChanged */:
6634
+ // Got PendingFormatStateChanged event, cache current position and pending format
6635
+ this.state.pendableFormatPosition = this.getCurrentPosition();
6636
+ this.state.pendableFormatState = event.formatState;
6637
+ break;
6638
+ case 0 /* KeyDown */:
6639
+ case 5 /* MouseDown */:
6640
+ case 7 /* ContentChanged */:
6641
+ // If content or position is changed (by keyboard, mouse, or code),
6642
+ // check if current position is still the same with the cached one (if exist),
6643
+ // and clear cached format if position is changed since it is out-of-date now
6644
+ if (this.state.pendableFormatPosition &&
6645
+ !this.state.pendableFormatPosition.equalTo(this.getCurrentPosition())) {
6646
+ this.clear();
6449
6647
  }
6450
- }
6648
+ break;
6451
6649
  }
6452
6650
  };
6453
- return TypeAfterLinkPlugin;
6651
+ PendingFormatStatePlugin.prototype.clear = function () {
6652
+ this.state.pendableFormatPosition = null;
6653
+ this.state.pendableFormatState = null;
6654
+ };
6655
+ PendingFormatStatePlugin.prototype.getCurrentPosition = function () {
6656
+ var range = this.editor.getSelectionRange();
6657
+ return range && roosterjs_editor_dom_1.Position.getStart(range).normalize();
6658
+ };
6659
+ return PendingFormatStatePlugin;
6454
6660
  }());
6455
- exports.default = TypeAfterLinkPlugin;
6661
+ exports.default = PendingFormatStatePlugin;
6456
6662
 
6457
6663
 
6458
6664
  /***/ }),
@@ -6508,7 +6714,9 @@ var TypeInContainerPlugin = /** @class */ (function () {
6508
6714
  //
6509
6715
  // Only schedule when the range is not collapsed to catch this edge case.
6510
6716
  var range = this.editor.getSelectionRange();
6511
- if (!range || this.editor.contains(roosterjs_editor_dom_1.findClosestElementAncestor(range.startContainer))) {
6717
+ var shouldAlwaysApplyDefaultFormat = this.editor.isFeatureEnabled("AlwaysApplyDefaultFormat" /* AlwaysApplyDefaultFormat */);
6718
+ if (!range ||
6719
+ this.editor.contains(roosterjs_editor_dom_1.findClosestElementAncestor(range.startContainer, null /* root */, shouldAlwaysApplyDefaultFormat ? '[style]' : null /*selector*/))) {
6512
6720
  return;
6513
6721
  }
6514
6722
  if (range.collapsed) {
@@ -6735,13 +6943,8 @@ var EntityPlugin_1 = __webpack_require__(/*! ./EntityPlugin */ "./packages/roost
6735
6943
  var LifecyclePlugin_1 = __webpack_require__(/*! ./LifecyclePlugin */ "./packages/roosterjs-editor-core/lib/corePlugins/LifecyclePlugin.ts");
6736
6944
  var MouseUpPlugin_1 = __webpack_require__(/*! ./MouseUpPlugin */ "./packages/roosterjs-editor-core/lib/corePlugins/MouseUpPlugin.ts");
6737
6945
  var PendingFormatStatePlugin_1 = __webpack_require__(/*! ./PendingFormatStatePlugin */ "./packages/roosterjs-editor-core/lib/corePlugins/PendingFormatStatePlugin.ts");
6738
- var TypeAfterLinkPlugin_1 = __webpack_require__(/*! ./TypeAfterLinkPlugin */ "./packages/roosterjs-editor-core/lib/corePlugins/TypeAfterLinkPlugin.ts");
6739
6946
  var TypeInContainerPlugin_1 = __webpack_require__(/*! ./TypeInContainerPlugin */ "./packages/roosterjs-editor-core/lib/corePlugins/TypeInContainerPlugin.ts");
6740
6947
  var UndoPlugin_1 = __webpack_require__(/*! ./UndoPlugin */ "./packages/roosterjs-editor-core/lib/corePlugins/UndoPlugin.ts");
6741
- /**
6742
- * @internal
6743
- */
6744
- exports.PLACEHOLDER_PLUGIN_NAME = '_placeholder';
6745
6948
  /**
6746
6949
  * @internal
6747
6950
  * Create Core Plugins
@@ -6756,7 +6959,7 @@ function createCorePlugins(contentDiv, options) {
6756
6959
  typeInContainer: map.typeInContainer || new TypeInContainerPlugin_1.default(),
6757
6960
  edit: map.edit || new EditPlugin_1.default(),
6758
6961
  _placeholder: null,
6759
- typeAfterLink: map.typeAfterLink || new TypeAfterLinkPlugin_1.default(),
6962
+ typeAfterLink: null,
6760
6963
  undo: map.undo || new UndoPlugin_1.default(options),
6761
6964
  domEvent: map.domEvent || new DOMEventPlugin_1.default(options, contentDiv),
6762
6965
  pendingFormatState: map.pendingFormatState || new PendingFormatStatePlugin_1.default(),
@@ -6833,14 +7036,14 @@ var Editor = /** @class */ (function () {
6833
7036
  var corePlugins = createCorePlugins_1.default(contentDiv, options);
6834
7037
  var plugins = [];
6835
7038
  Object.keys(corePlugins).forEach(function (name) {
6836
- if (name == createCorePlugins_1.PLACEHOLDER_PLUGIN_NAME) {
7039
+ if (name == '_placeholder') {
6837
7040
  roosterjs_editor_dom_1.arrayPush(plugins, options.plugins);
6838
7041
  }
6839
7042
  else {
6840
7043
  plugins.push(corePlugins[name]);
6841
7044
  }
6842
7045
  });
6843
- this.core = __assign({ contentDiv: contentDiv, api: __assign(__assign({}, coreApiMap_1.coreApiMap), (options.coreApiOverride || {})), plugins: plugins.filter(function (x) { return !!x; }) }, createCorePlugins_1.getPluginState(corePlugins));
7046
+ this.core = __assign(__assign({ contentDiv: contentDiv, api: __assign(__assign({}, coreApiMap_1.coreApiMap), (options.coreApiOverride || {})), plugins: plugins.filter(function (x) { return !!x; }) }, createCorePlugins_1.getPluginState(corePlugins)), { trustedHTMLHandler: options.trustedHTMLHandler || (function (html) { return html; }) });
6844
7047
  // 3. Initialize plugins
6845
7048
  this.core.plugins.forEach(function (plugin) { return plugin.initialize(_this); });
6846
7049
  // 4. Ensure user will type in a container node, not the editor content DIV
@@ -6973,9 +7176,11 @@ var Editor = /** @class */ (function () {
6973
7176
  * insertOnNewLine: false
6974
7177
  */
6975
7178
  Editor.prototype.insertContent = function (content, option) {
7179
+ var _a;
6976
7180
  if (content) {
6977
7181
  var doc = this.getDocument();
6978
- var allNodes = roosterjs_editor_dom_1.fromHtml(content, doc);
7182
+ var body = (_a = new DOMParser().parseFromString(this.core.trustedHTMLHandler(content), 'text/html')) === null || _a === void 0 ? void 0 : _a.body;
7183
+ var allNodes = (body === null || body === void 0 ? void 0 : body.childNodes) ? roosterjs_editor_dom_1.toArray(body.childNodes) : [];
6979
7184
  // If it is to insert on new line, and there are more than one node in the collection, wrap all nodes with
6980
7185
  // a parent DIV before calling insertNode on each top level sub node. Otherwise, every sub node may get wrapped
6981
7186
  // separately to show up on its own line
@@ -7275,15 +7480,19 @@ var Editor = /** @class */ (function () {
7275
7480
  /**
7276
7481
  * Run a callback function asynchronously
7277
7482
  * @param callback The callback function to run
7483
+ * @returns a function to cancel this async run
7278
7484
  */
7279
7485
  Editor.prototype.runAsync = function (callback) {
7280
7486
  var _this = this;
7281
7487
  var win = this.core.contentDiv.ownerDocument.defaultView || window;
7282
- win.requestAnimationFrame(function () {
7488
+ var handle = win.requestAnimationFrame(function () {
7283
7489
  if (!_this.isDisposed() && callback) {
7284
7490
  callback(_this);
7285
7491
  }
7286
7492
  });
7493
+ return function () {
7494
+ win.cancelAnimationFrame(handle);
7495
+ };
7287
7496
  };
7288
7497
  /**
7289
7498
  * Set DOM attribute of editor content DIV
@@ -7351,6 +7560,14 @@ var Editor = /** @class */ (function () {
7351
7560
  }
7352
7561
  return this.core.api.getStyleBasedFormatState(this.core, node);
7353
7562
  };
7563
+ /**
7564
+ * Get the pendable format such as underline and bold
7565
+ * @param forceGetStateFromDOM If set to true, will force get the format state from DOM tree.
7566
+ * @returns The pending format state
7567
+ */
7568
+ Editor.prototype.getPendableFormatState = function (forceGetStateFromDOM) {
7569
+ return this.core.api.getPendableFormatState(this.core, forceGetStateFromDOM);
7570
+ };
7354
7571
  /**
7355
7572
  * Ensure user will type into a container element rather than into the editor content DIV directly
7356
7573
  * @param position The position that user is about to type to
@@ -7410,6 +7627,15 @@ var Editor = /** @class */ (function () {
7410
7627
  Editor.prototype.isFeatureEnabled = function (feature) {
7411
7628
  return this.core.lifecycle.experimentalFeatures.indexOf(feature) >= 0;
7412
7629
  };
7630
+ /**
7631
+ * Get a function to convert HTML string to trusted HTML string.
7632
+ * By default it will just return the input HTML directly. To override this behavior,
7633
+ * pass your own trusted HTML handler to EditorOptions.trustedHTMLHandler
7634
+ * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/trusted-types
7635
+ */
7636
+ Editor.prototype.getTrustedHTMLHandler = function () {
7637
+ return this.core.trustedHTMLHandler;
7638
+ };
7413
7639
  return Editor;
7414
7640
  }());
7415
7641
  exports.default = Editor;
@@ -8791,7 +9017,7 @@ exports.default = getEntityFromElement;
8791
9017
 
8792
9018
  Object.defineProperty(exports, "__esModule", { value: true });
8793
9019
  /**
8794
- * @internal Get a selector string for specified entity type and id
9020
+ * Get a selector string for specified entity type and id
8795
9021
  * @param type (Optional) Type of entity
8796
9022
  * @param id (Optional) Id of entity
8797
9023
  */
@@ -8904,14 +9130,17 @@ exports.default = isCharacterValue;
8904
9130
 
8905
9131
  Object.defineProperty(exports, "__esModule", { value: true });
8906
9132
  var Browser_1 = __webpack_require__(/*! ../utils/Browser */ "./packages/roosterjs-editor-dom/lib/utils/Browser.ts");
9133
+ var isCtrlOrMetaPressedImpl = Browser_1.Browser.isMac
9134
+ ? function (event) { return event.metaKey; }
9135
+ : function (event) { return event.ctrlKey; };
8907
9136
  /**
8908
9137
  * Check if Ctrl key (Windows) or Meta key (Mac) is pressed for the given Event
8909
9138
  * @param event A Keyboard event or Mouse event object
8910
9139
  * @returns True if Ctrl key is pressed on Windows or Meta key is pressed on Mac
8911
9140
  */
8912
- var isCtrlOrMetaPressed = Browser_1.Browser.isMac
8913
- ? function (event) { return event.metaKey; }
8914
- : function (event) { return event.ctrlKey; };
9141
+ function isCtrlOrMetaPressed(event) {
9142
+ return isCtrlOrMetaPressedImpl(event);
9143
+ }
8915
9144
  exports.default = isCtrlOrMetaPressed;
8916
9145
 
8917
9146
 
@@ -9025,7 +9254,7 @@ var HtmlSanitizer = /** @class */ (function () {
9025
9254
  */
9026
9255
  HtmlSanitizer.prototype.exec = function (html, convertCssOnly, currentStyles) {
9027
9256
  var parser = new DOMParser();
9028
- var doc = parser.parseFromString(html || '', 'text/html');
9257
+ var doc = parser.parseFromString(unsafeConvertToTrustedHTML(html) || '', 'text/html');
9029
9258
  if (doc && doc.body && doc.body.firstChild) {
9030
9259
  this.convertGlobalCssToInlineCss(doc);
9031
9260
  if (!convertCssOnly) {
@@ -9231,6 +9460,15 @@ var HtmlSanitizer = /** @class */ (function () {
9231
9460
  return HtmlSanitizer;
9232
9461
  }());
9233
9462
  exports.default = HtmlSanitizer;
9463
+ var trustedTypes = window.trustedTypes;
9464
+ var policy = trustedTypes === null || trustedTypes === void 0 ? void 0 : trustedTypes.createPolicy('roosterjsUnsafeConvertHTML', {
9465
+ // This is unsafe. However, we only use this function for HtmlSanitizer which we will
9466
+ // sanitize HTML tree by our own code. So we just directly return the HTML string here.
9467
+ createHTML: function (html) { return html; },
9468
+ });
9469
+ var unsafeConvertToTrustedHTML = policy
9470
+ ? function (html) { return policy.createHTML(html || ''); }
9471
+ : function (html) { return html; };
9234
9472
 
9235
9473
 
9236
9474
  /***/ }),
@@ -9297,10 +9535,14 @@ function customClone(source, existingObj) {
9297
9535
  }
9298
9536
  return result;
9299
9537
  }
9538
+ var cloneObjectImpl = Object.assign ? nativeClone : customClone;
9300
9539
  /**
9301
9540
  * @internal
9302
9541
  */
9303
- exports.cloneObject = Object.assign ? nativeClone : customClone;
9542
+ function cloneObject(source, existingObj) {
9543
+ return cloneObjectImpl(source, existingObj);
9544
+ }
9545
+ exports.cloneObject = cloneObject;
9304
9546
 
9305
9547
 
9306
9548
  /***/ }),
@@ -9805,6 +10047,15 @@ var setColor_1 = __webpack_require__(/*! ./utils/setColor */ "./packages/rooster
9805
10047
  exports.setColor = setColor_1.default;
9806
10048
  var matchesSelector_1 = __webpack_require__(/*! ./utils/matchesSelector */ "./packages/roosterjs-editor-dom/lib/utils/matchesSelector.ts");
9807
10049
  exports.matchesSelector = matchesSelector_1.default;
10050
+ var adjustInsertPosition_1 = __webpack_require__(/*! ./utils/adjustInsertPosition */ "./packages/roosterjs-editor-dom/lib/utils/adjustInsertPosition.ts");
10051
+ exports.adjustInsertPosition = adjustInsertPosition_1.default;
10052
+ var createElement_1 = __webpack_require__(/*! ./utils/createElement */ "./packages/roosterjs-editor-dom/lib/utils/createElement.ts");
10053
+ exports.createElement = createElement_1.default;
10054
+ exports.KnownCreateElementData = createElement_1.KnownCreateElementData;
10055
+ var moveChildNodes_1 = __webpack_require__(/*! ./utils/moveChildNodes */ "./packages/roosterjs-editor-dom/lib/utils/moveChildNodes.ts");
10056
+ exports.moveChildNodes = moveChildNodes_1.default;
10057
+ var setListItemStyle_1 = __webpack_require__(/*! ./utils/setListItemStyle */ "./packages/roosterjs-editor-dom/lib/utils/setListItemStyle.ts");
10058
+ exports.setListItemStyle = setListItemStyle_1.default;
9808
10059
  var VTable_1 = __webpack_require__(/*! ./table/VTable */ "./packages/roosterjs-editor-dom/lib/table/VTable.ts");
9809
10060
  exports.VTable = VTable_1.default;
9810
10061
  var VList_1 = __webpack_require__(/*! ./list/VList */ "./packages/roosterjs-editor-dom/lib/list/VList.ts");
@@ -10613,6 +10864,10 @@ var VList = /** @class */ (function () {
10613
10864
  // Use a placeholder to hold the position since the root list may be moved into document fragment later
10614
10865
  this.rootList.parentNode.replaceChild(placeholder, this.rootList);
10615
10866
  this.items.forEach(function (item) {
10867
+ if (item.getNewListStart() && item.getNewListStart() != start) {
10868
+ listStack.splice(1, listStack.length - 1);
10869
+ start = item.getNewListStart();
10870
+ }
10616
10871
  item.writeBack(listStack, _this.rootList);
10617
10872
  var topList = listStack[1];
10618
10873
  if (safeInstanceOf_1.default(topList, 'HTMLOListElement')) {
@@ -10636,6 +10891,23 @@ var VList = /** @class */ (function () {
10636
10891
  // after change the rootList may not be available any more (e.g. outdent all items).
10637
10892
  this.rootList = null;
10638
10893
  };
10894
+ /**
10895
+ * Sets the New List Start Property, that is going to be used to create a new List in the WriteBack function
10896
+ * @param separator The HTML element that indicates when to split the VList
10897
+ * @param startNumber The start number of the new List
10898
+ */
10899
+ VList.prototype.split = function (separator, startNumber) {
10900
+ if (!this.rootList) {
10901
+ throw new Error('rootList must not be null');
10902
+ }
10903
+ //Traverse the items of the VList, when the separator is found, set the New List Start Property
10904
+ for (var index = 0; index < this.items.length; index++) {
10905
+ if (this.items[index].getNode() == separator) {
10906
+ this.items[index].setNewListStart(startNumber);
10907
+ return;
10908
+ }
10909
+ }
10910
+ };
10639
10911
  VList.prototype.setIndentation = function (start, end, indentation, softOutdent) {
10640
10912
  this.findListItems(start, end, function (item) {
10641
10913
  return indentation == 1 /* Decrease */
@@ -10953,13 +11225,14 @@ var contains_1 = __webpack_require__(/*! ../utils/contains */ "./packages/rooste
10953
11225
  var getListTypeFromNode_1 = __webpack_require__(/*! ./getListTypeFromNode */ "./packages/roosterjs-editor-dom/lib/list/getListTypeFromNode.ts");
10954
11226
  var getTagOfNode_1 = __webpack_require__(/*! ../utils/getTagOfNode */ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts");
10955
11227
  var isBlockElement_1 = __webpack_require__(/*! ../utils/isBlockElement */ "./packages/roosterjs-editor-dom/lib/utils/isBlockElement.ts");
11228
+ var moveChildNodes_1 = __webpack_require__(/*! ../utils/moveChildNodes */ "./packages/roosterjs-editor-dom/lib/utils/moveChildNodes.ts");
10956
11229
  var safeInstanceOf_1 = __webpack_require__(/*! ../utils/safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts");
11230
+ var setListItemStyle_1 = __webpack_require__(/*! ../utils/setListItemStyle */ "./packages/roosterjs-editor-dom/lib/utils/setListItemStyle.ts");
10957
11231
  var toArray_1 = __webpack_require__(/*! ../utils/toArray */ "./packages/roosterjs-editor-dom/lib/utils/toArray.ts");
10958
11232
  var unwrap_1 = __webpack_require__(/*! ../utils/unwrap */ "./packages/roosterjs-editor-dom/lib/utils/unwrap.ts");
10959
11233
  var wrap_1 = __webpack_require__(/*! ../utils/wrap */ "./packages/roosterjs-editor-dom/lib/utils/wrap.ts");
10960
11234
  var orderListStyles = [null, 'lower-alpha', 'lower-roman'];
10961
11235
  /**
10962
- * @internal
10963
11236
  * !!! Never directly create instance of this class. It should be created within VList class !!!
10964
11237
  *
10965
11238
  * Represent a list item.
@@ -10967,7 +11240,6 @@ var orderListStyles = [null, 'lower-alpha', 'lower-roman'];
10967
11240
  * A list item is normally wrapped using a LI tag. But this class is only a logical item,
10968
11241
  * it can be a LI tag, or another other type of node which means it is actually not a list item.
10969
11242
  * That can happen after we do "outdent" on a 1-level list item, then it becomes not a list item.
10970
- * @internal
10971
11243
  */
10972
11244
  var VListItem = /** @class */ (function () {
10973
11245
  /**
@@ -10981,12 +11253,13 @@ var VListItem = /** @class */ (function () {
10981
11253
  for (var _i = 1; _i < arguments.length; _i++) {
10982
11254
  listTypes[_i - 1] = arguments[_i];
10983
11255
  }
11256
+ this.newListStart = undefined;
10984
11257
  if (!node) {
10985
11258
  throw new Error('node must not be null');
10986
11259
  }
10987
11260
  this.node = safeInstanceOf_1.default(node, 'HTMLLIElement')
10988
11261
  ? node
10989
- : wrap_1.default(node, '<li style="display:block"></li>');
11262
+ : wrap_1.default(node, 4 /* BlockListItem */);
10990
11263
  var display = this.node.style.display;
10991
11264
  this.dummy = display != 'list-item' && display != '';
10992
11265
  // Always add a None list type in front of all other types to represent non-list scenario.
@@ -11010,6 +11283,12 @@ var VListItem = /** @class */ (function () {
11010
11283
  VListItem.prototype.getNode = function () {
11011
11284
  return this.node;
11012
11285
  };
11286
+ /**
11287
+ * Get the Start Number of the new List
11288
+ */
11289
+ VListItem.prototype.getNewListStart = function () {
11290
+ return this.newListStart;
11291
+ };
11013
11292
  /**
11014
11293
  * Check if a given node is contained by this list item
11015
11294
  * @param node The node to check
@@ -11088,6 +11367,13 @@ var VListItem = /** @class */ (function () {
11088
11367
  VListItem.prototype.setIsDummy = function (isDummy) {
11089
11368
  this.dummy = isDummy;
11090
11369
  };
11370
+ /**
11371
+ * Set the start Number of the new list
11372
+ * @param isDummy Whether the item is a dummy item
11373
+ */
11374
+ VListItem.prototype.setNewListStart = function (startNumber) {
11375
+ this.newListStart = startNumber;
11376
+ };
11091
11377
  /**
11092
11378
  * Write the change result back into DOM
11093
11379
  * @param listStack current stack of list elements
@@ -11119,7 +11405,14 @@ var VListItem = /** @class */ (function () {
11119
11405
  // 3. Add current node into deepest list element
11120
11406
  listStack[listStack.length - 1].appendChild(this.node);
11121
11407
  this.node.style.display = this.dummy ? 'block' : null;
11122
- // 4. If this is not a list item now, need to unwrap the LI node and do proper handling
11408
+ // 4. Inherit styles of the childelement to the li, so we are able to apply the styles to the ::marker
11409
+ if (this.listTypes.length > 1) {
11410
+ if (!(this.node.style.fontSize || this.node.style.color || this.node.style.fontFamily)) {
11411
+ var stylesToInherit = ['font-size', 'font-family', 'color'];
11412
+ setListItemStyle_1.default(this.node, stylesToInherit);
11413
+ }
11414
+ }
11415
+ // 5. If this is not a list item now, need to unwrap the LI node and do proper handling
11123
11416
  if (this.listTypes.length <= 1) {
11124
11417
  wrapIfNotBlockNode(getTagOfNode_1.default(this.node) == 'LI' ? getChildrenAndUnwrap(this.node) : [this.node], true /*checkFirst*/, true /*checkLast*/);
11125
11418
  }
@@ -11144,9 +11437,7 @@ function createListElement(newRoot, listType, nextLevel, originalRoot) {
11144
11437
  }
11145
11438
  else {
11146
11439
  // Remove all child nodes, they will be added back later when write back other items
11147
- while (originalRoot.firstChild) {
11148
- originalRoot.removeChild(originalRoot.firstChild);
11149
- }
11440
+ moveChildNodes_1.default(originalRoot);
11150
11441
  result = originalRoot;
11151
11442
  }
11152
11443
  }
@@ -11186,7 +11477,7 @@ function getChildrenAndUnwrap(node) {
11186
11477
  "use strict";
11187
11478
 
11188
11479
  Object.defineProperty(exports, "__esModule", { value: true });
11189
- var fromHtml_1 = __webpack_require__(/*! ../utils/fromHtml */ "./packages/roosterjs-editor-dom/lib/utils/fromHtml.ts");
11480
+ var createElement_1 = __webpack_require__(/*! ../utils/createElement */ "./packages/roosterjs-editor-dom/lib/utils/createElement.ts");
11190
11481
  var getRootListNode_1 = __webpack_require__(/*! ./getRootListNode */ "./packages/roosterjs-editor-dom/lib/list/getRootListNode.ts");
11191
11482
  var getSelectedBlockElementsInRegion_1 = __webpack_require__(/*! ../region/getSelectedBlockElementsInRegion */ "./packages/roosterjs-editor-dom/lib/region/getSelectedBlockElementsInRegion.ts");
11192
11483
  var isNodeInRegion_1 = __webpack_require__(/*! ../region/isNodeInRegion */ "./packages/roosterjs-editor-dom/lib/region/isNodeInRegion.ts");
@@ -11200,7 +11491,7 @@ var getLeafSibling_1 = __webpack_require__(/*! ../utils/getLeafSibling */ "./pac
11200
11491
  var getListTypeFromNode_1 = __webpack_require__(/*! ./getListTypeFromNode */ "./packages/roosterjs-editor-dom/lib/list/getListTypeFromNode.ts");
11201
11492
  var ListSelector = 'ol,ul';
11202
11493
  /**
11203
- * @internal
11494
+ * Create a VList object from the given region.
11204
11495
  * @param region The region to get VList from
11205
11496
  * @param includeSiblingLists True to also try get lists before and after the selection and merge them together,
11206
11497
  * false to only include the list for the selected blocks
@@ -11238,7 +11529,7 @@ function createVListFromRegion(region, includeSiblingLists, startNode) {
11238
11529
  }
11239
11530
  });
11240
11531
  if (nodes.length == 0 && !region.rootNode.firstChild) {
11241
- var newNode = fromHtml_1.default('<div><br></div>', region.rootNode.ownerDocument)[0];
11532
+ var newNode = createElement_1.default(1 /* EmptyLine */, region.rootNode.ownerDocument);
11242
11533
  region.rootNode.appendChild(newNode);
11243
11534
  nodes.push(newNode);
11244
11535
  region.fullSelectionStart = new Position_1.default(newNode, 0 /* Begin */);
@@ -11426,13 +11717,20 @@ exports.default = collapseNodesInRegion;
11426
11717
 
11427
11718
  "use strict";
11428
11719
 
11720
+ var _a;
11429
11721
  Object.defineProperty(exports, "__esModule", { value: true });
11430
11722
  var contains_1 = __webpack_require__(/*! ../utils/contains */ "./packages/roosterjs-editor-dom/lib/utils/contains.ts");
11431
11723
  var findClosestElementAncestor_1 = __webpack_require__(/*! ../utils/findClosestElementAncestor */ "./packages/roosterjs-editor-dom/lib/utils/findClosestElementAncestor.ts");
11432
11724
  var Position_1 = __webpack_require__(/*! ../selection/Position */ "./packages/roosterjs-editor-dom/lib/selection/Position.ts");
11433
11725
  var queryElements_1 = __webpack_require__(/*! ../utils/queryElements */ "./packages/roosterjs-editor-dom/lib/utils/queryElements.ts");
11434
- var regionTypeData_1 = __webpack_require__(/*! ./regionTypeData */ "./packages/roosterjs-editor-dom/lib/region/regionTypeData.ts");
11435
11726
  var getLeafSibling_1 = __webpack_require__(/*! ../utils/getLeafSibling */ "./packages/roosterjs-editor-dom/lib/utils/getLeafSibling.ts");
11727
+ var regionTypeData = (_a = {},
11728
+ _a[0 /* Table */] = {
11729
+ skipTags: ['TABLE'],
11730
+ outerSelector: 'table',
11731
+ innerSelector: 'td,th',
11732
+ },
11733
+ _a);
11436
11734
  /**
11437
11735
  * Get regions impacted by the given range under the root node
11438
11736
  * @param root Root node to get regions from
@@ -11443,7 +11741,7 @@ var getLeafSibling_1 = __webpack_require__(/*! ../utils/getLeafSibling */ "./pac
11443
11741
  function getRegionsFromRange(root, range, type) {
11444
11742
  var regions = [];
11445
11743
  if (root && range) {
11446
- var _a = regionTypeData_1.default[type], innerSelector = _a.innerSelector, skipTags = _a.skipTags;
11744
+ var _a = regionTypeData[type], innerSelector = _a.innerSelector, skipTags = _a.skipTags;
11447
11745
  var boundaryTree = buildBoundaryTree(root, range, type);
11448
11746
  var start = findClosestElementAncestor_1.default(range.startContainer, root, innerSelector) || root;
11449
11747
  var end = findClosestElementAncestor_1.default(range.endContainer, root, innerSelector) || root;
@@ -11481,7 +11779,7 @@ exports.getRegionCreator = getRegionCreator;
11481
11779
  */
11482
11780
  function buildBoundaryTree(root, range, type) {
11483
11781
  var allBoundaries = [{ innerNode: root, children: [] }];
11484
- var _a = regionTypeData_1.default[type], outerSelector = _a.outerSelector, innerSelector = _a.innerSelector;
11782
+ var _a = regionTypeData[type], outerSelector = _a.outerSelector, innerSelector = _a.innerSelector;
11485
11783
  var inSelectionOuterNode = queryElements_1.default(root, outerSelector, null /*callback*/, 2 /* InSelection */, range);
11486
11784
  // According to https://www.w3.org/TR/selectors-api/#queryselectorall, the result of querySelectorAll
11487
11785
  // is in document order, which is what we expect. So we don't need to sort the result here.
@@ -11588,7 +11886,7 @@ function areNodesValid(root, nodeBefore, nodeAfter, skipTags) {
11588
11886
 
11589
11887
  Object.defineProperty(exports, "__esModule", { value: true });
11590
11888
  var ContentTraverser_1 = __webpack_require__(/*! ../contentTraverser/ContentTraverser */ "./packages/roosterjs-editor-dom/lib/contentTraverser/ContentTraverser.ts");
11591
- var fromHtml_1 = __webpack_require__(/*! ../utils/fromHtml */ "./packages/roosterjs-editor-dom/lib/utils/fromHtml.ts");
11889
+ var createElement_1 = __webpack_require__(/*! ../utils/createElement */ "./packages/roosterjs-editor-dom/lib/utils/createElement.ts");
11592
11890
  var getBlockElementAtNode_1 = __webpack_require__(/*! ../blockElements/getBlockElementAtNode */ "./packages/roosterjs-editor-dom/lib/blockElements/getBlockElementAtNode.ts");
11593
11891
  var getSelectionRangeInRegion_1 = __webpack_require__(/*! ./getSelectionRangeInRegion */ "./packages/roosterjs-editor-dom/lib/region/getSelectionRangeInRegion.ts");
11594
11892
  var shouldSkipNode_1 = __webpack_require__(/*! ../utils/shouldSkipNode */ "./packages/roosterjs-editor-dom/lib/utils/shouldSkipNode.ts");
@@ -11622,7 +11920,7 @@ function getSelectedBlockElementsInRegion(regionBase, createBlockIfEmpty) {
11622
11920
  });
11623
11921
  }
11624
11922
  if (blocks.length == 0 && regionBase && !regionBase.rootNode.firstChild && createBlockIfEmpty) {
11625
- var newNode = fromHtml_1.default('<div><br></div>', regionBase.rootNode.ownerDocument)[0];
11923
+ var newNode = createElement_1.default(1 /* EmptyLine */, regionBase.rootNode.ownerDocument);
11626
11924
  regionBase.rootNode.appendChild(newNode);
11627
11925
  blocks.push(getBlockElementAtNode_1.default(regionBase.rootNode, newNode));
11628
11926
  }
@@ -11748,9 +12046,9 @@ var getBlockElementAtNode_1 = __webpack_require__(/*! ../blockElements/getBlockE
11748
12046
  var getPredefinedCssForElement_1 = __webpack_require__(/*! ../htmlSanitizer/getPredefinedCssForElement */ "./packages/roosterjs-editor-dom/lib/htmlSanitizer/getPredefinedCssForElement.ts");
11749
12047
  var getStyles_1 = __webpack_require__(/*! ../style/getStyles */ "./packages/roosterjs-editor-dom/lib/style/getStyles.ts");
11750
12048
  var isNodeInRegion_1 = __webpack_require__(/*! ../region/isNodeInRegion */ "./packages/roosterjs-editor-dom/lib/region/isNodeInRegion.ts");
12049
+ var safeInstanceOf_1 = __webpack_require__(/*! ../utils/safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts");
11751
12050
  var setStyles_1 = __webpack_require__(/*! ../style/setStyles */ "./packages/roosterjs-editor-dom/lib/style/setStyles.ts");
11752
12051
  var collapseNodes_1 = __webpack_require__(/*! ../utils/collapseNodes */ "./packages/roosterjs-editor-dom/lib/utils/collapseNodes.ts");
11753
- var __1 = __webpack_require__(/*! .. */ "./packages/roosterjs-editor-dom/lib/index.ts");
11754
12052
  /**
11755
12053
  * Merge a BlockElement of given node after another node
11756
12054
  * @param region Region to operate in
@@ -11771,7 +12069,7 @@ function mergeBlocksInRegion(region, refNode, targetNode) {
11771
12069
  // Copy styles of parent nodes into blockRoot
11772
12070
  for (var node = blockRoot; contains_1.default(commonContainer, node);) {
11773
12071
  var parent_1 = node.parentNode;
11774
- if (__1.safeInstanceOf(parent_1, 'HTMLElement')) {
12072
+ if (safeInstanceOf_1.default(parent_1, 'HTMLElement')) {
11775
12073
  var styles = __assign(__assign(__assign({}, (getPredefinedCssForElement_1.default(parent_1) || {})), getStyles_1.default(parent_1)), getStyles_1.default(blockRoot));
11776
12074
  setStyles_1.default(blockRoot, styles);
11777
12075
  }
@@ -11793,32 +12091,6 @@ function mergeBlocksInRegion(region, refNode, targetNode) {
11793
12091
  exports.default = mergeBlocksInRegion;
11794
12092
 
11795
12093
 
11796
- /***/ }),
11797
-
11798
- /***/ "./packages/roosterjs-editor-dom/lib/region/regionTypeData.ts":
11799
- /*!********************************************************************!*\
11800
- !*** ./packages/roosterjs-editor-dom/lib/region/regionTypeData.ts ***!
11801
- \********************************************************************/
11802
- /*! no static exports found */
11803
- /***/ (function(module, exports, __webpack_require__) {
11804
-
11805
- "use strict";
11806
-
11807
- var _a;
11808
- Object.defineProperty(exports, "__esModule", { value: true });
11809
- var regionTypeData = (_a = {},
11810
- _a[0 /* Table */] = {
11811
- skipTags: ['TABLE'],
11812
- outerSelector: 'table',
11813
- innerSelector: 'td,th',
11814
- },
11815
- _a);
11816
- /**
11817
- * @internal
11818
- */
11819
- exports.default = regionTypeData;
11820
-
11821
-
11822
12094
  /***/ }),
11823
12095
 
11824
12096
  /***/ "./packages/roosterjs-editor-dom/lib/selection/Position.ts":
@@ -12290,6 +12562,7 @@ exports.default = getHtmlWithSelectionPath;
12290
12562
  "use strict";
12291
12563
 
12292
12564
  Object.defineProperty(exports, "__esModule", { value: true });
12565
+ var createElement_1 = __webpack_require__(/*! ../utils/createElement */ "./packages/roosterjs-editor-dom/lib/utils/createElement.ts");
12293
12566
  var createRange_1 = __webpack_require__(/*! ./createRange */ "./packages/roosterjs-editor-dom/lib/selection/createRange.ts");
12294
12567
  var normalizeRect_1 = __webpack_require__(/*! ../utils/normalizeRect */ "./packages/roosterjs-editor-dom/lib/utils/normalizeRect.ts");
12295
12568
  /**
@@ -12315,9 +12588,7 @@ function getPositionRect(position) {
12315
12588
  }
12316
12589
  // 3) if node is text node, try inserting a SPAN and get the rect of SPAN for others
12317
12590
  if (position.node.nodeType == 3 /* Text */) {
12318
- var document_1 = position.node.ownerDocument;
12319
- var span = document_1.createElement('SPAN');
12320
- span.innerHTML = '\u200b';
12591
+ var span = createElement_1.default({ tag: 'span', children: ['\u200b'] }, position.node.ownerDocument);
12321
12592
  range = createRange_1.default(position);
12322
12593
  range.insertNode(span);
12323
12594
  rect = span.getBoundingClientRect && normalizeRect_1.default(span.getBoundingClientRect());
@@ -12485,6 +12756,7 @@ function areAllPreviousNodesEmpty(node) {
12485
12756
 
12486
12757
  Object.defineProperty(exports, "__esModule", { value: true });
12487
12758
  var createRange_1 = __webpack_require__(/*! ./createRange */ "./packages/roosterjs-editor-dom/lib/selection/createRange.ts");
12759
+ var LastCommentRegex = /<!--([^-]+)-->$/;
12488
12760
  /**
12489
12761
  * Restore inner Html of a root element from given html string. If the string contains selection path,
12490
12762
  * remove the selection path and return a range represented by the path
@@ -12492,26 +12764,45 @@ var createRange_1 = __webpack_require__(/*! ./createRange */ "./packages/rooster
12492
12764
  * @param html The html to restore
12493
12765
  * @returns A selection range if the html contains a valid selection path, otherwise null
12494
12766
  */
12495
- function setHtmlWithSelectionPath(rootNode, html) {
12496
- rootNode.innerHTML = html || '';
12497
- var path = null;
12498
- var pathComment = rootNode.lastChild;
12499
- try {
12500
- path =
12501
- pathComment &&
12502
- pathComment.nodeType == 8 /* Comment */ &&
12503
- JSON.parse(pathComment.nodeValue);
12504
- if (path && path.end && path.end.length > 0 && path.start && path.start.length > 0) {
12505
- rootNode.removeChild(pathComment);
12506
- }
12507
- else {
12508
- path = null;
12509
- }
12767
+ function setHtmlWithSelectionPath(rootNode, html, trustedHTMLHandler) {
12768
+ if (!rootNode) {
12769
+ return null;
12510
12770
  }
12511
- catch (_a) { }
12771
+ html = html || '';
12772
+ var lastComment = LastCommentRegex.exec(html);
12773
+ rootNode.innerHTML = (trustedHTMLHandler === null || trustedHTMLHandler === void 0 ? void 0 : trustedHTMLHandler(html)) || html;
12774
+ var path = getSelectionPath(rootNode, lastComment === null || lastComment === void 0 ? void 0 : lastComment[1]);
12512
12775
  return path && createRange_1.default(rootNode, path.start, path.end);
12513
12776
  }
12514
12777
  exports.default = setHtmlWithSelectionPath;
12778
+ function getSelectionPath(root, alternativeComment) {
12779
+ var _a, _b, _c;
12780
+ var pathCommentValue = '';
12781
+ var pathCommentNode = null;
12782
+ var path = null;
12783
+ if (((_a = root.lastChild) === null || _a === void 0 ? void 0 : _a.nodeType) == 8 /* Comment */) {
12784
+ pathCommentNode = root.lastChild;
12785
+ pathCommentValue = pathCommentNode.nodeValue;
12786
+ }
12787
+ else {
12788
+ pathCommentValue = alternativeComment;
12789
+ }
12790
+ if (pathCommentValue) {
12791
+ try {
12792
+ path = JSON.parse(pathCommentValue);
12793
+ if (path && ((_b = path.start) === null || _b === void 0 ? void 0 : _b.length) > 0 && ((_c = path.end) === null || _c === void 0 ? void 0 : _c.length) > 0) {
12794
+ if (pathCommentNode) {
12795
+ root.removeChild(pathCommentNode);
12796
+ }
12797
+ }
12798
+ else {
12799
+ path = null;
12800
+ }
12801
+ }
12802
+ catch (_d) { }
12803
+ }
12804
+ return path;
12805
+ }
12515
12806
 
12516
12807
 
12517
12808
  /***/ }),
@@ -12784,6 +13075,7 @@ exports.default = setStyles;
12784
13075
  "use strict";
12785
13076
 
12786
13077
  Object.defineProperty(exports, "__esModule", { value: true });
13078
+ var moveChildNodes_1 = __webpack_require__(/*! ../utils/moveChildNodes */ "./packages/roosterjs-editor-dom/lib/utils/moveChildNodes.ts");
12787
13079
  var normalizeRect_1 = __webpack_require__(/*! ../utils/normalizeRect */ "./packages/roosterjs-editor-dom/lib/utils/normalizeRect.ts");
12788
13080
  var safeInstanceOf_1 = __webpack_require__(/*! ../utils/safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts");
12789
13081
  var toArray_1 = __webpack_require__(/*! ../utils/toArray */ "./packages/roosterjs-editor-dom/lib/utils/toArray.ts");
@@ -12839,7 +13131,7 @@ var VTable = /** @class */ (function () {
12839
13131
  VTable.prototype.writeBack = function () {
12840
13132
  var _this = this;
12841
13133
  if (this.cells) {
12842
- moveChildren(this.table);
13134
+ moveChildNodes_1.default(this.table);
12843
13135
  this.cells.forEach(function (row, r) {
12844
13136
  var tr = cloneNode(_this.trs[r % 2] || _this.trs[0]);
12845
13137
  _this.table.appendChild(tr);
@@ -12890,6 +13182,7 @@ var VTable = /** @class */ (function () {
12890
13182
  }
12891
13183
  var currentRow = this.cells[this.row];
12892
13184
  var currentCell = currentRow[this.col];
13185
+ var style = currentCell.td.style;
12893
13186
  switch (operation) {
12894
13187
  case 0 /* InsertAbove */:
12895
13188
  this.cells.splice(this.row, 0, currentRow.map(cloneCell));
@@ -12965,7 +13258,7 @@ var VTable = /** @class */ (function () {
12965
13258
  var aboveCell = rowIndex < this.row ? cell : currentCell;
12966
13259
  var belowCell = rowIndex < this.row ? currentCell : cell;
12967
13260
  if (aboveCell.td.colSpan == belowCell.td.colSpan) {
12968
- moveChildren(belowCell.td, aboveCell.td);
13261
+ moveChildNodes_1.default(aboveCell.td, belowCell.td, true /*keepExistingChildren*/);
12969
13262
  belowCell.td = null;
12970
13263
  belowCell.spanAbove = true;
12971
13264
  }
@@ -12982,7 +13275,7 @@ var VTable = /** @class */ (function () {
12982
13275
  var leftCell = colIndex < this.col ? cell : currentCell;
12983
13276
  var rightCell = colIndex < this.col ? currentCell : cell;
12984
13277
  if (leftCell.td.rowSpan == rightCell.td.rowSpan) {
12985
- moveChildren(rightCell.td, leftCell.td);
13278
+ moveChildNodes_1.default(leftCell.td, rightCell.td, true /*keepExistingChildren*/);
12986
13279
  rightCell.td = null;
12987
13280
  rightCell.spanLeft = true;
12988
13281
  }
@@ -13022,6 +13315,33 @@ var VTable = /** @class */ (function () {
13022
13315
  });
13023
13316
  }
13024
13317
  break;
13318
+ case 13 /* AlignCenter */:
13319
+ this.table.setAttribute('align', 'center');
13320
+ break;
13321
+ case 14 /* AlignLeft */:
13322
+ this.table.setAttribute('align', 'left');
13323
+ break;
13324
+ case 15 /* AlignRight */:
13325
+ this.table.setAttribute('align', 'right');
13326
+ break;
13327
+ case 17 /* AlignCellCenter */:
13328
+ style.textAlign = 'center';
13329
+ break;
13330
+ case 16 /* AlignCellLeft */:
13331
+ style.textAlign = 'left';
13332
+ break;
13333
+ case 18 /* AlignCellRight */:
13334
+ style.textAlign = 'right';
13335
+ break;
13336
+ case 19 /* AlignCellTop */:
13337
+ style.verticalAlign = 'top';
13338
+ break;
13339
+ case 20 /* AlignCellMiddle */:
13340
+ style.verticalAlign = 'middle';
13341
+ break;
13342
+ case 21 /* AlignCellBottom */:
13343
+ style.verticalAlign = 'bottom';
13344
+ break;
13025
13345
  }
13026
13346
  };
13027
13347
  /**
@@ -13258,21 +13578,6 @@ function cloneNode(node) {
13258
13578
  }
13259
13579
  return newNode;
13260
13580
  }
13261
- /**
13262
- * Move all children from one node to another
13263
- * @param fromNode The source node to move children from
13264
- * @param toNode Target node. If not passed, children nodes of source node will be removed
13265
- */
13266
- function moveChildren(fromNode, toNode) {
13267
- while (fromNode.firstChild) {
13268
- if (toNode) {
13269
- toNode.appendChild(fromNode.firstChild);
13270
- }
13271
- else {
13272
- fromNode.removeChild(fromNode.firstChild);
13273
- }
13274
- }
13275
- }
13276
13581
 
13277
13582
 
13278
13583
  /***/ }),
@@ -13335,13 +13640,205 @@ function getBrowserInfo(userAgent, appVersion) {
13335
13640
  isIEOrEdge: isIE || isEdge,
13336
13641
  };
13337
13642
  }
13338
- exports.getBrowserInfo = getBrowserInfo;
13339
- /**
13340
- * Browser object contains browser and operating system information of current environment
13341
- */
13342
- exports.Browser = window
13343
- ? getBrowserInfo(window.navigator.userAgent, window.navigator.appVersion)
13344
- : {};
13643
+ exports.getBrowserInfo = getBrowserInfo;
13644
+ /**
13645
+ * Browser object contains browser and operating system information of current environment
13646
+ */
13647
+ exports.Browser = window
13648
+ ? getBrowserInfo(window.navigator.userAgent, window.navigator.appVersion)
13649
+ : {};
13650
+
13651
+
13652
+ /***/ }),
13653
+
13654
+ /***/ "./packages/roosterjs-editor-dom/lib/utils/adjustInsertPosition.ts":
13655
+ /*!*************************************************************************!*\
13656
+ !*** ./packages/roosterjs-editor-dom/lib/utils/adjustInsertPosition.ts ***!
13657
+ \*************************************************************************/
13658
+ /*! no static exports found */
13659
+ /***/ (function(module, exports, __webpack_require__) {
13660
+
13661
+ "use strict";
13662
+
13663
+ Object.defineProperty(exports, "__esModule", { value: true });
13664
+ var changeElementTag_1 = __webpack_require__(/*! ./changeElementTag */ "./packages/roosterjs-editor-dom/lib/utils/changeElementTag.ts");
13665
+ var contains_1 = __webpack_require__(/*! ./contains */ "./packages/roosterjs-editor-dom/lib/utils/contains.ts");
13666
+ var createRange_1 = __webpack_require__(/*! ../selection/createRange */ "./packages/roosterjs-editor-dom/lib/selection/createRange.ts");
13667
+ var findClosestElementAncestor_1 = __webpack_require__(/*! ./findClosestElementAncestor */ "./packages/roosterjs-editor-dom/lib/utils/findClosestElementAncestor.ts");
13668
+ var getBlockElementAtNode_1 = __webpack_require__(/*! ../blockElements/getBlockElementAtNode */ "./packages/roosterjs-editor-dom/lib/blockElements/getBlockElementAtNode.ts");
13669
+ var getTagOfNode_1 = __webpack_require__(/*! ./getTagOfNode */ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts");
13670
+ var isNodeEmpty_1 = __webpack_require__(/*! ./isNodeEmpty */ "./packages/roosterjs-editor-dom/lib/utils/isNodeEmpty.ts");
13671
+ var isPositionAtBeginningOf_1 = __webpack_require__(/*! ../selection/isPositionAtBeginningOf */ "./packages/roosterjs-editor-dom/lib/selection/isPositionAtBeginningOf.ts");
13672
+ var isVoidHtmlElement_1 = __webpack_require__(/*! ./isVoidHtmlElement */ "./packages/roosterjs-editor-dom/lib/utils/isVoidHtmlElement.ts");
13673
+ var LinkInlineElement_1 = __webpack_require__(/*! ../inlineElements/LinkInlineElement */ "./packages/roosterjs-editor-dom/lib/inlineElements/LinkInlineElement.ts");
13674
+ var Position_1 = __webpack_require__(/*! ../selection/Position */ "./packages/roosterjs-editor-dom/lib/selection/Position.ts");
13675
+ var PositionContentSearcher_1 = __webpack_require__(/*! ../contentTraverser/PositionContentSearcher */ "./packages/roosterjs-editor-dom/lib/contentTraverser/PositionContentSearcher.ts");
13676
+ var queryElements_1 = __webpack_require__(/*! ./queryElements */ "./packages/roosterjs-editor-dom/lib/utils/queryElements.ts");
13677
+ var splitTextNode_1 = __webpack_require__(/*! ./splitTextNode */ "./packages/roosterjs-editor-dom/lib/utils/splitTextNode.ts");
13678
+ var toArray_1 = __webpack_require__(/*! ./toArray */ "./packages/roosterjs-editor-dom/lib/utils/toArray.ts");
13679
+ var unwrap_1 = __webpack_require__(/*! ./unwrap */ "./packages/roosterjs-editor-dom/lib/utils/unwrap.ts");
13680
+ var VTable_1 = __webpack_require__(/*! ../table/VTable */ "./packages/roosterjs-editor-dom/lib/table/VTable.ts");
13681
+ var wrap_1 = __webpack_require__(/*! ./wrap */ "./packages/roosterjs-editor-dom/lib/utils/wrap.ts");
13682
+ var splitParentNode_1 = __webpack_require__(/*! ./splitParentNode */ "./packages/roosterjs-editor-dom/lib/utils/splitParentNode.ts");
13683
+ var adjustSteps = [
13684
+ adjustInsertPositionForHyperLink,
13685
+ adjustInsertPositionForStructuredNode,
13686
+ adjustInsertPositionForParagraph,
13687
+ adjustInsertPositionForVoidElement,
13688
+ adjustInsertPositionForMoveCursorOutOfALink,
13689
+ ];
13690
+ /**
13691
+ * Adjust position for A tag don't be nested inside another A tag.
13692
+ */
13693
+ function adjustInsertPositionForHyperLink(root, nodeToInsert, position, range) {
13694
+ var _a, _b;
13695
+ var blockElement = getBlockElementAtNode_1.default(root, position.node);
13696
+ if (blockElement) {
13697
+ // Find the first <A> tag within current block which covers current selection
13698
+ // If there are more than one nested, let's handle the first one only since that is not a common scenario.
13699
+ var anchor = queryElements_1.default(root, 'a[href]', null /*forEachCallback*/, 1 /* OnSelection */, createRange_1.default(position)).filter(function (a) { return blockElement.contains(a); })[0];
13700
+ // If this is about to insert node to an empty A tag, clear the A tag and reset position
13701
+ if (anchor && isNodeEmpty_1.default(anchor)) {
13702
+ position = new Position_1.default(anchor, -2 /* Before */);
13703
+ safeRemove(anchor);
13704
+ anchor = null;
13705
+ }
13706
+ // If this is about to insert nodes which contains A tag into another A tag, need to break current A tag
13707
+ // otherwise we will have nested A tags which is a wrong HTML structure
13708
+ if (anchor && ((_a = nodeToInsert) === null || _a === void 0 ? void 0 : _a.querySelector) && ((_b = nodeToInsert) === null || _b === void 0 ? void 0 : _b.querySelector('a[href]'))) {
13709
+ var normalizedPosition = position.normalize();
13710
+ var parentNode = normalizedPosition.node.parentNode;
13711
+ var nextNode = normalizedPosition.node.nodeType == 3 /* Text */
13712
+ ? splitTextNode_1.default(normalizedPosition.node, normalizedPosition.offset, false /*returnFirstPart*/)
13713
+ : normalizedPosition.isAtEnd
13714
+ ? normalizedPosition.node.nextSibling
13715
+ : normalizedPosition.node;
13716
+ var splitter = root.ownerDocument.createTextNode('');
13717
+ parentNode.insertBefore(splitter, nextNode);
13718
+ while (contains_1.default(anchor, splitter)) {
13719
+ splitter = splitParentNode_1.splitBalancedNodeRange(splitter);
13720
+ }
13721
+ position = new Position_1.default(splitter, -2 /* Before */);
13722
+ safeRemove(splitter);
13723
+ }
13724
+ }
13725
+ return position;
13726
+ }
13727
+ /**
13728
+ * Adjust position for a node don't be nested inside tags like BR, LI, TD.
13729
+ */
13730
+ function adjustInsertPositionForStructuredNode(root, nodeToInsert, position, range) {
13731
+ var rootNodeToInsert = nodeToInsert;
13732
+ if (rootNodeToInsert.nodeType == 11 /* DocumentFragment */) {
13733
+ var rootNodes = toArray_1.default(rootNodeToInsert.childNodes).filter(function (n) { return getTagOfNode_1.default(n) != 'BR'; });
13734
+ rootNodeToInsert = rootNodes.length == 1 ? rootNodes[0] : null;
13735
+ }
13736
+ var tag = getTagOfNode_1.default(rootNodeToInsert);
13737
+ var hasBrNextToRoot = tag && getTagOfNode_1.default(rootNodeToInsert.nextSibling) == 'BR';
13738
+ var listItem = findClosestElementAncestor_1.default(position.node, root, 'LI');
13739
+ var listNode = listItem && findClosestElementAncestor_1.default(listItem, root, 'OL,UL');
13740
+ var tdNode = findClosestElementAncestor_1.default(position.node, root, 'TD,TH');
13741
+ var trNode = tdNode && findClosestElementAncestor_1.default(tdNode, root, 'TR');
13742
+ if (tag == 'LI') {
13743
+ tag = listNode ? getTagOfNode_1.default(listNode) : 'UL';
13744
+ rootNodeToInsert = wrap_1.default(rootNodeToInsert, tag);
13745
+ }
13746
+ if ((tag == 'OL' || tag == 'UL') && getTagOfNode_1.default(rootNodeToInsert.firstChild) == 'LI') {
13747
+ var shouldInsertListAsText = !rootNodeToInsert.firstChild.nextSibling && !hasBrNextToRoot;
13748
+ if (hasBrNextToRoot && rootNodeToInsert.parentNode) {
13749
+ safeRemove(rootNodeToInsert.nextSibling);
13750
+ }
13751
+ if (shouldInsertListAsText) {
13752
+ unwrap_1.default(rootNodeToInsert.firstChild);
13753
+ unwrap_1.default(rootNodeToInsert);
13754
+ }
13755
+ else if (getTagOfNode_1.default(listNode) == tag) {
13756
+ unwrap_1.default(rootNodeToInsert);
13757
+ position = new Position_1.default(listItem, isPositionAtBeginningOf_1.default(position, listItem)
13758
+ ? -2 /* Before */
13759
+ : -3 /* After */);
13760
+ }
13761
+ }
13762
+ else if (tag == 'TABLE' && trNode) {
13763
+ // When inserting a table into a table, if these tables have the same column count, and
13764
+ // current position is at beginning of a row, then merge these two tables
13765
+ var newTable = new VTable_1.default(rootNodeToInsert);
13766
+ var currentTable = new VTable_1.default(tdNode);
13767
+ if (currentTable.col == 0 &&
13768
+ tdNode == currentTable.getCell(currentTable.row, 0).td &&
13769
+ newTable.cells[0] &&
13770
+ newTable.cells[0].length == currentTable.cells[0].length &&
13771
+ isPositionAtBeginningOf_1.default(position, tdNode)) {
13772
+ if (getTagOfNode_1.default(rootNodeToInsert.firstChild) == 'TBODY' &&
13773
+ !rootNodeToInsert.firstChild.nextSibling) {
13774
+ unwrap_1.default(rootNodeToInsert.firstChild);
13775
+ }
13776
+ unwrap_1.default(rootNodeToInsert);
13777
+ position = new Position_1.default(trNode, -3 /* After */);
13778
+ }
13779
+ }
13780
+ return position;
13781
+ }
13782
+ /**
13783
+ * Change P tag to DIV, when a new node when insert node.
13784
+ */
13785
+ function adjustInsertPositionForParagraph(root, nodeToInsert, position, range) {
13786
+ if (getTagOfNode_1.default(position.node) == 'P') {
13787
+ // Insert into a P tag may cause issues when the inserted content contains any block element.
13788
+ // Change P tag to DIV to make sure it works well
13789
+ var pos = position.normalize();
13790
+ var div = changeElementTag_1.default(position.node, 'div');
13791
+ if (pos.node != div) {
13792
+ position = pos;
13793
+ }
13794
+ }
13795
+ return position;
13796
+ }
13797
+ /**
13798
+ * Adjust position for a node that can have children.
13799
+ */
13800
+ function adjustInsertPositionForVoidElement(root, nodeToInsert, position, range) {
13801
+ if (isVoidHtmlElement_1.default(position.node)) {
13802
+ position = new Position_1.default(position.node, position.isAtEnd ? -3 /* After */ : -2 /* Before */);
13803
+ }
13804
+ return position;
13805
+ }
13806
+ /**
13807
+ * Adjust the position cursor out of link when a new node is inserted.
13808
+ */
13809
+ function adjustInsertPositionForMoveCursorOutOfALink(root, nodeToInsert, position, range) {
13810
+ if (range && range.collapsed) {
13811
+ var searcher = new PositionContentSearcher_1.default(root, Position_1.default.getStart(range));
13812
+ var inlineElementBefore = searcher.getInlineElementBefore();
13813
+ var inlineElementAfter = searcher.getInlineElementAfter();
13814
+ if (inlineElementBefore instanceof LinkInlineElement_1.default) {
13815
+ position = new Position_1.default(inlineElementBefore.getContainerNode(), -3 /* After */);
13816
+ }
13817
+ else if (inlineElementAfter instanceof LinkInlineElement_1.default) {
13818
+ position = new Position_1.default(inlineElementAfter.getContainerNode(), -2 /* Before */);
13819
+ }
13820
+ }
13821
+ return position;
13822
+ }
13823
+ /**
13824
+ *
13825
+ * @param root the contentDiv of the ditor
13826
+ * @param nodeToInsert the node to be inserted
13827
+ * @param position the position of the node to be inserted
13828
+ * @param range the range current or cached range of the editor
13829
+ * @returns the adjusted position of the inserted node
13830
+ */
13831
+ function adjustInsertPositionBySteps(root, nodeToInsert, position, range) {
13832
+ adjustSteps.forEach(function (handler) {
13833
+ position = handler(root, nodeToInsert, position, range);
13834
+ });
13835
+ return position;
13836
+ }
13837
+ exports.default = adjustInsertPositionBySteps;
13838
+ function safeRemove(node) {
13839
+ var _a;
13840
+ (_a = node === null || node === void 0 ? void 0 : node.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(node);
13841
+ }
13345
13842
 
13346
13843
 
13347
13844
  /***/ }),
@@ -13504,6 +14001,7 @@ exports.default = arrayPush;
13504
14001
  Object.defineProperty(exports, "__esModule", { value: true });
13505
14002
  var getComputedStyles_1 = __webpack_require__(/*! ./getComputedStyles */ "./packages/roosterjs-editor-dom/lib/utils/getComputedStyles.ts");
13506
14003
  var getTagOfNode_1 = __webpack_require__(/*! ./getTagOfNode */ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts");
14004
+ var moveChildNodes_1 = __webpack_require__(/*! ./moveChildNodes */ "./packages/roosterjs-editor-dom/lib/utils/moveChildNodes.ts");
13507
14005
  function changeElementTag(element, newTag) {
13508
14006
  var _a;
13509
14007
  if (!element || !newTag) {
@@ -13514,9 +14012,7 @@ function changeElementTag(element, newTag) {
13514
14012
  var attr = element.attributes[i];
13515
14013
  newElement.setAttribute(attr.name, attr.value);
13516
14014
  }
13517
- while (element.firstChild) {
13518
- newElement.appendChild(element.firstChild);
13519
- }
14015
+ moveChildNodes_1.default(newElement, element);
13520
14016
  if (getTagOfNode_1.default(element) == 'P' || getTagOfNode_1.default(newElement) == 'P') {
13521
14017
  _a = getComputedStyles_1.default(element, [
13522
14018
  'margin-top',
@@ -13582,6 +14078,7 @@ function collapseNodes(root, start, end, canSplitParent) {
13582
14078
  }
13583
14079
  exports.default = collapseNodes;
13584
14080
  /**
14081
+ * @internal
13585
14082
  * Collapse a node by traversing its parent nodes until we get the common ancestor node of node and ref node
13586
14083
  * @param root Root node, traversing will be limited under this scope
13587
14084
  * @param node The node to collapse
@@ -13656,6 +14153,116 @@ function internalContains(container, contained) {
13656
14153
  }
13657
14154
 
13658
14155
 
14156
+ /***/ }),
14157
+
14158
+ /***/ "./packages/roosterjs-editor-dom/lib/utils/createElement.ts":
14159
+ /*!******************************************************************!*\
14160
+ !*** ./packages/roosterjs-editor-dom/lib/utils/createElement.ts ***!
14161
+ \******************************************************************/
14162
+ /*! no static exports found */
14163
+ /***/ (function(module, exports, __webpack_require__) {
14164
+
14165
+ "use strict";
14166
+
14167
+ var _a;
14168
+ Object.defineProperty(exports, "__esModule", { value: true });
14169
+ var safeInstanceOf_1 = __webpack_require__(/*! ./safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts");
14170
+ var Browser_1 = __webpack_require__(/*! ./Browser */ "./packages/roosterjs-editor-dom/lib/utils/Browser.ts");
14171
+ /**
14172
+ * All known CreateElementData used by roosterjs to create elements
14173
+ */
14174
+ exports.KnownCreateElementData = (_a = {},
14175
+ _a[0 /* None */] = null,
14176
+ // Edge can sometimes lose current format when Enter to new line.
14177
+ // So here we add an extra SPAN for Edge to workaround this bug
14178
+ _a[1 /* EmptyLine */] = Browser_1.Browser.isEdge
14179
+ ? { tag: 'div', children: [{ tag: 'span', children: [{ tag: 'br' }] }] }
14180
+ : { tag: 'div', children: [{ tag: 'br' }] },
14181
+ _a[2 /* BlockquoteWrapper */] = {
14182
+ tag: 'blockquote',
14183
+ style: 'margin-top:0;margin-bottom:0',
14184
+ },
14185
+ _a[3 /* CopyPasteTempDiv */] = {
14186
+ tag: 'div',
14187
+ style: 'width: 1px; height: 1px; overflow: hidden; position: fixed; top: 0; left; 0; -webkit-user-select: text',
14188
+ attributes: {
14189
+ contenteditable: 'true',
14190
+ },
14191
+ },
14192
+ _a[4 /* BlockListItem */] = { tag: 'li', style: 'display:block' },
14193
+ _a[5 /* ContextMenuWrapper */] = {
14194
+ tag: 'div',
14195
+ style: 'position: fixed; width: 0; height: 0',
14196
+ },
14197
+ _a[6 /* ImageEditWrapper */] = {
14198
+ tag: 'div',
14199
+ style: 'width:100%;height:100%;position:relative;overflow:hidden',
14200
+ },
14201
+ _a[7 /* TableHorizontalResizer */] = {
14202
+ tag: 'div',
14203
+ style: 'position: fixed; cursor: row-resize; user-select: none',
14204
+ },
14205
+ _a[8 /* TableVerticalResizer */] = {
14206
+ tag: 'div',
14207
+ style: 'position: fixed; cursor: col-resize; user-select: none',
14208
+ },
14209
+ _a[9 /* TableResizerLTR */] = {
14210
+ tag: 'div',
14211
+ style: 'position: fixed; cursor: nw-resize; user-select: none; border: 1px solid #808080',
14212
+ },
14213
+ _a[10 /* TableResizerRTL */] = {
14214
+ tag: 'div',
14215
+ style: 'position: fixed; cursor: ne-resize; user-select: none; border: 1px solid #808080',
14216
+ },
14217
+ _a);
14218
+ /**
14219
+ * Create DOM element from the given CreateElementData
14220
+ * @param elementData The CreateElementData or an index of a known CreateElementData used for creating this element
14221
+ * @param document The document to create the element from
14222
+ * @returns The root DOM element just created
14223
+ */
14224
+ function createElement(elementData, document) {
14225
+ if (typeof elementData == 'number') {
14226
+ elementData = exports.KnownCreateElementData[elementData];
14227
+ }
14228
+ if (!elementData || !elementData.tag) {
14229
+ return null;
14230
+ }
14231
+ var tag = elementData.tag, namespace = elementData.namespace, className = elementData.className, style = elementData.style, dataset = elementData.dataset, attributes = elementData.attributes, children = elementData.children;
14232
+ var result = namespace
14233
+ ? document.createElementNS(namespace, tag)
14234
+ : document.createElement(tag);
14235
+ if (style) {
14236
+ result.setAttribute('style', style);
14237
+ }
14238
+ if (className) {
14239
+ result.className = className;
14240
+ }
14241
+ if (dataset && safeInstanceOf_1.default(result, 'HTMLElement')) {
14242
+ Object.keys(dataset).forEach(function (datasetName) {
14243
+ result.dataset[datasetName] = dataset[datasetName];
14244
+ });
14245
+ }
14246
+ if (attributes) {
14247
+ Object.keys(attributes).forEach(function (attrName) {
14248
+ result.setAttribute(attrName, attributes[attrName]);
14249
+ });
14250
+ }
14251
+ if (children) {
14252
+ children.forEach(function (child) {
14253
+ if (typeof child === 'string') {
14254
+ result.appendChild(document.createTextNode(child));
14255
+ }
14256
+ else if (child) {
14257
+ result.appendChild(createElement(child, document));
14258
+ }
14259
+ });
14260
+ }
14261
+ return result;
14262
+ }
14263
+ exports.default = createElement;
14264
+
14265
+
13659
14266
  /***/ }),
13660
14267
 
13661
14268
  /***/ "./packages/roosterjs-editor-dom/lib/utils/findClosestElementAncestor.ts":
@@ -13710,6 +14317,7 @@ exports.default = findClosestElementAncestor;
13710
14317
  Object.defineProperty(exports, "__esModule", { value: true });
13711
14318
  var toArray_1 = __webpack_require__(/*! ./toArray */ "./packages/roosterjs-editor-dom/lib/utils/toArray.ts");
13712
14319
  /**
14320
+ * @deprecated
13713
14321
  * Creates an HTML node array from html
13714
14322
  * @param html the html string to create HTML elements from
13715
14323
  * @param ownerDocument Owner document of the result HTML elements
@@ -13754,7 +14362,8 @@ function getComputedStyles(node, styleNames) {
13754
14362
  if (styles) {
13755
14363
  for (var _i = 0, styleNames_1 = styleNames; _i < styleNames_1.length; _i++) {
13756
14364
  var style = styleNames_1[_i];
13757
- var value = (styles.getPropertyValue(style) || '').toLowerCase();
14365
+ var value = styles.getPropertyValue(style) || '';
14366
+ value = style != 'font-family' ? value.toLowerCase() : value;
13758
14367
  value = style == 'font-size' ? px2Pt(value) : value;
13759
14368
  result.push(value);
13760
14369
  }
@@ -13880,6 +14489,7 @@ var contains_1 = __webpack_require__(/*! ./contains */ "./packages/roosterjs-edi
13880
14489
  var getTagOfNode_1 = __webpack_require__(/*! ./getTagOfNode */ "./packages/roosterjs-editor-dom/lib/utils/getTagOfNode.ts");
13881
14490
  var shouldSkipNode_1 = __webpack_require__(/*! ./shouldSkipNode */ "./packages/roosterjs-editor-dom/lib/utils/shouldSkipNode.ts");
13882
14491
  /**
14492
+ * @internal
13883
14493
  * This walks forwards/backwards DOM tree to get next meaningful node
13884
14494
  * @param rootNode Root node to scope the leaf sibling node
13885
14495
  * @param startNode current node to get sibling node from
@@ -14097,6 +14707,7 @@ exports.default = isBlockElement;
14097
14707
 
14098
14708
  Object.defineProperty(exports, "__esModule", { value: true });
14099
14709
  /**
14710
+ * @internal
14100
14711
  * Checks if node1 is after node2
14101
14712
  * @param node1 The node to check if it is after another node
14102
14713
  * @param node2 The node to check if another node is after this one
@@ -14306,6 +14917,38 @@ function matchesSelector(element, selector) {
14306
14917
  exports.default = matchesSelector;
14307
14918
 
14308
14919
 
14920
+ /***/ }),
14921
+
14922
+ /***/ "./packages/roosterjs-editor-dom/lib/utils/moveChildNodes.ts":
14923
+ /*!*******************************************************************!*\
14924
+ !*** ./packages/roosterjs-editor-dom/lib/utils/moveChildNodes.ts ***!
14925
+ \*******************************************************************/
14926
+ /*! no static exports found */
14927
+ /***/ (function(module, exports, __webpack_require__) {
14928
+
14929
+ "use strict";
14930
+
14931
+ Object.defineProperty(exports, "__esModule", { value: true });
14932
+ /**
14933
+ * Replace all child nodes of the given target node to the child nodes of source node.
14934
+ * @param target Target node, all child nodes of this node will be removed if keepExistingChildren is not set to true
14935
+ * @param source (Optional) source node, all child nodes of this node will be move to target node
14936
+ * @param keepExistingChildren (Optional) When set to true, all existing child nodes of target will be kept
14937
+ */
14938
+ function moveChildNodes(target, source, keepExistingChildren) {
14939
+ if (!target) {
14940
+ return;
14941
+ }
14942
+ while (!keepExistingChildren && target.firstChild) {
14943
+ target.removeChild(target.firstChild);
14944
+ }
14945
+ while (source === null || source === void 0 ? void 0 : source.firstChild) {
14946
+ target.appendChild(source.firstChild);
14947
+ }
14948
+ }
14949
+ exports.default = moveChildNodes;
14950
+
14951
+
14309
14952
  /***/ }),
14310
14953
 
14311
14954
  /***/ "./packages/roosterjs-editor-dom/lib/utils/normalizeRect.ts":
@@ -14500,6 +15143,13 @@ exports.default = safeInstanceOf;
14500
15143
  "use strict";
14501
15144
 
14502
15145
  Object.defineProperty(exports, "__esModule", { value: true });
15146
+ /**
15147
+ * Set text color or background color to the given element
15148
+ * @param element The element to set color to
15149
+ * @param color The color to set, it can be a string of color name/value or a ModeIndependentColor object
15150
+ * @param isBackgroundColor Whether set background color or text color
15151
+ * @param isDarkMode Whether current mode is dark mode. @default false
15152
+ */
14503
15153
  function setColor(element, color, isBackgroundColor, isDarkMode) {
14504
15154
  var colorString = typeof color === 'string' ? color.trim() : '';
14505
15155
  var modeIndependentColor = typeof color === 'string' ? null : color;
@@ -14522,6 +15172,65 @@ function setColor(element, color, isBackgroundColor, isDarkMode) {
14522
15172
  exports.default = setColor;
14523
15173
 
14524
15174
 
15175
+ /***/ }),
15176
+
15177
+ /***/ "./packages/roosterjs-editor-dom/lib/utils/setListItemStyle.ts":
15178
+ /*!*********************************************************************!*\
15179
+ !*** ./packages/roosterjs-editor-dom/lib/utils/setListItemStyle.ts ***!
15180
+ \*********************************************************************/
15181
+ /*! no static exports found */
15182
+ /***/ (function(module, exports, __webpack_require__) {
15183
+
15184
+ "use strict";
15185
+
15186
+ Object.defineProperty(exports, "__esModule", { value: true });
15187
+ var ContentTraverser_1 = __webpack_require__(/*! ../contentTraverser/ContentTraverser */ "./packages/roosterjs-editor-dom/lib/contentTraverser/ContentTraverser.ts");
15188
+ var findClosestElementAncestor_1 = __webpack_require__(/*! ./findClosestElementAncestor */ "./packages/roosterjs-editor-dom/lib/utils/findClosestElementAncestor.ts");
15189
+ var getStyles_1 = __webpack_require__(/*! ../style/getStyles */ "./packages/roosterjs-editor-dom/lib/style/getStyles.ts");
15190
+ var safeInstanceOf_1 = __webpack_require__(/*! ./safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts");
15191
+ var setStyles_1 = __webpack_require__(/*! ../style/setStyles */ "./packages/roosterjs-editor-dom/lib/style/setStyles.ts");
15192
+ /**
15193
+ * Set the Style of a List Item provided, with the styles that the inline child elements have
15194
+ * If the child inline elements have different styles, it will not modify the styles of the list item
15195
+ * @param element the LI Element to set the styles
15196
+ * @param styles The styles that should be applied to the element.
15197
+ */
15198
+ function setListItemStyle(element, styles) {
15199
+ var elementsStyles = getInlineChildElementsStyle(element);
15200
+ var stylesToApply = getStyles_1.default(element);
15201
+ styles.forEach(function (styleName) {
15202
+ var styleValues = elementsStyles.map(function (style) {
15203
+ return style[styleName] !== undefined ? style[styleName] : '';
15204
+ });
15205
+ if (styleValues &&
15206
+ (styleValues.length == 1 || new Set(styleValues).size == 1) &&
15207
+ styleValues[0]) {
15208
+ stylesToApply[styleName] = styleValues[0];
15209
+ }
15210
+ });
15211
+ setStyles_1.default(element, stylesToApply);
15212
+ }
15213
+ exports.default = setListItemStyle;
15214
+ function getInlineChildElementsStyle(element) {
15215
+ var result = [];
15216
+ var contentTraverser = ContentTraverser_1.default.createBodyTraverser(element);
15217
+ var currentInlineElement;
15218
+ while (contentTraverser.currentInlineElement != currentInlineElement) {
15219
+ currentInlineElement = contentTraverser.currentInlineElement;
15220
+ var currentNode = currentInlineElement.getContainerNode();
15221
+ currentNode = findClosestElementAncestor_1.default(currentNode);
15222
+ if (safeInstanceOf_1.default(currentNode, 'HTMLElement')) {
15223
+ var childStyle = getStyles_1.default(currentNode);
15224
+ if (childStyle) {
15225
+ result.push(childStyle);
15226
+ }
15227
+ }
15228
+ contentTraverser.getNextInlineElement();
15229
+ }
15230
+ return result;
15231
+ }
15232
+
15233
+
14525
15234
  /***/ }),
14526
15235
 
14527
15236
  /***/ "./packages/roosterjs-editor-dom/lib/utils/shouldSkipNode.ts":
@@ -14539,6 +15248,7 @@ var getComputedStyles_1 = __webpack_require__(/*! ./getComputedStyles */ "./pack
14539
15248
  var CRLF = /^[\r\n]+$/gm;
14540
15249
  var CRLF_SPACE = /[\t\r\n\u0020\u200B]/gm; // We should only find new line, real space or ZeroWidthSpace (TAB, %20, but not &nbsp;)
14541
15250
  /**
15251
+ * @internal
14542
15252
  * Skip a node when any of following conditions are true
14543
15253
  * - it is neither Element nor Text
14544
15254
  * - it is a text node but is empty
@@ -14757,6 +15467,7 @@ exports.default = unwrap;
14757
15467
  "use strict";
14758
15468
 
14759
15469
  Object.defineProperty(exports, "__esModule", { value: true });
15470
+ var createElement_1 = __webpack_require__(/*! ./createElement */ "./packages/roosterjs-editor-dom/lib/utils/createElement.ts");
14760
15471
  var fromHtml_1 = __webpack_require__(/*! ./fromHtml */ "./packages/roosterjs-editor-dom/lib/utils/fromHtml.ts");
14761
15472
  var safeInstanceOf_1 = __webpack_require__(/*! ../utils/safeInstanceOf */ "./packages/roosterjs-editor-dom/lib/utils/safeInstanceOf.ts");
14762
15473
  function wrap(nodes, wrapper) {
@@ -14764,12 +15475,19 @@ function wrap(nodes, wrapper) {
14764
15475
  if (nodes.length == 0 || !nodes[0]) {
14765
15476
  return null;
14766
15477
  }
15478
+ if (!wrapper) {
15479
+ wrapper = 'div';
15480
+ }
14767
15481
  if (!safeInstanceOf_1.default(wrapper, 'HTMLElement')) {
14768
15482
  var document_1 = nodes[0].ownerDocument;
14769
- wrapper = wrapper || 'div';
14770
- wrapper = /^\w+$/.test(wrapper)
14771
- ? document_1.createElement(wrapper)
14772
- : fromHtml_1.default(wrapper, document_1)[0];
15483
+ if (typeof wrapper === 'string') {
15484
+ wrapper = /^\w+$/.test(wrapper)
15485
+ ? document_1.createElement(wrapper)
15486
+ : fromHtml_1.default(wrapper, document_1)[0]; // This will be removed in next major release
15487
+ }
15488
+ else {
15489
+ wrapper = createElement_1.default(wrapper, document_1);
15490
+ }
14773
15491
  }
14774
15492
  var parentNode = nodes[0].parentNode;
14775
15493
  if (parentNode) {
@@ -14903,64 +15621,11 @@ __export(__webpack_require__(/*! ./plugins/ImageEdit/index */ "./packages/rooste
14903
15621
 
14904
15622
  "use strict";
14905
15623
 
14906
- var __extends = (this && this.__extends) || (function () {
14907
- var extendStatics = function (d, b) {
14908
- extendStatics = Object.setPrototypeOf ||
14909
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
14910
- function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
14911
- return extendStatics(d, b);
14912
- };
14913
- return function (d, b) {
14914
- extendStatics(d, b);
14915
- function __() { this.constructor = d; }
14916
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
14917
- };
14918
- })();
15624
+ function __export(m) {
15625
+ for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
15626
+ }
14919
15627
  Object.defineProperty(exports, "__esModule", { value: true });
14920
- var ImageEdit_1 = __webpack_require__(/*! ./ImageEdit */ "./packages/roosterjs-editor-plugins/lib/ImageEdit.ts");
14921
- /**
14922
- * @deprecated Use ImageEdit plugin instead
14923
- */
14924
- var ImageResize = /** @class */ (function (_super) {
14925
- __extends(ImageResize, _super);
14926
- /**
14927
- * Create a new instance of ImageResize
14928
- * @param minWidth Minimum width of image when resize in pixel, default value is 10
14929
- * @param minHeight Minimum height of image when resize in pixel, default value is 10
14930
- * @param selectionBorderColor Color of resize border and handles, default value is #DB626C
14931
- * @param forcePreserveRatio Whether always preserve width/height ratio when resize, default value is false
14932
- * @param resizableImageSelector Selector for picking which image is resizable (e.g. for all images not placeholders), note
14933
- * that the tag must be IMG regardless what the selector is
14934
- */
14935
- function ImageResize(minWidth, minHeight, selectionBorderColor, forcePreserveRatio, resizableImageSelector) {
14936
- if (minWidth === void 0) { minWidth = 10; }
14937
- if (minHeight === void 0) { minHeight = 10; }
14938
- if (selectionBorderColor === void 0) { selectionBorderColor = '#DB626C'; }
14939
- if (forcePreserveRatio === void 0) { forcePreserveRatio = false; }
14940
- if (resizableImageSelector === void 0) { resizableImageSelector = 'img'; }
14941
- return _super.call(this, {
14942
- minHeight: minHeight,
14943
- minWidth: minWidth,
14944
- borderColor: selectionBorderColor,
14945
- preserveRatio: forcePreserveRatio,
14946
- imageSelector: resizableImageSelector,
14947
- }) || this;
14948
- }
14949
- /**
14950
- * @deprecated
14951
- */
14952
- ImageResize.prototype.showResizeHandle = function (img) {
14953
- this.setEditingImage(img, 3 /* Resize */);
14954
- };
14955
- /**
14956
- * @deprecated
14957
- */
14958
- ImageResize.prototype.hideResizeHandle = function (selectImageAfterUnSelect) {
14959
- this.setEditingImage(null /*image*/, selectImageAfterUnSelect);
14960
- };
14961
- return ImageResize;
14962
- }(ImageEdit_1.ImageEdit));
14963
- exports.ImageResize = ImageResize;
15628
+ __export(__webpack_require__(/*! ./plugins/ImageResize/index */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageResize/index.ts"));
14964
15629
 
14965
15630
 
14966
15631
  /***/ }),
@@ -15481,6 +16146,7 @@ function cacheGetNeighborEntityElement(event, editor, isNext, collapseOnly, oper
15481
16146
  if (collapseOnly && !range.collapsed) {
15482
16147
  return null;
15483
16148
  }
16149
+ range.commonAncestorContainer.normalize();
15484
16150
  var pos = roosterjs_editor_dom_1.Position.getEnd(range).normalize();
15485
16151
  var isAtBeginOrEnd = pos.offset == 0 || pos.isAtEnd;
15486
16152
  var entityNode = null;
@@ -15537,7 +16203,6 @@ exports.EntityFeatures = {
15537
16203
  "use strict";
15538
16204
 
15539
16205
  Object.defineProperty(exports, "__esModule", { value: true });
15540
- var blockFormat_1 = __webpack_require__(/*! roosterjs-editor-api/lib/utils/blockFormat */ "./packages/roosterjs-editor-api/lib/utils/blockFormat.ts");
15541
16206
  var roosterjs_editor_api_1 = __webpack_require__(/*! roosterjs-editor-api */ "./packages/roosterjs-editor-api/lib/index.ts");
15542
16207
  var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
15543
16208
  /**
@@ -15580,7 +16245,7 @@ var MergeInNewLine = {
15580
16245
  handleEvent: function (event, editor) {
15581
16246
  var li = editor.getElementAtCursor('LI', null /*startFrom*/, event);
15582
16247
  if (li.previousSibling) {
15583
- blockFormat_1.default(editor, function (region, start, end) {
16248
+ roosterjs_editor_api_1.blockFormat(editor, function (region, start, end) {
15584
16249
  var vList = roosterjs_editor_dom_1.createVListFromRegion(region, false /*includeSiblingList*/, li);
15585
16250
  vList.setIndentation(start, end, 1 /* Decrease */, true /*softOutdent*/);
15586
16251
  vList.writeBack();
@@ -15637,7 +16302,7 @@ var OutdentWhenEnterOnEmptyLine = {
15637
16302
  return !event.rawEvent.shiftKey && li && roosterjs_editor_dom_1.isNodeEmpty(li);
15638
16303
  },
15639
16304
  handleEvent: function (event, editor) {
15640
- editor.addUndoSnapshot(function () { return toggleListAndPreventDefault(event, editor); }, null /*changeSource*/, true /*canUndoByBackspace*/);
16305
+ editor.addUndoSnapshot(function () { return toggleListAndPreventDefault(event, editor, false /* includeSiblingLists */); }, null /*changeSource*/, true /*canUndoByBackspace*/);
15641
16306
  },
15642
16307
  defaultDisabled: !roosterjs_editor_dom_1.Browser.isIE && !roosterjs_editor_dom_1.Browser.isChrome,
15643
16308
  };
@@ -15663,27 +16328,29 @@ var AutoBullet = {
15663
16328
  editor.insertContent('&nbsp;');
15664
16329
  event.rawEvent.preventDefault();
15665
16330
  editor.addUndoSnapshot(function () {
16331
+ var _a;
15666
16332
  var regions;
15667
16333
  var searcher = editor.getContentSearcherOfCursor();
15668
16334
  var textBeforeCursor = searcher.getSubStringBefore(4);
15669
- var rangeToDelete = searcher.getRangeFromText(textBeforeCursor, true /*exactMatch*/);
15670
- if (!rangeToDelete) {
16335
+ var textRange = searcher.getRangeFromText(textBeforeCursor, true /*exactMatch*/);
16336
+ if (!textRange) {
15671
16337
  // no op if the range can't be found
15672
16338
  }
15673
16339
  else if (textBeforeCursor.indexOf('*') == 0 ||
15674
16340
  textBeforeCursor.indexOf('-') == 0) {
15675
- prepareAutoBullet(editor, rangeToDelete);
16341
+ prepareAutoBullet(editor, textRange);
15676
16342
  roosterjs_editor_api_1.toggleBullet(editor);
15677
16343
  }
15678
16344
  else if (isAListPattern(textBeforeCursor)) {
15679
- prepareAutoBullet(editor, rangeToDelete);
16345
+ prepareAutoBullet(editor, textRange);
15680
16346
  roosterjs_editor_api_1.toggleNumbering(editor);
15681
16347
  }
15682
16348
  else if ((regions = editor.getSelectedRegions()) && regions.length == 1) {
15683
16349
  var num = parseInt(textBeforeCursor);
15684
- prepareAutoBullet(editor, rangeToDelete);
16350
+ prepareAutoBullet(editor, textRange);
15685
16351
  roosterjs_editor_api_1.toggleNumbering(editor, num);
15686
16352
  }
16353
+ (_a = searcher.getRangeFromText(textBeforeCursor, true /*exactMatch*/)) === null || _a === void 0 ? void 0 : _a.deleteContents();
15687
16354
  }, null /*changeSource*/, true /*canUndoByBackspace*/);
15688
16355
  },
15689
16356
  };
@@ -15728,7 +16395,6 @@ function getCacheNextSibiling(event, editor) {
15728
16395
  return element;
15729
16396
  }
15730
16397
  function prepareAutoBullet(editor, range) {
15731
- range.deleteContents();
15732
16398
  var block = editor.getBlockElementAtNode(range.startContainer);
15733
16399
  var endNode = block === null || block === void 0 ? void 0 : block.getEndNode();
15734
16400
  if (endNode && roosterjs_editor_dom_1.getTagOfNode(endNode) != 'BR' && (block === null || block === void 0 ? void 0 : block.getTextContent().trim()) === '') {
@@ -15742,16 +16408,14 @@ function prepareAutoBullet(editor, range) {
15742
16408
  editor.select(range.startContainer, range.startOffset);
15743
16409
  }
15744
16410
  }
15745
- function toggleListAndPreventDefault(event, editor) {
16411
+ function toggleListAndPreventDefault(event, editor, includeSiblingLists) {
16412
+ if (includeSiblingLists === void 0) { includeSiblingLists = true; }
15746
16413
  var listInfo = cacheGetListElement(event, editor);
15747
16414
  if (listInfo) {
15748
16415
  var listElement = listInfo[0];
15749
16416
  var tag = roosterjs_editor_dom_1.getTagOfNode(listElement);
15750
- if (tag == 'UL') {
15751
- roosterjs_editor_api_1.toggleBullet(editor);
15752
- }
15753
- else if (tag == 'OL') {
15754
- roosterjs_editor_api_1.toggleNumbering(editor);
16417
+ if (tag == 'UL' || tag == 'OL') {
16418
+ roosterjs_editor_api_1.toggleListType(editor, tag == 'UL' ? 2 /* Unordered */ : 1 /* Ordered */, null /* startNumber */, includeSiblingLists);
15755
16419
  }
15756
16420
  editor.focus();
15757
16421
  event.rawEvent.preventDefault();
@@ -15909,6 +16573,7 @@ exports.MarkdownFeatures = {
15909
16573
  "use strict";
15910
16574
 
15911
16575
  Object.defineProperty(exports, "__esModule", { value: true });
16576
+ var roosterjs_editor_api_1 = __webpack_require__(/*! roosterjs-editor-api */ "./packages/roosterjs-editor-api/lib/index.ts");
15912
16577
  var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
15913
16578
  var QUOTE_TAG = 'BLOCKQUOTE';
15914
16579
  var STRUCTURED_TAGS = [QUOTE_TAG, 'LI', 'TD', 'TH'].join(',');
@@ -15959,15 +16624,31 @@ function splitQuote(event, editor) {
15959
16624
  editor.addUndoSnapshot(function () {
15960
16625
  var childOfQuote = cacheGetQuoteChild(event, editor);
15961
16626
  var parent;
16627
+ var shouldClearFormat;
15962
16628
  if (roosterjs_editor_dom_1.getTagOfNode(childOfQuote) == QUOTE_TAG) {
15963
16629
  childOfQuote = roosterjs_editor_dom_1.wrap(roosterjs_editor_dom_1.toArray(childOfQuote.childNodes));
15964
16630
  }
15965
16631
  parent = roosterjs_editor_dom_1.splitBalancedNodeRange(childOfQuote);
16632
+ shouldClearFormat = isStyledBlockquote(parent);
15966
16633
  roosterjs_editor_dom_1.unwrap(parent);
15967
16634
  editor.select(childOfQuote, 0 /* Begin */);
16635
+ if (shouldClearFormat) {
16636
+ roosterjs_editor_api_1.clearFormat(editor);
16637
+ }
15968
16638
  });
15969
16639
  event.rawEvent.preventDefault();
15970
16640
  }
16641
+ var isStyledBlockquote = function (element) {
16642
+ if (element &&
16643
+ roosterjs_editor_dom_1.safeInstanceOf(element, 'HTMLQuoteElement') &&
16644
+ element.style.borderLeft &&
16645
+ element.style.borderColor &&
16646
+ element.style.paddingLeft &&
16647
+ element.style.color) {
16648
+ return true;
16649
+ }
16650
+ return false;
16651
+ };
15971
16652
  /**
15972
16653
  * @internal
15973
16654
  */
@@ -16070,9 +16751,6 @@ exports.ShortcutFeatures = {
16070
16751
 
16071
16752
  Object.defineProperty(exports, "__esModule", { value: true });
16072
16753
  var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
16073
- // Edge can sometimes lose current format when Enter to new line.
16074
- // So here we add an extra SPAN for Edge to workaround this bug
16075
- var NEWLINE_HTML = roosterjs_editor_dom_1.Browser.isEdge ? '<div><span><br></span></div>' : '<div><br></div>';
16076
16754
  var CHILD_PARENT_TAG_MAP = {
16077
16755
  TD: 'TABLE',
16078
16756
  TH: 'TABLE',
@@ -16089,7 +16767,7 @@ var InsertLineBeforeStructuredNodeFeature = {
16089
16767
  shouldHandleEvent: cacheGetStructuredElement,
16090
16768
  handleEvent: function (event, editor) {
16091
16769
  var element = cacheGetStructuredElement(event, editor);
16092
- var div = roosterjs_editor_dom_1.fromHtml(NEWLINE_HTML, editor.getDocument())[0];
16770
+ var div = roosterjs_editor_dom_1.createElement(1 /* EmptyLine */, editor.getDocument());
16093
16771
  editor.addUndoSnapshot(function () {
16094
16772
  element.parentNode.insertBefore(div, element);
16095
16773
  // Select the new line when we are in table. This is the same behavior with Word
@@ -16310,7 +16988,6 @@ exports.getAllFeatures = getAllFeatures_1.default;
16310
16988
 
16311
16989
  Object.defineProperty(exports, "__esModule", { value: true });
16312
16990
  var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
16313
- var CONTAINER_HTML = '<div style="position: fixed; width: 0; height: 0"></div>';
16314
16991
  /**
16315
16992
  * An editor plugin that support showing a context menu using render() function from options parameter
16316
16993
  */
@@ -16372,7 +17049,7 @@ var ContextMenu = /** @class */ (function () {
16372
17049
  };
16373
17050
  ContextMenu.prototype.initContainer = function (x, y) {
16374
17051
  if (!this.container) {
16375
- this.container = roosterjs_editor_dom_1.fromHtml(CONTAINER_HTML, this.editor.getDocument())[0];
17052
+ this.container = roosterjs_editor_dom_1.createElement(5 /* ContextMenuWrapper */, this.editor.getDocument());
16376
17053
  this.editor.insertNode(this.container, {
16377
17054
  position: 4 /* Outside */,
16378
17055
  });
@@ -16413,7 +17090,12 @@ exports.ContextMenu = ContextMenu_1.default;
16413
17090
  "use strict";
16414
17091
 
16415
17092
  Object.defineProperty(exports, "__esModule", { value: true });
16416
- var makeReplacement = function (sourceString, replacementHTML, matchSourceCaseSensitive) { return ({ sourceString: sourceString, replacementHTML: replacementHTML, matchSourceCaseSensitive: matchSourceCaseSensitive }); };
17093
+ var makeReplacement = function (sourceString, replacementHTML, matchSourceCaseSensitive, shouldReplace) { return ({
17094
+ sourceString: sourceString,
17095
+ replacementHTML: replacementHTML,
17096
+ matchSourceCaseSensitive: matchSourceCaseSensitive,
17097
+ shouldReplace: shouldReplace,
17098
+ }); };
16417
17099
  var defaultReplacements = [
16418
17100
  makeReplacement(':)', '🙂', true),
16419
17101
  makeReplacement(';)', '😉', true),
@@ -16486,6 +17168,10 @@ var CustomReplacePlugin = /** @class */ (function () {
16486
17168
  if (replacement == null) {
16487
17169
  return;
16488
17170
  }
17171
+ if (replacement.shouldReplace &&
17172
+ !replacement.shouldReplace(replacement, searcher.getWordBefore())) {
17173
+ return;
17174
+ }
16489
17175
  // Reconstruct a selection of the text on the document that matches the
16490
17176
  // replacement we selected.
16491
17177
  var matchingText = searcher.getSubStringBefore(replacement.sourceString.length);
@@ -16493,7 +17179,7 @@ var CustomReplacePlugin = /** @class */ (function () {
16493
17179
  // parse the html string off the dom and inline the resulting element.
16494
17180
  var document = this.editor.getDocument();
16495
17181
  var parsingSpan = document.createElement('span');
16496
- parsingSpan.innerHTML = replacement.replacementHTML;
17182
+ parsingSpan.innerHTML = this.editor.getTrustedHTMLHandler()(replacement.replacementHTML);
16497
17183
  var nodeToInsert = parsingSpan.childNodes.length == 1 ? parsingSpan.childNodes[0] : parsingSpan;
16498
17184
  // Switch the node for the selection range
16499
17185
  this.editor.addUndoSnapshot(function () {
@@ -16506,11 +17192,12 @@ var CustomReplacePlugin = /** @class */ (function () {
16506
17192
  if (stringToSearch.length == 0) {
16507
17193
  return null;
16508
17194
  }
16509
- var lowerCaseStringToSearch = stringToSearch.toLocaleLowerCase();
17195
+ var originalStringToSearch = stringToSearch.replace(/\s/g, ' ');
17196
+ var lowerCaseStringToSearch = originalStringToSearch.toLocaleLowerCase();
16510
17197
  for (var _i = 0, _a = this.replacements; _i < _a.length; _i++) {
16511
17198
  var replacement = _a[_i];
16512
17199
  var _b = replacement.matchSourceCaseSensitive
16513
- ? [stringToSearch, replacement.sourceString]
17200
+ ? [originalStringToSearch, replacement.sourceString]
16514
17201
  : [lowerCaseStringToSearch, replacement.sourceString.toLocaleLowerCase()], sourceMatch = _b[0], replacementMatch = _b[1];
16515
17202
  if (sourceMatch.substring(sourceMatch.length - replacementMatch.length) ==
16516
17203
  replacementMatch) {
@@ -16901,18 +17588,20 @@ var _a, _b;
16901
17588
  Object.defineProperty(exports, "__esModule", { value: true });
16902
17589
  var applyChange_1 = __webpack_require__(/*! ./editInfoUtils/applyChange */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/applyChange.ts");
16903
17590
  var canRegenerateImage_1 = __webpack_require__(/*! ./api/canRegenerateImage */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/api/canRegenerateImage.ts");
16904
- var Cropper_1 = __webpack_require__(/*! ./imageEditors/Cropper */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/imageEditors/Cropper.ts");
16905
- var deleteEditInfo_1 = __webpack_require__(/*! ./editInfoUtils/deleteEditInfo */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/deleteEditInfo.ts");
16906
17591
  var DragAndDropHelper_1 = __webpack_require__(/*! ../../pluginUtils/DragAndDropHelper */ "./packages/roosterjs-editor-plugins/lib/pluginUtils/DragAndDropHelper.ts");
16907
- var getEditInfoFromImage_1 = __webpack_require__(/*! ./editInfoUtils/getEditInfoFromImage */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getEditInfoFromImage.ts");
16908
17592
  var getGeneratedImageSize_1 = __webpack_require__(/*! ./editInfoUtils/getGeneratedImageSize */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getGeneratedImageSize.ts");
17593
+ var Cropper_1 = __webpack_require__(/*! ./imageEditors/Cropper */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/imageEditors/Cropper.ts");
17594
+ var editInfo_1 = __webpack_require__(/*! ./editInfoUtils/editInfo */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/editInfo.ts");
16909
17595
  var Rotator_1 = __webpack_require__(/*! ./imageEditors/Rotator */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/imageEditors/Rotator.ts");
16910
17596
  var roosterjs_editor_api_1 = __webpack_require__(/*! roosterjs-editor-api */ "./packages/roosterjs-editor-api/lib/index.ts");
16911
- var Resizer_1 = __webpack_require__(/*! ./imageEditors/Resizer */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/imageEditors/Resizer.ts");
16912
17597
  var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
17598
+ var Resizer_1 = __webpack_require__(/*! ./imageEditors/Resizer */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/imageEditors/Resizer.ts");
16913
17599
  var SHIFT_KEYCODE = 16;
16914
17600
  var CTRL_KEYCODE = 17;
16915
17601
  var ALT_KEYCODE = 18;
17602
+ var DIRECTIONS = 8;
17603
+ var DirectionRad = (Math.PI * 2) / DIRECTIONS;
17604
+ var DirectionOrder = ['nw', 'n', 'ne', 'e', 'se', 's', 'sw', 'w'];
16916
17605
  /**
16917
17606
  * Map the experimental features to image edit operations to help determine which operation is allowed
16918
17607
  */
@@ -16943,10 +17632,6 @@ var ImageEditHTMLMap = (_b = {},
16943
17632
  _b[4 /* Rotate */] = Rotator_1.getRotateHTML,
16944
17633
  _b[8 /* Crop */] = Cropper_1.getCropHTML,
16945
17634
  _b);
16946
- /**
16947
- * A wrapper element to help hide cropped part of image
16948
- */
16949
- var IMAGE_WRAPPER_HTML = '<div style="width:100%;height:100%;position:relative;overflow:hidden"></div>';
16950
17635
  /**
16951
17636
  * Image edit entity name
16952
17637
  */
@@ -16983,8 +17668,8 @@ var ImageEdit = /** @class */ (function () {
16983
17668
  var img = wrapper === null || wrapper === void 0 ? void 0 : wrapper.querySelector('img');
16984
17669
  if (img && parent) {
16985
17670
  img.style.position = '';
16986
- img.style.maxWidth = '100%';
16987
17671
  img.style.margin = null;
17672
+ img.style.textAlign = null;
16988
17673
  parent.insertBefore(img, wrapper);
16989
17674
  parent.removeChild(wrapper);
16990
17675
  }
@@ -17001,9 +17686,11 @@ var ImageEdit = /** @class */ (function () {
17001
17686
  var cropOverlays = getEditElements(wrapper, "r_cropO" /* CropOverlay */);
17002
17687
  var rotateCenter = getEditElements(wrapper, "r_rotateC" /* RotateCenter */)[0];
17003
17688
  var rotateHandle = getEditElements(wrapper, "r_rotateH" /* RotateHandle */)[0];
17689
+ var resizeHandles = getEditElements(wrapper, "r_resizeH" /* ResizeHandle */);
17690
+ var cropHandles = getEditElements(wrapper, "r_cropH" /* CropHandle */);
17004
17691
  // Cropping and resizing will show different UI, so check if it is cropping here first
17005
17692
  var isCropping = cropContainers.length == 1 && cropOverlays.length == 4;
17006
- var _a = _this.editInfo, angleRad = _a.angleRad, heightPx = _a.heightPx, bottomPercent = _a.bottomPercent, leftPercent = _a.leftPercent, rightPercent = _a.rightPercent, topPercent = _a.topPercent;
17693
+ var _a = _this.editInfo, angleRad = _a.angleRad, bottomPercent = _a.bottomPercent, leftPercent = _a.leftPercent, rightPercent = _a.rightPercent, topPercent = _a.topPercent;
17007
17694
  // Width/height of the image
17008
17695
  var _b = getGeneratedImageSize_1.default(_this.editInfo, isCropping), targetWidth = _b.targetWidth, targetHeight = _b.targetHeight, originalWidth = _b.originalWidth, originalHeight = _b.originalHeight, visibleWidth = _b.visibleWidth, visibleHeight = _b.visibleHeight;
17009
17696
  var marginHorizontal = (targetWidth - visibleWidth) / 2;
@@ -17017,6 +17704,9 @@ var ImageEdit = /** @class */ (function () {
17017
17704
  wrapper.style.height = getPx(visibleHeight);
17018
17705
  wrapper.style.margin = marginVertical + "px " + marginHorizontal + "px";
17019
17706
  wrapper.style.transform = "rotate(" + angleRad + "rad)";
17707
+ // Update the text-alignment to avoid the image to overflow if the parent element have align center or right
17708
+ // or if the direction is Right To Left
17709
+ wrapper.style.textAlign = isRtl(wrapper.parentNode) ? 'right' : 'left';
17020
17710
  // Update size of the image
17021
17711
  _this.image.style.width = getPx(originalWidth);
17022
17712
  _this.image.style.height = getPx(originalHeight);
@@ -17027,6 +17717,7 @@ var ImageEdit = /** @class */ (function () {
17027
17717
  setSize(cropOverlays[1], undefined, 0, 0, cropBottomPx, cropRightPx, undefined);
17028
17718
  setSize(cropOverlays[2], cropLeftPx, undefined, 0, 0, undefined, cropBottomPx);
17029
17719
  setSize(cropOverlays[3], 0, cropTopPx, undefined, 0, cropLeftPx, undefined);
17720
+ updateHandleCursor(cropHandles, angleRad);
17030
17721
  }
17031
17722
  else {
17032
17723
  // For rotate/resize, set the margin of the image so that cropped part won't be visible
@@ -17035,24 +17726,12 @@ var ImageEdit = /** @class */ (function () {
17035
17726
  if ((context === null || context === void 0 ? void 0 : context.elementClass) == "r_resizeH" /* ResizeHandle */) {
17036
17727
  var clientWidth = wrapper.clientWidth;
17037
17728
  var clientHeight = wrapper.clientHeight;
17729
+ _this.wasResized = true;
17038
17730
  Resizer_1.doubleCheckResize(_this.editInfo, _this.options.preserveRatio, clientWidth, clientHeight);
17039
17731
  _this.updateWrapper();
17040
17732
  }
17041
- // Move rotate handle. When image is very close to the border of editor, rotate handle may not be visible.
17042
- // Fix it by reduce the distance from image to rotate handle
17043
- var distance = _this.editor.getRelativeDistanceToEditor(wrapper, true /*addScroll*/);
17044
- if (rotateCenter && rotateHandle && distance) {
17045
- var cosAngle = Math.cos(angleRad);
17046
- var adjustedDistance = cosAngle <= 0
17047
- ? Number.MAX_SAFE_INTEGER
17048
- : (distance[1] + heightPx / 2 + marginVertical) / cosAngle -
17049
- heightPx / 2;
17050
- var rotateGap = Math.max(Math.min(Rotator_1.ROTATE_GAP, adjustedDistance), 0);
17051
- var rotateTop = Math.max(Math.min(Rotator_1.ROTATE_SIZE, adjustedDistance - rotateGap), 0);
17052
- rotateCenter.style.top = getPx(-rotateGap);
17053
- rotateCenter.style.height = getPx(rotateGap);
17054
- rotateHandle.style.top = getPx(-rotateTop);
17055
- }
17733
+ Rotator_1.updateRotateHandlePosition(_this.editInfo, _this.editor.getRelativeDistanceToEditor(wrapper, true /*addScroll*/), marginVertical, rotateCenter, rotateHandle);
17734
+ updateHandleCursor(resizeHandles, angleRad);
17056
17735
  }
17057
17736
  }
17058
17737
  };
@@ -17116,7 +17795,7 @@ var ImageEdit = /** @class */ (function () {
17116
17795
  }
17117
17796
  else if (key == 27 /* ESCAPE */ && this.image) {
17118
17797
  // Press ESC should cancel current editing operation, resume back to original edit info
17119
- this.editInfo = getEditInfoFromImage_1.default(this.image);
17798
+ this.editInfo = editInfo_1.getEditInfoFromImage(this.image);
17120
17799
  this.setEditingImage(null);
17121
17800
  e.rawEvent.preventDefault();
17122
17801
  }
@@ -17145,7 +17824,7 @@ var ImageEdit = /** @class */ (function () {
17145
17824
  case 8 /* ExtractContentWithDom */:
17146
17825
  // When extract content, remove all image info since they may not be valid when load the content again
17147
17826
  roosterjs_editor_dom_1.toArray(e.clonedRoot.querySelectorAll(this.options.imageSelector)).forEach(function (img) {
17148
- deleteEditInfo_1.default(img);
17827
+ editInfo_1.deleteEditInfo(img);
17149
17828
  });
17150
17829
  break;
17151
17830
  }
@@ -17158,7 +17837,7 @@ var ImageEdit = /** @class */ (function () {
17158
17837
  // When there is image in editing, clean up any cached objects and elements
17159
17838
  this.clearDndHelpers();
17160
17839
  // Apply the changes, and add undo snapshot if necessary
17161
- if (applyChange_1.default(this.editor, this.image, this.editInfo, this.lastSrc)) {
17840
+ if (applyChange_1.default(this.editor, this.image, this.editInfo, this.lastSrc, this.wasResized)) {
17162
17841
  this.editor.addUndoSnapshot(function () { return _this.image; }, "ImageResize" /* ImageResize */);
17163
17842
  }
17164
17843
  // Remove editing wrapper
@@ -17178,7 +17857,9 @@ var ImageEdit = /** @class */ (function () {
17178
17857
  this.editor.addUndoSnapshot();
17179
17858
  this.image = image;
17180
17859
  // Get initial edit info
17181
- this.editInfo = getEditInfoFromImage_1.default(image);
17860
+ this.editInfo = editInfo_1.getEditInfoFromImage(image);
17861
+ //Check if the image was resized by the user
17862
+ this.wasResized = checkIfImageWasResized(this.image);
17182
17863
  operation =
17183
17864
  (canRegenerateImage_1.default(image) ? operation : 3 /* Resize */) &
17184
17865
  this.allowedOperations;
@@ -17186,7 +17867,7 @@ var ImageEdit = /** @class */ (function () {
17186
17867
  var wrapper = this.createWrapper(operation);
17187
17868
  this.updateWrapper();
17188
17869
  // Init drag and drop
17189
- this.dndHelpers = __spreadArrays(this.createDndHelpers("r_resizeH" /* ResizeHandle */, Resizer_1.default), this.createDndHelpers("r_rotateH" /* RotateHandle */, Rotator_1.default), this.createDndHelpers("r_cropH" /* CropHandle */, Cropper_1.default), this.createDndHelpers("r_cropC" /* CropContainer */, Cropper_1.default));
17870
+ this.dndHelpers = __spreadArrays(this.createDndHelpers("r_resizeH" /* ResizeHandle */, Resizer_1.Resizer), this.createDndHelpers("r_rotateH" /* RotateHandle */, Rotator_1.Rotator), this.createDndHelpers("r_cropH" /* CropHandle */, Cropper_1.Cropper), this.createDndHelpers("r_cropC" /* CropContainer */, Cropper_1.Cropper));
17190
17871
  // Put cursor next to the image
17191
17872
  this.editor.select(wrapper, -3 /* After */);
17192
17873
  }
@@ -17195,8 +17876,9 @@ var ImageEdit = /** @class */ (function () {
17195
17876
  * Create editing wrapper for the image
17196
17877
  */
17197
17878
  ImageEdit.prototype.createWrapper = function (operation) {
17879
+ var _this = this;
17198
17880
  // Wrap the image with an entity so that we can easily retrieve it later
17199
- var wrapper = roosterjs_editor_api_1.insertEntity(this.editor, IMAGE_EDIT_WRAPPER_ENTITY_TYPE, roosterjs_editor_dom_1.wrap(this.image, IMAGE_WRAPPER_HTML), false /*isBlock*/, true /*isReadonly*/).wrapper;
17881
+ var wrapper = roosterjs_editor_api_1.insertEntity(this.editor, IMAGE_EDIT_WRAPPER_ENTITY_TYPE, roosterjs_editor_dom_1.wrap(this.image, 6 /* ImageEditWrapper */), false /*isBlock*/, true /*isReadonly*/).wrapper;
17200
17882
  wrapper.style.position = 'relative';
17201
17883
  wrapper.style.maxWidth = '100%';
17202
17884
  wrapper.style.verticalAlign = 'bottom';
@@ -17215,14 +17897,18 @@ var ImageEdit = /** @class */ (function () {
17215
17897
  ? DARK_MODE_BGCOLOR
17216
17898
  : LIGHT_MODE_BGCOLOR,
17217
17899
  };
17218
- var html = Object.keys(ImageEditHTMLMap)
17219
- .map(function (thisOperation) {
17220
- return (operation & thisOperation) == thisOperation
17221
- ? ImageEditHTMLMap[thisOperation](options)
17222
- : '';
17223
- })
17224
- .join('');
17225
- roosterjs_editor_dom_1.fromHtml(html, this.image.ownerDocument).forEach(function (node) { return wrapper.appendChild(node); });
17900
+ var htmlData = [];
17901
+ Object.keys(ImageEditHTMLMap).forEach(function (thisOperation) {
17902
+ if ((operation & thisOperation) == thisOperation) {
17903
+ roosterjs_editor_dom_1.arrayPush(htmlData, ImageEditHTMLMap[thisOperation](options));
17904
+ }
17905
+ });
17906
+ htmlData.forEach(function (data) {
17907
+ var element = roosterjs_editor_dom_1.createElement(data, _this.image.ownerDocument);
17908
+ if (element) {
17909
+ wrapper.appendChild(element);
17910
+ }
17911
+ });
17226
17912
  return wrapper;
17227
17913
  };
17228
17914
  /**
@@ -17280,6 +17966,54 @@ function getPx(value) {
17280
17966
  function getEditElements(wrapper, elementClass) {
17281
17967
  return roosterjs_editor_dom_1.toArray(wrapper.querySelectorAll('.' + elementClass));
17282
17968
  }
17969
+ function isRtl(element) {
17970
+ return roosterjs_editor_dom_1.safeInstanceOf(element, 'HTMLElement')
17971
+ ? roosterjs_editor_dom_1.getComputedStyle(element, 'direction') == 'rtl'
17972
+ : false;
17973
+ }
17974
+ function handleRadIndexCalculator(angleRad) {
17975
+ var idx = Math.round(angleRad / DirectionRad) % DIRECTIONS;
17976
+ return idx < 0 ? idx + DIRECTIONS : idx;
17977
+ }
17978
+ function rotateHandles(element, angleRad) {
17979
+ var radIndex = handleRadIndexCalculator(angleRad);
17980
+ var originalDirection = element.dataset.y + element.dataset.x;
17981
+ var originalIndex = DirectionOrder.indexOf(originalDirection);
17982
+ var rotatedIndex = originalIndex >= 0 && originalIndex + radIndex;
17983
+ return DirectionOrder[rotatedIndex % DIRECTIONS];
17984
+ }
17985
+ /**
17986
+ * Rotate the resizer and cropper handles according to the image position.
17987
+ * @param handles The resizer handles.
17988
+ * @param angleRad The angle that the image was rotated.
17989
+ */
17990
+ function updateHandleCursor(handles, angleRad) {
17991
+ handles.map(function (handle) {
17992
+ handle.style.cursor = rotateHandles(handle, angleRad) + "-resize";
17993
+ });
17994
+ }
17995
+ /**
17996
+ * Check if the current image was resized by the user
17997
+ * @param image the current image
17998
+ * @returns if the user resized the image, returns true, otherwise, returns false
17999
+ */
18000
+ function checkIfImageWasResized(image) {
18001
+ var width = image.width, height = image.height, style = image.style;
18002
+ if (style.maxWidth === 'initial' &&
18003
+ (isFixedNumberValue(style.height) ||
18004
+ isFixedNumberValue(style.width) ||
18005
+ isFixedNumberValue(width) ||
18006
+ isFixedNumberValue(height))) {
18007
+ return true;
18008
+ }
18009
+ else {
18010
+ return false;
18011
+ }
18012
+ }
18013
+ function isFixedNumberValue(value) {
18014
+ var numberValue = typeof value === 'string' ? parseInt(value) : value;
18015
+ return !isNaN(numberValue);
18016
+ }
17283
18017
 
17284
18018
 
17285
18019
  /***/ }),
@@ -17332,15 +18066,15 @@ exports.default = canRegenerateImage;
17332
18066
  "use strict";
17333
18067
 
17334
18068
  Object.defineProperty(exports, "__esModule", { value: true });
17335
- var getEditInfoFromImage_1 = __webpack_require__(/*! ../editInfoUtils/getEditInfoFromImage */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getEditInfoFromImage.ts");
17336
18069
  var getTargetSizeByPercentage_1 = __webpack_require__(/*! ../editInfoUtils/getTargetSizeByPercentage */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getTargetSizeByPercentage.ts");
18070
+ var editInfo_1 = __webpack_require__(/*! ../editInfoUtils/editInfo */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/editInfo.ts");
17337
18071
  /**
17338
18072
  * Check if the image is already resized to the given percentage
17339
18073
  * @param image The image to check
17340
18074
  * @param percentage The percentage to check
17341
18075
  */
17342
18076
  function isResizedTo(image, percentage) {
17343
- var editInfo = getEditInfoFromImage_1.default(image);
18077
+ var editInfo = editInfo_1.getEditInfoFromImage(image);
17344
18078
  var _a = getTargetSizeByPercentage_1.default(editInfo, percentage), width = _a.width, height = _a.height;
17345
18079
  return (Math.round(width) == Math.round(editInfo.widthPx) &&
17346
18080
  Math.round(height) == Math.round(editInfo.heightPx));
@@ -17360,7 +18094,7 @@ exports.default = isResizedTo;
17360
18094
  "use strict";
17361
18095
 
17362
18096
  Object.defineProperty(exports, "__esModule", { value: true });
17363
- var deleteEditInfo_1 = __webpack_require__(/*! ../editInfoUtils/deleteEditInfo */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/deleteEditInfo.ts");
18097
+ var editInfo_1 = __webpack_require__(/*! ../editInfoUtils/editInfo */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/editInfo.ts");
17364
18098
  /**
17365
18099
  * Remove explicit width & height attributes on the image element.
17366
18100
  * @param editor The editor that contains the image
@@ -17373,7 +18107,7 @@ function resetImage(editor, image) {
17373
18107
  image.style.maxWidth = '100%';
17374
18108
  image.removeAttribute('width');
17375
18109
  image.removeAttribute('height');
17376
- deleteEditInfo_1.default(image);
18110
+ editInfo_1.deleteEditInfo(image);
17377
18111
  }, "ImageResize" /* ImageResize */);
17378
18112
  }
17379
18113
  exports.default = resetImage;
@@ -17392,9 +18126,9 @@ exports.default = resetImage;
17392
18126
 
17393
18127
  Object.defineProperty(exports, "__esModule", { value: true });
17394
18128
  var applyChange_1 = __webpack_require__(/*! ../editInfoUtils/applyChange */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/applyChange.ts");
17395
- var getEditInfoFromImage_1 = __webpack_require__(/*! ../editInfoUtils/getEditInfoFromImage */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getEditInfoFromImage.ts");
17396
18129
  var getTargetSizeByPercentage_1 = __webpack_require__(/*! ../editInfoUtils/getTargetSizeByPercentage */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getTargetSizeByPercentage.ts");
17397
18130
  var isResizedTo_1 = __webpack_require__(/*! ./isResizedTo */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/api/isResizedTo.ts");
18131
+ var editInfo_1 = __webpack_require__(/*! ../editInfoUtils/editInfo */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/editInfo.ts");
17398
18132
  /**
17399
18133
  * Resize the image by percentage of its natural size. If the image is cropped or rotated,
17400
18134
  * the final size will also calculated with crop and rotate info.
@@ -17405,7 +18139,7 @@ var isResizedTo_1 = __webpack_require__(/*! ./isResizedTo */ "./packages/rooster
17405
18139
  * @param minHeight Minimum height
17406
18140
  */
17407
18141
  function resizeByPercentage(editor, image, percentage, minWidth, minHeight) {
17408
- var editInfo = getEditInfoFromImage_1.default(image);
18142
+ var editInfo = editInfo_1.getEditInfoFromImage(image);
17409
18143
  if (!isResizedTo_1.default(image, percentage)) {
17410
18144
  loadImage(image, editInfo.src, function () {
17411
18145
  if (!editor.isDisposed() && editor.contains(image)) {
@@ -17414,7 +18148,7 @@ function resizeByPercentage(editor, image, percentage, minWidth, minHeight) {
17414
18148
  editInfo.widthPx = Math.max(width, minWidth);
17415
18149
  editInfo.heightPx = Math.max(height, minHeight);
17416
18150
  editor.addUndoSnapshot(function () {
17417
- applyChange_1.default(editor, image, editInfo, lastSrc_1);
18151
+ applyChange_1.default(editor, image, editInfo, lastSrc_1, true /*wasResized*/);
17418
18152
  }, "ImageResize" /* ImageResize */);
17419
18153
  }
17420
18154
  });
@@ -17449,11 +18183,9 @@ function loadImage(img, src, callback) {
17449
18183
 
17450
18184
  Object.defineProperty(exports, "__esModule", { value: true });
17451
18185
  var checkEditInfoState_1 = __webpack_require__(/*! ./checkEditInfoState */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/checkEditInfoState.ts");
17452
- var deleteEditInfo_1 = __webpack_require__(/*! ./deleteEditInfo */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/deleteEditInfo.ts");
17453
18186
  var generateDataURL_1 = __webpack_require__(/*! ./generateDataURL */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/generateDataURL.ts");
17454
- var getEditInfoFromImage_1 = __webpack_require__(/*! ./getEditInfoFromImage */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getEditInfoFromImage.ts");
17455
18187
  var getGeneratedImageSize_1 = __webpack_require__(/*! ./getGeneratedImageSize */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getGeneratedImageSize.ts");
17456
- var saveEditInfo_1 = __webpack_require__(/*! ./saveEditInfo */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/saveEditInfo.ts");
18188
+ var editInfo_1 = __webpack_require__(/*! ./editInfo */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/editInfo.ts");
17457
18189
  /**
17458
18190
  * @internal
17459
18191
  * Apply changes from the edit info of an image, write result to the image
@@ -17463,9 +18195,9 @@ var saveEditInfo_1 = __webpack_require__(/*! ./saveEditInfo */ "./packages/roost
17463
18195
  * @param previousSrc Last src value of the image before the change was made
17464
18196
  * @returns True if the image is changed, otherwise false
17465
18197
  */
17466
- function applyChange(editor, image, editInfo, previousSrc) {
18198
+ function applyChange(editor, image, editInfo, previousSrc, wasResized) {
17467
18199
  var newSrc = '';
17468
- var initEditInfo = getEditInfoFromImage_1.default(image);
18200
+ var initEditInfo = editInfo_1.getEditInfoFromImage(image);
17469
18201
  var state = checkEditInfoState_1.default(editInfo, initEditInfo);
17470
18202
  switch (state) {
17471
18203
  case 1 /* ResizeOnly */:
@@ -17497,25 +18229,42 @@ function applyChange(editor, image, editInfo, previousSrc) {
17497
18229
  if (newSrc == editInfo.src) {
17498
18230
  // If newSrc is the same with original one, it means there is only size change, but no rotation, no cropping,
17499
18231
  // so we don't need to keep edit info, we can delete it
17500
- deleteEditInfo_1.default(image);
18232
+ editInfo_1.deleteEditInfo(image);
17501
18233
  }
17502
18234
  else {
17503
18235
  // Otherwise, save the new edit info to the image so that next time when we edit the same image, we know
17504
18236
  // the edit info
17505
- saveEditInfo_1.default(image, editInfo);
18237
+ editInfo_1.saveEditInfo(image, editInfo);
17506
18238
  }
17507
18239
  // Write back the change to image, and set its new size
17508
18240
  var _a = getGeneratedImageSize_1.default(editInfo), targetWidth = _a.targetWidth, targetHeight = _a.targetHeight;
17509
18241
  image.src = newSrc;
17510
- image.style.width = targetWidth + 'px';
17511
- image.style.height = targetHeight + 'px';
17512
- image.width = targetWidth;
17513
- image.height = targetHeight;
18242
+ setImageSize(image, wasResized, targetWidth, targetHeight);
17514
18243
  return (srcChanged ||
17515
18244
  editInfo.widthPx != initEditInfo.widthPx ||
17516
18245
  editInfo.heightPx != initEditInfo.heightPx);
17517
18246
  }
17518
18247
  exports.default = applyChange;
18248
+ /**
18249
+ * @param img The current image.
18250
+ * @param wasResized the current resize state of the image
18251
+ */
18252
+ function setImageSize(image, wasResized, targetWidth, targetHeight) {
18253
+ if (wasResized) {
18254
+ image.style.maxWidth = 'initial';
18255
+ image.width = targetWidth;
18256
+ image.height = targetHeight;
18257
+ image.style.width = targetWidth + 'px';
18258
+ image.style.height = targetHeight + 'px';
18259
+ }
18260
+ else {
18261
+ image.style.maxWidth = '100%';
18262
+ image.style.height = 'initial';
18263
+ image.style.width = 'initial';
18264
+ image.removeAttribute('height');
18265
+ image.removeAttribute('width');
18266
+ }
18267
+ }
17519
18268
 
17520
18269
 
17521
18270
  /***/ }),
@@ -17585,17 +18334,30 @@ function areSameNumber(n1, n2) {
17585
18334
 
17586
18335
  /***/ }),
17587
18336
 
17588
- /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/deleteEditInfo.ts":
17589
- /*!*************************************************************************************************!*\
17590
- !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/deleteEditInfo.ts ***!
17591
- \*************************************************************************************************/
18337
+ /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/editInfo.ts":
18338
+ /*!*******************************************************************************************!*\
18339
+ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/editInfo.ts ***!
18340
+ \*******************************************************************************************/
17592
18341
  /*! no static exports found */
17593
18342
  /***/ (function(module, exports, __webpack_require__) {
17594
18343
 
17595
18344
  "use strict";
17596
18345
 
17597
18346
  Object.defineProperty(exports, "__esModule", { value: true });
17598
- var ImageEditInfo_1 = __webpack_require__(/*! ../types/ImageEditInfo */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/types/ImageEditInfo.ts");
18347
+ var checkEditInfoState_1 = __webpack_require__(/*! ./checkEditInfoState */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/checkEditInfoState.ts");
18348
+ var IMAGE_EDIT_INFO_NAME = 'roosterEditInfo';
18349
+ /**
18350
+ * @internal
18351
+ * Save edit info to image
18352
+ * @param image The image to save edit info to
18353
+ * @param editInfo The edit info to save
18354
+ */
18355
+ function saveEditInfo(image, editInfo) {
18356
+ if (image) {
18357
+ image.dataset[IMAGE_EDIT_INFO_NAME] = JSON.stringify(editInfo);
18358
+ }
18359
+ }
18360
+ exports.saveEditInfo = saveEditInfo;
17599
18361
  /**
17600
18362
  * @internal
17601
18363
  * Delete edit info of an image if any
@@ -17603,10 +18365,45 @@ var ImageEditInfo_1 = __webpack_require__(/*! ../types/ImageEditInfo */ "./packa
17603
18365
  */
17604
18366
  function deleteEditInfo(image) {
17605
18367
  if (image) {
17606
- delete image.dataset[ImageEditInfo_1.IMAGE_EDIT_INFO_NAME];
18368
+ delete image.dataset[IMAGE_EDIT_INFO_NAME];
18369
+ }
18370
+ }
18371
+ exports.deleteEditInfo = deleteEditInfo;
18372
+ /**
18373
+ * @internal
18374
+ * Get image edit info from an image. If the image doesn't have edit info, create one from this image.
18375
+ * When create new edit info, it will have width/height set to the image's current client width/height, and
18376
+ * natural width/height set to the image's natural width/height, src set to its current src, and all
18377
+ * other fields set to 0.
18378
+ * @param image The image to get edit info from
18379
+ */
18380
+ function getEditInfoFromImage(image) {
18381
+ var obj = safeParseJSON(image === null || image === void 0 ? void 0 : image.dataset[IMAGE_EDIT_INFO_NAME]);
18382
+ return checkEditInfoState_1.default(obj) == 0 /* Invalid */ ? getInitialEditInfo(image) : obj;
18383
+ }
18384
+ exports.getEditInfoFromImage = getEditInfoFromImage;
18385
+ function getInitialEditInfo(image) {
18386
+ return {
18387
+ src: image.src,
18388
+ widthPx: image.clientWidth,
18389
+ heightPx: image.clientHeight,
18390
+ naturalWidth: image.naturalWidth,
18391
+ naturalHeight: image.naturalHeight,
18392
+ leftPercent: 0,
18393
+ rightPercent: 0,
18394
+ topPercent: 0,
18395
+ bottomPercent: 0,
18396
+ angleRad: 0,
18397
+ };
18398
+ }
18399
+ function safeParseJSON(json) {
18400
+ try {
18401
+ return JSON.parse(json);
18402
+ }
18403
+ catch (_a) {
18404
+ return null;
17607
18405
  }
17608
18406
  }
17609
- exports.default = deleteEditInfo;
17610
18407
 
17611
18408
 
17612
18409
  /***/ }),
@@ -17650,57 +18447,6 @@ function generateDataURL(image, editInfo) {
17650
18447
  exports.default = generateDataURL;
17651
18448
 
17652
18449
 
17653
- /***/ }),
17654
-
17655
- /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getEditInfoFromImage.ts":
17656
- /*!*******************************************************************************************************!*\
17657
- !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getEditInfoFromImage.ts ***!
17658
- \*******************************************************************************************************/
17659
- /*! no static exports found */
17660
- /***/ (function(module, exports, __webpack_require__) {
17661
-
17662
- "use strict";
17663
-
17664
- Object.defineProperty(exports, "__esModule", { value: true });
17665
- var checkEditInfoState_1 = __webpack_require__(/*! ./checkEditInfoState */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/checkEditInfoState.ts");
17666
- var ImageEditInfo_1 = __webpack_require__(/*! ../types/ImageEditInfo */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/types/ImageEditInfo.ts");
17667
- /**
17668
- * @internal
17669
- * Get image edit info from an image. If the image doesn't have edit info, create one from this image.
17670
- * When create new edit info, it will have width/height set to the image's current client width/height, and
17671
- * natural width/height set to the image's natural width/height, src set to its current src, and all
17672
- * other fields set to 0.
17673
- * @param image The image to get edit info from
17674
- */
17675
- function getEditInfoFromImage(image) {
17676
- var obj = safeParseJSON(image === null || image === void 0 ? void 0 : image.dataset[ImageEditInfo_1.IMAGE_EDIT_INFO_NAME]);
17677
- return checkEditInfoState_1.default(obj) == 0 /* Invalid */ ? getInitialEditInfo(image) : obj;
17678
- }
17679
- exports.default = getEditInfoFromImage;
17680
- function getInitialEditInfo(image) {
17681
- return {
17682
- src: image.src,
17683
- widthPx: image.clientWidth,
17684
- heightPx: image.clientHeight,
17685
- naturalWidth: image.naturalWidth,
17686
- naturalHeight: image.naturalHeight,
17687
- leftPercent: 0,
17688
- rightPercent: 0,
17689
- topPercent: 0,
17690
- bottomPercent: 0,
17691
- angleRad: 0,
17692
- };
17693
- }
17694
- function safeParseJSON(json) {
17695
- try {
17696
- return JSON.parse(json);
17697
- }
17698
- catch (_a) {
17699
- return null;
17700
- }
17701
- }
17702
-
17703
-
17704
18450
  /***/ }),
17705
18451
 
17706
18452
  /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/getGeneratedImageSize.ts":
@@ -17776,33 +18522,6 @@ function getTargetSizeByPercentage(editInfo, percentage) {
17776
18522
  exports.default = getTargetSizeByPercentage;
17777
18523
 
17778
18524
 
17779
- /***/ }),
17780
-
17781
- /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/saveEditInfo.ts":
17782
- /*!***********************************************************************************************!*\
17783
- !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/editInfoUtils/saveEditInfo.ts ***!
17784
- \***********************************************************************************************/
17785
- /*! no static exports found */
17786
- /***/ (function(module, exports, __webpack_require__) {
17787
-
17788
- "use strict";
17789
-
17790
- Object.defineProperty(exports, "__esModule", { value: true });
17791
- var ImageEditInfo_1 = __webpack_require__(/*! ../types/ImageEditInfo */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/types/ImageEditInfo.ts");
17792
- /**
17793
- * @internal
17794
- * Save edit info to image
17795
- * @param image The image to save edit info to
17796
- * @param editInfo The edit info to save
17797
- */
17798
- function saveEditInfo(image, editInfo) {
17799
- if (image) {
17800
- image.dataset[ImageEditInfo_1.IMAGE_EDIT_INFO_NAME] = JSON.stringify(editInfo);
17801
- }
17802
- }
17803
- exports.default = saveEditInfo;
17804
-
17805
-
17806
18525
  /***/ }),
17807
18526
 
17808
18527
  /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/imageEditors/Cropper.ts":
@@ -17838,9 +18557,10 @@ var ROTATION = {
17838
18557
  se: 270,
17839
18558
  };
17840
18559
  /**
18560
+ * @internal
17841
18561
  * Crop handle for DragAndDropHelper
17842
18562
  */
17843
- var Cropper = {
18563
+ exports.Cropper = {
17844
18564
  onDragStart: function (_a) {
17845
18565
  var editInfo = _a.editInfo;
17846
18566
  return (__assign({}, editInfo));
@@ -17887,39 +18607,56 @@ function crop(basePercentage, deltaValue, fullValue, currentPercentage, minValue
17887
18607
  var validValue = Math.max(Math.min(newValue, maxValue), 0);
17888
18608
  return validValue / fullValue;
17889
18609
  }
17890
- /**
17891
- * @internal
17892
- */
17893
- exports.default = Cropper;
17894
18610
  /**
17895
18611
  * @internal
17896
18612
  * Get HTML for crop elements, including 4 overlays (to show dark shadow), 1 container and 4 crop handles
17897
18613
  */
17898
18614
  function getCropHTML() {
17899
- var overlayHTML = "<div style=\"position:absolute;background-color:rgb(0,0,0,0.5);pointer-events:none\" class=\"" + "r_cropO" /* CropOverlay */ + "\"></div>";
17900
- var handlesHTML = Xs.map(function (x) { return Ys.map(function (y) { return getCropHTMLInternal(x, y); }).join(''); }).join('');
17901
- var containerHTML = "\n <div style=\"position:absolute;overflow:hidden\" class=\"" + "r_cropC" /* CropContainer */ + "\">\n " + handlesHTML + "\n </div>";
17902
- return containerHTML + overlayHTML + overlayHTML + overlayHTML + overlayHTML;
18615
+ var overlayHTML = {
18616
+ tag: 'div',
18617
+ style: 'position:absolute;background-color:rgb(0,0,0,0.5);pointer-events:none',
18618
+ className: "r_cropO" /* CropOverlay */,
18619
+ };
18620
+ var containerHTML = {
18621
+ tag: 'div',
18622
+ style: 'position:absolute;overflow:hidden',
18623
+ className: "r_cropC" /* CropContainer */,
18624
+ children: [],
18625
+ };
18626
+ Xs.forEach(function (x) { return Ys.forEach(function (y) { return containerHTML.children.push(getCropHTMLInternal(x, y)); }); });
18627
+ return [containerHTML, overlayHTML, overlayHTML, overlayHTML, overlayHTML];
17903
18628
  }
17904
18629
  exports.getCropHTML = getCropHTML;
17905
18630
  function getCropHTMLInternal(x, y) {
17906
18631
  var leftOrRight = x == 'w' ? 'left' : 'right';
17907
18632
  var topOrBottom = y == 'n' ? 'top' : 'bottom';
17908
18633
  var rotation = ROTATION[y + x];
17909
- var context = "data-x=\"" + x + "\" data-y=\"" + y + "\"";
17910
- return "\n <div class=\"" + "r_cropH" /* CropHandle */ + "\" " + context + " style=\"position:absolute;pointer-events:auto;cursor:" + y + x + "-resize;" + leftOrRight + ":0;" + topOrBottom + ":0;width:" + CROP_HANDLE_SIZE + "px;height:" + CROP_HANDLE_SIZE + "px;transform:rotate(" + rotation + "deg)\">\n " + getCropHandleHTML() + "\n </div>";
18634
+ return {
18635
+ tag: 'div',
18636
+ className: "r_cropH" /* CropHandle */,
18637
+ style: "position:absolute;pointer-events:auto;cursor:" + y + x + "-resize;" + leftOrRight + ":0;" + topOrBottom + ":0;width:" + CROP_HANDLE_SIZE + "px;height:" + CROP_HANDLE_SIZE + "px;transform:rotate(" + rotation + "deg)",
18638
+ dataset: { x: x, y: y },
18639
+ children: getCropHandleHTML(),
18640
+ };
17911
18641
  }
17912
18642
  function getCropHandleHTML() {
17913
- return [0, 1]
17914
- .map(function (layer) { return [0, 1].map(function (dir) { return getCropHandleHTMLInternal(layer, dir); }).join(''); })
17915
- .join('');
18643
+ var result = [];
18644
+ [0, 1].forEach(function (layer) {
18645
+ return [0, 1].forEach(function (dir) {
18646
+ result.push(getCropHandleHTMLInternal(layer, dir));
18647
+ });
18648
+ });
18649
+ return result;
17916
18650
  }
17917
18651
  function getCropHandleHTMLInternal(layer, dir) {
17918
18652
  var position = dir == 0
17919
18653
  ? "right:" + layer + "px;height:" + (CROP_HANDLE_WIDTH - layer * 2) + "px;"
17920
18654
  : "top:" + layer + "px;width:" + (CROP_HANDLE_WIDTH - layer * 2) + "px;";
17921
18655
  var bgColor = layer == 0 ? 'white' : 'black';
17922
- return "<div style=\"position:absolute;left:" + layer + "px;bottom:" + layer + "px;" + position + ";background-color:" + bgColor + "\"></div>";
18656
+ return {
18657
+ tag: 'div',
18658
+ style: "position:absolute;left:" + layer + "px;bottom:" + layer + "px;" + position + ";background-color:" + bgColor,
18659
+ };
17923
18660
  }
17924
18661
 
17925
18662
 
@@ -17951,9 +18688,10 @@ var RESIZE_HANDLE_MARGIN = 3;
17951
18688
  var Xs = ['w', '', 'e'];
17952
18689
  var Ys = ['s', '', 'n'];
17953
18690
  /**
18691
+ * @internal
17954
18692
  * The resize drag and drop handler
17955
18693
  */
17956
- var Resizer = {
18694
+ exports.Resizer = {
17957
18695
  onDragStart: function (_a) {
17958
18696
  var editInfo = _a.editInfo;
17959
18697
  return (__assign({}, editInfo));
@@ -17987,10 +18725,6 @@ var Resizer = {
17987
18725
  return true;
17988
18726
  },
17989
18727
  };
17990
- /**
17991
- * @internal
17992
- */
17993
- exports.default = Resizer;
17994
18728
  /**
17995
18729
  * @internal Calculate the rotated x and y distance for mouse moving
17996
18730
  * @param x Original x distance
@@ -18042,11 +18776,13 @@ exports.doubleCheckResize = doubleCheckResize;
18042
18776
  */
18043
18777
  function getCornerResizeHTML(_a) {
18044
18778
  var resizeBorderColor = _a.borderColor;
18045
- return Xs.map(function (x) {
18046
- return Ys.map(function (y) {
18047
- return (x == '') == (y == '') ? getResizeHandleHTML(x, y, resizeBorderColor) : '';
18048
- }).join('');
18049
- }).join('');
18779
+ var result = [];
18780
+ Xs.forEach(function (x) {
18781
+ return Ys.forEach(function (y) {
18782
+ return result.push((x == '') == (y == '') ? getResizeHandleHTML(x, y, resizeBorderColor) : null);
18783
+ });
18784
+ });
18785
+ return result;
18050
18786
  }
18051
18787
  exports.getCornerResizeHTML = getCornerResizeHTML;
18052
18788
  /**
@@ -18055,11 +18791,13 @@ exports.getCornerResizeHTML = getCornerResizeHTML;
18055
18791
  */
18056
18792
  function getSideResizeHTML(_a) {
18057
18793
  var resizeBorderColor = _a.borderColor;
18058
- return Xs.map(function (x) {
18059
- return Ys.map(function (y) {
18060
- return (x == '') != (y == '') ? getResizeHandleHTML(x, y, resizeBorderColor) : '';
18061
- }).join('');
18062
- }).join('');
18794
+ var result = [];
18795
+ Xs.forEach(function (x) {
18796
+ return Ys.forEach(function (y) {
18797
+ return result.push((x == '') != (y == '') ? getResizeHandleHTML(x, y, resizeBorderColor) : null);
18798
+ });
18799
+ });
18800
+ return result;
18063
18801
  }
18064
18802
  exports.getSideResizeHTML = getSideResizeHTML;
18065
18803
  function getResizeHandleHTML(x, y, borderColor) {
@@ -18068,10 +18806,23 @@ function getResizeHandleHTML(x, y, borderColor) {
18068
18806
  var leftOrRightValue = x == '' ? '50%' : '0px';
18069
18807
  var topOrBottomValue = y == '' ? '50%' : '0px';
18070
18808
  var direction = y + x;
18071
- var context = "data-x=\"" + x + "\" data-y=\"" + y + "\"";
18072
18809
  return x == '' && y == ''
18073
- ? "<div style=\"position:absolute;left:0;right:0;top:0;bottom:0;border:solid 1px " + borderColor + ";pointer-events:none;\"></div>"
18074
- : "\n <div style=\"position:absolute;" + leftOrRight + ":" + leftOrRightValue + ";" + topOrBottom + ":" + topOrBottomValue + "\">\n <div class=\"" + "r_resizeH" /* ResizeHandle */ + "\" " + context + " style=\"position:relative;width:" + RESIZE_HANDLE_SIZE + "px;height:" + RESIZE_HANDLE_SIZE + "px;background-color: " + borderColor + ";cursor:" + direction + "-resize;" + topOrBottom + ":-" + RESIZE_HANDLE_MARGIN + "px;" + leftOrRight + ":-" + RESIZE_HANDLE_MARGIN + "px\">\n </div>\n </div>";
18810
+ ? {
18811
+ tag: 'div',
18812
+ style: "position:absolute;left:0;right:0;top:0;bottom:0;border:solid 1px " + borderColor + ";pointer-events:none",
18813
+ }
18814
+ : {
18815
+ tag: 'div',
18816
+ style: "position:absolute;" + leftOrRight + ":" + leftOrRightValue + ";" + topOrBottom + ":" + topOrBottomValue,
18817
+ children: [
18818
+ {
18819
+ tag: 'div',
18820
+ style: "position:relative;width:" + RESIZE_HANDLE_SIZE + "px;height:" + RESIZE_HANDLE_SIZE + "px;background-color: " + borderColor + ";cursor:" + direction + "-resize;" + topOrBottom + ":-" + RESIZE_HANDLE_MARGIN + "px;" + leftOrRight + ":-" + RESIZE_HANDLE_MARGIN + "px",
18821
+ className: "r_resizeH" /* ResizeHandle */,
18822
+ dataset: { x: x, y: y },
18823
+ },
18824
+ ],
18825
+ };
18075
18826
  }
18076
18827
 
18077
18828
 
@@ -18098,21 +18849,16 @@ var __assign = (this && this.__assign) || function () {
18098
18849
  return __assign.apply(this, arguments);
18099
18850
  };
18100
18851
  Object.defineProperty(exports, "__esModule", { value: true });
18101
- /**
18102
- * @internal Size of rotate icon
18103
- */
18104
- exports.ROTATE_SIZE = 32;
18105
- /**
18106
- * @internal Gap between image and the rotate handle
18107
- */
18108
- exports.ROTATE_GAP = 15;
18852
+ var ROTATE_SIZE = 32;
18853
+ var ROTATE_GAP = 15;
18109
18854
  var DEG_PER_RAD = 180 / Math.PI;
18110
- var DEFAULT_ROTATE_HANDLE_HEIGHT = exports.ROTATE_SIZE / 2 + exports.ROTATE_GAP;
18855
+ var DEFAULT_ROTATE_HANDLE_HEIGHT = ROTATE_SIZE / 2 + ROTATE_GAP;
18111
18856
  var ROTATE_ICON_MARGIN = 8;
18112
18857
  /**
18858
+ * @internal
18113
18859
  * The rotate drag and drop handler
18114
18860
  */
18115
- var Rotator = {
18861
+ exports.Rotator = {
18116
18862
  onDragStart: function (_a) {
18117
18863
  var editInfo = _a.editInfo;
18118
18864
  return (__assign({}, editInfo));
@@ -18139,20 +18885,76 @@ var Rotator = {
18139
18885
  };
18140
18886
  /**
18141
18887
  * @internal
18888
+ * Move rotate handle. When image is very close to the border of editor, rotate handle may not be visible.
18889
+ * Fix it by reduce the distance from image to rotate handle
18142
18890
  */
18143
- exports.default = Rotator;
18891
+ function updateRotateHandlePosition(editInfo, distance, marginVertical, rotateCenter, rotateHandle) {
18892
+ if (rotateCenter && rotateHandle && distance) {
18893
+ var angleRad = editInfo.angleRad, heightPx = editInfo.heightPx;
18894
+ var cosAngle = Math.cos(angleRad);
18895
+ var adjustedDistance = cosAngle <= 0
18896
+ ? Number.MAX_SAFE_INTEGER
18897
+ : (distance[1] + heightPx / 2 + marginVertical) / cosAngle - heightPx / 2;
18898
+ var rotateGap = Math.max(Math.min(ROTATE_GAP, adjustedDistance), 0);
18899
+ var rotateTop = Math.max(Math.min(ROTATE_SIZE, adjustedDistance - rotateGap), 0);
18900
+ rotateCenter.style.top = -rotateGap + 'px';
18901
+ rotateCenter.style.height = rotateGap + 'px';
18902
+ rotateHandle.style.top = -rotateTop + 'px';
18903
+ }
18904
+ }
18905
+ exports.updateRotateHandlePosition = updateRotateHandlePosition;
18144
18906
  /**
18145
18907
  * @internal
18146
18908
  * Get HTML for rotate elements, including the rotate handle with icon, and a line between the handle and the image
18147
18909
  */
18148
18910
  function getRotateHTML(_a) {
18149
- var borderColor = _a.borderColor, rotateHandleHTML = _a.rotateIconHTML, rotateHandleBackColor = _a.rotateHandleBackColor;
18150
- var handleLeft = exports.ROTATE_SIZE / 2;
18151
- return "\n <div class=\"" + "r_rotateC" /* RotateCenter */ + "\" style=\"position:absolute;left:50%;width:1px;background-color:" + borderColor + "\">\n <div class=\"" + "r_rotateH" /* RotateHandle */ + "\" style=\"position:absolute;background-color:" + rotateHandleBackColor + ";border:solid 1px " + borderColor + ";border-radius:50%;width:" + exports.ROTATE_SIZE + "px;height:" + exports.ROTATE_SIZE + "px;left:-" + handleLeft + "px;cursor:move\">\n " + (rotateHandleHTML || getRotateIconHTML(borderColor)) + "\n </div>\n </div>";
18911
+ var borderColor = _a.borderColor, rotateHandleBackColor = _a.rotateHandleBackColor;
18912
+ var handleLeft = ROTATE_SIZE / 2;
18913
+ return [
18914
+ {
18915
+ tag: 'div',
18916
+ className: "r_rotateC" /* RotateCenter */,
18917
+ style: "position:absolute;left:50%;width:1px;background-color:" + borderColor,
18918
+ children: [
18919
+ {
18920
+ tag: 'div',
18921
+ className: "r_rotateH" /* RotateHandle */,
18922
+ style: "position:absolute;background-color:" + rotateHandleBackColor + ";border:solid 1px " + borderColor + ";border-radius:50%;width:" + ROTATE_SIZE + "px;height:" + ROTATE_SIZE + "px;left:-" + handleLeft + "px;cursor:move",
18923
+ children: [getRotateIconHTML(borderColor)],
18924
+ },
18925
+ ],
18926
+ },
18927
+ ];
18152
18928
  }
18153
18929
  exports.getRotateHTML = getRotateHTML;
18154
18930
  function getRotateIconHTML(borderColor) {
18155
- return "\n <svg style=\"width:16px;height:16px;margin: " + ROTATE_ICON_MARGIN + "px " + ROTATE_ICON_MARGIN + "px\">\n <path d=\"M 10.5,10.0 A 3.8,3.8 0 1 1 6.7,6.3\" transform=\"matrix(1.1 1.1 -1.1 1.1 11.6 -10.8)\" fill-opacity=\"0\" stroke-width=\"1\" stroke=\"" + borderColor + "\" />\n <path d=\"M12.0 3.648l.884-.884.53 2.298-2.298-.53z\" stroke=\"" + borderColor + "\" />\n </svg>";
18931
+ var _a;
18932
+ return {
18933
+ tag: 'svg',
18934
+ namespace: 'http://www.w3.org/2000/svg',
18935
+ style: "width:16px;height:16px;margin: " + ROTATE_ICON_MARGIN + "px " + ROTATE_ICON_MARGIN + "px",
18936
+ children: [
18937
+ {
18938
+ tag: 'path',
18939
+ namespace: 'http://www.w3.org/2000/svg',
18940
+ attributes: (_a = {
18941
+ d: 'M 10.5,10.0 A 3.8,3.8 0 1 1 6.7,6.3',
18942
+ transform: 'matrix(1.1 1.1 -1.1 1.1 11.6 -10.8)'
18943
+ },
18944
+ _a['fill-opacity'] = '0',
18945
+ _a.stroke = borderColor,
18946
+ _a),
18947
+ },
18948
+ {
18949
+ tag: 'path',
18950
+ namespace: 'http://www.w3.org/2000/svg',
18951
+ attributes: {
18952
+ d: 'M12.0 3.648l.884-.884.53 2.298-2.298-.53z',
18953
+ stroke: borderColor,
18954
+ },
18955
+ },
18956
+ ],
18957
+ };
18156
18958
  }
18157
18959
 
18158
18960
 
@@ -18182,17 +18984,89 @@ exports.resetImage = resetImage_1.default;
18182
18984
 
18183
18985
  /***/ }),
18184
18986
 
18185
- /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/types/ImageEditInfo.ts":
18186
- /*!****************************************************************************************!*\
18187
- !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/types/ImageEditInfo.ts ***!
18188
- \****************************************************************************************/
18987
+ /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageResize/ImageResize.ts":
18988
+ /*!**********************************************************************************!*\
18989
+ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageResize/ImageResize.ts ***!
18990
+ \**********************************************************************************/
18991
+ /*! no static exports found */
18992
+ /***/ (function(module, exports, __webpack_require__) {
18993
+
18994
+ "use strict";
18995
+
18996
+ var __extends = (this && this.__extends) || (function () {
18997
+ var extendStatics = function (d, b) {
18998
+ extendStatics = Object.setPrototypeOf ||
18999
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
19000
+ function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
19001
+ return extendStatics(d, b);
19002
+ };
19003
+ return function (d, b) {
19004
+ extendStatics(d, b);
19005
+ function __() { this.constructor = d; }
19006
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
19007
+ };
19008
+ })();
19009
+ Object.defineProperty(exports, "__esModule", { value: true });
19010
+ var ImageEdit_1 = __webpack_require__(/*! ../ImageEdit/ImageEdit */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageEdit/ImageEdit.ts");
19011
+ /**
19012
+ * @deprecated Use ImageEdit plugin instead
19013
+ */
19014
+ var ImageResize = /** @class */ (function (_super) {
19015
+ __extends(ImageResize, _super);
19016
+ /**
19017
+ * Create a new instance of ImageResize
19018
+ * @param minWidth Minimum width of image when resize in pixel, default value is 10
19019
+ * @param minHeight Minimum height of image when resize in pixel, default value is 10
19020
+ * @param selectionBorderColor Color of resize border and handles, default value is #DB626C
19021
+ * @param forcePreserveRatio Whether always preserve width/height ratio when resize, default value is false
19022
+ * @param resizableImageSelector Selector for picking which image is resizable (e.g. for all images not placeholders), note
19023
+ * that the tag must be IMG regardless what the selector is
19024
+ */
19025
+ function ImageResize(minWidth, minHeight, selectionBorderColor, forcePreserveRatio, resizableImageSelector) {
19026
+ if (minWidth === void 0) { minWidth = 10; }
19027
+ if (minHeight === void 0) { minHeight = 10; }
19028
+ if (selectionBorderColor === void 0) { selectionBorderColor = '#DB626C'; }
19029
+ if (forcePreserveRatio === void 0) { forcePreserveRatio = false; }
19030
+ if (resizableImageSelector === void 0) { resizableImageSelector = 'img'; }
19031
+ return _super.call(this, {
19032
+ minHeight: minHeight,
19033
+ minWidth: minWidth,
19034
+ borderColor: selectionBorderColor,
19035
+ preserveRatio: forcePreserveRatio,
19036
+ imageSelector: resizableImageSelector,
19037
+ }) || this;
19038
+ }
19039
+ /**
19040
+ * @deprecated
19041
+ */
19042
+ ImageResize.prototype.showResizeHandle = function (img) {
19043
+ this.setEditingImage(img, 3 /* Resize */);
19044
+ };
19045
+ /**
19046
+ * @deprecated
19047
+ */
19048
+ ImageResize.prototype.hideResizeHandle = function (selectImageAfterUnSelect) {
19049
+ this.setEditingImage(null /*image*/, selectImageAfterUnSelect);
19050
+ };
19051
+ return ImageResize;
19052
+ }(ImageEdit_1.default));
19053
+ exports.default = ImageResize;
19054
+
19055
+
19056
+ /***/ }),
19057
+
19058
+ /***/ "./packages/roosterjs-editor-plugins/lib/plugins/ImageResize/index.ts":
19059
+ /*!****************************************************************************!*\
19060
+ !*** ./packages/roosterjs-editor-plugins/lib/plugins/ImageResize/index.ts ***!
19061
+ \****************************************************************************/
18189
19062
  /*! no static exports found */
18190
19063
  /***/ (function(module, exports, __webpack_require__) {
18191
19064
 
18192
19065
  "use strict";
18193
19066
 
18194
19067
  Object.defineProperty(exports, "__esModule", { value: true });
18195
- exports.IMAGE_EDIT_INFO_NAME = 'roosterEditInfo';
19068
+ var ImageResize_1 = __webpack_require__(/*! ./ImageResize */ "./packages/roosterjs-editor-plugins/lib/plugins/ImageResize/ImageResize.ts");
19069
+ exports.ImageResize = ImageResize_1.default;
18196
19070
 
18197
19071
 
18198
19072
  /***/ }),
@@ -18207,13 +19081,13 @@ exports.IMAGE_EDIT_INFO_NAME = 'roosterEditInfo';
18207
19081
  "use strict";
18208
19082
 
18209
19083
  Object.defineProperty(exports, "__esModule", { value: true });
19084
+ var convertPasteContentForSingleImage_1 = __webpack_require__(/*! ./imageConverter/convertPasteContentForSingleImage */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/imageConverter/convertPasteContentForSingleImage.ts");
18210
19085
  var convertPastedContentForLI_1 = __webpack_require__(/*! ./commonConverter/convertPastedContentForLI */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/commonConverter/convertPastedContentForLI.ts");
18211
19086
  var convertPastedContentFromExcel_1 = __webpack_require__(/*! ./excelConverter/convertPastedContentFromExcel */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/excelConverter/convertPastedContentFromExcel.ts");
18212
19087
  var convertPastedContentFromPowerPoint_1 = __webpack_require__(/*! ./pptConverter/convertPastedContentFromPowerPoint */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/pptConverter/convertPastedContentFromPowerPoint.ts");
18213
19088
  var convertPastedContentFromWord_1 = __webpack_require__(/*! ./wordConverter/convertPastedContentFromWord */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/wordConverter/convertPastedContentFromWord.ts");
18214
19089
  var handleLineMerge_1 = __webpack_require__(/*! ./lineMerge/handleLineMerge */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/lineMerge/handleLineMerge.ts");
18215
19090
  var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
18216
- var constants_1 = __webpack_require__(/*! ./officeOnlineConverter/constants */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/officeOnlineConverter/constants.ts");
18217
19091
  var convertPastedContentFromWordOnline_1 = __webpack_require__(/*! ./officeOnlineConverter/convertPastedContentFromWordOnline */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/officeOnlineConverter/convertPastedContentFromWordOnline.ts");
18218
19092
  var WORD_ATTRIBUTE_NAME = 'xmlns:w';
18219
19093
  var WORD_ATTRIBUTE_VALUE = 'urn:schemas-microsoft-com:office:word';
@@ -18223,6 +19097,7 @@ var PROG_ID_NAME = 'ProgId';
18223
19097
  var EXCEL_ONLINE_ATTRIBUTE_VALUE = 'Excel.Sheet';
18224
19098
  var POWERPOINT_ATTRIBUTE_VALUE = 'PowerPoint.Slide';
18225
19099
  var GOOGLE_SHEET_NODE_NAME = 'google-sheets-html-origin';
19100
+ var WAC_IDENTIFY_SELECTOR = 'ul[class^="BulletListStyle"]>.OutlineElement,ol[class^="NumberListStyle"]>.OutlineElement';
18226
19101
  /**
18227
19102
  * Paste plugin, handles BeforePaste event and reformat some special content, including:
18228
19103
  * 1. Content copied from Word
@@ -18248,18 +19123,24 @@ var Paste = /** @class */ (function () {
18248
19123
  * Initialize this plugin. This should only be called from Editor
18249
19124
  * @param editor Editor instance
18250
19125
  */
18251
- Paste.prototype.initialize = function () { };
19126
+ Paste.prototype.initialize = function (editor) {
19127
+ this.editor = editor;
19128
+ };
18252
19129
  /**
18253
19130
  * Dispose this plugin
18254
19131
  */
18255
- Paste.prototype.dispose = function () { };
19132
+ Paste.prototype.dispose = function () {
19133
+ this.editor = null;
19134
+ };
18256
19135
  /**
18257
19136
  * Handle events triggered from editor
18258
19137
  * @param event PluginEvent object
18259
19138
  */
18260
19139
  Paste.prototype.onPluginEvent = function (event) {
19140
+ var _a;
18261
19141
  if (event.eventType == 10 /* BeforePaste */) {
18262
- var htmlAttributes = event.htmlAttributes, fragment = event.fragment, sanitizingOption = event.sanitizingOption;
19142
+ var htmlAttributes = event.htmlAttributes, fragment = event.fragment, sanitizingOption = event.sanitizingOption, clipboardData = event.clipboardData;
19143
+ var trustedHTMLHandler = this.editor.getTrustedHTMLHandler();
18263
19144
  var wacListElements = void 0;
18264
19145
  if (htmlAttributes[WORD_ATTRIBUTE_NAME] == WORD_ATTRIBUTE_VALUE) {
18265
19146
  // Handle HTML copied from Word
@@ -18268,12 +19149,12 @@ var Paste = /** @class */ (function () {
18268
19149
  else if (htmlAttributes[EXCEL_ATTRIBUTE_NAME] == EXCEL_ATTRIBUTE_VALUE ||
18269
19150
  htmlAttributes[PROG_ID_NAME] == EXCEL_ONLINE_ATTRIBUTE_VALUE) {
18270
19151
  // Handle HTML copied from Excel
18271
- convertPastedContentFromExcel_1.default(event);
19152
+ convertPastedContentFromExcel_1.default(event, trustedHTMLHandler);
18272
19153
  }
18273
19154
  else if (htmlAttributes[PROG_ID_NAME] == POWERPOINT_ATTRIBUTE_VALUE) {
18274
- convertPastedContentFromPowerPoint_1.default(event);
19155
+ convertPastedContentFromPowerPoint_1.default(event, trustedHTMLHandler);
18275
19156
  }
18276
- else if ((wacListElements = roosterjs_editor_dom_1.toArray(fragment.querySelectorAll(constants_1.WAC_IDENTIFY_SELECTOR))) &&
19157
+ else if ((wacListElements = roosterjs_editor_dom_1.toArray(fragment.querySelectorAll(WAC_IDENTIFY_SELECTOR))) &&
18277
19158
  wacListElements.length > 0) {
18278
19159
  // Once it is known that the document is from WAC
18279
19160
  // We need to remove the display property and margin from all the list item
@@ -18290,6 +19171,11 @@ var Paste = /** @class */ (function () {
18290
19171
  else if (fragment.querySelector(GOOGLE_SHEET_NODE_NAME)) {
18291
19172
  sanitizingOption.additionalTagReplacements[GOOGLE_SHEET_NODE_NAME] = '*';
18292
19173
  }
19174
+ else if (this.editor.isFeatureEnabled("ConvertSingleImageBody" /* ConvertSingleImageBody */) &&
19175
+ ((_a = clipboardData.htmlFirstLevelChildTags) === null || _a === void 0 ? void 0 : _a.length) == 1 &&
19176
+ clipboardData.htmlFirstLevelChildTags[0] == 'IMG') {
19177
+ convertPasteContentForSingleImage_1.default(event, trustedHTMLHandler);
19178
+ }
18293
19179
  else {
18294
19180
  convertPastedContentForLI_1.default(fragment);
18295
19181
  handleLineMerge_1.default(fragment);
@@ -18380,18 +19266,12 @@ var DEFAULT_BORDER_STYLE = 'solid 1px #d4d4d4';
18380
19266
  * Convert pasted content from Excel, add borders when source doc doesn't have a border
18381
19267
  * @param event The BeforePaste event
18382
19268
  */
18383
- function convertPastedContentFromExcel(event) {
18384
- var _a;
19269
+ function convertPastedContentFromExcel(event, trustedHTMLHandler) {
18385
19270
  var fragment = event.fragment, sanitizingOption = event.sanitizingOption, htmlBefore = event.htmlBefore, clipboardData = event.clipboardData;
18386
19271
  var html = excelHandler(clipboardData.html, htmlBefore);
18387
19272
  if (clipboardData.html != html) {
18388
- var doc = new DOMParser().parseFromString(html, 'text/html');
18389
- while (fragment.firstChild) {
18390
- fragment.removeChild(fragment.firstChild);
18391
- }
18392
- while ((_a = doc === null || doc === void 0 ? void 0 : doc.body) === null || _a === void 0 ? void 0 : _a.firstChild) {
18393
- fragment.appendChild(doc.body.firstChild);
18394
- }
19273
+ var doc = new DOMParser().parseFromString(trustedHTMLHandler(html), 'text/html');
19274
+ roosterjs_editor_dom_1.moveChildNodes(fragment, doc === null || doc === void 0 ? void 0 : doc.body);
18395
19275
  }
18396
19276
  roosterjs_editor_dom_1.chainSanitizerCallback(sanitizingOption.elementCallbacks, 'TD', function (element) {
18397
19277
  if (element.style.borderStyle == 'none') {
@@ -18421,6 +19301,36 @@ function excelHandler(html, htmlBefore) {
18421
19301
  exports.excelHandler = excelHandler;
18422
19302
 
18423
19303
 
19304
+ /***/ }),
19305
+
19306
+ /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/imageConverter/convertPasteContentForSingleImage.ts":
19307
+ /*!*****************************************************************************************************************!*\
19308
+ !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/imageConverter/convertPasteContentForSingleImage.ts ***!
19309
+ \*****************************************************************************************************************/
19310
+ /*! no static exports found */
19311
+ /***/ (function(module, exports, __webpack_require__) {
19312
+
19313
+ "use strict";
19314
+
19315
+ Object.defineProperty(exports, "__esModule", { value: true });
19316
+ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
19317
+ /**
19318
+ * @internal
19319
+ * Convert pasted content if there are HTML and Image data in the Clipboard
19320
+ * @param event The BeforePaste event
19321
+ */
19322
+ function convertPasteContentForSingleImage(event, trustedHTMLHandler) {
19323
+ var fragment = event.fragment, clipboardData = event.clipboardData;
19324
+ var html = clipboardData.html, image = clipboardData.image;
19325
+ if (html && image) {
19326
+ //If there are Html in the clipboard, and the html body only have one img children, use the HTML
19327
+ var doc = new DOMParser().parseFromString(trustedHTMLHandler(html), 'text/html');
19328
+ roosterjs_editor_dom_1.moveChildNodes(fragment, doc === null || doc === void 0 ? void 0 : doc.body);
19329
+ }
19330
+ }
19331
+ exports.default = convertPasteContentForSingleImage;
19332
+
19333
+
18424
19334
  /***/ }),
18425
19335
 
18426
19336
  /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/index.ts":
@@ -18451,6 +19361,7 @@ exports.Paste = Paste_1.default;
18451
19361
  Object.defineProperty(exports, "__esModule", { value: true });
18452
19362
  var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
18453
19363
  /**
19364
+ * @internal
18454
19365
  * Process pasted content, if there are multiple blocks that are not wrapped by a shared ancestor node,
18455
19366
  * change the tag of first and last node to be SPAN so that it will be merged into current block
18456
19367
  * @param root Root node of content to process
@@ -18530,49 +19441,6 @@ function createListItemBlock(listItem) {
18530
19441
  exports.createListItemBlock = createListItemBlock;
18531
19442
 
18532
19443
 
18533
- /***/ }),
18534
-
18535
- /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/officeOnlineConverter/constants.ts":
18536
- /*!************************************************************************************************!*\
18537
- !*** ./packages/roosterjs-editor-plugins/lib/plugins/Paste/officeOnlineConverter/constants.ts ***!
18538
- \************************************************************************************************/
18539
- /*! no static exports found */
18540
- /***/ (function(module, exports, __webpack_require__) {
18541
-
18542
- "use strict";
18543
-
18544
- Object.defineProperty(exports, "__esModule", { value: true });
18545
- /**
18546
- * @internal
18547
- */
18548
- exports.WORD_ORDERED_LIST_SELECTOR = 'div.ListContainerWrapper > ul[class^="BulletListStyle"]';
18549
- /**
18550
- * @internal
18551
- */
18552
- exports.WORD_UNORDERED_LIST_SELECTOR = 'div.ListContainerWrapper > ol[class^="NumberListStyle"]';
18553
- /**
18554
- * @internal
18555
- */
18556
- exports.WORD_ONLINE_IDENTIFYING_SELECTOR = exports.WORD_ORDERED_LIST_SELECTOR + "," + exports.WORD_UNORDERED_LIST_SELECTOR;
18557
- /**
18558
- * @internal
18559
- */
18560
- exports.LIST_CONTAINER_ELEMENT_CLASS_NAME = 'ListContainerWrapper';
18561
- /**
18562
- * @internal
18563
- */
18564
- exports.UNORDERED_LIST_TAG_NAME = 'UL';
18565
- /**
18566
- * @internal
18567
- */
18568
- exports.ORDERED_LIST_TAG_NAME = 'OL';
18569
- var TEXT_CONTAINER_ELEMENT_CLASS_NAME = 'OutlineElement';
18570
- /**
18571
- * @internal
18572
- */
18573
- exports.WAC_IDENTIFY_SELECTOR = "ul[class^=\"BulletListStyle\"]>." + TEXT_CONTAINER_ELEMENT_CLASS_NAME + ",ol[class^=\"NumberListStyle\"]>." + TEXT_CONTAINER_ELEMENT_CLASS_NAME;
18574
-
18575
-
18576
19444
  /***/ }),
18577
19445
 
18578
19446
  /***/ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/officeOnlineConverter/convertPastedContentFromWordOnline.ts":
@@ -18586,13 +19454,14 @@ exports.WAC_IDENTIFY_SELECTOR = "ul[class^=\"BulletListStyle\"]>." + TEXT_CONTAI
18586
19454
 
18587
19455
  Object.defineProperty(exports, "__esModule", { value: true });
18588
19456
  var ListItemBlock_1 = __webpack_require__(/*! ./ListItemBlock */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/officeOnlineConverter/ListItemBlock.ts");
18589
- var constants_1 = __webpack_require__(/*! ./constants */ "./packages/roosterjs-editor-plugins/lib/plugins/Paste/officeOnlineConverter/constants.ts");
18590
19457
  var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
19458
+ var WORD_ONLINE_IDENTIFYING_SELECTOR = 'div.ListContainerWrapper>ul[class^="BulletListStyle"],div.ListContainerWrapper>ol[class^="NumberListStyle"]';
19459
+ var LIST_CONTAINER_ELEMENT_CLASS_NAME = 'ListContainerWrapper';
18591
19460
  /**
18592
19461
  * @internal
18593
19462
  */
18594
19463
  function isWordOnlineWithList(fragment) {
18595
- return !!(fragment && fragment.querySelector(constants_1.WORD_ONLINE_IDENTIFYING_SELECTOR));
19464
+ return !!(fragment && fragment.querySelector(WORD_ONLINE_IDENTIFYING_SELECTOR));
18596
19465
  }
18597
19466
  exports.isWordOnlineWithList = isWordOnlineWithList;
18598
19467
  // Word Online pasted content DOM structure as of July 12th 2019
@@ -18707,9 +19576,9 @@ exports.default = convertPastedContentFromWordOnline;
18707
19576
  * @param fragment pasted document that contains all the list element.
18708
19577
  */
18709
19578
  function sanitizeListItemContainer(fragment) {
18710
- var listItemContainerListEl = roosterjs_editor_dom_1.toArray(fragment.querySelectorAll(constants_1.WORD_ORDERED_LIST_SELECTOR + ", " + constants_1.WORD_UNORDERED_LIST_SELECTOR));
19579
+ var listItemContainerListEl = roosterjs_editor_dom_1.toArray(fragment.querySelectorAll(WORD_ONLINE_IDENTIFYING_SELECTOR));
18711
19580
  listItemContainerListEl.forEach(function (el) {
18712
- var replaceRegex = new RegExp("\\b" + constants_1.LIST_CONTAINER_ELEMENT_CLASS_NAME + "\\b", 'g');
19581
+ var replaceRegex = new RegExp("\\b" + LIST_CONTAINER_ELEMENT_CLASS_NAME + "\\b", 'g');
18713
19582
  if (el.previousSibling) {
18714
19583
  var prevParent = roosterjs_editor_dom_1.splitParentNode(el, true);
18715
19584
  prevParent.className = prevParent.className.replace(replaceRegex, '');
@@ -18725,7 +19594,7 @@ function sanitizeListItemContainer(fragment) {
18725
19594
  * @param fragment pasted document that contains all the list element.
18726
19595
  */
18727
19596
  function getListItemBlocks(fragment) {
18728
- var listElements = fragment.querySelectorAll('.' + constants_1.LIST_CONTAINER_ELEMENT_CLASS_NAME);
19597
+ var listElements = fragment.querySelectorAll('.' + LIST_CONTAINER_ELEMENT_CLASS_NAME);
18729
19598
  var result = [];
18730
19599
  var curListItemBlock;
18731
19600
  for (var i = 0; i < listElements.length; i++) {
@@ -18774,7 +19643,7 @@ function flattenListBlock(fragment, listItemBlock) {
18774
19643
  */
18775
19644
  function getContainerListType(listItemContainer) {
18776
19645
  var tag = roosterjs_editor_dom_1.getTagOfNode(listItemContainer.firstChild);
18777
- return tag == constants_1.UNORDERED_LIST_TAG_NAME || tag == constants_1.ORDERED_LIST_TAG_NAME ? tag : null;
19646
+ return tag == 'UL' || tag == 'OL' ? tag : null;
18778
19647
  }
18779
19648
  /**
18780
19649
  * Insert list item into the correct position of a list
@@ -18802,7 +19671,7 @@ function insertListItem(listRootElement, itemToInsert, listType, doc) {
18802
19671
  // and the level iterator should move to the UL/OL at the last position.
18803
19672
  var lastChild = curListLevel.lastElementChild;
18804
19673
  var lastChildTag = roosterjs_editor_dom_1.getTagOfNode(lastChild);
18805
- if (lastChildTag == constants_1.UNORDERED_LIST_TAG_NAME || lastChildTag == constants_1.ORDERED_LIST_TAG_NAME) {
19674
+ if (lastChildTag == 'UL' || lastChildTag == 'OL') {
18806
19675
  // If the last child is a list(UL/OL), then move the level iterator to last child.
18807
19676
  curListLevel = lastChild;
18808
19677
  }
@@ -18859,27 +19728,22 @@ function insertConvertedListToDoc(convertedListElement, fragment, listItemBlock)
18859
19728
  "use strict";
18860
19729
 
18861
19730
  Object.defineProperty(exports, "__esModule", { value: true });
19731
+ var roosterjs_editor_dom_1 = __webpack_require__(/*! roosterjs-editor-dom */ "./packages/roosterjs-editor-dom/lib/index.ts");
18862
19732
  /**
18863
19733
  * @internal
18864
19734
  * Convert pasted content from PowerPoint
18865
19735
  * @param event The BeforePaste event
18866
19736
  */
18867
- function convertPastedContentFromExcel(event) {
18868
- var _a;
19737
+ function convertPastedContentFromPowerPoint(event, trustedHTMLHandler) {
18869
19738
  var fragment = event.fragment, clipboardData = event.clipboardData;
18870
19739
  if (clipboardData.html && !clipboardData.text && clipboardData.image) {
18871
19740
  // It is possible that PowerPoint copied both image and HTML but not plain text.
18872
19741
  // We always prefer HTML if any.
18873
- var doc = new DOMParser().parseFromString(clipboardData.html, 'text/html');
18874
- while (fragment.firstChild) {
18875
- fragment.removeChild(fragment.firstChild);
18876
- }
18877
- while ((_a = doc === null || doc === void 0 ? void 0 : doc.body) === null || _a === void 0 ? void 0 : _a.firstChild) {
18878
- fragment.appendChild(doc.body.firstChild);
18879
- }
19742
+ var doc = new DOMParser().parseFromString(trustedHTMLHandler(clipboardData.html), 'text/html');
19743
+ roosterjs_editor_dom_1.moveChildNodes(fragment, doc === null || doc === void 0 ? void 0 : doc.body);
18880
19744
  }
18881
19745
  }
18882
- exports.default = convertPastedContentFromExcel;
19746
+ exports.default = convertPastedContentFromPowerPoint;
18883
19747
 
18884
19748
 
18885
19749
  /***/ }),
@@ -19033,7 +19897,8 @@ function convertPastedContentFromWord(event) {
19033
19897
  var sanitizingOption = event.sanitizingOption, fragment = event.fragment;
19034
19898
  // Preserve <o:p> when its innerHTML is "&nbsp;" to avoid dropping an empty line
19035
19899
  roosterjs_editor_dom_1.chainSanitizerCallback(sanitizingOption.elementCallbacks, 'O:P', function (element) {
19036
- element.innerHTML = '&nbsp;';
19900
+ roosterjs_editor_dom_1.moveChildNodes(element);
19901
+ element.appendChild(element.ownerDocument.createTextNode('\u00A0')); // &nbsp;
19037
19902
  return true;
19038
19903
  });
19039
19904
  var wordConverter = wordConverter_1.createWordConverter();
@@ -19169,9 +20034,7 @@ function processNodesDiscovery(wordConverter) {
19169
20034
  // Add 2 line breaks and move all the nodes to the last item
19170
20035
  last.appendChild(last.ownerDocument.createElement('br'));
19171
20036
  last.appendChild(last.ownerDocument.createElement('br'));
19172
- while (node.firstChild != null) {
19173
- last.appendChild(node.firstChild);
19174
- }
20037
+ roosterjs_editor_dom_1.moveChildNodes(last, node, true /*keepExistingChildren*/);
19175
20038
  // Remove the item that we don't need anymore
19176
20039
  node.parentNode.removeChild(node);
19177
20040
  }
@@ -19204,9 +20067,7 @@ function processNodeConvert(wordConverter) {
19204
20067
  cleanupListIgnore(node, LOOKUP_DEPTH);
19205
20068
  // Create a new list item and transfer the children
19206
20069
  var li = node.ownerDocument.createElement('LI');
19207
- while (node.firstChild) {
19208
- li.appendChild(node.firstChild);
19209
- }
20070
+ roosterjs_editor_dom_1.moveChildNodes(li, node);
19210
20071
  // Append the list item into the list
19211
20072
  list.appendChild(li);
19212
20073
  // Remove the node we just converted
@@ -19260,9 +20121,7 @@ function convertListIfNeeded(wordConverter, list, listMetadata) {
19260
20121
  // We have the wrong list type.. convert it, set the id again and transfer all the children
19261
20122
  var newList = list.ownerDocument.createElement(listMetadata.tagName);
19262
20123
  WordCustomData_1.setObject(wordConverter.wordCustomData, newList, UNIQUE_LIST_ID_CUSTOM_DATA, WordCustomData_1.getObject(wordConverter.wordCustomData, list, UNIQUE_LIST_ID_CUSTOM_DATA));
19263
- while (list.firstChild) {
19264
- newList.appendChild(list.firstChild);
19265
- }
20124
+ roosterjs_editor_dom_1.moveChildNodes(newList, list);
19266
20125
  list.parentNode.insertBefore(newList, list);
19267
20126
  list.parentNode.removeChild(list);
19268
20127
  list = newList;
@@ -20060,10 +20919,6 @@ var MIN_CELL_WIDTH = 30;
20060
20919
  var MIN_CELL_HEIGHT = 20;
20061
20920
  var CELL_RESIZER_WIDTH = 4;
20062
20921
  var TABLE_RESIZER_LENGTH = 12;
20063
- var HORIZONTAL_RESIZER_HTML = '<div style="position: fixed; cursor: row-resize; user-select: none"></div>';
20064
- var VERTICAL_RESIZER_HTML = '<div style="position: fixed; cursor: col-resize; user-select: none"></div>';
20065
- var TABLE_RESIZER_HTML_LTR = '<div style="position: fixed; cursor: nw-resize; user-select: none; border: 1px solid #808080"></div>';
20066
- var TABLE_RESIZER_HTML_RTL = '<div style="position: fixed; cursor: ne-resize; user-select: none; border: 1px solid #808080""></div>';
20067
20922
  function getHorizontalDistance(rect, pos, toLeft) {
20068
20923
  return toLeft ? pos - rect.left : rect.right - pos;
20069
20924
  }
@@ -20477,11 +21332,30 @@ var TableResize = /** @class */ (function () {
20477
21332
  var inserterBackgroundColor = editorBackgroundColor || 'white';
20478
21333
  var inserterColor = this.editor.isDarkMode() ? INSERTER_COLOR_DARK_MODE : INSERTER_COLOR;
20479
21334
  var leftOrRight = this.isRTL ? 'right' : 'left';
20480
- var HORIZONTAL_INSERTER_HTML = "<div style=\"position: fixed; width: " + INSERTER_SIDE_LENGTH + "px; height: " + INSERTER_SIDE_LENGTH + "px; font-size: 16px; color: " + inserterColor + "; line-height: 10px; vertical-align: middle; text-align: center; cursor: pointer; border: solid " + INSERTER_BORDER_SIZE + "px " + inserterColor + "; border-radius: 50%; background-color: " + inserterBackgroundColor + "\"><div style=\"position: absolute; " + leftOrRight + ": 12px; top: 5px; height: 3px; border-top: 1px solid " + inserterColor + "; border-bottom: 1px solid " + inserterColor + "; border-right: 1px solid " + inserterColor + "; border-left: 0px; box-sizing: border-box; background-color: " + inserterBackgroundColor + ";\"></div>+</div>";
20481
- var VERTICAL_INSERTER_HTML = "<div style=\"position: fixed; width: " + INSERTER_SIDE_LENGTH + "px; height: " + INSERTER_SIDE_LENGTH + "px; font-size: 16px; color: " + inserterColor + "; line-height: 10px; vertical-align: middle; text-align: center; cursor: pointer; border: solid " + INSERTER_BORDER_SIZE + "px " + inserterColor + "; border-radius: 50%; background-color: " + inserterBackgroundColor + "\"><div style=\"position: absolute; left: 5px; top: 12px; width: 3px; border-left: 1px solid " + inserterColor + "; border-right: 1px solid " + inserterColor + "; border-bottom: 1px solid " + inserterColor + "; border-top: 0px; box-sizing: border-box; background-color: " + inserterBackgroundColor + ";\"></div>+</div>";
20482
- var inserter = roosterjs_editor_dom_1.fromHtml(this.insertingState == 1 /* Horizontal */
20483
- ? HORIZONTAL_INSERTER_HTML
20484
- : VERTICAL_INSERTER_HTML, this.editor.getDocument())[0];
21335
+ var outerDivStyle = "position: fixed; width: " + INSERTER_SIDE_LENGTH + "px; height: " + INSERTER_SIDE_LENGTH + "px; font-size: 16px; color: " + inserterColor + "; line-height: 10px; vertical-align: middle; text-align: center; cursor: pointer; border: solid " + INSERTER_BORDER_SIZE + "px " + inserterColor + "; border-radius: 50%; background-color: " + inserterBackgroundColor;
21336
+ var HORIZONTAL_INSERTER = {
21337
+ tag: 'div',
21338
+ style: outerDivStyle,
21339
+ children: [
21340
+ {
21341
+ tag: 'div',
21342
+ style: "position: absolute; " + leftOrRight + ": 12px; top: 5px; height: 3px; border-top: 1px solid " + inserterColor + "; border-bottom: 1px solid " + inserterColor + "; border-right: 1px solid " + inserterColor + "; border-left: 0px; box-sizing: border-box; background-color: " + inserterBackgroundColor + ";",
21343
+ },
21344
+ '+',
21345
+ ],
21346
+ };
21347
+ var VERTICAL_INSERTER = {
21348
+ tag: 'div',
21349
+ style: outerDivStyle,
21350
+ children: [
21351
+ {
21352
+ tag: 'div',
21353
+ style: "position: absolute; left: 5px; top: 12px; width: 3px; border-left: 1px solid " + inserterColor + "; border-right: 1px solid " + inserterColor + "; border-bottom: 1px solid " + inserterColor + "; border-top: 0px; box-sizing: border-box; background-color: " + inserterBackgroundColor,
21354
+ },
21355
+ '+',
21356
+ ],
21357
+ };
21358
+ var inserter = roosterjs_editor_dom_1.createElement(this.insertingState == 1 /* Horizontal */ ? HORIZONTAL_INSERTER : VERTICAL_INSERTER, this.editor.getDocument());
20485
21359
  if (rect) {
20486
21360
  if (this.insertingState == 1 /* Horizontal */) {
20487
21361
  if (this.isRTL) {
@@ -20547,7 +21421,9 @@ var TableResize = /** @class */ (function () {
20547
21421
  }
20548
21422
  };
20549
21423
  TableResize.prototype.createTableResizer = function (rect) {
20550
- var div = roosterjs_editor_dom_1.fromHtml(this.isRTL ? TABLE_RESIZER_HTML_RTL : TABLE_RESIZER_HTML_LTR, this.editor.getDocument())[0];
21424
+ var div = roosterjs_editor_dom_1.createElement(this.isRTL
21425
+ ? 10 /* TableResizerRTL */
21426
+ : 9 /* TableResizerLTR */, this.editor.getDocument());
20551
21427
  div.style.top = rect.bottom + "px";
20552
21428
  div.style.left = this.isRTL
20553
21429
  ? rect.left - TABLE_RESIZER_LENGTH - 2 + "px"
@@ -20558,7 +21434,9 @@ var TableResize = /** @class */ (function () {
20558
21434
  return div;
20559
21435
  };
20560
21436
  TableResize.prototype.createCellsResizer = function (horizontal, left, top, width, height) {
20561
- var div = roosterjs_editor_dom_1.fromHtml(horizontal ? HORIZONTAL_RESIZER_HTML : VERTICAL_RESIZER_HTML, this.editor.getDocument())[0];
21437
+ var div = roosterjs_editor_dom_1.createElement(horizontal
21438
+ ? 7 /* TableHorizontalResizer */
21439
+ : 8 /* TableVerticalResizer */, this.editor.getDocument());
20562
21440
  div.style.top = top + "px";
20563
21441
  div.style.left = left + "px";
20564
21442
  div.style.width = width + "px";
@@ -20760,11 +21638,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
20760
21638
  "use strict";
20761
21639
 
20762
21640
  Object.defineProperty(exports, "__esModule", { value: true });
20763
- var ContentEdit_1 = __webpack_require__(/*! roosterjs-editor-plugins/lib/ContentEdit */ "./packages/roosterjs-editor-plugins/lib/ContentEdit.ts");
20764
21641
  var roosterjs_editor_core_1 = __webpack_require__(/*! roosterjs-editor-core */ "./packages/roosterjs-editor-core/lib/index.ts");
20765
21642
  var roosterjs_color_utils_1 = __webpack_require__(/*! roosterjs-color-utils */ "./packages/roosterjs-color-utils/lib/index.ts");
20766
- var HyperLink_1 = __webpack_require__(/*! roosterjs-editor-plugins/lib/HyperLink */ "./packages/roosterjs-editor-plugins/lib/HyperLink.ts");
20767
- var Paste_1 = __webpack_require__(/*! roosterjs-editor-plugins/lib/Paste */ "./packages/roosterjs-editor-plugins/lib/Paste.ts");
21643
+ var roosterjs_editor_plugins_1 = __webpack_require__(/*! roosterjs-editor-plugins */ "./packages/roosterjs-editor-plugins/lib/index.ts");
20768
21644
  /**
20769
21645
  * Create an editor instance with most common options
20770
21646
  * @param contentDiv The html div element needed for creating the editor
@@ -20774,7 +21650,7 @@ var Paste_1 = __webpack_require__(/*! roosterjs-editor-plugins/lib/Paste */ "./p
20774
21650
  * @returns The editor instance
20775
21651
  */
20776
21652
  function createEditor(contentDiv, additionalPlugins, initialContent) {
20777
- var plugins = [new HyperLink_1.HyperLink(), new Paste_1.Paste(), new ContentEdit_1.ContentEdit()];
21653
+ var plugins = [new roosterjs_editor_plugins_1.HyperLink(), new roosterjs_editor_plugins_1.Paste(), new roosterjs_editor_plugins_1.ContentEdit()];
20778
21654
  if (additionalPlugins) {
20779
21655
  plugins = plugins.concat(additionalPlugins);
20780
21656
  }