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