Skip to content

Commit

Permalink
Add PasteTypeOrGetter so we can update the default paste type based o…
Browse files Browse the repository at this point in the history
…n the content and clipboard items of the Paste Event #2753
  • Loading branch information
BryanValverdeU authored Jul 26, 2024
1 parent 2db36de commit 84ac428
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 8 deletions.
10 changes: 7 additions & 3 deletions packages/roosterjs-content-model-core/lib/command/paste/paste.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { createPasteFragment } from './createPasteFragment';
import { generatePasteOptionFromPlugins } from './generatePasteOptionFromPlugins';
import { retrieveHtmlInfo } from './retrieveHtmlInfo';
import type {
PasteType,
PasteTypeOrGetter,
ClipboardData,
TrustedHTMLHandler,
IEditor,
Expand All @@ -14,12 +14,12 @@ import type {
* Paste into editor using a clipboardData object
* @param editor The Editor object.
* @param clipboardData Clipboard data retrieved from clipboard
* @param pasteType Type of content to paste. @default normal
* @param pasteTypeOrGetter Type of content to paste or function that returns the Paste Type to use based on the document and the clipboard Data. @default normal
*/
export function paste(
editor: IEditor,
clipboardData: ClipboardData,
pasteType: PasteType = 'normal'
pasteTypeOrGetter: PasteTypeOrGetter = 'normal'
) {
editor.focus();

Expand All @@ -35,6 +35,10 @@ export function paste(

// 1. Prepare variables
const doc = createDOMFromHtml(clipboardData.rawHtml, trustedHTMLHandler);
const pasteType =
typeof pasteTypeOrGetter == 'function'
? pasteTypeOrGetter(doc, clipboardData)
: pasteTypeOrGetter;

// 2. Handle HTML from clipboard
const htmlFromClipboard = retrieveHtmlInfo(doc, clipboardData);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import * as addParserF from 'roosterjs-content-model-plugins/lib/paste/utils/addParser';
import * as createPasteFragmentFile from '../../../lib/command/paste/createPasteFragment';
import * as domToContentModel from 'roosterjs-content-model-dom/lib/domToModel/domToContentModel';
import * as ExcelF from 'roosterjs-content-model-plugins/lib/paste/Excel/processPastedContentFromExcel';
import * as generatePasteOptionFromPluginsFile from '../../../lib/command/paste/generatePasteOptionFromPlugins';
import * as getPasteSourceF from 'roosterjs-content-model-plugins/lib/paste/pasteSourceValidations/getPasteSource';
import * as getSelectedSegmentsF from 'roosterjs-content-model-dom/lib/modelApi/selection/collectSelections';
import * as mergeModelFile from 'roosterjs-content-model-dom/lib/modelApi/editing/mergeModel';
Expand All @@ -18,6 +20,7 @@ import {
IEditor,
BeforePasteEvent,
PluginEvent,
PasteTypeOrGetter,
} from 'roosterjs-content-model-types';

let clipboardData: ClipboardData;
Expand Down Expand Up @@ -98,6 +101,34 @@ describe('Paste ', () => {

expect(mockedModel).toEqual(mockedMergeModel);
});

it('Execute | With callback to return paste type', () => {
spyOn(createPasteFragmentFile, 'createPasteFragment').and.callThrough();
spyOn(
generatePasteOptionFromPluginsFile,
'generatePasteOptionFromPlugins'
).and.callThrough();

const cb: PasteTypeOrGetter = () => 'normal';
paste(editor, clipboardData, cb);

expect(mockedModel).toEqual(mockedMergeModel);
expect(createPasteFragmentFile.createPasteFragment).toHaveBeenCalledWith(
jasmine.anything(),
jasmine.anything(),
'normal',
jasmine.anything()
);
expect(
generatePasteOptionFromPluginsFile.generatePasteOptionFromPlugins
).toHaveBeenCalledWith(
jasmine.anything(),
jasmine.anything(),
jasmine.anything(),
jasmine.anything(),
'normal'
);
});
});

describe('paste with content model & paste plugin', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
CopyPastePluginState,
PluginWithState,
DarkColorHandler,
PasteTypeOrGetter,
} from 'roosterjs-content-model-types';
import {
adjustSelectionForCopyCut,
Expand Down Expand Up @@ -752,6 +753,37 @@ describe('CopyPastePlugin |', () => {
);
expect(preventDefaultSpy).toHaveBeenCalledTimes(1);
});

it('Handle with defaultPasteType as callback', () => {
const preventDefaultSpy = jasmine.createSpy('preventDefaultPaste');
const cb: PasteTypeOrGetter = () => 'normal';
plugin.getState().defaultPasteType = cb;
let clipboardEvent = <ClipboardEvent>{
clipboardData: <DataTransfer>(<any>{
items: [<DataTransferItem>{}],
}),
preventDefault() {
preventDefaultSpy();
},
};
spyOn(extractClipboardItemsFile, 'extractClipboardItems').and.returnValue(<
Promise<ClipboardData>
>{
then: (cb: (value: ClipboardData) => void | PromiseLike<void>) => {
cb(clipboardData);
},
});
isDisposed.and.returnValue(false);

domEvents.paste.beforeDispatch?.(clipboardEvent);

expect(pasteSpy).toHaveBeenCalledWith(editor, clipboardData, cb);
expect(extractClipboardItemsFile.extractClipboardItems).toHaveBeenCalledWith(
Array.from(clipboardEvent.clipboardData!.items),
allowedCustomPasteType
);
expect(preventDefaultSpy).toHaveBeenCalledTimes(1);
});
});

