Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Publish 8.37.0 with 4 changes #1430

Merged
merged 5 commits into from
Nov 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { Editor } from 'roosterjs-editor-core';
import { EditorOptions, SelectionRangeTypes } from 'roosterjs-editor-types';
import { getComputedStyles, Position } from 'roosterjs-editor-dom';
import {
getComputedStyles,
Position,
restoreContentWithEntityPlaceholder,
} from 'roosterjs-editor-dom';
import {
EditorContext,
ContentModelDocument,
Expand All @@ -9,7 +13,6 @@ import {
DomToModelOption,
IExperimentalContentModelEditor,
ModelToDomOption,
mergeFragmentWithEntity,
} from 'roosterjs-content-model';

/**
Expand Down Expand Up @@ -70,7 +73,7 @@ export default class ExperimentalContentModelEditor extends Editor
this.createEditorContext(),
option
);
const mergingCallback = option?.mergingCallback || mergeFragmentWithEntity;
const mergingCallback = option?.mergingCallback || restoreContentWithEntityPlaceholder;

if (range) {
if (range.type == SelectionRangeTypes.Normal) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const initialState: BuildInPluginState = {
ExperimentalFeatures.ListItemAlignment,
ExperimentalFeatures.PendingStyleBasedFormat,
ExperimentalFeatures.DefaultFormatInSpan,
ExperimentalFeatures.AutoFormatList,
],
isRtl: false,
};
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "roosterjs",
"version": "8.36.0",
"version": "8.37.0",
"description": "Framework-independent javascript editor",
"repository": {
"type": "git",
Expand Down
9 changes: 1 addition & 8 deletions packages/roosterjs-content-model/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
export { default as domToContentModel } from './publicApi/domToContentModel';
export { default as contentModelToDom } from './publicApi/contentModelToDom';
export {
default as mergeFragmentWithEntity,
preprocessEntitiesFromContentModel,
} from './publicApi/mergeFragmentWithEntity';
export { default as insertTable } from './publicApi/table/insertTable';
export { default as formatTable } from './publicApi/table/formatTable';
export { default as setTableCellShade } from './publicApi/table/setTableCellShade';
Expand Down Expand Up @@ -134,10 +130,7 @@ export {
ContentModelHandlerTypeMap,
DefaultImplicitSegmentFormatMap,
} from './publicTypes/context/ModelToDomSettings';
export {
ModelToDomEntityContext,
EntityPlaceholderPair,
} from './publicTypes/context/ModelToDomEntityContext';
export { ModelToDomEntityContext } from './publicTypes/context/ModelToDomEntityContext';
export { ElementProcessor } from './publicTypes/context/ElementProcessor';
export { ContentModelHandler } from './publicTypes/context/ContentModelHandler';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,10 @@ export function createModelToDomContext(
...defaultImplicitSegmentFormatMap,
...(options?.defaultImplicitSegmentFormatOverride || {}),
},
entityPairs: [],
entities: {},

defaultModelHandlers: defaultContentModelHandlers,
defaultFormatAppliers: defaultFormatAppliers,
doNotReuseEntityDom: !!options?.doNotReuseEntityDom,
};
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { applyFormat } from '../utils/applyFormat';
import { commitEntity, getObjectKeys } from 'roosterjs-editor-dom';
import { commitEntity, createEntityPlaceholder, getObjectKeys } from 'roosterjs-editor-dom';
import { ContentModelEntity } from '../../publicTypes/entity/ContentModelEntity';
import { ContentModelHandler } from '../../publicTypes/context/ContentModelHandler';
import { ModelToDomContext } from '../../publicTypes/context/ModelToDomContext';
Expand All @@ -18,12 +18,6 @@ export const handleEntity: ContentModelHandler<ContentModelEntity> = (
// Commit the entity attributes in case there is any change
commitEntity(wrapper, type, isReadonly, id);

// Create a comment as placeholder and insert into DOM tree.
// If the entity DOM can be reused, the original DOM node will be preserved without any change
// so that in case there is something that is sensitive to its DOM path (e.g. IFRAME), no need to cause it reloaded.
// For entity that is not directly under root, later we will replace the comment with its original DOM node
const placeholder = doc.createComment('Entity:' + id);

if (getObjectKeys(format).length > 0) {
const span = doc.createElement('span');

Expand All @@ -32,11 +26,16 @@ export const handleEntity: ContentModelHandler<ContentModelEntity> = (
parent = span;
}

parent.appendChild(placeholder);
if (context.doNotReuseEntityDom) {
parent.appendChild(wrapper);
} else {
// Create a comment as placeholder and insert into DOM tree.
// If the entity DOM can be reused, the original DOM node will be preserved without any change
// so that in case there is something that is sensitive to its DOM path (e.g. IFRAME), no need to cause it reloaded.
// For entity that is not directly under root, later we will replace the comment with its original DOM node
parent.appendChild(createEntityPlaceholder(entityModel));

// Save the entity DOM wrapper node and its placeholder into context so that later we know how to handle it
context.entityPairs.push({
entityWrapper: wrapper,
placeholder: placeholder,
});
// Save the entity DOM wrapper node and its placeholder into context so that later we know how to handle it
context.entities[id] = wrapper;
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { ContentModelDocument } from '../publicTypes/group/ContentModelDocument'
import { createModelToDomContext } from '../modelToDom/context/createModelToDomContext';
import { createRange, Position, toArray } from 'roosterjs-editor-dom';
import { EditorContext } from '../publicTypes/context/EditorContext';
import { EntityPlaceholderPair } from '../publicTypes/context/ModelToDomEntityContext';
import { isNodeOfType } from '../domUtils/isNodeOfType';
import { ModelToDomBlockAndSegmentNode } from '../publicTypes/context/ModelToDomSelectionContext';
import { ModelToDomContext } from '../publicTypes/context/ModelToDomContext';
Expand All @@ -29,7 +28,7 @@ export default function contentModelToDom(
model: ContentModelDocument,
editorContext: EditorContext,
option?: ModelToDomOption
): [DocumentFragment, SelectionRangeEx | null, EntityPlaceholderPair[]] {
): [DocumentFragment, SelectionRangeEx | null, Record<string, HTMLElement>] {
const fragment = model.document.createDocumentFragment();
const modelToDomContext = createModelToDomContext(editorContext, option);

Expand All @@ -40,7 +39,7 @@ export default function contentModelToDom(

fragment.normalize();

return [fragment, range, modelToDomContext.entityPairs];
return [fragment, range, modelToDomContext.entities];
}

function extractSelectionRange(context: ModelToDomContext): SelectionRangeEx | null {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { mergeTableCells } from '../../modelApi/table/mergeTableCells';
import { mergeTableColumn } from '../../modelApi/table/mergeTableColumn';
import { mergeTableRow } from '../../modelApi/table/mergeTableRow';
import { normalizeTable } from '../../modelApi/table/normalizeTable';
import { preprocessEntitiesFromContentModel } from '../mergeFragmentWithEntity';
import { splitTableCellHorizontally } from '../../modelApi/table/splitTableCellHorizontally';
import { splitTableCellVertically } from '../../modelApi/table/splitTableCellVertically';

Expand Down Expand Up @@ -103,8 +102,8 @@ export default function editTable(
editor.focus();
if (model && table) {
editor.setContentModel(model, {
mergingCallback: (fragment, _, entityPairs) => {
preprocessEntitiesFromContentModel(entityPairs);
doNotReuseEntityDom: true,
mergingCallback: fragment => {
editor.replaceNode(table, fragment);
},
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { applyTableFormat } from '../../modelApi/table/applyTableFormat';
import { ChangeSource } from 'roosterjs-editor-types';
import { IExperimentalContentModelEditor } from '../../publicTypes/IExperimentalContentModelEditor';
import { preprocessEntitiesFromContentModel } from '../mergeFragmentWithEntity';
import { TableMetadataFormat } from '../../publicTypes/format/formatParts/TableMetadataFormat';

/**
Expand All @@ -27,8 +26,8 @@ export default function formatTable(
editor.focus();
if (model && table) {
editor.setContentModel(model, {
mergingCallback: (fragment, _, entityPairs) => {
preprocessEntitiesFromContentModel(entityPairs);
doNotReuseEntityDom: true,
mergingCallback: fragment => {
editor.replaceNode(table, fragment);
},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { createSelectionMarker } from '../../modelApi/creators/createSelectionMa
import { createTableStructure } from '../../modelApi/table/createTableStructure';
import { IExperimentalContentModelEditor } from '../../publicTypes/IExperimentalContentModelEditor';
import { normalizeTable } from '../../modelApi/table/normalizeTable';
import { preprocessEntitiesFromContentModel } from '../mergeFragmentWithEntity';
import { TableMetadataFormat } from '../../publicTypes/format/formatParts/TableMetadataFormat';

/**
Expand Down Expand Up @@ -38,8 +37,8 @@ export default function insertTable(
editor.addUndoSnapshot(
() => {
editor.setContentModel(doc, {
mergingCallback: (fragment, _, entityPairs) => {
preprocessEntitiesFromContentModel(entityPairs);
doNotReuseEntityDom: true,
mergingCallback: fragment => {
editor.insertNode(fragment);
},
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ChangeSource } from 'roosterjs-editor-types';
import { IExperimentalContentModelEditor } from '../../publicTypes/IExperimentalContentModelEditor';
import { normalizeTable } from '../../modelApi/table/normalizeTable';
import { preprocessEntitiesFromContentModel } from '../mergeFragmentWithEntity';
import { setTableCellBackgroundColor } from '../../modelApi/table/setTableCellBackgroundColor';

/**
Expand All @@ -22,8 +21,8 @@ export default function setTableCellShade(editor: IExperimentalContentModelEdito
editor.focus();
if (model && table) {
editor.setContentModel(model, {
mergingCallback: (fragment, _, entityPairs) => {
preprocessEntitiesFromContentModel(entityPairs);
doNotReuseEntityDom: true,
mergingCallback: fragment => {
editor.replaceNode(table, fragment);
},
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { ContentModelDocument } from './group/ContentModelDocument';
import { EditorContext } from './context/EditorContext';
import { EntityPlaceholderPair } from './context/ModelToDomEntityContext';
import { IEditor, SelectionRangeEx } from 'roosterjs-editor-types';
import {
ContentModelHandlerMap,
Expand Down Expand Up @@ -65,14 +64,19 @@ export interface ModelToDomOption {
* A callback to specify how to merge DOM tree generated from Content Model in to existing container
* @param source Source document fragment that is generated from Content Model
* @param target Target container, usually to be editor root container
* @param entityPairs An array of entity wrapper - placeholder pairs, used for reuse existing DOM structure for entity
* @param entities An array of entity wrapper - placeholder pairs, used for reuse existing DOM structure for entity
*/
mergingCallback?: (
source: DocumentFragment,
target: HTMLElement,
entityPairs: EntityPlaceholderPair[]
entities: Record<string, HTMLElement>
) => void;

/**
* When set to true, directly put entity DOM nodes into the result DOM tree when doing Content Model to DOM conversion and do not use placeholder
*/
doNotReuseEntityDom?: boolean;

/**
* Overrides default format appliers
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
/**
* Represent an object pair of Entity DOM node and placeholder comment node
* Represents context for entity
*/
export interface EntityPlaceholderPair {
export interface ModelToDomEntityContext {
/**
* Wrapper element of element
* When set to true, directly put entity DOM nodes into the result DOM tree when doing Content Model to DOM conversion and do not use placeholder
*/
entityWrapper: HTMLElement;
doNotReuseEntityDom: boolean;

/**
* Placeholder comment node
* Entities collected during DOM tree generation, used for reusing existing DOM structure of entities
*/
placeholder: Comment;
}

/**
* Represents context for entity
*/
export interface ModelToDomEntityContext {
entityPairs: EntityPlaceholderPair[];
entities: Record<string, HTMLElement>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ describe('createModelToDomContext', () => {
formatAppliers: getFormatAppliers(),
modelHandlers: defaultContentModelHandlers,
defaultImplicitSegmentFormatMap: defaultImplicitSegmentFormatMap,
entityPairs: [],
entities: {},
defaultModelHandlers: defaultContentModelHandlers,
defaultFormatAppliers: defaultFormatAppliers,
doNotReuseEntityDom: false,
};
it('no param', () => {
const context = createModelToDomContext();
Expand Down Expand Up @@ -96,7 +97,7 @@ describe('createModelToDomContext', () => {
]);
expect(context.modelHandlers.br).toBe(mockedBrHandler);
expect(context.defaultImplicitSegmentFormatMap.a).toEqual(mockedAStyle);
expect(context.entityPairs).toEqual([]);
expect(context.entities).toEqual({});
expect(context.defaultModelHandlers).toEqual(defaultContentModelHandlers);
expect(context.defaultFormatAppliers).toEqual(defaultFormatAppliers);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,10 @@ describe('handleEntity', () => {

handleEntity(document, parent, entityModel, context);

expect(parent.innerHTML).toBe('<!--Entity:entity_1-->');
expect(context.entityPairs).toEqual([
{
entityWrapper: div,
placeholder: parent.firstChild as Comment,
},
]);
expect(parent.innerHTML).toBe('<entity-placeholder id="entity_1"></entity-placeholder>');
expect(context.entities).toEqual({
entity_1: div,
});
expect(div.outerHTML).toBe(
'<div class="_Entity _EType_entity _EId_entity_1 _EReadonly_1" contenteditable="false"></div>'
);
Expand Down
Loading