Skip to content

Commit

Permalink
RoosterJs 9.10.0 (#2786)
Browse files Browse the repository at this point in the history
* image-selection

* fixes

* safari fix

* fix drag and drop

* fixes

* fixes

* Add `<del>` elements to default processors and use knownElementProcessor for this type of element. (#2770)

* init

* Use alphabet order

* Dont remove the MarginTop/Bottom from lists when pasting from Word Online (#2778)

* init

* remove unneeded function

* try fix build

* Reconcile table and image selection for cache (#2714)

* Improve cache

* fix build

* improve

* add test

* Cache and entity 2

* Add test

* Reconcile table and image selection for cache

* support reconcile entity delimiter

* fix build

* add test

---------

Co-authored-by: Bryan Valverde U <[email protected]>

* Set segmentFormat text color to black when creating the model of the clipboard content and using Keep source formatting paste type (#2773)

* init

* add a link to tests and make sure it is handled correctly

* fixes image in tables

* Bump webpack from 5.84.1 to 5.94.0 (#2780)

Bumps [webpack](https://github.com/webpack/webpack) from 5.84.1 to 5.94.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](webpack/webpack@v5.84.1...v5.94.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Resolve null sheet in convertInlineCss (#2784)

* init

* update

* Update paste code to add a paragraph when the clipboard contains atleast a block element (#2777)

* init

* add a link to tests and make sure it is handled correctly

* init

* try fix build

* fix build

* Fix 300391: [Mail] The numbers will become a continuous sequence after typing enter at the last line of the numbering above (#2782)

Co-authored-by: Bryan Valverde U <[email protected]>

* Pressing Tab inside a table should select all node contents of the next cell (#2764)

* normalise position

* revert

* empty cell check

* select using children

* fix tests

* fix

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: Julia Roldi (from Dev Box) <[email protected]>
Co-authored-by: Julia Roldi <[email protected]>
Co-authored-by: Bryan Valverde U <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Andres-CT98 <[email protected]>
  • Loading branch information
6 people authored Sep 6, 2024
1 parent 2a58f4f commit a74f5ad
Show file tree
Hide file tree
Showing 54 changed files with 6,578 additions and 1,932 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
"typedoc-plugin-remove-references": "0.0.5",
"typescript": "4.4.4",
"url-loader": "4.1.0",
"webpack": "5.84.1",
"webpack": "5.94.0",
"webpack-cli": "3.3.11",
"webpack-dev-server": "3.10.3"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export function generatePasteOptionFromPlugins(
htmlAttributes: htmlFromClipboard.metadata,
pasteType: pasteType,
domToModelOption,
containsBlockElements: !!htmlFromClipboard.containsBlockElements,
};

return pasteType == 'asPlainText'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,18 @@ import {
} from 'roosterjs-content-model-dom';
import type {
BeforePasteEvent,
ClipboardData,
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),
};
Expand All @@ -32,12 +36,15 @@ export function cloneModelForPaste(model: ReadonlyContentModelDocument) {
/**
* @internal
*/
export function mergePasteContent(
editor: IEditor,
eventResult: BeforePasteEvent,
clipboardData: ClipboardData
) {
const { fragment, domToModelOption, customizedMerge, pasteType } = eventResult;
export function mergePasteContent(editor: IEditor, eventResult: BeforePasteEvent) {
const {
fragment,
domToModelOption,
customizedMerge,
pasteType,
clipboardData,
containsBlockElements,
} = eventResult;

editor.formatContentModel(
(model, context) => {
Expand All @@ -46,22 +53,20 @@ export function mergePasteContent(
model.blocks = clonedModel.blocks;
}

const selectedSegment = getSelectedSegments(model, true /*includeFormatHolder*/)[0];
const domToModelContext = createDomToModelContextForSanitizing(
editor.getDocument(),
undefined /*defaultFormat*/,
editor.getEnvironment().domToModelSettings.customized,
domToModelOption
);

domToModelContext.segmentFormat = selectedSegment
? getSegmentTextFormat(selectedSegment)
: {};
domToModelContext.segmentFormat = getSegmentFormatForPaste(model, pasteType);

const pasteModel = domToContentModel(fragment, domToModelContext);
const mergeOption: MergeModelOption = {
mergeFormat: pasteType == 'mergeFormat' ? 'keepSourceEmphasisFormat' : 'none',
mergeTable: shouldMergeTable(pasteModel),
addParagraphAfterMergedContent: containsBlockElements,
};

const insertPoint = customizedMerge
Expand All @@ -72,7 +77,9 @@ export function mergePasteContent(
context.newPendingFormat = {
...EmptySegmentFormat,
...model.format,
...insertPoint.marker.format,
...(pasteType == 'normal' && !containsBlockElements
? getLastSegmentFormat(pasteModel)
: insertPoint.marker.format),
};
}

Expand All @@ -87,6 +94,27 @@ export function mergePasteContent(
);
}

function getSegmentFormatForPaste(
model: ShallowMutableContentModelDocument,
pasteType: PasteType
): ContentModelSegmentFormat {
const selectedSegment = getSelectedSegments(model, true /*includeFormatHolder*/)[0];

if (selectedSegment) {
const result = getSegmentTextFormat(selectedSegment);
if (pasteType == 'normal') {
// When using normal paste (Keep source formatting) set the default text color to black when creating the
// Model from the clipboard content, so the elements that do not contain any text color in their style
// Are set to black. Otherwise, These segments would get the selected segments format or the default text set in the content.
result.textColor = BlackColor;
}

return result;
}

return {};
}

function shouldMergeTable(pasteModel: ContentModelDocument): boolean | undefined {
// If model contains a table and a paragraph element after the table with a single BR segment, remove the Paragraph after the table
if (
Expand All @@ -101,3 +129,19 @@ function shouldMergeTable(pasteModel: ContentModelDocument): boolean | undefined
// Only merge table when the document contain a single table.
return pasteModel.blocks.length === 1 && pasteModel.blocks[0].blockType === 'Table';
}

function getLastSegmentFormat(pasteModel: ContentModelDocument): ContentModelSegmentFormat {
if (pasteModel.blocks.length == 1) {
const [firstBlock] = pasteModel.blocks;

if (firstBlock.blockType == 'Paragraph') {
const segment = firstBlock.segments[firstBlock.segments.length - 1];

return {
...segment.format,
};
}
}

return {};
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export function paste(
convertInlineCss(eventResult.fragment, htmlFromClipboard.globalCssRules);

// 6. Merge pasted content into main Content Model
mergePasteContent(editor, eventResult, clipboardData);
mergePasteContent(editor, eventResult);
}

function createDOMFromHtml(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isNodeOfType, toArray } from 'roosterjs-content-model-dom';
import { isBlockElement, isNodeOfType, toArray } from 'roosterjs-content-model-dom';
import { retrieveCssRules } from '../createModelFromHtml/convertInlineCss';
import type { ClipboardData } from 'roosterjs-content-model-types';
import type { CssRule } from '../createModelFromHtml/convertInlineCss';
Expand All @@ -14,6 +14,7 @@ export interface HtmlFromClipboard {
globalCssRules: CssRule[];
htmlBefore?: string;
htmlAfter?: string;
containsBlockElements?: boolean;
}

/**
Expand All @@ -33,6 +34,7 @@ export function retrieveHtmlInfo(
...retrieveHtmlStrings(clipboardData),
globalCssRules: retrieveCssRules(doc),
metadata: retrieveMetadata(doc),
containsBlockElements: checkBlockElements(doc),
};

clipboardData.htmlFirstLevelChildTags = retrieveTopLevelTags(doc);
Expand Down Expand Up @@ -96,3 +98,9 @@ function retrieveHtmlStrings(

return { htmlBefore, htmlAfter };
}

function checkBlockElements(doc: Document): boolean {
const elements = toArray(doc.body.querySelectorAll('*'));

return elements.some(el => isNodeOfType(el, 'ELEMENT_NODE') && isBlockElement(el));
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { areSameSelections } from './areSameSelections';
import { createTextMutationObserver } from './textMutationObserver';
import { DomIndexerImpl } from './domIndexerImpl';
import { updateCache } from './updateCache';
import type { Mutation } from './textMutationObserver';
import type { Mutation } from './MutationType';
import type {
CachePluginState,
IEditor,
Expand Down Expand Up @@ -90,6 +90,19 @@ class CachePlugin implements PluginWithState<CachePluginState> {
}

switch (event.eventType) {
case 'logicalRootChanged':
this.invalidateCache();

if (this.state.textMutationObserver) {
this.state.textMutationObserver.stopObserving();
this.state.textMutationObserver = createTextMutationObserver(
event.logicalRoot,
this.onMutation
);
this.state.textMutationObserver.startObserving();
}
break;

case 'keyDown':
case 'input':
if (!this.state.textMutationObserver) {
Expand Down Expand Up @@ -133,6 +146,15 @@ class CachePlugin implements PluginWithState<CachePluginState> {
this.updateCachedModel(this.editor, true /*forceUpdate*/);
break;

case 'elementId':
const element = mutation.element;

if (!this.state.domIndexer?.reconcileElementId(element)) {
this.invalidateCache();
}

break;

case 'unknown':
this.invalidateCache();
break;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* @internal Type of mutations
*/
export type MutationType =
/**
* We found some change happened but we cannot handle it, so set mutation type as "unknown"
*/
| 'unknown'
/**
* Element id is changed
*/
| 'elementId'
/**
* Only text is changed
*/
| 'text'
/**
* Child list is changed
*/
| 'childList';

/**
* @internal
*/
export interface MutationBase<T extends MutationType> {
type: T;
}

/**
* @internal
*/
export interface UnknownMutation extends MutationBase<'unknown'> {}

/**
* @internal
*/
export interface ElementIdMutation extends MutationBase<'elementId'> {
element: HTMLElement;
}

/**
* @internal
*/
export interface TextMutation extends MutationBase<'text'> {}

/**
* @internal
*/
export interface ChildListMutation extends MutationBase<'childList'> {
addedNodes: Node[];
removedNodes: Node[];
}

/**
* @internal
*/
export type Mutation = UnknownMutation | ElementIdMutation | TextMutation | ChildListMutation;
Loading

0 comments on commit a74f5ad

Please sign in to comment.