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