Skip to content

Commit

Permalink
Refactor paste options handling to use editor environment settings an…
Browse files Browse the repository at this point in the history
…d simplify function signatures
  • Loading branch information
BryanValverdeU committed Dec 10, 2024
1 parent 5d0c2ad commit 20fa3e5
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,6 @@ import type {
IEditor,
} from 'roosterjs-content-model-types';

const emptyDomToModelOption: Readonly<DomToModelOptionForSanitizing> = {
additionalAllowedTags: [],
additionalDisallowedTags: [],
additionalFormatParsers: {},
formatParserOverride: {},
processorOverride: {},
styleSanitizers: {},
attributeSanitizers: {},
};

/**
* @internal
*/
Expand All @@ -25,8 +15,7 @@ export function generatePasteOptionFromPlugins(
clipboardData: ClipboardData,
fragment: DocumentFragment,
htmlFromClipboard: HtmlFromClipboard,
pasteType: PasteType,
domToModelOption: Readonly<Partial<DomToModelOptionForSanitizing>>
pasteType: PasteType
): BeforePasteEvent {
const event: BeforePasteEvent = {
eventType: 'beforePaste',
Expand All @@ -36,11 +25,24 @@ export function generatePasteOptionFromPlugins(
htmlAfter: htmlFromClipboard.htmlAfter ?? '',
htmlAttributes: htmlFromClipboard.metadata,
pasteType: pasteType,
domToModelOption: Object.assign({}, emptyDomToModelOption, domToModelOption),
domToModelOption: createDomToModelOption(editor),
containsBlockElements: !!htmlFromClipboard.containsBlockElements,
};

return pasteType == 'asPlainText'
? event
: editor.triggerEvent('beforePaste', event, true /* broadcast */);
}
function createDomToModelOption(editor: IEditor): DomToModelOptionForSanitizing {
const pasteDomToModel = editor.getEnvironment().domToModelSettings.paste;
const emptyDomToModelOption: Readonly<DomToModelOptionForSanitizing> = {
additionalAllowedTags: [],
additionalDisallowedTags: [],
additionalFormatParsers: {},
formatParserOverride: {},
processorOverride: {},
styleSanitizers: {},
attributeSanitizers: {},
};
return Object.assign({}, emptyDomToModelOption, pasteDomToModel);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import type {
ClipboardData,
TrustedHTMLHandler,
IEditor,
DomToModelOptionForSanitizing,
} from 'roosterjs-content-model-types';

/**
Expand All @@ -20,8 +19,7 @@ import type {
export function paste(
editor: IEditor,
clipboardData: ClipboardData,
pasteTypeOrGetter: PasteTypeOrGetter = 'normal',
pasteDomToModelOption: Readonly<Partial<DomToModelOptionForSanitizing>> = {}
pasteTypeOrGetter: PasteTypeOrGetter = 'normal'
) {
editor.focus();

Expand Down Expand Up @@ -62,8 +60,7 @@ export function paste(
clipboardData,
sourceFragment,
htmlFromClipboard,
pasteType,
pasteDomToModelOption
pasteType
);

// 5. Convert global CSS to inline CSS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ class CopyPastePlugin implements PluginWithState<CopyPastePluginState> {
allowedCustomPasteType: option.allowedCustomPasteType || [],
tempDiv: null,
defaultPasteType: option.defaultPasteType,
pasteOptionDomToModel: option.pasteOptionDomToModel,
};
}

Expand Down Expand Up @@ -206,12 +205,7 @@ class CopyPastePlugin implements PluginWithState<CopyPastePluginState> {
this.state.allowedCustomPasteType
).then((clipboardData: ClipboardData) => {
if (!editor.isDisposed()) {
paste(
editor,
clipboardData,
this.state.defaultPasteType,
this.state.pasteOptionDomToModel
);
paste(editor, clipboardData, this.state.defaultPasteType);
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,27 @@ import {
listLevelMetadataApplier,
} from '../../override/listMetadataApplier';
import type {
ContentModelSettings,
DomToModelOption,
DomToModelSettings,
ModelToDomOption,
ModelToDomSettings,
EditorOptions,
ModelToDomSetting,
DomToModelSetting,
} from 'roosterjs-content-model-types';

/**
* @internal
* Create default DOM to Content Model conversion settings for an editor
* @param options The editor options
*/
export function createDomToModelSettings(
options: EditorOptions
): ContentModelSettings<DomToModelOption, DomToModelSettings> {
export function createDomToModelSettings(options: EditorOptions): DomToModelSetting {
const builtIn: DomToModelOption = {};
const customized: DomToModelOption = options.defaultDomToModelOptions ?? {};

return {
builtIn,
customized,
calculated: createDomToModelConfig([builtIn, customized]),
paste: options.pasteOptionDomToModel ?? {},
};
}

Expand All @@ -35,9 +33,7 @@ export function createDomToModelSettings(
* Create default Content Model to DOM conversion settings for an editor
* @param options The editor options
*/
export function createModelToDomSettings(
options: EditorOptions
): ContentModelSettings<ModelToDomOption, ModelToDomSettings> {
export function createModelToDomSettings(options: EditorOptions): ModelToDomSetting {
const builtIn: ModelToDomOption = {
metadataAppliers: {
listItem: listItemMetadataApplier,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { IEditor } from 'roosterjs-content-model-types';
describe('generatePasteOptionFromPlugins', () => {
let editor: IEditor;
let triggerPluginEventSpy: jasmine.Spy;
let getEnvironmentSpy: jasmine.Spy;

const mockedClipboardData = 'CLIPBOARDDATA' as any;
const mockedFragment = 'FRAGMENT' as any;
Expand All @@ -19,8 +20,14 @@ describe('generatePasteOptionFromPlugins', () => {

beforeEach(() => {
triggerPluginEventSpy = jasmine.createSpy('triggerEvent');
getEnvironmentSpy = jasmine.createSpy('getEnvironment').and.returnValue({
domToModelSettings: {
paste: {},
},
});
editor = {
triggerEvent: triggerPluginEventSpy,
getEnvironment: getEnvironmentSpy,
} as any;
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,24 @@ describe('createDomToModelSettings', () => {
builtIn: {},
customized: {},
calculated: mockedCalculatedConfig,
paste: {},
});
expect(createDomToModelContext.createDomToModelConfig).toHaveBeenCalledWith([{}, {}]);
});

it('Has options', () => {
const defaultDomToModelOptions = 'MockedOptions' as any;
const pasteOptionDomToModel = 'PasteMockedOptions' as any;
const settings = createDomToModelSettings({
defaultDomToModelOptions: defaultDomToModelOptions,
pasteOptionDomToModel,
});

expect(settings).toEqual({
builtIn: {},
customized: defaultDomToModelOptions,
calculated: mockedCalculatedConfig,
paste: pasteOptionDomToModel,
});
expect(createDomToModelContext.createDomToModelConfig).toHaveBeenCalledWith([
{},
Expand Down
7 changes: 6 additions & 1 deletion packages/roosterjs-content-model-types/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,12 @@ export {
export { ContextMenuPluginState } from './pluginState/ContextMenuPluginState';

export { AutoLinkOptions } from './parameter/AutoLinkOptions';
export { EditorEnvironment, ContentModelSettings } from './parameter/EditorEnvironment';
export {
EditorEnvironment,
ContentModelSettings,
DomToModelSetting,
ModelToDomSetting,
} from './parameter/EditorEnvironment';
export {
EntityState,
DeletedEntity,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,26 @@ export interface ContentModelSettings<OptionType, ConfigType> {
* This is a cached object so that we don't need to cache it every time when we use Content Model
*/
calculated: ConfigType;

/**
* Paste option used by editor
*/
paste: OptionType;
}

/**
* Settings used by DOM to Content Model conversion
*/
export type DomToModelSetting = ContentModelSettings<DomToModelOption, DomToModelSettings>;

/**
* Settings used by Content Model to DOM conversion
*/
export type ModelToDomSetting = Omit<
ContentModelSettings<ModelToDomOption, ModelToDomSettings>,
'paste'
>;

/**
* Current running environment
*/
Expand Down Expand Up @@ -52,10 +70,10 @@ export interface EditorEnvironment {
/**
* Settings used by DOM to Content Model conversion
*/
readonly domToModelSettings: ContentModelSettings<DomToModelOption, DomToModelSettings>;
readonly domToModelSettings: DomToModelSetting;

/**
* Settings used by Content Model to DOM conversion
*/
readonly modelToDomSettings: ContentModelSettings<ModelToDomOption, ModelToDomSettings>;
readonly modelToDomSettings: ModelToDomSetting;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { DomToModelOptionForSanitizing } from '../context/DomToModelOption';
import type { PasteTypeOrGetter } from '../parameter/PasteTypeOrGetter';

/**
Expand All @@ -20,9 +19,4 @@ export interface CopyPastePluginState {
* Default paste type. By default will use the normal (as-is) paste type.
*/
defaultPasteType?: PasteTypeOrGetter;

/**
* Paste options for sanitizing HTML before paste
*/
pasteOptionDomToModel?: Partial<DomToModelOptionForSanitizing>;
}

0 comments on commit 20fa3e5

Please sign in to comment.