Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ const initialState: OptionState = {
},
markdownPasteOptions: {
autoConversion: false,
undoConversion: false,
},
editPluginOptions: {
handleTabKey: {
Expand Down
8 changes: 8 additions & 0 deletions demo/scripts/controlsV2/sidePane/editorOptions/Plugins.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ export class Plugins extends PluginsBase<keyof BuildInPluginList> {
private markdownStrikethrough = React.createRef<HTMLInputElement>();
private markdownCode = React.createRef<HTMLInputElement>();
private markdownPasteAutoConversion = React.createRef<HTMLInputElement>();
private markdownPasteUndoConversion = React.createRef<HTMLInputElement>();
private linkTitle = React.createRef<HTMLInputElement>();
private disableSideResize = React.createRef<HTMLInputElement>();

Expand Down Expand Up @@ -337,6 +338,13 @@ export class Plugins extends PluginsBase<keyof BuildInPluginList> {
(state, value) =>
(state.markdownPasteOptions.autoConversion = value)
)}
{this.renderCheckBox(
'Undo auto-converted markdown',
this.markdownPasteUndoConversion,
this.props.state.markdownPasteOptions.undoConversion,
(state, value) =>
(state.markdownPasteOptions.undoConversion = value)
)}
</>
)}
{this.renderPluginItem(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export class MarkdownPasteCode extends CodeElement {
getCode() {
return `new roosterjs.MarkdownPastePlugin({
autoConversion: ${this.markdownPasteOptions.autoConversion},
undoConversion: ${this.markdownPasteOptions.undoConversion},
})`;
}
}
5 changes: 4 additions & 1 deletion demo/scripts/utils/readClipboardData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ export async function readClipboardData(doc: Document): Promise<ClipboardData |
try {
const clipboardItems = await clipboard.read();
const dataTransferItems = await Promise.all(createDataTransferItems(clipboardItems));
return await extractClipboardItems(dataTransferItems);
return await extractClipboardItems(
dataTransferItems,
undefined /* allowedCustomPasteType */
);
} catch {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,24 @@ import { createDomToModelContextForSanitizing } from '../createModelFromHtml/cre
import {
ChangeSource,
EmptySegmentFormat,
cloneModel,
domToContentModel,
getSegmentTextFormat,
getSelectedSegments,
mergeModel,
cloneModelForPaste,
} from 'roosterjs-content-model-dom';
import type {
BeforePasteEvent,
CloneModelOptions,
ContentModelDocument,
ContentModelSegmentFormat,
IEditor,
MergeModelOption,
PasteType,
ReadonlyContentModelDocument,
ShallowMutableContentModelDocument,
} from 'roosterjs-content-model-types';

const BlackColor = 'rgb(0,0,0)';

const CloneOption: CloneModelOptions = {
includeCachedElement: (node, type) => (type == 'cache' ? undefined : node),
};

/**
* @internal
*/
export function cloneModelForPaste(model: ReadonlyContentModelDocument) {
return cloneModel(model, CloneOption);
}

/**
* @internal
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { cleanHtmlComments } from './cleanHtmlComments';
import { cloneModelForPaste, mergePasteContent } from './mergePasteContent';
import { cloneModelForPaste } from 'roosterjs-content-model-dom';
import { convertInlineCss } from '../createModelFromHtml/convertInlineCss';
import { createPasteFragment } from './createPasteFragment';
import { generatePasteOptionFromPlugins } from './generatePasteOptionFromPlugins';
import { mergePasteContent } from './mergePasteContent';
import { retrieveHtmlInfo } from './retrieveHtmlInfo';
import type {
PasteTypeOrGetter,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ class CopyPastePlugin implements PluginWithState<CopyPastePluginState> {
event.preventDefault();
extractClipboardItems(
toArray(dataTransfer!.items),
this.state.allowedCustomPasteType
this.state.allowedCustomPasteType,
true /* isPasteNative */
).then((clipboardData: ClipboardData) => {
if (!editor.isDisposed()) {
paste(editor, clipboardData, this.state.defaultPasteType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1890,7 +1890,7 @@ describe('mergePasteContent', () => {
document.body
);
const div = document.createElement('div');
const cloneModelSpy = spyOn(cloneModel, 'cloneModel').and.callThrough();
const cloneModelSpy = spyOn(cloneModel, 'cloneModelForPaste').and.callThrough();

sourceModel = {
blockGroupType: 'Document',
Expand Down Expand Up @@ -1973,7 +1973,7 @@ describe('mergePasteContent', () => {
document.body
);
const div = document.createElement('div');
const cloneModelSpy = spyOn(cloneModel, 'cloneModel').and.callThrough();
const cloneModelSpy = spyOn(cloneModel, 'cloneModelForPaste').and.callThrough();

sourceModel = {
blockGroupType: 'Document',
Expand Down Expand Up @@ -2042,8 +2042,5 @@ describe('mergePasteContent', () => {
format: {},
});
expect(cloneModelSpy).toHaveBeenCalledTimes(1);
expect(cloneModelSpy).toHaveBeenCalledWith(modelBeforePaste, {
includeCachedElement: jasmine.anything(),
} as any);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -995,7 +995,8 @@ describe('CopyPastePlugin |', () => {
expect(pasteSpy).toHaveBeenCalledWith(editor, clipboardData, undefined);
expect(extractClipboardItemsFile.extractClipboardItems).toHaveBeenCalledWith(
Array.from(clipboardEvent.clipboardData!.items),
allowedCustomPasteType
allowedCustomPasteType,
true
);
expect(preventDefaultSpy).toHaveBeenCalledTimes(1);
});
Expand Down Expand Up @@ -1025,7 +1026,8 @@ describe('CopyPastePlugin |', () => {
expect(pasteSpy).toHaveBeenCalledWith(editor, clipboardData, undefined);
expect(extractClipboardItemsFile.extractClipboardItems).toHaveBeenCalledWith(
Array.from(clipboardEvent.clipboardData!.items),
allowedCustomPasteType
allowedCustomPasteType,
true
);
expect(preventDefaultSpy).toHaveBeenCalledTimes(1);
});
Expand Down Expand Up @@ -1056,7 +1058,8 @@ describe('CopyPastePlugin |', () => {
expect(pasteSpy).toHaveBeenCalledWith(editor, clipboardData, 'mergeFormat');
expect(extractClipboardItemsFile.extractClipboardItems).toHaveBeenCalledWith(
Array.from(clipboardEvent.clipboardData!.items),
allowedCustomPasteType
allowedCustomPasteType,
true
);
expect(preventDefaultSpy).toHaveBeenCalledTimes(1);
});
Expand Down Expand Up @@ -1087,7 +1090,8 @@ describe('CopyPastePlugin |', () => {
expect(pasteSpy).toHaveBeenCalledWith(editor, clipboardData, 'asImage');
expect(extractClipboardItemsFile.extractClipboardItems).toHaveBeenCalledWith(
Array.from(clipboardEvent.clipboardData!.items),
allowedCustomPasteType
allowedCustomPasteType,
true
);
expect(preventDefaultSpy).toHaveBeenCalledTimes(1);
});
Expand Down Expand Up @@ -1118,7 +1122,8 @@ describe('CopyPastePlugin |', () => {
expect(pasteSpy).toHaveBeenCalledWith(editor, clipboardData, 'asPlainText');
expect(extractClipboardItemsFile.extractClipboardItems).toHaveBeenCalledWith(
Array.from(clipboardEvent.clipboardData!.items),
allowedCustomPasteType
allowedCustomPasteType,
true
);
expect(preventDefaultSpy).toHaveBeenCalledTimes(1);
});
Expand Down Expand Up @@ -1149,7 +1154,8 @@ describe('CopyPastePlugin |', () => {
expect(pasteSpy).toHaveBeenCalledWith(editor, clipboardData, 'normal');
expect(extractClipboardItemsFile.extractClipboardItems).toHaveBeenCalledWith(
Array.from(clipboardEvent.clipboardData!.items),
allowedCustomPasteType
allowedCustomPasteType,
true
);
expect(preventDefaultSpy).toHaveBeenCalledTimes(1);
});
Expand Down Expand Up @@ -1179,7 +1185,8 @@ describe('CopyPastePlugin |', () => {
expect(pasteSpy).not.toHaveBeenCalled();
expect(extractClipboardItemsFile.extractClipboardItems).toHaveBeenCalledWith(
Array.from(clipboardEvent.clipboardData!.items),
allowedCustomPasteType
allowedCustomPasteType,
true
);
expect(preventDefaultSpy).toHaveBeenCalledTimes(1);
});
Expand Down Expand Up @@ -1210,7 +1217,8 @@ describe('CopyPastePlugin |', () => {
expect(pasteSpy).toHaveBeenCalledWith(editor, clipboardData, cb);
expect(extractClipboardItemsFile.extractClipboardItems).toHaveBeenCalledWith(
Array.from(clipboardEvent.clipboardData!.items),
allowedCustomPasteType
allowedCustomPasteType,
true
);
expect(preventDefaultSpy).toHaveBeenCalledTimes(1);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ const ContentHandlers: {
*/
export function extractClipboardItems(
items: DataTransferItem[],
allowedCustomPasteType?: string[]
allowedCustomPasteType?: string[],
isPasteNative?: boolean
): Promise<ClipboardData> {
const data: ClipboardData = {
types: [],
Expand All @@ -28,7 +29,7 @@ export function extractClipboardItems(
files: [],
rawHtml: null,
customValues: {},
pasteNativeEvent: true,
pasteNativeEvent: !!isPasteNative,
};

return Promise.all(
Expand Down
2 changes: 1 addition & 1 deletion packages/roosterjs-content-model-dom/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ export { hasSelectionInSegment } from './modelApi/selection/hasSelectionInSegmen
export { hasSelectionInBlockGroup } from './modelApi/selection/hasSelectionInBlockGroup';
export { setSelection } from './modelApi/selection/setSelection';

export { cloneModel } from './modelApi/editing/cloneModel';
export { cloneModel, cloneModelForPaste } from './modelApi/editing/cloneModel';
export { mergeModel } from './modelApi/editing/mergeModel';
export { deleteSelection } from './modelApi/editing/deleteSelection';
export { deleteSegment } from './modelApi/editing/deleteSegment';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@ import type {
ReadonlyContentModelText,
} from 'roosterjs-content-model-types';

const CloneOption: CloneModelOptions = {
includeCachedElement: (node, type) => (type == 'cache' ? undefined : node),
};

/**
* Clone a content model for paste operations, ensuring that cached elements are handled appropriately.
* @param model The content model to clone
* @returns A cloned content model suitable for paste operations
*/
export function cloneModelForPaste(model: ReadonlyContentModelDocument) {
return cloneModel(model, CloneOption);
}

/**
* Clone a content model
* @param model The content model to clone
Expand Down
Loading
Loading