it('onNodeCreated with table', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { PasteTypeOrGetter } from '../parameter/PasteTypeOrGetter';
import type { ExperimentalFeature } from './ExperimentalFeature';
import type { KnownAnnounceStrings } from '../parameter/AnnounceData';
import type { PasteType } from '../enum/PasteType';
import type { Colors, ColorTransformFunction } from '../context/DarkColorHandler';
import type { EditorPlugin } from './EditorPlugin';
import type { ContentModelSegmentFormat } from '../contentModel/format/ContentModelSegmentFormat';
Expand Down Expand Up @@ -100,9 +100,9 @@ export interface PasteOptions {
allowedCustomPasteType?: string[];

/**
* Default paste type. By default will use the normal (as-is) paste type.
* Default paste type or function that returns the paste type. By default will use the normal (as-is) paste type.
*/
defaultPasteType?: PasteType;
defaultPasteType?: PasteTypeOrGetter;
}

/**
Expand Down
1 change: 1 addition & 0 deletions packages/roosterjs-content-model-types/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ export {
ContentModelFormatter,
} from './parameter/FormatContentModelOptions';
export { ContentModelFormatState } from './parameter/ContentModelFormatState';
export { PasteTypeOrGetter } from './parameter/PasteTypeOrGetter';
export { ImageFormatState } from './parameter/ImageFormatState';
export { Border } from './parameter/Border';
export { InsertEntityOptions } from './parameter/InsertEntityOptions';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { ClipboardData } from './ClipboardData';
import type { PasteType } from '../enum/PasteType';

/**
* Represents the PasteType parameter used to set the paste type to use.
* It can be either the Paste Type value or a callback that retuns the Paste Type to use.
*/
export type PasteTypeOrGetter =
| PasteType
| ((document: Document | null, clipboardData: ClipboardData) => PasteType);
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { PasteType } from '../enum/PasteType';
import type { PasteTypeOrGetter } from '../parameter/PasteTypeOrGetter';

/**
* The state object for CopyPastePlugin
Expand All @@ -18,5 +18,5 @@ export interface CopyPastePluginState {
/**
* Default paste type. By default will use the normal (as-is) paste type.
*/
defaultPasteType?: PasteType;
defaultPasteType?: PasteTypeOrGetter;
}

0 comments on commit 84ac428

Please sign in to comment.