roosterjs 9.53.0 → 9.55.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/rooster-adapter-amd-min.js +1 -1
- package/dist/rooster-adapter-amd-min.js.map +1 -1
- package/dist/rooster-adapter-amd.js +10 -8
- package/dist/rooster-adapter-amd.js.map +1 -1
- package/dist/rooster-adapter-min.js +1 -1
- package/dist/rooster-adapter-min.js.map +1 -1
- package/dist/rooster-adapter.js +10 -8
- package/dist/rooster-adapter.js.map +1 -1
- package/dist/rooster-amd-min.js +1 -1
- package/dist/rooster-amd-min.js.map +1 -1
- package/dist/rooster-amd.d.ts +112 -5
- package/dist/rooster-amd.js +502 -41
- package/dist/rooster-amd.js.map +1 -1
- package/dist/rooster-min.js +1 -1
- package/dist/rooster-min.js.map +1 -1
- package/dist/rooster.d.ts +112 -5
- package/dist/rooster.js +502 -41
- package/dist/rooster.js.map +1 -1
- package/package.json +7 -7
package/dist/rooster-amd.js
CHANGED
|
@@ -6751,7 +6751,7 @@ var formatSegmentWithContentModel_1 = __webpack_require__(/*! ../utils/formatSeg
|
|
|
6751
6751
|
*/
|
|
6752
6752
|
function changeCapitalization(editor, capitalization, language) {
|
|
6753
6753
|
editor.focus();
|
|
6754
|
-
(0, formatSegmentWithContentModel_1.formatSegmentWithContentModel)(editor, 'changeCapitalization', function (_, __, segment) {
|
|
6754
|
+
(0, formatSegmentWithContentModel_1.formatSegmentWithContentModel)(editor, 'changeCapitalization', function (_, __, segment, paragraph) {
|
|
6755
6755
|
if ((segment === null || segment === void 0 ? void 0 : segment.segmentType) == 'Text') {
|
|
6756
6756
|
switch (capitalization) {
|
|
6757
6757
|
case 'lowerCase':
|
|
@@ -6762,7 +6762,13 @@ function changeCapitalization(editor, capitalization, language) {
|
|
|
6762
6762
|
break;
|
|
6763
6763
|
case 'capitalize':
|
|
6764
6764
|
var wordArray = segment.text.toLocaleLowerCase(language).split(' ');
|
|
6765
|
-
|
|
6765
|
+
// When a collapsed selection is in the middle of a word, the word is split
|
|
6766
|
+
// into multiple text segments around the selection marker. In that case the
|
|
6767
|
+
// first segment of the word continues from a previous segment, so its first
|
|
6768
|
+
// word must not be capitalized to avoid results like "HeLlo" for "he|llo".
|
|
6769
|
+
var precedingChar = getPrecedingCharacter(paragraph, segment);
|
|
6770
|
+
var startIndex = precedingChar && precedingChar != ' ' ? 1 : 0;
|
|
6771
|
+
for (var i = startIndex; i < wordArray.length; i++) {
|
|
6766
6772
|
wordArray[i] =
|
|
6767
6773
|
wordArray[i].charAt(0).toLocaleUpperCase(language) +
|
|
6768
6774
|
wordArray[i].slice(1);
|
|
@@ -6786,6 +6792,30 @@ function changeCapitalization(editor, capitalization, language) {
|
|
|
6786
6792
|
});
|
|
6787
6793
|
}
|
|
6788
6794
|
exports.changeCapitalization = changeCapitalization;
|
|
6795
|
+
/**
|
|
6796
|
+
* Get the character immediately preceding the given segment within its paragraph, skipping
|
|
6797
|
+
* selection markers (which carry no text). Returns an empty string if there is no preceding
|
|
6798
|
+
* text character (e.g. the segment starts the paragraph or follows a non-text segment).
|
|
6799
|
+
*/
|
|
6800
|
+
function getPrecedingCharacter(paragraph, segment) {
|
|
6801
|
+
if (!paragraph) {
|
|
6802
|
+
return '';
|
|
6803
|
+
}
|
|
6804
|
+
var index = paragraph.segments.indexOf(segment);
|
|
6805
|
+
for (var i = index - 1; i >= 0; i--) {
|
|
6806
|
+
var previous = paragraph.segments[i];
|
|
6807
|
+
if (previous.segmentType == 'SelectionMarker') {
|
|
6808
|
+
continue;
|
|
6809
|
+
}
|
|
6810
|
+
else if (previous.segmentType == 'Text' && previous.text.length > 0) {
|
|
6811
|
+
return previous.text[previous.text.length - 1];
|
|
6812
|
+
}
|
|
6813
|
+
else {
|
|
6814
|
+
break;
|
|
6815
|
+
}
|
|
6816
|
+
}
|
|
6817
|
+
return '';
|
|
6818
|
+
}
|
|
6789
6819
|
|
|
6790
6820
|
|
|
6791
6821
|
/***/ },
|
|
@@ -8019,6 +8049,15 @@ function formatInsertPointWithContentModel(editor, insertPoint, callback, option
|
|
|
8019
8049
|
textWithSelection: getShadowTextProcessor(bundle),
|
|
8020
8050
|
},
|
|
8021
8051
|
tryGetFromCache: false,
|
|
8052
|
+
// When an element carries "container level" styles such as margin or padding, we first
|
|
8053
|
+
// wrap it in a FormatContainer. After all its child nodes are processed, we decide whether
|
|
8054
|
+
// to keep the FormatContainer or fall back to a plain paragraph when it only wraps a single
|
|
8055
|
+
// paragraph. However, formatInsertPointWithContentModel persists the Content Model group path
|
|
8056
|
+
// during processing so the later formatting callback can still use it (see the
|
|
8057
|
+
// DomToModelContextWithPath interface below). If the FormatContainer falls back to a paragraph,
|
|
8058
|
+
// it is removed from the model and the persisted path becomes invalid. To keep the path valid,
|
|
8059
|
+
// we skip the fallback check here and always keep the FormatContainer when one is needed.
|
|
8060
|
+
skipFormatContainerFallbackCheck: true,
|
|
8022
8061
|
});
|
|
8023
8062
|
}
|
|
8024
8063
|
exports.formatInsertPointWithContentModel = formatInsertPointWithContentModel;
|
|
@@ -9339,21 +9378,11 @@ exports.generatePasteOptionFromPlugins = generatePasteOptionFromPlugins;
|
|
|
9339
9378
|
"use strict";
|
|
9340
9379
|
|
|
9341
9380
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
9342
|
-
exports.mergePasteContent =
|
|
9381
|
+
exports.mergePasteContent = void 0;
|
|
9343
9382
|
var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
|
|
9344
9383
|
var createDomToModelContextForSanitizing_1 = __webpack_require__(/*! ../createModelFromHtml/createDomToModelContextForSanitizing */ "./packages/roosterjs-content-model-core/lib/command/createModelFromHtml/createDomToModelContextForSanitizing.ts");
|
|
9345
9384
|
var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
|
|
9346
9385
|
var BlackColor = 'rgb(0,0,0)';
|
|
9347
|
-
var CloneOption = {
|
|
9348
|
-
includeCachedElement: function (node, type) { return (type == 'cache' ? undefined : node); },
|
|
9349
|
-
};
|
|
9350
|
-
/**
|
|
9351
|
-
* @internal
|
|
9352
|
-
*/
|
|
9353
|
-
function cloneModelForPaste(model) {
|
|
9354
|
-
return (0, roosterjs_content_model_dom_1.cloneModel)(model, CloneOption);
|
|
9355
|
-
}
|
|
9356
|
-
exports.cloneModelForPaste = cloneModelForPaste;
|
|
9357
9386
|
/**
|
|
9358
9387
|
* @internal
|
|
9359
9388
|
*/
|
|
@@ -9361,7 +9390,7 @@ function mergePasteContent(editor, eventResult, isFirstPaste) {
|
|
|
9361
9390
|
var fragment = eventResult.fragment, domToModelOption = eventResult.domToModelOption, customizedMerge = eventResult.customizedMerge, pasteType = eventResult.pasteType, clipboardData = eventResult.clipboardData, containsBlockElements = eventResult.containsBlockElements;
|
|
9362
9391
|
editor.formatContentModel(function (model, context) {
|
|
9363
9392
|
if (!isFirstPaste && clipboardData.modelBeforePaste) {
|
|
9364
|
-
var clonedModel = cloneModelForPaste(clipboardData.modelBeforePaste);
|
|
9393
|
+
var clonedModel = (0, roosterjs_content_model_dom_1.cloneModelForPaste)(clipboardData.modelBeforePaste);
|
|
9365
9394
|
model.blocks = clonedModel.blocks;
|
|
9366
9395
|
}
|
|
9367
9396
|
var domToModelContext = (0, createDomToModelContextForSanitizing_1.createDomToModelContextForSanitizing)(editor.getDocument(), undefined /*defaultFormat*/, editor.getEnvironment().domToModelSettings.customized, domToModelOption, editor.getDOMHelper());
|
|
@@ -9440,10 +9469,11 @@ function getLastSegmentFormat(pasteModel) {
|
|
|
9440
9469
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
9441
9470
|
exports.paste = void 0;
|
|
9442
9471
|
var cleanHtmlComments_1 = __webpack_require__(/*! ./cleanHtmlComments */ "./packages/roosterjs-content-model-core/lib/command/paste/cleanHtmlComments.ts");
|
|
9443
|
-
var
|
|
9472
|
+
var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
|
|
9444
9473
|
var convertInlineCss_1 = __webpack_require__(/*! ../createModelFromHtml/convertInlineCss */ "./packages/roosterjs-content-model-core/lib/command/createModelFromHtml/convertInlineCss.ts");
|
|
9445
9474
|
var createPasteFragment_1 = __webpack_require__(/*! ./createPasteFragment */ "./packages/roosterjs-content-model-core/lib/command/paste/createPasteFragment.ts");
|
|
9446
9475
|
var generatePasteOptionFromPlugins_1 = __webpack_require__(/*! ./generatePasteOptionFromPlugins */ "./packages/roosterjs-content-model-core/lib/command/paste/generatePasteOptionFromPlugins.ts");
|
|
9476
|
+
var mergePasteContent_1 = __webpack_require__(/*! ./mergePasteContent */ "./packages/roosterjs-content-model-core/lib/command/paste/mergePasteContent.ts");
|
|
9447
9477
|
var retrieveHtmlInfo_1 = __webpack_require__(/*! ./retrieveHtmlInfo */ "./packages/roosterjs-content-model-core/lib/command/paste/retrieveHtmlInfo.ts");
|
|
9448
9478
|
/**
|
|
9449
9479
|
* Paste into editor using a clipboardData object
|
|
@@ -9459,7 +9489,7 @@ function paste(editor, clipboardData, pasteTypeOrGetter) {
|
|
|
9459
9489
|
if (!clipboardData.modelBeforePaste) {
|
|
9460
9490
|
isFirstPaste = true;
|
|
9461
9491
|
editor.formatContentModel(function (model) {
|
|
9462
|
-
clipboardData.modelBeforePaste = (0,
|
|
9492
|
+
clipboardData.modelBeforePaste = (0, roosterjs_content_model_dom_1.cloneModelForPaste)(model);
|
|
9463
9493
|
return false;
|
|
9464
9494
|
});
|
|
9465
9495
|
}
|
|
@@ -10103,6 +10133,9 @@ var createContentModel = function (core, option, selectionOverride) {
|
|
|
10103
10133
|
var domToModelContext = option
|
|
10104
10134
|
? (0, roosterjs_content_model_dom_1.createDomToModelContext)(editorContext, settings.builtIn, settings.customized, option)
|
|
10105
10135
|
: (0, roosterjs_content_model_dom_1.createDomToModelContextWithConfig)(settings.calculated, editorContext);
|
|
10136
|
+
if (option === null || option === void 0 ? void 0 : option.skipFormatContainerFallbackCheck) {
|
|
10137
|
+
domToModelContext.skipFormatContainerFallbackCheck = true;
|
|
10138
|
+
}
|
|
10106
10139
|
if (selection) {
|
|
10107
10140
|
domToModelContext.selection = selection;
|
|
10108
10141
|
}
|
|
@@ -11574,6 +11607,11 @@ var CachePlugin = /** @class */ (function () {
|
|
|
11574
11607
|
_this.invalidateCache();
|
|
11575
11608
|
}
|
|
11576
11609
|
break;
|
|
11610
|
+
case 'attribute':
|
|
11611
|
+
if (!_this.state.domIndexer.reconcileImageAttribute(mutation.element, mutation.attributeName)) {
|
|
11612
|
+
_this.invalidateCache();
|
|
11613
|
+
}
|
|
11614
|
+
break;
|
|
11577
11615
|
case 'unknown':
|
|
11578
11616
|
_this.invalidateCache();
|
|
11579
11617
|
break;
|
|
@@ -12105,6 +12143,33 @@ var DomIndexerImpl = /** @class */ (function () {
|
|
|
12105
12143
|
return false;
|
|
12106
12144
|
}
|
|
12107
12145
|
};
|
|
12146
|
+
DomIndexerImpl.prototype.reconcileImageAttribute = function (element, attributeName) {
|
|
12147
|
+
var _a, _b;
|
|
12148
|
+
if ((0, roosterjs_content_model_dom_1.isElementOfType)(element, 'img')) {
|
|
12149
|
+
var image = (_a = getIndexedSegmentItem(element)) === null || _a === void 0 ? void 0 : _a.segments[0];
|
|
12150
|
+
if ((image === null || image === void 0 ? void 0 : image.segmentType) == 'Image') {
|
|
12151
|
+
if (attributeName == 'src') {
|
|
12152
|
+
// Use getAttribute('src') instead of retrieving src directly, in case the src
|
|
12153
|
+
// has port and may be stripped by browser. This matches imageProcessor.
|
|
12154
|
+
image.src = (_b = element.getAttribute('src')) !== null && _b !== void 0 ? _b : '';
|
|
12155
|
+
return true;
|
|
12156
|
+
}
|
|
12157
|
+
else if (attributeName.indexOf('data-') == 0) {
|
|
12158
|
+
// A data-* attribute may be added, modified or removed. Rebuild the whole
|
|
12159
|
+
// dataset from DOM to keep it in sync, the same way imageProcessor builds it.
|
|
12160
|
+
var dataset_1 = image.dataset;
|
|
12161
|
+
(0, roosterjs_content_model_dom_1.getObjectKeys)(dataset_1).forEach(function (key) {
|
|
12162
|
+
delete dataset_1[key];
|
|
12163
|
+
});
|
|
12164
|
+
(0, roosterjs_content_model_dom_1.getObjectKeys)(element.dataset).forEach(function (key) {
|
|
12165
|
+
dataset_1[key] = element.dataset[key] || '';
|
|
12166
|
+
});
|
|
12167
|
+
return true;
|
|
12168
|
+
}
|
|
12169
|
+
}
|
|
12170
|
+
}
|
|
12171
|
+
return false;
|
|
12172
|
+
};
|
|
12108
12173
|
DomIndexerImpl.prototype.onBlockEntityDelimiter = function (node, entity, parent) {
|
|
12109
12174
|
if ((0, roosterjs_content_model_dom_1.isNodeOfType)(node, 'ELEMENT_NODE') && (0, roosterjs_content_model_dom_1.isEntityDelimiter)(node) && node.firstChild) {
|
|
12110
12175
|
var indexedDelimiter = node.firstChild;
|
|
@@ -12420,6 +12485,16 @@ var TextMutationObserverImpl = /** @class */ (function () {
|
|
|
12420
12485
|
(0, roosterjs_content_model_dom_1.isNodeOfType)(target, 'ELEMENT_NODE')) {
|
|
12421
12486
|
_this.onMutation({ type: 'elementId', element: target });
|
|
12422
12487
|
}
|
|
12488
|
+
else if (mutation.attributeName &&
|
|
12489
|
+
(0, roosterjs_content_model_dom_1.isNodeOfType)(target, 'ELEMENT_NODE') &&
|
|
12490
|
+
(mutation.attributeName == 'src' ||
|
|
12491
|
+
mutation.attributeName.indexOf('data-') == 0)) {
|
|
12492
|
+
_this.onMutation({
|
|
12493
|
+
type: 'attribute',
|
|
12494
|
+
element: target,
|
|
12495
|
+
attributeName: mutation.attributeName,
|
|
12496
|
+
});
|
|
12497
|
+
}
|
|
12423
12498
|
else {
|
|
12424
12499
|
// We cannot handle attributes changes on editor content for now
|
|
12425
12500
|
canHandle = false;
|
|
@@ -12699,7 +12774,7 @@ var CopyPastePlugin = /** @class */ (function () {
|
|
|
12699
12774
|
var dataTransfer = event.clipboardData;
|
|
12700
12775
|
if (shouldPreventDefaultPaste(dataTransfer, editor_1)) {
|
|
12701
12776
|
event.preventDefault();
|
|
12702
|
-
(0, roosterjs_content_model_dom_1.extractClipboardItems)((0, roosterjs_content_model_dom_1.toArray)(dataTransfer.items), _this.state.allowedCustomPasteType).then(function (clipboardData) {
|
|
12777
|
+
(0, roosterjs_content_model_dom_1.extractClipboardItems)((0, roosterjs_content_model_dom_1.toArray)(dataTransfer.items), _this.state.allowedCustomPasteType, true /* isPasteNative */).then(function (clipboardData) {
|
|
12703
12778
|
if (!editor_1.isDisposed()) {
|
|
12704
12779
|
(0, paste_1.paste)(editor_1, clipboardData, _this.state.defaultPasteType);
|
|
12705
12780
|
}
|
|
@@ -18136,7 +18211,9 @@ var formatContainerProcessorInternal = function (group, element, context, forceF
|
|
|
18136
18211
|
if (element.style.fontSize && parseInt(element.style.fontSize) == 0) {
|
|
18137
18212
|
formatContainer.zeroFontSize = true;
|
|
18138
18213
|
}
|
|
18139
|
-
if (
|
|
18214
|
+
if (!context.skipFormatContainerFallbackCheck &&
|
|
18215
|
+
shouldFallbackToParagraph(formatContainer) &&
|
|
18216
|
+
!forceFormatContainer) {
|
|
18140
18217
|
// For DIV container that only has one paragraph child, container style can be merged into paragraph
|
|
18141
18218
|
// and no need to have this container
|
|
18142
18219
|
var paragraph = formatContainer.blocks[0];
|
|
@@ -19717,7 +19794,7 @@ var ContentHandlers = (_a = {},
|
|
|
19717
19794
|
* @param allowedCustomPasteType Allowed custom content type when paste besides text/plain, text/html and images
|
|
19718
19795
|
Only text types are supported, and do not add "text/" prefix to the type values
|
|
19719
19796
|
*/
|
|
19720
|
-
function extractClipboardItems(items, allowedCustomPasteType) {
|
|
19797
|
+
function extractClipboardItems(items, allowedCustomPasteType, isPasteNative) {
|
|
19721
19798
|
var data = {
|
|
19722
19799
|
types: [],
|
|
19723
19800
|
text: '',
|
|
@@ -19725,7 +19802,7 @@ function extractClipboardItems(items, allowedCustomPasteType) {
|
|
|
19725
19802
|
files: [],
|
|
19726
19803
|
rawHtml: null,
|
|
19727
19804
|
customValues: {},
|
|
19728
|
-
pasteNativeEvent:
|
|
19805
|
+
pasteNativeEvent: !!isPasteNative,
|
|
19729
19806
|
};
|
|
19730
19807
|
return Promise.all((items || []).map(function (item) {
|
|
19731
19808
|
var type = item.type;
|
|
@@ -20666,6 +20743,7 @@ function pruneUnselectedModel(model) {
|
|
|
20666
20743
|
exports.pruneUnselectedModel = pruneUnselectedModel;
|
|
20667
20744
|
function pruneUnselectedModelInternal(model, isSelectionAfterElement) {
|
|
20668
20745
|
var e_1, _a, _b;
|
|
20746
|
+
var _c;
|
|
20669
20747
|
for (var index = model.blocks.length - 1; index >= 0; index--) {
|
|
20670
20748
|
var block = model.blocks[index];
|
|
20671
20749
|
switch (block.blockType) {
|
|
@@ -20689,15 +20767,17 @@ function pruneUnselectedModelInternal(model, isSelectionAfterElement) {
|
|
|
20689
20767
|
case 'Paragraph':
|
|
20690
20768
|
var newSegments = [];
|
|
20691
20769
|
try {
|
|
20692
|
-
for (var
|
|
20693
|
-
var segment =
|
|
20770
|
+
for (var _d = (e_1 = void 0, (0, tslib_1.__values)(block.segments)), _e = _d.next(); !_e.done; _e = _d.next()) {
|
|
20771
|
+
var segment = _e.value;
|
|
20772
|
+
var isSelectedOrUndeletable = segment.isSelected || ((_c = segment.link) === null || _c === void 0 ? void 0 : _c.format.undeletable);
|
|
20694
20773
|
if (segment.segmentType == 'General') {
|
|
20695
20774
|
pruneUnselectedModel(segment);
|
|
20696
|
-
if (segment.blocks.length > 0 ||
|
|
20775
|
+
if (segment.blocks.length > 0 || isSelectedOrUndeletable) {
|
|
20697
20776
|
newSegments.push(segment);
|
|
20698
20777
|
}
|
|
20699
20778
|
}
|
|
20700
|
-
else if (
|
|
20779
|
+
else if (isSelectedOrUndeletable &&
|
|
20780
|
+
segment.segmentType != 'SelectionMarker') {
|
|
20701
20781
|
newSegments.push(segment);
|
|
20702
20782
|
}
|
|
20703
20783
|
}
|
|
@@ -20705,7 +20785,7 @@ function pruneUnselectedModelInternal(model, isSelectionAfterElement) {
|
|
|
20705
20785
|
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
20706
20786
|
finally {
|
|
20707
20787
|
try {
|
|
20708
|
-
if (
|
|
20788
|
+
if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
|
|
20709
20789
|
}
|
|
20710
20790
|
finally { if (e_1) throw e_1.error; }
|
|
20711
20791
|
}
|
|
@@ -23678,8 +23758,8 @@ exports.shouldSetValue = shouldSetValue;
|
|
|
23678
23758
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
23679
23759
|
exports.createImage = exports.createText = exports.createTableCell = exports.createTable = exports.createSelectionMarker = exports.createParagraph = exports.createFormatContainer = exports.createListItem = exports.createBr = exports.isLinkUndeletable = exports.setLinkUndeletable = exports.scrollRectIntoView = exports.normalizeRect = exports.isWhiteSpacePreserved = exports.reuseCachedElement = exports.findClosestBlockEntityContainer = exports.isBlockEntityContainer = exports.isEntityDelimiter = exports.addDelimiters = exports.generateEntityClassNames = exports.parseEntityFormat = exports.getAllEntityWrappers = exports.findClosestEntityWrapper = exports.isEntityElement = exports.unwrap = exports.wrap = exports.wrapAllChildNodes = exports.moveChildNodes = exports.toArray = exports.getSafeIdSelector = exports.getObjectKeys = exports.isElementOfType = exports.isNodeOfType = exports.hasMetadata = exports.getMetadata = exports.updateMetadata = exports.buildSelectionMarker = exports.isBlockElement = exports.areSameFormats = exports.parseFormat = exports.getRegularSelectionOffsets = exports.formatContainerProcessor = exports.tableProcessor = exports.entityProcessor = exports.processChildNode = exports.handleRegularSelection = exports.childProcessor = exports.contentModelToText = exports.contentModelToDom = exports.domToContentModel = void 0;
|
|
23680
23760
|
exports.trimModelForSelection = exports.getDOMInsertPointRect = exports.getSelectionRootNode = exports.isBold = exports.createModelToDomConfig = exports.createModelToDomContextWithConfig = exports.createModelToDomContext = exports.createDomToModelConfig = exports.createDomToModelContextWithConfig = exports.createDomToModelContext = exports.defaultGenerateColorKey = exports.parseColor = exports.setColor = exports.getColor = exports.DeprecatedColors = exports.BorderKeys = exports.parseValueWithUnit = exports.getAutoListStyleType = exports.getOrderedListNumberStr = exports.ParagraphFormats = exports.ListFormatsToMove = exports.ListFormatsToKeep = exports.ListFormats = exports.copyFormat = exports.setParagraphNotImplicit = exports.normalizeSegmentFormat = exports.mergeTextSegments = exports.normalizeSingleSegment = exports.isEmpty = exports.addSegment = exports.unwrapBlock = exports.isGeneralSegment = exports.normalizeContentModel = exports.normalizeParagraph = exports.addTextSegment = exports.addLink = exports.addCode = exports.addBlock = exports.mutateSegment = exports.mutateSegments = exports.mutateBlock = exports.createTableRow = exports.createEmptyModel = exports.createListLevel = exports.createDivider = exports.createEntity = exports.createGeneralBlock = exports.createGeneralSegment = exports.createParagraphDecorator = exports.createContentModelDocument = void 0;
|
|
23681
|
-
exports.
|
|
23682
|
-
exports.EmptySegmentFormat = exports.UnorderedListStyleMap = exports.OrderedListStyleMap = exports.TableBorderFormat = exports.NumberingListType = exports.BulletListType = exports.ChangeSource = exports.ListMetadataDefinition = exports.getListMetadata = exports.updateListMetadata = exports.getTableMetadata = exports.updateTableMetadata = exports.getTableCellMetadata = exports.updateTableCellMetadata = exports.getImageMetadata = exports.updateImageMetadata = void 0;
|
|
23761
|
+
exports.getClosestAncestorBlockGroupIndex = exports.getSegmentTextFormat = exports.getListStyleTypeFromString = exports.retrieveModelFormatState = exports.setTableCellBackgroundColor = exports.MIN_ALLOWED_TABLE_CELL_HEIGHT = exports.MIN_ALLOWED_TABLE_CELL_WIDTH = exports.normalizeTable = exports.setFirstColumnFormatBorders = exports.applyTableFormat = exports.deleteBlock = exports.deleteSegment = exports.deleteSelection = exports.mergeModel = exports.cloneModelForPaste = exports.cloneModel = exports.setSelection = exports.hasSelectionInBlockGroup = exports.hasSelectionInSegment = exports.hasSelectionInBlock = exports.getSelectedCells = exports.getSelectedSegmentsAndParagraphs = exports.getSelectedSegments = exports.getSelectedParagraphs = exports.getOperationalBlocks = exports.getFirstSelectedTable = exports.getFirstSelectedListItem = exports.iterateSelections = exports.isBlockGroupOfType = exports.getRangesByText = exports.getImageState = exports.setImageState = exports.getParagraphMarker = exports.setParagraphMarker = exports.cacheGetEventData = exports.extractClipboardItems = exports.normalizeFontFamily = exports.transformColor = exports.retrieveDocumentMetadata = exports.readFile = exports.parseTableCells = exports.normalizeText = exports.isSpace = exports.isPunctuation = exports.extractBorderValues = exports.combineBorderValue = exports.getNodePositionFromEvent = exports.isCursorMovingKey = exports.isModifierKey = exports.isCharacterValue = void 0;
|
|
23762
|
+
exports.EmptySegmentFormat = exports.UnorderedListStyleMap = exports.OrderedListStyleMap = exports.TableBorderFormat = exports.NumberingListType = exports.BulletListType = exports.ChangeSource = exports.ListMetadataDefinition = exports.getListMetadata = exports.updateListMetadata = exports.getTableMetadata = exports.updateTableMetadata = exports.getTableCellMetadata = exports.updateTableCellMetadata = exports.getImageMetadata = exports.updateImageMetadata = exports.runEditSteps = void 0;
|
|
23683
23763
|
var domToContentModel_1 = __webpack_require__(/*! ./domToModel/domToContentModel */ "./packages/roosterjs-content-model-dom/lib/domToModel/domToContentModel.ts");
|
|
23684
23764
|
Object.defineProperty(exports, "domToContentModel", ({ enumerable: true, get: function () { return domToContentModel_1.domToContentModel; } }));
|
|
23685
23765
|
var contentModelToDom_1 = __webpack_require__(/*! ./modelToDom/contentModelToDom */ "./packages/roosterjs-content-model-dom/lib/modelToDom/contentModelToDom.ts");
|
|
@@ -23910,6 +23990,7 @@ var setSelection_1 = __webpack_require__(/*! ./modelApi/selection/setSelection *
|
|
|
23910
23990
|
Object.defineProperty(exports, "setSelection", ({ enumerable: true, get: function () { return setSelection_1.setSelection; } }));
|
|
23911
23991
|
var cloneModel_1 = __webpack_require__(/*! ./modelApi/editing/cloneModel */ "./packages/roosterjs-content-model-dom/lib/modelApi/editing/cloneModel.ts");
|
|
23912
23992
|
Object.defineProperty(exports, "cloneModel", ({ enumerable: true, get: function () { return cloneModel_1.cloneModel; } }));
|
|
23993
|
+
Object.defineProperty(exports, "cloneModelForPaste", ({ enumerable: true, get: function () { return cloneModel_1.cloneModelForPaste; } }));
|
|
23913
23994
|
var mergeModel_1 = __webpack_require__(/*! ./modelApi/editing/mergeModel */ "./packages/roosterjs-content-model-dom/lib/modelApi/editing/mergeModel.ts");
|
|
23914
23995
|
Object.defineProperty(exports, "mergeModel", ({ enumerable: true, get: function () { return mergeModel_1.mergeModel; } }));
|
|
23915
23996
|
var deleteSelection_1 = __webpack_require__(/*! ./modelApi/editing/deleteSelection */ "./packages/roosterjs-content-model-dom/lib/modelApi/editing/deleteSelection.ts");
|
|
@@ -24739,7 +24820,34 @@ exports.normalizeAllSegments = normalizeAllSegments;
|
|
|
24739
24820
|
function normalizeSingleSegment(paragraph, segment, ignoreTrailingSpaces) {
|
|
24740
24821
|
if (ignoreTrailingSpaces === void 0) { ignoreTrailingSpaces = false; }
|
|
24741
24822
|
var context = resetNormalizeSegmentContext();
|
|
24823
|
+
var index = paragraph.segments.indexOf(segment);
|
|
24742
24824
|
context.ignoreTrailingSpaces = ignoreTrailingSpaces;
|
|
24825
|
+
// Search backward for the nearest non-empty text segment (skipping SelectionMarkers and empty text),
|
|
24826
|
+
// to determine whether leading spaces of the current segment should be preserved.
|
|
24827
|
+
// If the previous text doesn't end with a space, keep the leading space to maintain word separation.
|
|
24828
|
+
for (var i = index - 1; i >= 0; i--) {
|
|
24829
|
+
var s = paragraph.segments[i];
|
|
24830
|
+
if (s.segmentType == 'Text') {
|
|
24831
|
+
if (s.text.length > 0) {
|
|
24832
|
+
if (s.text.substr(-1) != SPACE) {
|
|
24833
|
+
context.ignoreLeadingSpaces = false;
|
|
24834
|
+
}
|
|
24835
|
+
break;
|
|
24836
|
+
}
|
|
24837
|
+
}
|
|
24838
|
+
else if (s.segmentType == 'Image') {
|
|
24839
|
+
// If the previous segment is an image, we should keep the leading space of the current segment to maintain word separation.
|
|
24840
|
+
context.ignoreLeadingSpaces = false;
|
|
24841
|
+
break;
|
|
24842
|
+
}
|
|
24843
|
+
else if (s.segmentType == 'Br') {
|
|
24844
|
+
// If the previous segment is a line break, we should ignore the leading space of the current segment.
|
|
24845
|
+
context.ignoreLeadingSpaces = true;
|
|
24846
|
+
}
|
|
24847
|
+
else if (s.segmentType != 'SelectionMarker') {
|
|
24848
|
+
break;
|
|
24849
|
+
}
|
|
24850
|
+
}
|
|
24743
24851
|
normalizeSegment(paragraph, segment, context);
|
|
24744
24852
|
}
|
|
24745
24853
|
exports.normalizeSingleSegment = normalizeSingleSegment;
|
|
@@ -24780,6 +24888,10 @@ function normalizeSegment(paragraph, segment, context) {
|
|
|
24780
24888
|
context.ignoreLeadingSpaces = false;
|
|
24781
24889
|
break;
|
|
24782
24890
|
case 'Text':
|
|
24891
|
+
// Skip empty text segments to avoid affecting normalization context
|
|
24892
|
+
if (segment.text.length == 0) {
|
|
24893
|
+
break;
|
|
24894
|
+
}
|
|
24783
24895
|
context.textSegments.push(segment);
|
|
24784
24896
|
context.lastInlineSegment = segment;
|
|
24785
24897
|
context.lastTextSegment = segment;
|
|
@@ -24787,9 +24899,9 @@ function normalizeSegment(paragraph, segment, context) {
|
|
|
24787
24899
|
var last = segment.text.substr(-1);
|
|
24788
24900
|
if (!(0, hasSpacesOnly_1.hasSpacesOnly)(segment.text)) {
|
|
24789
24901
|
if (first == SPACE) {
|
|
24790
|
-
// 1. Multiple leading space => single
|
|
24902
|
+
// 1. Multiple leading space => single space or empty (depends on if previous segment ends with space)
|
|
24791
24903
|
(0, mutate_1.mutateSegment)(paragraph, segment, function (textSegment) {
|
|
24792
|
-
textSegment.text = textSegment.text.replace(LEADING_SPACE_REGEX, context.ignoreLeadingSpaces ? '' :
|
|
24904
|
+
textSegment.text = textSegment.text.replace(LEADING_SPACE_REGEX, context.ignoreLeadingSpaces ? '' : SPACE);
|
|
24793
24905
|
});
|
|
24794
24906
|
}
|
|
24795
24907
|
if (last == SPACE) {
|
|
@@ -25888,8 +26000,20 @@ function getBorderStyleFromColor(color) {
|
|
|
25888
26000
|
"use strict";
|
|
25889
26001
|
|
|
25890
26002
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
25891
|
-
exports.cloneModel = void 0;
|
|
26003
|
+
exports.cloneModel = exports.cloneModelForPaste = void 0;
|
|
25892
26004
|
var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
|
|
26005
|
+
var CloneOption = {
|
|
26006
|
+
includeCachedElement: function (node, type) { return (type == 'cache' ? undefined : node); },
|
|
26007
|
+
};
|
|
26008
|
+
/**
|
|
26009
|
+
* Clone a content model for paste operations, ensuring that cached elements are handled appropriately.
|
|
26010
|
+
* @param model The content model to clone
|
|
26011
|
+
* @returns A cloned content model suitable for paste operations
|
|
26012
|
+
*/
|
|
26013
|
+
function cloneModelForPaste(model) {
|
|
26014
|
+
return cloneModel(model, CloneOption);
|
|
26015
|
+
}
|
|
26016
|
+
exports.cloneModelForPaste = cloneModelForPaste;
|
|
25893
26017
|
/**
|
|
25894
26018
|
* Clone a content model
|
|
25895
26019
|
* @param model The content model to clone
|
|
@@ -28673,6 +28797,7 @@ function internalIterateSelections(path, callback, option, table, treatAllAsSele
|
|
|
28673
28797
|
|
|
28674
28798
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
28675
28799
|
exports.setSelection = void 0;
|
|
28800
|
+
var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
|
|
28676
28801
|
var isGeneralSegment_1 = __webpack_require__(/*! ../typeCheck/isGeneralSegment */ "./packages/roosterjs-content-model-dom/lib/modelApi/typeCheck/isGeneralSegment.ts");
|
|
28677
28802
|
var mutate_1 = __webpack_require__(/*! ../common/mutate */ "./packages/roosterjs-content-model-dom/lib/modelApi/common/mutate.ts");
|
|
28678
28803
|
/**
|
|
@@ -28710,6 +28835,7 @@ function setSelectionToBlockGroup(group, isInSelection, start, end) {
|
|
|
28710
28835
|
});
|
|
28711
28836
|
}
|
|
28712
28837
|
function setSelectionToBlock(block, isInSelection, start, end) {
|
|
28838
|
+
var _a;
|
|
28713
28839
|
switch (block.blockType) {
|
|
28714
28840
|
case 'BlockGroup':
|
|
28715
28841
|
return setSelectionToBlockGroup(block, isInSelection, start, end);
|
|
@@ -28730,16 +28856,31 @@ function setSelectionToBlock(block, isInSelection, start, end) {
|
|
|
28730
28856
|
return isInSelection;
|
|
28731
28857
|
});
|
|
28732
28858
|
case 'Paragraph':
|
|
28733
|
-
var
|
|
28859
|
+
var state_1 = {
|
|
28860
|
+
segmentsToDelete: [],
|
|
28861
|
+
boundaryMarkers: [],
|
|
28862
|
+
hasSelectedNonMarker: false,
|
|
28863
|
+
};
|
|
28734
28864
|
block.segments.forEach(function (segment, i) {
|
|
28735
28865
|
isInSelection = handleSelection(isInSelection, segment, start, end, function (isInSelection) {
|
|
28736
|
-
return setSelectionToSegment(block, segment, isInSelection,
|
|
28866
|
+
return setSelectionToSegment(block, segment, isInSelection, state_1, start, end, i);
|
|
28737
28867
|
});
|
|
28738
28868
|
});
|
|
28739
|
-
if (
|
|
28869
|
+
if (state_1.hasSelectedNonMarker) {
|
|
28870
|
+
// This paragraph contains a real (non-marker) selected segment, so any leading/trailing
|
|
28871
|
+
// selection marker of the range is redundant within this paragraph and can be removed.
|
|
28872
|
+
// We only do this within the same paragraph: a boundary marker at a paragraph edge must be
|
|
28873
|
+
// kept to distinguish "selection starts at the beginning of this line" from "selection
|
|
28874
|
+
// starts at the end of the previous line".
|
|
28875
|
+
(_a = state_1.segmentsToDelete).push.apply(_a, (0, tslib_1.__spreadArray)([], (0, tslib_1.__read)(state_1.boundaryMarkers), false));
|
|
28876
|
+
}
|
|
28877
|
+
if (state_1.segmentsToDelete.length > 0) {
|
|
28740
28878
|
var mutablePara = (0, mutate_1.mutateBlock)(block);
|
|
28741
28879
|
var index = void 0;
|
|
28742
|
-
|
|
28880
|
+
// Sort ascending so the pop()-based splice below always removes the highest index first,
|
|
28881
|
+
// keeping the remaining indices valid (boundary markers may sit before queued deletions).
|
|
28882
|
+
state_1.segmentsToDelete.sort(function (a, b) { return a - b; });
|
|
28883
|
+
while ((index = state_1.segmentsToDelete.pop()) !== undefined) {
|
|
28743
28884
|
if (index >= 0) {
|
|
28744
28885
|
mutablePara.segments.splice(index, 1);
|
|
28745
28886
|
}
|
|
@@ -28788,14 +28929,23 @@ function findCell(table, cell) {
|
|
|
28788
28929
|
: -1;
|
|
28789
28930
|
return { row: row, col: col };
|
|
28790
28931
|
}
|
|
28791
|
-
function setSelectionToSegment(paragraph, segment, isInSelection,
|
|
28932
|
+
function setSelectionToSegment(paragraph, segment, isInSelection, state, start, end, i) {
|
|
28933
|
+
if (segment.segmentType != 'SelectionMarker' && isInSelection) {
|
|
28934
|
+
state.hasSelectedNonMarker = true;
|
|
28935
|
+
}
|
|
28792
28936
|
switch (segment.segmentType) {
|
|
28793
28937
|
case 'SelectionMarker':
|
|
28794
28938
|
if (!isInSelection || (segment != start && segment != end)) {
|
|
28795
28939
|
// Delete the selection marker when
|
|
28796
28940
|
// 1. It is not in selection any more. Or
|
|
28797
28941
|
// 2. It is in middle of selection, so no need to have it
|
|
28798
|
-
segmentsToDelete.push(i);
|
|
28942
|
+
state.segmentsToDelete.push(i);
|
|
28943
|
+
}
|
|
28944
|
+
else {
|
|
28945
|
+
// It is a leading/trailing selection marker of a range selection. Keep it for now, but
|
|
28946
|
+
// remember it so it can be removed later if this same paragraph also contains a real
|
|
28947
|
+
// (non-marker) selected segment, in which case the marker is redundant.
|
|
28948
|
+
state.boundaryMarkers.push(i);
|
|
28799
28949
|
}
|
|
28800
28950
|
return isInSelection;
|
|
28801
28951
|
case 'General':
|
|
@@ -29236,7 +29386,7 @@ var handleBlockGroupChildren = function (doc, parent, group, context) {
|
|
|
29236
29386
|
(_a = context.domIndexer) === null || _a === void 0 ? void 0 : _a.onBlockEntity(childBlock, group);
|
|
29237
29387
|
}
|
|
29238
29388
|
});
|
|
29239
|
-
cleanUpNodeStack(listFormat.nodeStack, context);
|
|
29389
|
+
cleanUpNodeStack(listFormat.nodeStack, context, parent);
|
|
29240
29390
|
// Remove all rest node if any since they don't appear in content model
|
|
29241
29391
|
(0, cleanUpRestNodes_1.cleanUpRestNodes)(refNode, context.rewriteFromModel);
|
|
29242
29392
|
}
|
|
@@ -29245,7 +29395,7 @@ var handleBlockGroupChildren = function (doc, parent, group, context) {
|
|
|
29245
29395
|
}
|
|
29246
29396
|
};
|
|
29247
29397
|
exports.handleBlockGroupChildren = handleBlockGroupChildren;
|
|
29248
|
-
function cleanUpNodeStack(nodeStack, context) {
|
|
29398
|
+
function cleanUpNodeStack(nodeStack, context, leavingParent) {
|
|
29249
29399
|
var _a, _b;
|
|
29250
29400
|
if (nodeStack.length > 0) {
|
|
29251
29401
|
// Clear list stack, only run to nodeStack[1] because nodeStack[0] is the parent node
|
|
@@ -29253,6 +29403,13 @@ function cleanUpNodeStack(nodeStack, context) {
|
|
|
29253
29403
|
var node = (_b = (_a = nodeStack.pop()) === null || _a === void 0 ? void 0 : _a.refNode) !== null && _b !== void 0 ? _b : null;
|
|
29254
29404
|
(0, cleanUpRestNodes_1.cleanUpRestNodes)(node, context.rewriteFromModel);
|
|
29255
29405
|
}
|
|
29406
|
+
if (leavingParent && nodeStack[0].node == leavingParent) {
|
|
29407
|
+
// When leaving a parent node that is the same with the root of node stack
|
|
29408
|
+
// It means the whole list node stack is being invalidated, so we clear it
|
|
29409
|
+
while (nodeStack.length > 0) {
|
|
29410
|
+
nodeStack.pop();
|
|
29411
|
+
}
|
|
29412
|
+
}
|
|
29256
29413
|
}
|
|
29257
29414
|
}
|
|
29258
29415
|
|
|
@@ -30641,11 +30798,17 @@ exports.MarkdownHeadings = {
|
|
|
30641
30798
|
"use strict";
|
|
30642
30799
|
|
|
30643
30800
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
30644
|
-
exports.convertContentModelToMarkdown = exports.convertMarkdownToContentModel = void 0;
|
|
30801
|
+
exports.MarkdownPastePlugin = exports.isPastedContentMarkdown = exports.isContentMarkdown = exports.convertContentModelToMarkdown = exports.convertMarkdownToContentModel = void 0;
|
|
30645
30802
|
var convertMarkdownToContentModel_1 = __webpack_require__(/*! ./markdownToModel/convertMarkdownToContentModel */ "./packages/roosterjs-content-model-markdown/lib/markdownToModel/convertMarkdownToContentModel.ts");
|
|
30646
30803
|
Object.defineProperty(exports, "convertMarkdownToContentModel", ({ enumerable: true, get: function () { return convertMarkdownToContentModel_1.convertMarkdownToContentModel; } }));
|
|
30647
30804
|
var convertContentModelToMarkdown_1 = __webpack_require__(/*! ./modelToMarkdown/convertContentModelToMarkdown */ "./packages/roosterjs-content-model-markdown/lib/modelToMarkdown/convertContentModelToMarkdown.ts");
|
|
30648
30805
|
Object.defineProperty(exports, "convertContentModelToMarkdown", ({ enumerable: true, get: function () { return convertContentModelToMarkdown_1.convertContentModelToMarkdown; } }));
|
|
30806
|
+
var isContentMarkdown_1 = __webpack_require__(/*! ./publicApi/isContentMarkdown */ "./packages/roosterjs-content-model-markdown/lib/publicApi/isContentMarkdown.ts");
|
|
30807
|
+
Object.defineProperty(exports, "isContentMarkdown", ({ enumerable: true, get: function () { return isContentMarkdown_1.isContentMarkdown; } }));
|
|
30808
|
+
var isPastedContentMarkdown_1 = __webpack_require__(/*! ./publicApi/isPastedContentMarkdown */ "./packages/roosterjs-content-model-markdown/lib/publicApi/isPastedContentMarkdown.ts");
|
|
30809
|
+
Object.defineProperty(exports, "isPastedContentMarkdown", ({ enumerable: true, get: function () { return isPastedContentMarkdown_1.isPastedContentMarkdown; } }));
|
|
30810
|
+
var MarkdownPastePlugin_1 = __webpack_require__(/*! ./plugins/MarkdownPastePlugin */ "./packages/roosterjs-content-model-markdown/lib/plugins/MarkdownPastePlugin.ts");
|
|
30811
|
+
Object.defineProperty(exports, "MarkdownPastePlugin", ({ enumerable: true, get: function () { return MarkdownPastePlugin_1.MarkdownPastePlugin; } }));
|
|
30649
30812
|
|
|
30650
30813
|
|
|
30651
30814
|
/***/ },
|
|
@@ -31335,6 +31498,13 @@ function parseInlineSegments(text, segments, state, link) {
|
|
|
31335
31498
|
};
|
|
31336
31499
|
while (i < text.length) {
|
|
31337
31500
|
var remaining = text.substring(i);
|
|
31501
|
+
// Escaped character: a backslash followed by an ASCII punctuation character emits
|
|
31502
|
+
// that character literally (e.g. "\*" -> "*") and is never treated as a marker.
|
|
31503
|
+
if (text[i] === '\\' && i + 1 < text.length && isEscapable(text[i + 1])) {
|
|
31504
|
+
buffer += text[i + 1];
|
|
31505
|
+
i += 2;
|
|
31506
|
+
continue;
|
|
31507
|
+
}
|
|
31338
31508
|
// Image: 
|
|
31339
31509
|
var imgMatch = imagePattern.exec(remaining);
|
|
31340
31510
|
if (imgMatch && isValidUrl(imgMatch[2])) {
|
|
@@ -31398,6 +31568,10 @@ function shouldToggleFormatting(text, index, marker, currentState) {
|
|
|
31398
31568
|
function isWhitespace(char) {
|
|
31399
31569
|
return /\s/.test(char);
|
|
31400
31570
|
}
|
|
31571
|
+
function isEscapable(char) {
|
|
31572
|
+
// Per CommonMark, any ASCII punctuation character may be backslash-escaped.
|
|
31573
|
+
return /[!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~]/.test(char);
|
|
31574
|
+
}
|
|
31401
31575
|
function toggleFormatting(state, type) {
|
|
31402
31576
|
switch (type) {
|
|
31403
31577
|
case 'bold':
|
|
@@ -31901,6 +32075,278 @@ function modelProcessor(model, newLine) {
|
|
|
31901
32075
|
exports.modelProcessor = modelProcessor;
|
|
31902
32076
|
|
|
31903
32077
|
|
|
32078
|
+
/***/ },
|
|
32079
|
+
|
|
32080
|
+
/***/ "./packages/roosterjs-content-model-markdown/lib/plugins/MarkdownPastePlugin.ts"
|
|
32081
|
+
/*!**************************************************************************************!*\
|
|
32082
|
+
!*** ./packages/roosterjs-content-model-markdown/lib/plugins/MarkdownPastePlugin.ts ***!
|
|
32083
|
+
\**************************************************************************************/
|
|
32084
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
32085
|
+
|
|
32086
|
+
"use strict";
|
|
32087
|
+
|
|
32088
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
32089
|
+
exports.MarkdownPastePlugin = void 0;
|
|
32090
|
+
var convertMarkdownToContentModel_1 = __webpack_require__(/*! ../markdownToModel/convertMarkdownToContentModel */ "./packages/roosterjs-content-model-markdown/lib/markdownToModel/convertMarkdownToContentModel.ts");
|
|
32091
|
+
var isPastedContentMarkdown_1 = __webpack_require__(/*! ../publicApi/isPastedContentMarkdown */ "./packages/roosterjs-content-model-markdown/lib/publicApi/isPastedContentMarkdown.ts");
|
|
32092
|
+
var roosterjs_content_model_dom_1 = __webpack_require__(/*! roosterjs-content-model-dom */ "./packages/roosterjs-content-model-dom/lib/index.ts");
|
|
32093
|
+
var DefaultOptions = {
|
|
32094
|
+
autoConversion: false,
|
|
32095
|
+
undoConversion: false,
|
|
32096
|
+
};
|
|
32097
|
+
/**
|
|
32098
|
+
* Markdown paste plugin. Handles the BeforePaste event and, when the pasted content
|
|
32099
|
+
* can be interpreted as markdown, converts the plain text into a Content Model and
|
|
32100
|
+
* pastes it as rich markdown content instead of the original clipboard HTML.
|
|
32101
|
+
*/
|
|
32102
|
+
var MarkdownPastePlugin = /** @class */ (function () {
|
|
32103
|
+
/**
|
|
32104
|
+
* Construct a new instance of MarkdownPastePlugin
|
|
32105
|
+
* @param options Options to control the markdown paste behavior
|
|
32106
|
+
*/
|
|
32107
|
+
function MarkdownPastePlugin(options) {
|
|
32108
|
+
this.editor = null;
|
|
32109
|
+
this.options = options !== null && options !== void 0 ? options : DefaultOptions;
|
|
32110
|
+
}
|
|
32111
|
+
/**
|
|
32112
|
+
* Get name of this plugin
|
|
32113
|
+
*/
|
|
32114
|
+
MarkdownPastePlugin.prototype.getName = function () {
|
|
32115
|
+
return 'MarkdownPaste';
|
|
32116
|
+
};
|
|
32117
|
+
/**
|
|
32118
|
+
* The first method that editor will call to a plugin when editor is initializing.
|
|
32119
|
+
* It will pass in the editor instance, plugin should take this chance to save the
|
|
32120
|
+
* editor reference so that it can call to any editor method or format API later.
|
|
32121
|
+
* @param editor The editor object
|
|
32122
|
+
*/
|
|
32123
|
+
MarkdownPastePlugin.prototype.initialize = function (editor) {
|
|
32124
|
+
this.editor = editor;
|
|
32125
|
+
};
|
|
32126
|
+
/**
|
|
32127
|
+
* The last method that editor will call to a plugin before it is disposed.
|
|
32128
|
+
* Plugin can take this chance to clear the reference to editor. After this method is
|
|
32129
|
+
* called, plugin should not call to any editor method since it will result in error.
|
|
32130
|
+
*/
|
|
32131
|
+
MarkdownPastePlugin.prototype.dispose = function () {
|
|
32132
|
+
this.editor = null;
|
|
32133
|
+
};
|
|
32134
|
+
/**
|
|
32135
|
+
* Core method for a plugin. Once an event happens in editor, editor will call this
|
|
32136
|
+
* method of each plugin to handle the event as long as the event is not handled
|
|
32137
|
+
* exclusively by another plugin.
|
|
32138
|
+
* @param event The event to handle:
|
|
32139
|
+
*/
|
|
32140
|
+
MarkdownPastePlugin.prototype.onPluginEvent = function (event) {
|
|
32141
|
+
if (!this.editor) {
|
|
32142
|
+
return;
|
|
32143
|
+
}
|
|
32144
|
+
if (event.eventType === 'contentChanged' &&
|
|
32145
|
+
event.source === roosterjs_content_model_dom_1.ChangeSource.Paste &&
|
|
32146
|
+
this.options.autoConversion &&
|
|
32147
|
+
event.data) {
|
|
32148
|
+
var clipboardData = event.data;
|
|
32149
|
+
var shouldConvert = clipboardData && clipboardData.pasteNativeEvent && this.options.autoConversion;
|
|
32150
|
+
if (shouldConvert &&
|
|
32151
|
+
(0, isPastedContentMarkdown_1.isPastedContentMarkdown)(this.editor, clipboardData) &&
|
|
32152
|
+
clipboardData.modelBeforePaste) {
|
|
32153
|
+
var modelBeforePaste_1 = (0, roosterjs_content_model_dom_1.cloneModelForPaste)(clipboardData.modelBeforePaste);
|
|
32154
|
+
(0, roosterjs_content_model_dom_1.mergeModel)(modelBeforePaste_1, (0, convertMarkdownToContentModel_1.convertMarkdownToContentModel)(clipboardData.text, { emptyLine: 'merge' }));
|
|
32155
|
+
if (this.options.undoConversion) {
|
|
32156
|
+
this.editor.takeSnapshot();
|
|
32157
|
+
}
|
|
32158
|
+
this.editor.formatContentModel(function (model) {
|
|
32159
|
+
model.blocks = modelBeforePaste_1.blocks;
|
|
32160
|
+
return true;
|
|
32161
|
+
}, {
|
|
32162
|
+
apiName: 'MarkdownConversion',
|
|
32163
|
+
scrollCaretIntoView: true,
|
|
32164
|
+
});
|
|
32165
|
+
}
|
|
32166
|
+
}
|
|
32167
|
+
else if (event.eventType === 'beforePaste' && !event.clipboardData.pasteNativeEvent) {
|
|
32168
|
+
var shouldConvert = event.pasteType === 'asMarkdown';
|
|
32169
|
+
if (shouldConvert && (0, isPastedContentMarkdown_1.isPastedContentMarkdown)(this.editor, event.clipboardData)) {
|
|
32170
|
+
convertPastedTextToMarkdown(this.editor, event.fragment, event.clipboardData.text);
|
|
32171
|
+
}
|
|
32172
|
+
}
|
|
32173
|
+
};
|
|
32174
|
+
return MarkdownPastePlugin;
|
|
32175
|
+
}());
|
|
32176
|
+
exports.MarkdownPastePlugin = MarkdownPastePlugin;
|
|
32177
|
+
function convertPastedTextToMarkdown(editor, fragment, text) {
|
|
32178
|
+
var model = (0, convertMarkdownToContentModel_1.convertMarkdownToContentModel)(text, {
|
|
32179
|
+
emptyLine: 'merge',
|
|
32180
|
+
});
|
|
32181
|
+
while (fragment.firstChild) {
|
|
32182
|
+
fragment.removeChild(fragment.firstChild);
|
|
32183
|
+
}
|
|
32184
|
+
(0, roosterjs_content_model_dom_1.contentModelToDom)(editor.getDocument(), fragment, model, (0, roosterjs_content_model_dom_1.createModelToDomContext)());
|
|
32185
|
+
}
|
|
32186
|
+
|
|
32187
|
+
|
|
32188
|
+
/***/ },
|
|
32189
|
+
|
|
32190
|
+
/***/ "./packages/roosterjs-content-model-markdown/lib/publicApi/isContentMarkdown.ts"
|
|
32191
|
+
/*!**************************************************************************************!*\
|
|
32192
|
+
!*** ./packages/roosterjs-content-model-markdown/lib/publicApi/isContentMarkdown.ts ***!
|
|
32193
|
+
\**************************************************************************************/
|
|
32194
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
32195
|
+
|
|
32196
|
+
"use strict";
|
|
32197
|
+
|
|
32198
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
32199
|
+
exports.isContentMarkdown = void 0;
|
|
32200
|
+
var tslib_1 = __webpack_require__(/*! tslib */ "./node_modules/tslib/tslib.es6.mjs");
|
|
32201
|
+
// Block-level markdown patterns. A line that matches any of these is considered markdown.
|
|
32202
|
+
var BlockPatterns = [
|
|
32203
|
+
/^#{1,6}\s.+/,
|
|
32204
|
+
/^\s*>\s.+/,
|
|
32205
|
+
/^\s*[\*\-\+]\s.+/,
|
|
32206
|
+
/^\s*\d+\.\s.+/,
|
|
32207
|
+
/^---+$/,
|
|
32208
|
+
/^\s*\|.*\|\s*$/, // table row: "| a | b |"
|
|
32209
|
+
];
|
|
32210
|
+
// Inline markdown patterns. The text contains markdown if any of these match anywhere.
|
|
32211
|
+
var InlinePatterns = [
|
|
32212
|
+
/!\[[^\[\]]+\]\([^\)\s]+\)/,
|
|
32213
|
+
/\[[^\[\]]+\]\([^\)\s]+\)/,
|
|
32214
|
+
/\*\*[^\s*][^*]*\*\*/,
|
|
32215
|
+
/(^|[^*])\*[^\s*][^*]*\*([^*]|$)/,
|
|
32216
|
+
/~~[^\s~][^~]*~~/, // strikethrough: ~~text~~
|
|
32217
|
+
];
|
|
32218
|
+
/**
|
|
32219
|
+
* Detect whether the given plain text contains any markdown markup.
|
|
32220
|
+
* Recognizes block-level patterns (headings, blockquotes, lists, horizontal rules, tables)
|
|
32221
|
+
* and inline patterns (bold, italic, strikethrough, links, images).
|
|
32222
|
+
* @param text The plain text to check.
|
|
32223
|
+
* @returns True if the text contains any markdown markup, false otherwise.
|
|
32224
|
+
*/
|
|
32225
|
+
function isContentMarkdown(text) {
|
|
32226
|
+
var e_1, _a, e_2, _b, e_3, _c;
|
|
32227
|
+
if (!text || !text.trim()) {
|
|
32228
|
+
return false;
|
|
32229
|
+
}
|
|
32230
|
+
var lines = text.split(/\r\n|\r|\n/);
|
|
32231
|
+
try {
|
|
32232
|
+
for (var lines_1 = (0, tslib_1.__values)(lines), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
|
|
32233
|
+
var line = lines_1_1.value;
|
|
32234
|
+
try {
|
|
32235
|
+
for (var BlockPatterns_1 = (e_2 = void 0, (0, tslib_1.__values)(BlockPatterns)), BlockPatterns_1_1 = BlockPatterns_1.next(); !BlockPatterns_1_1.done; BlockPatterns_1_1 = BlockPatterns_1.next()) {
|
|
32236
|
+
var pattern = BlockPatterns_1_1.value;
|
|
32237
|
+
if (pattern.test(line)) {
|
|
32238
|
+
return true;
|
|
32239
|
+
}
|
|
32240
|
+
}
|
|
32241
|
+
}
|
|
32242
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
32243
|
+
finally {
|
|
32244
|
+
try {
|
|
32245
|
+
if (BlockPatterns_1_1 && !BlockPatterns_1_1.done && (_b = BlockPatterns_1.return)) _b.call(BlockPatterns_1);
|
|
32246
|
+
}
|
|
32247
|
+
finally { if (e_2) throw e_2.error; }
|
|
32248
|
+
}
|
|
32249
|
+
}
|
|
32250
|
+
}
|
|
32251
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
32252
|
+
finally {
|
|
32253
|
+
try {
|
|
32254
|
+
if (lines_1_1 && !lines_1_1.done && (_a = lines_1.return)) _a.call(lines_1);
|
|
32255
|
+
}
|
|
32256
|
+
finally { if (e_1) throw e_1.error; }
|
|
32257
|
+
}
|
|
32258
|
+
try {
|
|
32259
|
+
for (var InlinePatterns_1 = (0, tslib_1.__values)(InlinePatterns), InlinePatterns_1_1 = InlinePatterns_1.next(); !InlinePatterns_1_1.done; InlinePatterns_1_1 = InlinePatterns_1.next()) {
|
|
32260
|
+
var pattern = InlinePatterns_1_1.value;
|
|
32261
|
+
if (pattern.test(text)) {
|
|
32262
|
+
return true;
|
|
32263
|
+
}
|
|
32264
|
+
}
|
|
32265
|
+
}
|
|
32266
|
+
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
32267
|
+
finally {
|
|
32268
|
+
try {
|
|
32269
|
+
if (InlinePatterns_1_1 && !InlinePatterns_1_1.done && (_c = InlinePatterns_1.return)) _c.call(InlinePatterns_1);
|
|
32270
|
+
}
|
|
32271
|
+
finally { if (e_3) throw e_3.error; }
|
|
32272
|
+
}
|
|
32273
|
+
return false;
|
|
32274
|
+
}
|
|
32275
|
+
exports.isContentMarkdown = isContentMarkdown;
|
|
32276
|
+
|
|
32277
|
+
|
|
32278
|
+
/***/ },
|
|
32279
|
+
|
|
32280
|
+
/***/ "./packages/roosterjs-content-model-markdown/lib/publicApi/isPastedContentMarkdown.ts"
|
|
32281
|
+
/*!********************************************************************************************!*\
|
|
32282
|
+
!*** ./packages/roosterjs-content-model-markdown/lib/publicApi/isPastedContentMarkdown.ts ***!
|
|
32283
|
+
\********************************************************************************************/
|
|
32284
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
32285
|
+
|
|
32286
|
+
"use strict";
|
|
32287
|
+
|
|
32288
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
32289
|
+
exports.isPastedContentMarkdown = void 0;
|
|
32290
|
+
var isContentMarkdown_1 = __webpack_require__(/*! ./isContentMarkdown */ "./packages/roosterjs-content-model-markdown/lib/publicApi/isContentMarkdown.ts");
|
|
32291
|
+
// Tags that are considered "thin wrappers", which only add structure (such as line breaks)
|
|
32292
|
+
// around the plain text without applying any real formatting to its content.
|
|
32293
|
+
var ThinWrapperTags = new Set(['DIV', 'P', 'BR', 'SPAN']);
|
|
32294
|
+
var AllowedAttributes = new Set(['class', 'style']);
|
|
32295
|
+
/**
|
|
32296
|
+
* Detect whether the given clipboard content can be interpreted as markdown.
|
|
32297
|
+
* @param editor The editor instance.
|
|
32298
|
+
* @param clipboardData The clipboard data to check.
|
|
32299
|
+
* @returns True if the content can be interpreted as markdown, false otherwise.
|
|
32300
|
+
*/
|
|
32301
|
+
function isPastedContentMarkdown(editor, clipboardData) {
|
|
32302
|
+
var text = clipboardData.text, rawHtml = clipboardData.rawHtml;
|
|
32303
|
+
if (!text || !text.trim()) {
|
|
32304
|
+
return false;
|
|
32305
|
+
}
|
|
32306
|
+
if ((0, isContentMarkdown_1.isContentMarkdown)(text)) {
|
|
32307
|
+
if (!rawHtml) {
|
|
32308
|
+
return true;
|
|
32309
|
+
}
|
|
32310
|
+
var doc = editor.getDocument();
|
|
32311
|
+
var trustedHTMLHandler = editor.getDOMCreator();
|
|
32312
|
+
var fragment = parseHtmlToFragment(rawHtml, doc, trustedHTMLHandler);
|
|
32313
|
+
return isThinWrapperOfPlainText(fragment, text);
|
|
32314
|
+
}
|
|
32315
|
+
return false;
|
|
32316
|
+
}
|
|
32317
|
+
exports.isPastedContentMarkdown = isPastedContentMarkdown;
|
|
32318
|
+
function isThinWrapperOfPlainText(fragment, text) {
|
|
32319
|
+
var elements = fragment.querySelectorAll('*');
|
|
32320
|
+
for (var i = 0; i < elements.length; i++) {
|
|
32321
|
+
var element = elements[i];
|
|
32322
|
+
if (!ThinWrapperTags.has(element.tagName)) {
|
|
32323
|
+
return false;
|
|
32324
|
+
}
|
|
32325
|
+
for (var j = 0; j < element.attributes.length; j++) {
|
|
32326
|
+
var attr = element.attributes[j];
|
|
32327
|
+
if (!AllowedAttributes.has(attr.name) && !attr.name.startsWith('data-')) {
|
|
32328
|
+
return false;
|
|
32329
|
+
}
|
|
32330
|
+
}
|
|
32331
|
+
}
|
|
32332
|
+
return removeWhitespace(fragment.textContent || '') === removeWhitespace(text);
|
|
32333
|
+
}
|
|
32334
|
+
function removeWhitespace(text) {
|
|
32335
|
+
return text.replace(/\s/g, '');
|
|
32336
|
+
}
|
|
32337
|
+
function parseHtmlToFragment(html, doc, trustedHTMLHandler) {
|
|
32338
|
+
var parsedDoc = trustedHTMLHandler.htmlToDOM(html);
|
|
32339
|
+
var fragment = doc.createDocumentFragment();
|
|
32340
|
+
var body = parsedDoc === null || parsedDoc === void 0 ? void 0 : parsedDoc.body;
|
|
32341
|
+
if (body) {
|
|
32342
|
+
while (body.firstChild) {
|
|
32343
|
+
fragment.appendChild(body.firstChild);
|
|
32344
|
+
}
|
|
32345
|
+
}
|
|
32346
|
+
return fragment;
|
|
32347
|
+
}
|
|
32348
|
+
|
|
32349
|
+
|
|
31904
32350
|
/***/ },
|
|
31905
32351
|
|
|
31906
32352
|
/***/ "./packages/roosterjs-content-model-plugins/lib/announce/AnnouncePlugin.ts"
|
|
@@ -37665,16 +38111,31 @@ function createImageWrapper(editor, image, options, editInfo, htmlOptions, opera
|
|
|
37665
38111
|
croppers = (0, createImageCropper_1.createImageCropper)(doc);
|
|
37666
38112
|
}
|
|
37667
38113
|
var wrapper = createWrapper(editor, imageClone, options, editInfo, resizers, rotators, croppers);
|
|
38114
|
+
// Capture the image footprint before attaching the shadow root, since the light-DOM image
|
|
38115
|
+
// stops being rendered once the shadow root takes over.
|
|
38116
|
+
var imageWidth = image.offsetWidth;
|
|
38117
|
+
var imageHeight = image.offsetHeight;
|
|
37668
38118
|
var imageSpan = (0, roosterjs_content_model_dom_1.wrap)(doc, image, 'span');
|
|
37669
|
-
var shadowSpan = createShadowSpan(wrapper, imageSpan);
|
|
38119
|
+
var shadowSpan = createShadowSpan(wrapper, imageSpan, imageWidth, imageHeight);
|
|
37670
38120
|
return { wrapper: wrapper, shadowSpan: shadowSpan, imageClone: imageClone, resizers: resizers, rotators: rotators, croppers: croppers };
|
|
37671
38121
|
}
|
|
37672
38122
|
exports.createImageWrapper = createImageWrapper;
|
|
37673
|
-
var createShadowSpan = function (wrapper, imageSpan) {
|
|
38123
|
+
var createShadowSpan = function (wrapper, imageSpan, imageWidth, imageHeight) {
|
|
37674
38124
|
var shadowRoot = imageSpan.attachShadow({
|
|
37675
38125
|
mode: 'open',
|
|
37676
38126
|
});
|
|
37677
38127
|
imageSpan.id = IMAGE_EDIT_SHADOW_ROOT;
|
|
38128
|
+
// Pin the shadow host to the original image's box so that wrapping the image does not grow the
|
|
38129
|
+
// surrounding line box. Without this, the taller edit wrapper enlarges the line and the browser
|
|
38130
|
+
// scrolls the selection back into view, making the editor jump. The wrapper and handles still
|
|
38131
|
+
// overflow the host visually because overflow is left visible.
|
|
38132
|
+
if (imageWidth > 0 && imageHeight > 0) {
|
|
38133
|
+
imageSpan.style.display = 'inline-block';
|
|
38134
|
+
imageSpan.style.width = imageWidth + "px";
|
|
38135
|
+
imageSpan.style.height = imageHeight + "px";
|
|
38136
|
+
imageSpan.style.verticalAlign = 'bottom';
|
|
38137
|
+
imageSpan.style.overflow = 'visible';
|
|
38138
|
+
}
|
|
37678
38139
|
shadowRoot.appendChild(wrapper);
|
|
37679
38140
|
return imageSpan;
|
|
37680
38141
|
};
|