Skip to content

Commit

Permalink
Remove display: flex style on paste (#2031)
Browse files Browse the repository at this point in the history
* init

* Fix
  • Loading branch information
BryanValverdeU authored Aug 16, 2023
1 parent 560db30 commit 8c7fa2b
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import addParser from './utils/addParser';
import ContentModelBeforePasteEvent from '../../../publicTypes/event/ContentModelBeforePasteEvent';
import { getPasteSource } from 'roosterjs-editor-dom';
import { chainSanitizerCallback, getPasteSource } from 'roosterjs-editor-dom';
import { IContentModelEditor } from '../../../publicTypes/IContentModelEditor';
import { parseDeprecatedColor } from './utils/deprecatedColorParser';
import { parseLink } from './utils/linkParser';
Expand All @@ -10,6 +10,7 @@ import { processPastedContentFromWordDesktop } from './WordDesktop/processPasted
import { processPastedContentWacComponents } from './WacComponents/processPastedContentWacComponents';
import {
EditorPlugin,
HtmlSanitizerOptions,
IEditor,
KnownPasteSourceType,
PasteType,
Expand Down Expand Up @@ -106,7 +107,14 @@ export default class ContentModelPastePlugin implements EditorPlugin {

addParser(ev.domToModelOption, 'link', parseLink);
parseDeprecatedColor(ev.sanitizingOption);
sanitizeBlockStyles(ev.sanitizingOption);

event.sanitizingOption.unknownTagReplacement = this.unknownTagReplacement;
}
}

function sanitizeBlockStyles(sanitizingOption: Required<HtmlSanitizerOptions>) {
chainSanitizerCallback(sanitizingOption.cssStyleCallbacks, 'display', (value: string) => {
return value != 'flex'; // return whether we keep the style
});
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,29 @@
import * as addParser from '../../../lib/editor/plugins/PastePlugin/utils/addParser';
import * as chainSanitizerCallbackFile from 'roosterjs-editor-dom/lib/htmlSanitizer/chainSanitizerCallback';
import * as ExcelFile from '../../../lib/editor/plugins/PastePlugin/Excel/processPastedContentFromExcel';
import * as getPasteSource from 'roosterjs-editor-dom/lib/pasteSourceValidations/getPasteSource';
import * as PowerPointFile from '../../../lib/editor/plugins/PastePlugin/PowerPoint/processPastedContentFromPowerPoint';
import * as setProcessor from '../../../lib/editor/plugins/PastePlugin/utils/setProcessor';
import * as WacFile from '../../../lib/editor/plugins/PastePlugin/WacComponents/processPastedContentWacComponents';
import * as WordDesktopFile from '../../../lib/editor/plugins/PastePlugin/WordDesktop/processPastedContentFromWordDesktop';
import ContentModelBeforePasteEvent from '../../../lib/publicTypes/event/ContentModelBeforePasteEvent';
import ContentModelPastePlugin from '../../../lib/editor/plugins/PastePlugin/ContentModelPastePlugin';
import { IContentModelEditor } from '../../../lib/publicTypes/IContentModelEditor';
import { KnownPasteSourceType, PluginEventType } from 'roosterjs-editor-types';
import { KnownPasteSourceType, PasteType, PluginEventType } from 'roosterjs-editor-types';

const trustedHTMLHandler = <any>'mock';
const GOOGLE_SHEET_NODE_NAME = 'google-sheets-html-origin';

describe('Paste', () => {
let editor: IContentModelEditor;

beforeEach(() => {
editor = ({} as any) as IContentModelEditor;
editor = ({
getTrustedHTMLHandler: () => trustedHTMLHandler,
} as any) as IContentModelEditor;
spyOn(addParser, 'default').and.callThrough();
spyOn(chainSanitizerCallbackFile, 'default').and.callThrough();
spyOn(setProcessor, 'setProcessor').and.callThrough();
});

let event: ContentModelBeforePasteEvent = <ContentModelBeforePasteEvent>(<any>{
Expand Down Expand Up @@ -57,6 +70,11 @@ describe('Paste', () => {
preserveHtmlComments: false,
unknownTagReplacement: null,
},
pasteType: PasteType.Normal,
clipboardData: <any>{
html: '',
},
fragment: document.createDocumentFragment(),
});
});

Expand All @@ -71,18 +89,131 @@ describe('Paste', () => {
expect(event.domToModelOption.processorOverride?.element).toBe(
WordDesktopFile.wordDesktopElementProcessor
);
expect(addParser.default).toHaveBeenCalledTimes(4);
expect(chainSanitizerCallbackFile.default).toHaveBeenCalledTimes(5);
expect(setProcessor.setProcessor).toHaveBeenCalledTimes(1);
});

it('Excel | merge format', () => {
spyOn(getPasteSource, 'default').and.returnValue(KnownPasteSourceType.ExcelDesktop);
spyOn(ExcelFile, 'processPastedContentFromExcel').and.callThrough();

(<any>event).pasteType = PasteType.MergeFormat;
plugin.initialize(editor);
plugin.onPluginEvent(event);

expect(ExcelFile.processPastedContentFromExcel).toHaveBeenCalledWith(
event,
trustedHTMLHandler
);
expect(addParser.default).toHaveBeenCalledTimes(2);
expect(setProcessor.setProcessor).toHaveBeenCalledTimes(0);
expect(chainSanitizerCallbackFile.default).toHaveBeenCalledTimes(3);
});

it('Excel | image', () => {
spyOn(getPasteSource, 'default').and.returnValue(KnownPasteSourceType.ExcelDesktop);
spyOn(ExcelFile, 'processPastedContentFromExcel').and.callThrough();

(<any>event).pasteType = PasteType.AsImage;
plugin.initialize(editor);
plugin.onPluginEvent(event);

expect(ExcelFile.processPastedContentFromExcel).not.toHaveBeenCalledWith(
event,
trustedHTMLHandler
);
expect(addParser.default).toHaveBeenCalledTimes(1);
expect(chainSanitizerCallbackFile.default).toHaveBeenCalledTimes(3);
expect(setProcessor.setProcessor).toHaveBeenCalledTimes(0);
});

it('Excel', () => {
spyOn(getPasteSource, 'default').and.returnValue(KnownPasteSourceType.ExcelDesktop);
spyOn(ExcelFile, 'processPastedContentFromExcel').and.callThrough();

plugin.initialize(editor);
plugin.onPluginEvent(event);

expect(ExcelFile.processPastedContentFromExcel).toHaveBeenCalledWith(
event,
trustedHTMLHandler
);
expect(addParser.default).toHaveBeenCalledTimes(2);
expect(setProcessor.setProcessor).toHaveBeenCalledTimes(0);
expect(chainSanitizerCallbackFile.default).toHaveBeenCalledTimes(3);
});

it('Excel Online', () => {
spyOn(getPasteSource, 'default').and.returnValue(KnownPasteSourceType.ExcelOnline);
spyOn(ExcelFile, 'processPastedContentFromExcel').and.callThrough();

plugin.initialize(editor);
plugin.onPluginEvent(event);

expect(ExcelFile.processPastedContentFromExcel).toHaveBeenCalledWith(
event,
trustedHTMLHandler
);
expect(addParser.default).toHaveBeenCalledTimes(2);
expect(setProcessor.setProcessor).toHaveBeenCalledTimes(0);
expect(chainSanitizerCallbackFile.default).toHaveBeenCalledTimes(3);
});

it('Power Point', () => {
spyOn(getPasteSource, 'default').and.returnValue(
KnownPasteSourceType.PowerPointDesktop
);
spyOn(PowerPointFile, 'processPastedContentFromPowerPoint').and.callThrough();

plugin.initialize(editor);
plugin.onPluginEvent(event);

expect(PowerPointFile.processPastedContentFromPowerPoint).toHaveBeenCalledWith(
event,
trustedHTMLHandler
);
expect(addParser.default).toHaveBeenCalledTimes(1);
expect(setProcessor.setProcessor).toHaveBeenCalledTimes(0);
expect(chainSanitizerCallbackFile.default).toHaveBeenCalledTimes(3);
});

it('Wac', () => {
spyOn(getPasteSource, 'default').and.returnValue(KnownPasteSourceType.WacComponents);
spyOn(WacFile, 'processPastedContentWacComponents').and.callThrough();

plugin.initialize(editor);
plugin.onPluginEvent(event);

expect(WacFile.processPastedContentWacComponents).toHaveBeenCalledWith(event);
expect(addParser.default).toHaveBeenCalledTimes(5);
expect(setProcessor.setProcessor).toHaveBeenCalledTimes(4);
expect(chainSanitizerCallbackFile.default).toHaveBeenCalledTimes(3);
});

it('Default', () => {
spyOn(getPasteSource, 'default').and.returnValue(KnownPasteSourceType.Default);
spyOn(WordDesktopFile, 'processPastedContentFromWordDesktop');
spyOn(addParser, 'default').and.callThrough();

plugin.initialize(editor);
plugin.onPluginEvent(event);

expect(WordDesktopFile.processPastedContentFromWordDesktop).not.toHaveBeenCalled();
expect(event.domToModelOption.processorOverride?.element).toBeUndefined();
expect(addParser.default).toHaveBeenCalledTimes(1);
expect(setProcessor.setProcessor).toHaveBeenCalledTimes(0);
expect(chainSanitizerCallbackFile.default).toHaveBeenCalledTimes(3);
});

it('Google Sheets', () => {
spyOn(getPasteSource, 'default').and.returnValue(KnownPasteSourceType.GoogleSheets);

plugin.initialize(editor);
plugin.onPluginEvent(event);

expect(addParser.default).toHaveBeenCalledTimes(1);
expect(setProcessor.setProcessor).toHaveBeenCalledTimes(0);
expect(chainSanitizerCallbackFile.default).toHaveBeenCalledTimes(3);
expect(
event.sanitizingOption.additionalTagReplacements[GOOGLE_SHEET_NODE_NAME]
).toEqual('*');
});
});
});
11 changes: 9 additions & 2 deletions packages/roosterjs-editor-plugins/lib/plugins/Paste/Paste.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import convertPastedContentFromWord from './wordConverter/convertPastedContentFr
import handleLineMerge from './lineMerge/handleLineMerge';
import sanitizeHtmlColorsFromPastedContent from './sanitizeHtmlColorsFromPastedContent/sanitizeHtmlColorsFromPastedContent';
import sanitizeLinks from './sanitizeLinks/sanitizeLinks';
import { getPasteSource } from 'roosterjs-editor-dom';
import { KnownPasteSourceType } from 'roosterjs-editor-types';
import { chainSanitizerCallback, getPasteSource } from 'roosterjs-editor-dom';
import { HtmlSanitizerOptions, KnownPasteSourceType } from 'roosterjs-editor-types';
import {
EditorPlugin,
IEditor,
Expand Down Expand Up @@ -104,9 +104,16 @@ export default class Paste implements EditorPlugin {
}
sanitizeLinks(sanitizingOption);
sanitizeHtmlColorsFromPastedContent(sanitizingOption);
sanitizeBlockStyles(sanitizingOption);

// Replace unknown tags with SPAN
sanitizingOption.unknownTagReplacement = this.unknownTagReplacement;
}
}
}

function sanitizeBlockStyles(sanitizingOption: Required<HtmlSanitizerOptions>) {
chainSanitizerCallback(sanitizingOption.cssStyleCallbacks, 'display', (value: string) => {
return value != 'flex'; // return whether we keep the style
});
}

0 comments on commit 8c7fa2b

Please sign in to comment.