Skip to content

Commit 54e3f91

Browse files
ianeli1JiuqingSongBryanValverdeUjuliaroldiAndres-CT98
authored
Bump rooster to 8.55.0, content model to 0.15.0 (#2060)
* Content Model: Improve cache behavior (#1999) * Content Model: Improve cache behavior * fix build * fix comment * Skip Trigger plugin event on plain text paste (#2011) * init * remove unneeded change * Update return type * Fix 218869: Do not allow dragging on readonly content (#2010) * Fix 218869: Do not allow dragging readonly content * fix test * Content Model: Fix 194024 and 220289 (#2012) * Content Model: Fix 221290 Support float for image (#2013) * Content Model: improve formatWithContentModel 1 (#2001) * Content Model: Improve cache behavior * fix build * Content Model: improve formatWithContentModel * Content Model: improve formatWithContentModel 2 (#2002) * Content Model: Improve cache behavior * fix build * Content Model: improve formatWithContentModel * Content Model: improve formatWithContentModel 2 * fix format * WIP * fix handles * MergeModel, do not inherit the styles of table when splitting the param (#2016) * init * init * address comment * update test names * fixes * Demo site: Fix insert link button in Content Model ribbon (#2018) * Content Model: insertEntity API (#1800) * Content Model insertEntity * improve * improve * Content Model: Improve cache behavior * fix build * Content Model: improve formatWithContentModel * Content Model: improve formatWithContentModel 2 * Improve * fix build * fix build * improve * add test * add test * add test * add test * fix dark color * fix test * fix build and test * crop * fix xase * check cell exist * Fix #1752, rename header to heading (#2020) * fix cell empty cells * fix flipped image * Update logic to decide if we need to merge a table on paste. (#2022) * Fix TableSelectionCopy * update unit tests * Fix 2 * address comment * Content Model: Rename a test file (#2029) * Fix Triple clicking a single cell selecting more than one (#2024) * fix triple click, optimisation * Remove `display: flex` style on paste (#2031) * init * Fix * Replace first cell content if input while on cell selection (#2030) * select first cell content and empty, add undo if change * Content Model: Fix 222135 (#2035) * Fix 222135 * fix build * Content Model: Fix 219312 (#2036) * Fix regression when creating the BeforePasteEvent (#2039) * init * fix build * Content Model: Fix 220050 (#2037) * Content Model: Fix 220050 * Fix build * improve * improve * Simplify the domToModel call in `paste.ts` (#2040) * add more changes * fix build * fix test * Content Model: Support vertical-align for image (#2041) * Content Model: Support vertical-align for image * fix build and test --------- Co-authored-by: Bryan Valverde U <bvalverde@microsoft.com> * Remove deprecated colors from borders, text and background. (#2045) * Support more border styles * init * Revert unrelated change * Fix dependencies * address comments * try fix build * reselection * add space * Content Model: Improve insertEntity (#2047) * Content Model: Improve insertEntity * fix test * Content Model: Fix selection of entity (#2051) * Content Model: Always return size in pt when getFormatState (#2052) * Content Model: trigger ShadowEdit events (#2053) * Content Model: trigger ShadowEdit events * improve * Content Model: Add solid paragraph in new table cell (#2055) * Content Model: Do color transform for entity when copy/paste (#2056) * Content Model: Do color transform for entity when copy/paste * Call normalizeContentModel * Content Model: Paste plain text applies current format (#2057) * Content Model: Paste plain text applies current format * fix build * Content Model: Fix a regression of shadow edit (#2058) * Update versions * Fix double import * Double import 2 --------- Co-authored-by: Jiuqing Song <jisong@microsoft.com> Co-authored-by: Bryan Valverde U <bvalverde@microsoft.com> Co-authored-by: Júlia Roldi <juliaroldi@microsoft.com> Co-authored-by: Julia Roldi <87443959+juliaroldi@users.noreply.github.com> Co-authored-by: Andres-CT98 <107568016+Andres-CT98@users.noreply.github.com>
1 parent e2ae751 commit 54e3f91

File tree

65 files changed

+2564
-1042
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+2564
-1042
lines changed

packages-content-model/roosterjs-content-model-dom/lib/formatHandlers/utils/color.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,35 @@
11
import { DarkColorHandler } from 'roosterjs-editor-types';
22
import { getTagOfNode } from 'roosterjs-editor-dom';
33

4+
/**
5+
* List of deprecated colors
6+
*/
7+
export const DeprecatedColors: string[] = [
8+
'inactiveborder',
9+
'activeborder',
10+
'inactivecaptiontext',
11+
'inactivecaption',
12+
'activecaption',
13+
'appworkspace',
14+
'infobackground',
15+
'background',
16+
'buttonhighlight',
17+
'buttonshadow',
18+
'captiontext',
19+
'infotext',
20+
'menutext',
21+
'menu',
22+
'scrollbar',
23+
'threeddarkshadow',
24+
'threedface',
25+
'threedhighlight',
26+
'threedlightshadow',
27+
'threedfhadow',
28+
'windowtext',
29+
'windowframe',
30+
'window',
31+
];
32+
433
/**
534
* @internal
635
*/
@@ -21,6 +50,10 @@ export function getColor(
2150
undefined;
2251
}
2352

53+
if (color && DeprecatedColors.indexOf(color) > -1) {
54+
color = undefined;
55+
}
56+
2457
if (darkColorHandler) {
2558
color = darkColorHandler.parseColorValue(color).lightModeColor;
2659
}

packages-content-model/roosterjs-content-model-dom/lib/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,13 @@ export { unwrapBlock } from './modelApi/common/unwrapBlock';
4242
export { addSegment } from './modelApi/common/addSegment';
4343
export { isWhiteSpacePreserved } from './modelApi/common/isWhiteSpacePreserved';
4444
export { normalizeSingleSegment } from './modelApi/common/normalizeSegment';
45+
export { applySegmentFormatToElement } from './modelApi/common/applySegmentFormatToElement';
4546

4647
export { setParagraphNotImplicit } from './modelApi/block/setParagraphNotImplicit';
4748

4849
export { parseValueWithUnit } from './formatHandlers/utils/parseValueWithUnit';
4950
export { BorderKeys } from './formatHandlers/common/borderFormatHandler';
51+
export { DeprecatedColors } from './formatHandlers/utils/color';
5052
export { defaultImplicitFormatMap } from './formatHandlers/utils/defaultStyles';
5153

5254
export { createDomToModelContext } from './domToModel/context/createDomToModelContext';
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { applyFormat } from '../../modelToDom/utils/applyFormat';
2+
import { ContentModelSegmentFormat } from 'roosterjs-content-model-types';
3+
import { createModelToDomContext } from '../../modelToDom/context/createModelToDomContext';
4+
5+
/**
6+
* Format an existing HTML element using Segment Format
7+
* @param element The element to format
8+
* @param format The format to apply
9+
*/
10+
export function applySegmentFormatToElement(
11+
element: HTMLElement,
12+
format: ContentModelSegmentFormat
13+
) {
14+
const context = createModelToDomContext();
15+
applyFormat(element, context.formatAppliers.segment, format, context);
16+
}

packages-content-model/roosterjs-content-model-dom/lib/modelToDom/handlers/handleEntity.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ export const handleEntity: ContentModelBlockHandler<ContentModelEntity> = (
6161
const [after] = addDelimiters(wrapper);
6262

6363
context.regularSelection.current.segment = after;
64+
} else if (isInlineEntity) {
65+
context.regularSelection.current.segment = wrapper;
6466
}
6567

6668
context.onNodeCreated?.(entityModel, wrapper);

packages-content-model/roosterjs-content-model-dom/test/formatHandlers/common/backgroundColorFormatHandlerTest.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import DarkColorHandlerImpl from 'roosterjs-editor-core/lib/editor/DarkColorHand
22
import { backgroundColorFormatHandler } from '../../../lib/formatHandlers/common/backgroundColorFormatHandler';
33
import { createDomToModelContext } from '../../../lib/domToModel/context/createDomToModelContext';
44
import { createModelToDomContext } from '../../../lib/modelToDom/context/createModelToDomContext';
5+
import { DeprecatedColors } from '../../../lib/formatHandlers/utils/color';
56
import { expectHtml } from 'roosterjs-editor-dom/test/DomTestHelper';
67
import {
78
BackgroundColorFormat,
@@ -62,6 +63,16 @@ describe('backgroundColorFormatHandler.parse', () => {
6263

6364
expect(format.backgroundColor).toBe('red');
6465
});
66+
67+
DeprecatedColors.forEach(color => {
68+
it('Remove deprecated color ' + color, () => {
69+
div.style.backgroundColor = color;
70+
71+
backgroundColorFormatHandler.parse(format, div, context, {});
72+
73+
expect(format.backgroundColor).toBe(undefined);
74+
});
75+
});
6576
});
6677

6778
describe('backgroundColorFormatHandler.apply', () => {

packages-content-model/roosterjs-content-model-dom/test/formatHandlers/segment/textColorFormatHandlerTest.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import DarkColorHandlerImpl from 'roosterjs-editor-core/lib/editor/DarkColorHandlerImpl';
22
import { createDomToModelContext } from '../../../lib/domToModel/context/createDomToModelContext';
33
import { createModelToDomContext } from '../../../lib/modelToDom/context/createModelToDomContext';
4+
import { DeprecatedColors } from '../../../lib';
45
import { expectHtml } from 'roosterjs-editor-dom/test/DomTestHelper';
56
import { textColorFormatHandler } from '../../../lib/formatHandlers/segment/textColorFormatHandler';
67
import {
@@ -87,6 +88,16 @@ describe('textColorFormatHandler.parse', () => {
8788

8889
expect(format.textColor).toBe('red');
8990
});
91+
92+
DeprecatedColors.forEach(color => {
93+
it('Remove deprecated color ' + color, () => {
94+
div.style.backgroundColor = color;
95+
96+
textColorFormatHandler.parse(format, div, context, {});
97+
98+
expect(format.textColor).toBe(undefined);
99+
});
100+
});
90101
});
91102

92103
describe('textColorFormatHandler.apply', () => {

packages-content-model/roosterjs-content-model-dom/test/modelToDom/handlers/handleEntityTest.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,33 @@ describe('handleEntity', () => {
174174
expect(context.regularSelection.current.segment).toBe(span.nextSibling);
175175
});
176176

177+
it('Entity without delimiter', () => {
178+
const span = document.createElement('span');
179+
const entityModel: ContentModelEntity = {
180+
blockType: 'Entity',
181+
segmentType: 'Entity',
182+
format: {},
183+
id: 'entity_1',
184+
type: 'entity',
185+
isReadonly: true,
186+
wrapper: span,
187+
};
188+
189+
span.textContent = 'test';
190+
191+
const parent = document.createElement('div');
192+
const result = handleEntity(document, parent, entityModel, context, null);
193+
194+
expect(parent.innerHTML).toBe(
195+
'<span class="_Entity _EType_entity _EId_entity_1 _EReadonly_1" contenteditable="false">test</span>'
196+
);
197+
expect(span.outerHTML).toBe(
198+
'<span class="_Entity _EType_entity _EId_entity_1 _EReadonly_1" contenteditable="false">test</span>'
199+
);
200+
expect(result).toBe(null);
201+
expect(context.regularSelection.current.segment).toBe(span);
202+
});
203+
177204
it('With onNodeCreated', () => {
178205
const entityDiv = document.createElement('div');
179206
const entityModel: ContentModelEntity = {

packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/switchShadowEdit.ts

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ContentModelEditorCore } from '../../publicTypes/ContentModelEditorCore';
22
import { getSelectionPath } from 'roosterjs-editor-dom';
3-
import { SwitchShadowEdit } from 'roosterjs-editor-types';
3+
import { PluginEventType, SwitchShadowEdit } from 'roosterjs-editor-types';
44

55
/**
66
* @internal
@@ -14,19 +14,44 @@ export const switchShadowEdit: SwitchShadowEdit = (editorCore, isOn): void => {
1414

1515
if (isOn != !!core.lifecycle.shadowEditFragment) {
1616
if (isOn) {
17-
if (!core.cachedModel) {
18-
core.cachedModel = core.api.createContentModel(core);
19-
}
20-
17+
const model = !core.cachedModel ? core.api.createContentModel(core) : null;
2118
const range = core.api.getSelectionRange(core, true /*tryGetFromCache*/);
2219

23-
core.lifecycle.shadowEditSelectionPath =
24-
range && getSelectionPath(core.contentDiv, range);
25-
core.lifecycle.shadowEditFragment = core.contentDiv.ownerDocument.createDocumentFragment();
20+
// Fake object, not used in Content Model Editor, just to satisfy original editor code
21+
// TODO: we can remove them once we have standalone Content Model Editor
22+
const fragment = core.contentDiv.ownerDocument.createDocumentFragment();
23+
const selectionPath = range && getSelectionPath(core.contentDiv, range);
24+
25+
core.api.triggerEvent(
26+
core,
27+
{
28+
eventType: PluginEventType.EnteredShadowEdit,
29+
fragment,
30+
selectionPath,
31+
},
32+
false /*broadcast*/
33+
);
34+
35+
// This need to be done after EnteredShadowEdit event is triggered since EnteredShadowEdit event will cause a SelectionChanged event
36+
// if current selection is table selection or image selection
37+
if (!core.cachedModel && model) {
38+
core.cachedModel = model;
39+
}
40+
41+
core.lifecycle.shadowEditSelectionPath = selectionPath;
42+
core.lifecycle.shadowEditFragment = fragment;
2643
} else {
2744
core.lifecycle.shadowEditFragment = null;
2845
core.lifecycle.shadowEditSelectionPath = null;
2946

47+
core.api.triggerEvent(
48+
core,
49+
{
50+
eventType: PluginEventType.LeavingShadowEdit,
51+
},
52+
false /*broadcast*/
53+
);
54+
3055
if (core.cachedModel) {
3156
core.api.setContentModel(core, core.cachedModel);
3257
}

packages-content-model/roosterjs-content-model-editor/lib/editor/corePlugins/ContentModelCopyPastePlugin.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import {
3333
ClipboardData,
3434
SelectionRangeTypes,
3535
SelectionRangeEx,
36+
ColorTransformDirection,
3637
} from 'roosterjs-editor-types';
3738

3839
/**
@@ -94,7 +95,24 @@ export default class ContentModelCopyPastePlugin implements PluginWithState<Copy
9495
if (selection && !selection.areAllCollapsed) {
9596
const model = this.editor.createContentModel();
9697

97-
const pasteModel = cloneModel(model);
98+
const pasteModel = cloneModel(model, {
99+
includeCachedElement: this.editor.isDarkMode()
100+
? (node, type) => {
101+
if (type == 'cache') {
102+
return undefined;
103+
} else {
104+
const result = node.cloneNode(true /*deep*/) as HTMLElement;
105+
106+
this.editor?.transformToDarkColor(
107+
result,
108+
ColorTransformDirection.DarkToLight
109+
);
110+
111+
return result;
112+
}
113+
}
114+
: false,
115+
});
98116
if (selection.type === SelectionRangeTypes.TableSelection) {
99117
iterateSelections([pasteModel], (path, tableContext) => {
100118
if (tableContext?.table) {

packages-content-model/roosterjs-content-model-editor/lib/editor/plugins/PastePlugin/ContentModelPastePlugin.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import addParser from './utils/addParser';
22
import ContentModelBeforePasteEvent from '../../../publicTypes/event/ContentModelBeforePasteEvent';
33
import { chainSanitizerCallback, getPasteSource } from 'roosterjs-editor-dom';
44
import { ContentModelBlockFormat, FormatParser } from 'roosterjs-content-model-types';
5+
import { deprecatedBorderColorParser } from './utils/deprecatedColorParser';
56
import { IContentModelEditor } from '../../../publicTypes/IContentModelEditor';
6-
import { parseDeprecatedColor } from './utils/deprecatedColorParser';
77
import { parseLink } from './utils/linkParser';
88
import { processPastedContentFromExcel } from './Excel/processPastedContentFromExcel';
99
import { processPastedContentFromPowerPoint } from './PowerPoint/processPastedContentFromPowerPoint';
@@ -80,7 +80,7 @@ export default class ContentModelPastePlugin implements EditorPlugin {
8080
if (!ev.domToModelOption) {
8181
return;
8282
}
83-
const pasteSource = getPasteSource(event, false);
83+
const pasteSource = getPasteSource(ev, false);
8484
switch (pasteSource) {
8585
case KnownPasteSourceType.WordDesktop:
8686
processPastedContentFromWordDesktop(ev);
@@ -90,32 +90,30 @@ export default class ContentModelPastePlugin implements EditorPlugin {
9090
break;
9191
case KnownPasteSourceType.ExcelOnline:
9292
case KnownPasteSourceType.ExcelDesktop:
93-
if (
94-
event.pasteType === PasteType.Normal ||
95-
event.pasteType === PasteType.MergeFormat
96-
) {
93+
if (ev.pasteType === PasteType.Normal || ev.pasteType === PasteType.MergeFormat) {
9794
// Handle HTML copied from Excel
9895
processPastedContentFromExcel(ev, this.editor.getTrustedHTMLHandler());
9996
}
10097
break;
10198
case KnownPasteSourceType.GoogleSheets:
102-
event.sanitizingOption.additionalTagReplacements[GOOGLE_SHEET_NODE_NAME] = '*';
99+
ev.sanitizingOption.additionalTagReplacements[GOOGLE_SHEET_NODE_NAME] = '*';
103100
break;
104101
case KnownPasteSourceType.PowerPointDesktop:
105102
processPastedContentFromPowerPoint(ev, this.editor.getTrustedHTMLHandler());
106103
break;
107104
}
108105

109106
addParser(ev.domToModelOption, 'link', parseLink);
110-
parseDeprecatedColor(ev.sanitizingOption);
107+
addParser(ev.domToModelOption, 'tableCell', deprecatedBorderColorParser);
108+
addParser(ev.domToModelOption, 'table', deprecatedBorderColorParser);
111109
sanitizeBlockStyles(ev.sanitizingOption);
112110

113-
if (event.pasteType === PasteType.MergeFormat) {
111+
if (ev.pasteType === PasteType.MergeFormat) {
114112
addParser(ev.domToModelOption, 'block', blockElementParser);
115113
addParser(ev.domToModelOption, 'listLevel', blockElementParser);
116114
}
117115

118-
event.sanitizingOption.unknownTagReplacement = this.unknownTagReplacement;
116+
ev.sanitizingOption.unknownTagReplacement = this.unknownTagReplacement;
119117
}
120118
}
121119

0 commit comments

Comments
 (0)