From c4f3b130127fe699546cccc715fa0ca6ae393ef1 Mon Sep 17 00:00:00 2001 From: Jiuqing Song Date: Thu, 9 Nov 2023 14:30:00 -0800 Subject: [PATCH] Move core API to roosterjs-content-model-core package (#2198) * Move ContentModelEdit plugin to plugins package * Move types to roosterjs-content-model-types package * improve * Improve * improve * Improve * improve * Move core API to core package * fix build * improve * fix build * fix build --- .../model/ContentModelImageView.tsx | 2 +- .../model/ContentModelListLevelView.tsx | 2 +- .../model/ContentModelTableCellView.tsx | 3 +- .../model/ContentModelTableView.tsx | 3 +- demo/scripts/tsconfig.json | 6 + .../lib/constants}/ChangeSource.ts | 0 .../lib}/coreApi/createContentModel.ts | 2 +- .../lib}/coreApi/createEditorContext.ts | 0 .../lib}/coreApi/formatContentModel.ts | 2 +- .../lib}/coreApi/getDOMSelection.ts | 0 .../lib}/coreApi/setContentModel.ts | 0 .../lib}/coreApi/setDOMSelection.ts | 0 .../lib}/coreApi/switchShadowEdit.ts | 11 +- .../editor/promoteToContentModelEditorCore.ts | 87 ++++ .../roosterjs-content-model-core/lib/index.ts | 15 + .../lib}/metadata/definitionCreators.ts | 0 .../lib}/metadata/updateImageMetadata.ts | 0 .../lib}/metadata/updateListMetadata.ts | 0 .../lib}/metadata/updateTableCellMetadata.ts | 0 .../lib}/metadata/updateTableMetadata.ts | 0 .../lib/override}/tablePreProcessor.ts | 2 +- .../lib/publicApi/model/cloneModel.ts | 0 .../selection/getSelectionRootNode.ts | 6 +- .../publicApi}/selection/iterateSelections.ts | 3 - .../roosterjs-content-model-core/package.json | 12 + .../test}/coreApi/createContentModelTest.ts | 11 +- .../test}/coreApi/createEditorContextTest.ts | 17 +- .../test}/coreApi/formatContentModelTest.ts | 24 +- .../test}/coreApi/setContentModelTest.ts | 9 +- .../test}/coreApi/switchShadowEditTest.ts | 16 +- .../promoteToContentModelEditorCoreTest.ts | 180 +++++++++ .../handleListItemWithMetadataTest.ts | 2 +- .../metadata/handleListWithMetadataTest.ts | 2 +- .../test}/metadata/updateImageMetadataTest.ts | 2 +- .../test}/metadata/updateListMetadataTest.ts | 2 +- .../metadata/updateTableCellMetadataTest.ts | 2 +- .../test}/metadata/updateTableMetadataTest.ts | 2 +- .../test}/overrides/tablePreProcessorTest.ts | 2 +- .../test/publicApi/model/cloneModelTest.ts | 0 .../selection/getSelectionRootNodeTest.ts | 41 ++ .../selection/iterateSelectionsTest.ts | 2 +- .../ContentModelCopyPastePlugin.ts | 13 +- .../editor/createContentModelEditorCore.ts | 94 +---- .../lib/index.ts | 11 +- .../lib/modelApi/common/clearModelFormat.ts | 8 +- .../common/retrieveModelFormatState.ts | 3 +- .../edit/utils/deleteExpandedSelection.ts | 4 +- .../lib/modelApi/format/applyPendingFormat.ts | 2 +- .../modelApi/selection/adjustWordSelection.ts | 2 +- .../modelApi/selection/collectSelections.ts | 4 +- .../lib/modelApi/table/alignTableCell.ts | 2 +- .../lib/modelApi/table/applyTableFormat.ts | 3 +- .../table/setTableCellBackgroundColor.ts | 2 +- .../lib/publicApi/entity/insertEntity.ts | 2 +- .../lib/publicApi/format/getFormatState.ts | 2 +- .../lib/publicApi/image/changeImage.ts | 2 +- .../lib/publicApi/link/insertLink.ts | 2 +- .../lib/publicApi/list/setListStyle.ts | 2 +- .../publicApi/table/applyTableBorderFormat.ts | 2 +- .../lib/publicApi/table/formatTable.ts | 2 +- .../lib/publicApi/utils/paste.ts | 2 +- .../package.json | 1 + .../createContentModelEditorCoreTest.ts | 372 ++++-------------- .../ContentModelCopyPastePluginTest.ts | 4 +- .../common/retrieveModelFormatStateTest.ts | 2 +- .../modelApi/format/applyPendingFormatTest.ts | 2 +- .../selection/collectSelectionsTest.ts | 2 +- .../test/publicApi/entity/insertEntityTest.ts | 2 +- .../publicApi/format/getFormatStateTest.ts | 2 +- .../test/publicApi/link/insertLinkTest.ts | 2 +- .../selection/getSelectedSegmentsTest.ts | 2 +- .../lib/edit/keyboardDelete.ts | 3 +- .../package.json | 1 + .../test/edit/keyboardDeleteTest.ts | 3 +- .../test/paste/e2e/cmPasteFromWordTest.ts | 3 +- .../test/paste/e2e/testUtils.ts | 2 +- .../paste/processPastedContentFromWacTest.ts | 2 +- ...processPastedContentFromWordDesktopTest.ts | 2 +- .../lib/editor/StandaloneEditorCore.ts | 5 +- 79 files changed, 542 insertions(+), 504 deletions(-) rename packages-content-model/{roosterjs-content-model-editor/lib/publicTypes => roosterjs-content-model-core/lib/constants}/ChangeSource.ts (100%) rename packages-content-model/{roosterjs-content-model-editor/lib/editor => roosterjs-content-model-core/lib}/coreApi/createContentModel.ts (96%) rename packages-content-model/{roosterjs-content-model-editor/lib/editor => roosterjs-content-model-core/lib}/coreApi/createEditorContext.ts (100%) rename packages-content-model/{roosterjs-content-model-editor/lib/editor => roosterjs-content-model-core/lib}/coreApi/formatContentModel.ts (99%) rename packages-content-model/{roosterjs-content-model-editor/lib/editor => roosterjs-content-model-core/lib}/coreApi/getDOMSelection.ts (100%) rename packages-content-model/{roosterjs-content-model-editor/lib/editor => roosterjs-content-model-core/lib}/coreApi/setContentModel.ts (100%) rename packages-content-model/{roosterjs-content-model-editor/lib/editor => roosterjs-content-model-core/lib}/coreApi/setDOMSelection.ts (100%) rename packages-content-model/{roosterjs-content-model-editor/lib/editor => roosterjs-content-model-core/lib}/coreApi/switchShadowEdit.ts (86%) create mode 100644 packages-content-model/roosterjs-content-model-core/lib/editor/promoteToContentModelEditorCore.ts create mode 100644 packages-content-model/roosterjs-content-model-core/lib/index.ts rename packages-content-model/{roosterjs-content-model-editor/lib/domUtils => roosterjs-content-model-core/lib}/metadata/definitionCreators.ts (100%) rename packages-content-model/{roosterjs-content-model-editor/lib/domUtils => roosterjs-content-model-core/lib}/metadata/updateImageMetadata.ts (100%) rename packages-content-model/{roosterjs-content-model-editor/lib/domUtils => roosterjs-content-model-core/lib}/metadata/updateListMetadata.ts (100%) rename packages-content-model/{roosterjs-content-model-editor/lib/domUtils => roosterjs-content-model-core/lib}/metadata/updateTableCellMetadata.ts (100%) rename packages-content-model/{roosterjs-content-model-editor/lib/domUtils => roosterjs-content-model-core/lib}/metadata/updateTableMetadata.ts (100%) rename packages-content-model/{roosterjs-content-model-editor/lib/editor/overrides => roosterjs-content-model-core/lib/override}/tablePreProcessor.ts (92%) rename packages-content-model/{roosterjs-content-model-editor => roosterjs-content-model-core}/lib/publicApi/model/cloneModel.ts (100%) rename packages-content-model/{roosterjs-content-model-editor/lib/modelApi => roosterjs-content-model-core/lib/publicApi}/selection/getSelectionRootNode.ts (59%) rename packages-content-model/{roosterjs-content-model-editor/lib/modelApi => roosterjs-content-model-core/lib/publicApi}/selection/iterateSelections.ts (99%) create mode 100644 packages-content-model/roosterjs-content-model-core/package.json rename packages-content-model/{roosterjs-content-model-editor/test/editor => roosterjs-content-model-core/test}/coreApi/createContentModelTest.ts (94%) rename packages-content-model/{roosterjs-content-model-editor/test/editor => roosterjs-content-model-core/test}/coreApi/createEditorContextTest.ts (92%) rename packages-content-model/{roosterjs-content-model-editor/test/editor => roosterjs-content-model-core/test}/coreApi/formatContentModelTest.ts (97%) rename packages-content-model/{roosterjs-content-model-editor/test/editor => roosterjs-content-model-core/test}/coreApi/setContentModelTest.ts (93%) rename packages-content-model/{roosterjs-content-model-editor/test/editor => roosterjs-content-model-core/test}/coreApi/switchShadowEditTest.ts (90%) create mode 100644 packages-content-model/roosterjs-content-model-core/test/editor/promoteToContentModelEditorCoreTest.ts rename packages-content-model/{roosterjs-content-model-editor/test/domUtils => roosterjs-content-model-core/test}/metadata/handleListItemWithMetadataTest.ts (99%) rename packages-content-model/{roosterjs-content-model-editor/test/domUtils => roosterjs-content-model-core/test}/metadata/handleListWithMetadataTest.ts (99%) rename packages-content-model/{roosterjs-content-model-editor/test/domUtils => roosterjs-content-model-core/test}/metadata/updateImageMetadataTest.ts (98%) rename packages-content-model/{roosterjs-content-model-editor/test/domUtils => roosterjs-content-model-core/test}/metadata/updateListMetadataTest.ts (99%) rename packages-content-model/{roosterjs-content-model-editor/test/domUtils => roosterjs-content-model-core/test}/metadata/updateTableCellMetadataTest.ts (98%) rename packages-content-model/{roosterjs-content-model-editor/test/domUtils => roosterjs-content-model-core/test}/metadata/updateTableMetadataTest.ts (98%) rename packages-content-model/{roosterjs-content-model-editor/test/editor => roosterjs-content-model-core/test}/overrides/tablePreProcessorTest.ts (98%) rename packages-content-model/{roosterjs-content-model-editor => roosterjs-content-model-core}/test/publicApi/model/cloneModelTest.ts (100%) create mode 100644 packages-content-model/roosterjs-content-model-core/test/publicApi/selection/getSelectionRootNodeTest.ts rename packages-content-model/{roosterjs-content-model-editor/test/modelApi => roosterjs-content-model-core/test/publicApi}/selection/iterateSelectionsTest.ts (99%) diff --git a/demo/scripts/controls/contentModel/components/model/ContentModelImageView.tsx b/demo/scripts/controls/contentModel/components/model/ContentModelImageView.tsx index 948a6390a1a..4d2db4664d1 100644 --- a/demo/scripts/controls/contentModel/components/model/ContentModelImageView.tsx +++ b/demo/scripts/controls/contentModel/components/model/ContentModelImageView.tsx @@ -13,7 +13,7 @@ import { MetadataView } from '../format/MetadataView'; import { PaddingFormatRenderer } from '../format/formatPart/PaddingFormatRenderer'; import { SegmentFormatView } from '../format/SegmentFormatView'; import { SizeFormatRenderers } from '../format/formatPart/SizeFormatRenderers'; -import { updateImageMetadata } from 'roosterjs-content-model-editor'; +import { updateImageMetadata } from 'roosterjs-content-model-core'; import { useProperty } from '../../hooks/useProperty'; const styles = require('./ContentModelImageView.scss'); diff --git a/demo/scripts/controls/contentModel/components/model/ContentModelListLevelView.tsx b/demo/scripts/controls/contentModel/components/model/ContentModelListLevelView.tsx index 96f9eb7f9db..e0c3523979a 100644 --- a/demo/scripts/controls/contentModel/components/model/ContentModelListLevelView.tsx +++ b/demo/scripts/controls/contentModel/components/model/ContentModelListLevelView.tsx @@ -10,7 +10,7 @@ import { MarginFormatRenderer } from '../format/formatPart/MarginFormatRenderer' import { MetadataView } from '../format/MetadataView'; import { PaddingFormatRenderer } from '../format/formatPart/PaddingFormatRenderer'; import { TextAlignFormatRenderer } from '../format/formatPart/TextAlignFormatRenderer'; -import { updateListMetadata } from 'roosterjs-content-model-editor'; +import { updateListMetadata } from 'roosterjs-content-model-core'; import { useProperty } from '../../hooks/useProperty'; import { ContentModelListItemLevelFormat, diff --git a/demo/scripts/controls/contentModel/components/model/ContentModelTableCellView.tsx b/demo/scripts/controls/contentModel/components/model/ContentModelTableCellView.tsx index c620b954528..f0a3ca81e4b 100644 --- a/demo/scripts/controls/contentModel/components/model/ContentModelTableCellView.tsx +++ b/demo/scripts/controls/contentModel/components/model/ContentModelTableCellView.tsx @@ -8,7 +8,7 @@ import { ContentModelView } from '../ContentModelView'; import { DirectionFormatRenderer } from '../format/formatPart/DirectionFormatRenderer'; import { FormatRenderer } from '../format/utils/FormatRenderer'; import { FormatView } from '../format/FormatView'; -import { hasSelectionInBlockGroup, updateTableCellMetadata } from 'roosterjs-content-model-editor'; +import { hasSelectionInBlockGroup } from 'roosterjs-content-model-editor'; import { HtmlAlignFormatRenderer } from '../format/formatPart/HtmlAlignFormatRenderer'; import { MetadataView } from '../format/MetadataView'; import { PaddingFormatRenderer } from '../format/formatPart/PaddingFormatRenderer'; @@ -16,6 +16,7 @@ import { SizeFormatRenderers } from '../format/formatPart/SizeFormatRenderers'; import { TableCellMetadataFormatRenders } from '../format/formatPart/TableCellMetadataFormatRenders'; import { TextAlignFormatRenderer } from '../format/formatPart/TextAlignFormatRenderer'; import { TextColorFormatRenderer } from '../format/formatPart/TextColorFormatRenderer'; +import { updateTableCellMetadata } from 'roosterjs-content-model-core'; import { useProperty } from '../../hooks/useProperty'; import { VerticalAlignFormatRenderer } from '../format/formatPart/VerticalAlignFormatRenderer'; import { WordBreakFormatRenderer } from '../format/formatPart/WordBreakFormatRenderer'; diff --git a/demo/scripts/controls/contentModel/components/model/ContentModelTableView.tsx b/demo/scripts/controls/contentModel/components/model/ContentModelTableView.tsx index bbee53af187..acd847ac78d 100644 --- a/demo/scripts/controls/contentModel/components/model/ContentModelTableView.tsx +++ b/demo/scripts/controls/contentModel/components/model/ContentModelTableView.tsx @@ -8,13 +8,14 @@ import { ContentModelView } from '../ContentModelView'; import { DisplayFormatRenderer } from '../format/formatPart/DisplayFormatRenderer'; import { FormatRenderer } from '../format/utils/FormatRenderer'; import { FormatView } from '../format/FormatView'; -import { hasSelectionInBlock, updateTableMetadata } from 'roosterjs-content-model-editor'; +import { hasSelectionInBlock } from 'roosterjs-content-model-editor'; import { IdFormatRenderer } from '../format/formatPart/IdFormatRenderer'; import { MarginFormatRenderer } from '../format/formatPart/MarginFormatRenderer'; import { MetadataView } from '../format/MetadataView'; import { SpacingFormatRenderer } from '../format/formatPart/SpacingFormatRenderer'; import { TableLayoutFormatRenderer } from '../format/formatPart/TableLayoutFormatRenderer'; import { TableMetadataFormatRenders } from '../format/formatPart/TableMetadataFormatRenders'; +import { updateTableMetadata } from 'roosterjs-content-model-core'; import { useProperty } from '../../hooks/useProperty'; const styles = require('./ContentModelTableView.scss'); diff --git a/demo/scripts/tsconfig.json b/demo/scripts/tsconfig.json index c964dda11ff..349e0655b2a 100644 --- a/demo/scripts/tsconfig.json +++ b/demo/scripts/tsconfig.json @@ -37,6 +37,12 @@ "roosterjs-content-model-dom/lib/*": [ "packages-content-model/roosterjs-content-model-dom/lib/*" ], + "roosterjs-content-model-core": [ + "packages-content-model/roosterjs-content-model-core/lib/index" + ], + "roosterjs-content-model-core/lib/*": [ + "packages-content-model/roosterjs-content-model-core/lib/*" + ], "roosterjs-content-model-editor": [ "packages-content-model/roosterjs-content-model-editor/lib/index" ], diff --git a/packages-content-model/roosterjs-content-model-editor/lib/publicTypes/ChangeSource.ts b/packages-content-model/roosterjs-content-model-core/lib/constants/ChangeSource.ts similarity index 100% rename from packages-content-model/roosterjs-content-model-editor/lib/publicTypes/ChangeSource.ts rename to packages-content-model/roosterjs-content-model-core/lib/constants/ChangeSource.ts diff --git a/packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/createContentModel.ts b/packages-content-model/roosterjs-content-model-core/lib/coreApi/createContentModel.ts similarity index 96% rename from packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/createContentModel.ts rename to packages-content-model/roosterjs-content-model-core/lib/coreApi/createContentModel.ts index 72d1810a9a5..a4428a172ac 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/createContentModel.ts +++ b/packages-content-model/roosterjs-content-model-core/lib/coreApi/createContentModel.ts @@ -1,4 +1,4 @@ -import { cloneModel } from '../../publicApi/model/cloneModel'; +import { cloneModel } from '../publicApi/model/cloneModel'; import { createDomToModelContext, createDomToModelContextWithConfig, diff --git a/packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/createEditorContext.ts b/packages-content-model/roosterjs-content-model-core/lib/coreApi/createEditorContext.ts similarity index 100% rename from packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/createEditorContext.ts rename to packages-content-model/roosterjs-content-model-core/lib/coreApi/createEditorContext.ts diff --git a/packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/formatContentModel.ts b/packages-content-model/roosterjs-content-model-core/lib/coreApi/formatContentModel.ts similarity index 99% rename from packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/formatContentModel.ts rename to packages-content-model/roosterjs-content-model-core/lib/coreApi/formatContentModel.ts index 159105c5c81..86e3365d913 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/formatContentModel.ts +++ b/packages-content-model/roosterjs-content-model-core/lib/coreApi/formatContentModel.ts @@ -1,4 +1,4 @@ -import { ChangeSource } from '../../publicTypes/ChangeSource'; +import { ChangeSource } from '../constants/ChangeSource'; import { ColorTransformDirection, EntityOperation, PluginEventType } from 'roosterjs-editor-types'; import type { EditorCore, Entity } from 'roosterjs-editor-types'; import type { diff --git a/packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/getDOMSelection.ts b/packages-content-model/roosterjs-content-model-core/lib/coreApi/getDOMSelection.ts similarity index 100% rename from packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/getDOMSelection.ts rename to packages-content-model/roosterjs-content-model-core/lib/coreApi/getDOMSelection.ts diff --git a/packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/setContentModel.ts b/packages-content-model/roosterjs-content-model-core/lib/coreApi/setContentModel.ts similarity index 100% rename from packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/setContentModel.ts rename to packages-content-model/roosterjs-content-model-core/lib/coreApi/setContentModel.ts diff --git a/packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/setDOMSelection.ts b/packages-content-model/roosterjs-content-model-core/lib/coreApi/setDOMSelection.ts similarity index 100% rename from packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/setDOMSelection.ts rename to packages-content-model/roosterjs-content-model-core/lib/coreApi/setDOMSelection.ts diff --git a/packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/switchShadowEdit.ts b/packages-content-model/roosterjs-content-model-core/lib/coreApi/switchShadowEdit.ts similarity index 86% rename from packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/switchShadowEdit.ts rename to packages-content-model/roosterjs-content-model-core/lib/coreApi/switchShadowEdit.ts index 0da88bb18e3..42329e710a2 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/switchShadowEdit.ts +++ b/packages-content-model/roosterjs-content-model-core/lib/coreApi/switchShadowEdit.ts @@ -1,8 +1,7 @@ -import { getSelectionPath } from 'roosterjs-editor-dom'; -import { iterateSelections } from '../../modelApi/selection/iterateSelections'; +import { iterateSelections } from '../publicApi/selection/iterateSelections'; import { PluginEventType } from 'roosterjs-editor-types'; import type { StandaloneEditorCore } from 'roosterjs-content-model-types'; -import type { EditorCore, SwitchShadowEdit } from 'roosterjs-editor-types'; +import type { EditorCore, SelectionPath, SwitchShadowEdit } from 'roosterjs-editor-types'; /** * @internal @@ -17,12 +16,14 @@ export const switchShadowEdit: SwitchShadowEdit = (editorCore, isOn): void => { if (isOn != !!core.lifecycle.shadowEditFragment) { if (isOn) { const model = !core.cache.cachedModel ? core.api.createContentModel(core) : null; - const range = core.api.getSelectionRange(core, true /*tryGetFromCache*/); // Fake object, not used in Content Model Editor, just to satisfy original editor code // TODO: we can remove them once we have standalone Content Model Editor const fragment = core.contentDiv.ownerDocument.createDocumentFragment(); - const selectionPath = range && getSelectionPath(core.contentDiv, range); + const selectionPath: SelectionPath = { + start: [], + end: [], + }; core.api.triggerEvent( core, diff --git a/packages-content-model/roosterjs-content-model-core/lib/editor/promoteToContentModelEditorCore.ts b/packages-content-model/roosterjs-content-model-core/lib/editor/promoteToContentModelEditorCore.ts new file mode 100644 index 00000000000..99902794182 --- /dev/null +++ b/packages-content-model/roosterjs-content-model-core/lib/editor/promoteToContentModelEditorCore.ts @@ -0,0 +1,87 @@ +import { createContentModel } from '../coreApi/createContentModel'; +import { createDomToModelConfig, createModelToDomConfig } from 'roosterjs-content-model-dom'; +import { createEditorContext } from '../coreApi/createEditorContext'; +import { formatContentModel } from '../coreApi/formatContentModel'; +import { getDOMSelection } from '../coreApi/getDOMSelection'; +import { listItemMetadataApplier, listLevelMetadataApplier } from '../metadata/updateListMetadata'; +import { setContentModel } from '../coreApi/setContentModel'; +import { setDOMSelection } from '../coreApi/setDOMSelection'; +import { switchShadowEdit } from '../coreApi/switchShadowEdit'; +import { tablePreProcessor } from '../override/tablePreProcessor'; +import type { + ContentModelPluginState, + StandaloneEditorCore, + StandaloneEditorOptions, +} from 'roosterjs-content-model-types'; +import type { EditorCore, EditorOptions } from 'roosterjs-editor-types'; + +/** + * Creator Content Model Editor Core from Editor Core + * @param core The original EditorCore object + * @param options Options of this editor + */ +export function promoteToContentModelEditorCore( + core: EditorCore, + options: EditorOptions & StandaloneEditorOptions, + pluginState: ContentModelPluginState +) { + const cmCore = core as EditorCore & StandaloneEditorCore; + + promoteCorePluginState(cmCore, pluginState); + promoteContentModelInfo(cmCore, options); + promoteCoreApi(cmCore); + promoteEnvironment(cmCore); +} + +function promoteCorePluginState( + cmCore: StandaloneEditorCore, + pluginState: ContentModelPluginState +) { + Object.assign(cmCore, pluginState); +} + +function promoteContentModelInfo(cmCore: StandaloneEditorCore, options: StandaloneEditorOptions) { + cmCore.defaultDomToModelOptions = [ + { + processorOverride: { + table: tablePreProcessor, + }, + }, + options.defaultDomToModelOptions, + ]; + cmCore.defaultModelToDomOptions = [ + { + metadataAppliers: { + listItem: listItemMetadataApplier, + listLevel: listLevelMetadataApplier, + }, + }, + options.defaultModelToDomOptions, + ]; + cmCore.defaultDomToModelConfig = createDomToModelConfig(cmCore.defaultDomToModelOptions); + cmCore.defaultModelToDomConfig = createModelToDomConfig(cmCore.defaultModelToDomOptions); +} + +function promoteCoreApi(cmCore: StandaloneEditorCore) { + cmCore.api.createEditorContext = createEditorContext; + cmCore.api.createContentModel = createContentModel; + cmCore.api.setContentModel = setContentModel; + cmCore.api.switchShadowEdit = switchShadowEdit; + cmCore.api.getDOMSelection = getDOMSelection; + cmCore.api.setDOMSelection = setDOMSelection; + cmCore.api.formatContentModel = formatContentModel; + cmCore.originalApi.createEditorContext = createEditorContext; + cmCore.originalApi.createContentModel = createContentModel; + cmCore.originalApi.setContentModel = setContentModel; + cmCore.originalApi.getDOMSelection = getDOMSelection; + cmCore.originalApi.setDOMSelection = setDOMSelection; + cmCore.originalApi.formatContentModel = formatContentModel; +} + +function promoteEnvironment(cmCore: StandaloneEditorCore) { + cmCore.environment = {}; + + // It is ok to use global window here since the environment should always be the same for all windows in one session + cmCore.environment.isMac = window.navigator.appVersion.indexOf('Mac') != -1; + cmCore.environment.isAndroid = /android/i.test(window.navigator.userAgent); +} diff --git a/packages-content-model/roosterjs-content-model-core/lib/index.ts b/packages-content-model/roosterjs-content-model-core/lib/index.ts new file mode 100644 index 00000000000..16ec47baf8c --- /dev/null +++ b/packages-content-model/roosterjs-content-model-core/lib/index.ts @@ -0,0 +1,15 @@ +export { CachedElementHandler, CloneModelOptions, cloneModel } from './publicApi/model/cloneModel'; +export { + iterateSelections, + IterateSelectionsCallback, + IterateSelectionsOption, +} from './publicApi/selection/iterateSelections'; +export { getSelectionRootNode } from './publicApi/selection/getSelectionRootNode'; + +export { updateImageMetadata } from './metadata/updateImageMetadata'; +export { updateTableCellMetadata } from './metadata/updateTableCellMetadata'; +export { updateTableMetadata } from './metadata/updateTableMetadata'; +export { updateListMetadata } from './metadata/updateListMetadata'; + +export { promoteToContentModelEditorCore } from './editor/promoteToContentModelEditorCore'; +export { ChangeSource } from './constants/ChangeSource'; diff --git a/packages-content-model/roosterjs-content-model-editor/lib/domUtils/metadata/definitionCreators.ts b/packages-content-model/roosterjs-content-model-core/lib/metadata/definitionCreators.ts similarity index 100% rename from packages-content-model/roosterjs-content-model-editor/lib/domUtils/metadata/definitionCreators.ts rename to packages-content-model/roosterjs-content-model-core/lib/metadata/definitionCreators.ts diff --git a/packages-content-model/roosterjs-content-model-editor/lib/domUtils/metadata/updateImageMetadata.ts b/packages-content-model/roosterjs-content-model-core/lib/metadata/updateImageMetadata.ts similarity index 100% rename from packages-content-model/roosterjs-content-model-editor/lib/domUtils/metadata/updateImageMetadata.ts rename to packages-content-model/roosterjs-content-model-core/lib/metadata/updateImageMetadata.ts diff --git a/packages-content-model/roosterjs-content-model-editor/lib/domUtils/metadata/updateListMetadata.ts b/packages-content-model/roosterjs-content-model-core/lib/metadata/updateListMetadata.ts similarity index 100% rename from packages-content-model/roosterjs-content-model-editor/lib/domUtils/metadata/updateListMetadata.ts rename to packages-content-model/roosterjs-content-model-core/lib/metadata/updateListMetadata.ts diff --git a/packages-content-model/roosterjs-content-model-editor/lib/domUtils/metadata/updateTableCellMetadata.ts b/packages-content-model/roosterjs-content-model-core/lib/metadata/updateTableCellMetadata.ts similarity index 100% rename from packages-content-model/roosterjs-content-model-editor/lib/domUtils/metadata/updateTableCellMetadata.ts rename to packages-content-model/roosterjs-content-model-core/lib/metadata/updateTableCellMetadata.ts diff --git a/packages-content-model/roosterjs-content-model-editor/lib/domUtils/metadata/updateTableMetadata.ts b/packages-content-model/roosterjs-content-model-core/lib/metadata/updateTableMetadata.ts similarity index 100% rename from packages-content-model/roosterjs-content-model-editor/lib/domUtils/metadata/updateTableMetadata.ts rename to packages-content-model/roosterjs-content-model-core/lib/metadata/updateTableMetadata.ts diff --git a/packages-content-model/roosterjs-content-model-editor/lib/editor/overrides/tablePreProcessor.ts b/packages-content-model/roosterjs-content-model-core/lib/override/tablePreProcessor.ts similarity index 92% rename from packages-content-model/roosterjs-content-model-editor/lib/editor/overrides/tablePreProcessor.ts rename to packages-content-model/roosterjs-content-model-core/lib/override/tablePreProcessor.ts index 08c09a384d4..3122c2d84fb 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/editor/overrides/tablePreProcessor.ts +++ b/packages-content-model/roosterjs-content-model-core/lib/override/tablePreProcessor.ts @@ -1,5 +1,5 @@ import { entityProcessor, hasMetadata, tableProcessor } from 'roosterjs-content-model-dom'; -import { getSelectionRootNode } from '../../modelApi/selection/getSelectionRootNode'; +import { getSelectionRootNode } from '../publicApi/selection/getSelectionRootNode'; import type { DomToModelContext, ElementProcessor } from 'roosterjs-content-model-types'; /** diff --git a/packages-content-model/roosterjs-content-model-editor/lib/publicApi/model/cloneModel.ts b/packages-content-model/roosterjs-content-model-core/lib/publicApi/model/cloneModel.ts similarity index 100% rename from packages-content-model/roosterjs-content-model-editor/lib/publicApi/model/cloneModel.ts rename to packages-content-model/roosterjs-content-model-core/lib/publicApi/model/cloneModel.ts diff --git a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/selection/getSelectionRootNode.ts b/packages-content-model/roosterjs-content-model-core/lib/publicApi/selection/getSelectionRootNode.ts similarity index 59% rename from packages-content-model/roosterjs-content-model-editor/lib/modelApi/selection/getSelectionRootNode.ts rename to packages-content-model/roosterjs-content-model-core/lib/publicApi/selection/getSelectionRootNode.ts index bc7115d0006..185edb6164f 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/selection/getSelectionRootNode.ts +++ b/packages-content-model/roosterjs-content-model-core/lib/publicApi/selection/getSelectionRootNode.ts @@ -1,7 +1,11 @@ import type { DOMSelection } from 'roosterjs-content-model-types'; /** - * @internal + * Get root node of a given DOM selection + * For table selection, root node is the selected table + * For image selection, root node is the selected image + * For range selection, root node is the common ancestor container node of the selection range + * @param selection The selection to get root node from */ export function getSelectionRootNode(selection: DOMSelection | undefined): Node | undefined { return !selection diff --git a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/selection/iterateSelections.ts b/packages-content-model/roosterjs-content-model-core/lib/publicApi/selection/iterateSelections.ts similarity index 99% rename from packages-content-model/roosterjs-content-model-editor/lib/modelApi/selection/iterateSelections.ts rename to packages-content-model/roosterjs-content-model-core/lib/publicApi/selection/iterateSelections.ts index 0f76fda08b0..33f39d2a987 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/selection/iterateSelections.ts +++ b/packages-content-model/roosterjs-content-model-core/lib/publicApi/selection/iterateSelections.ts @@ -7,7 +7,6 @@ import type { } from 'roosterjs-content-model-types'; /** - * @internal * Options for iterateSelections API */ export interface IterateSelectionsOption { @@ -42,7 +41,6 @@ export interface IterateSelectionsOption { } /** - * @internal * The callback function type for iterateSelections * @param path The block group path of current selection * @param tableContext Table context of current selection @@ -58,7 +56,6 @@ export type IterateSelectionsCallback = ( ) => void | boolean; /** - * @internal * Iterate all selected elements in a given model * @param group The given Content Model to iterate selection from * @param callback The callback function to access the selected element diff --git a/packages-content-model/roosterjs-content-model-core/package.json b/packages-content-model/roosterjs-content-model-core/package.json new file mode 100644 index 00000000000..ed1e640d214 --- /dev/null +++ b/packages-content-model/roosterjs-content-model-core/package.json @@ -0,0 +1,12 @@ +{ + "name": "roosterjs-content-model-core", + "description": "Content Model for roosterjs (Under development)", + "dependencies": { + "tslib": "^2.3.1", + "roosterjs-editor-types": "", + "roosterjs-content-model-dom": "", + "roosterjs-content-model-types": "" + }, + "version": "0.0.0", + "main": "./lib/index.ts" +} diff --git a/packages-content-model/roosterjs-content-model-editor/test/editor/coreApi/createContentModelTest.ts b/packages-content-model/roosterjs-content-model-core/test/coreApi/createContentModelTest.ts similarity index 94% rename from packages-content-model/roosterjs-content-model-editor/test/editor/coreApi/createContentModelTest.ts rename to packages-content-model/roosterjs-content-model-core/test/coreApi/createContentModelTest.ts index 8fc09a36183..16e33c508a5 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/editor/coreApi/createContentModelTest.ts +++ b/packages-content-model/roosterjs-content-model-core/test/coreApi/createContentModelTest.ts @@ -1,8 +1,9 @@ -import * as cloneModel from '../../../lib/publicApi/model/cloneModel'; +import * as cloneModel from '../../lib/publicApi/model/cloneModel'; import * as createDomToModelContext from 'roosterjs-content-model-dom/lib/domToModel/context/createDomToModelContext'; import * as domToContentModel from 'roosterjs-content-model-dom/lib/domToModel/domToContentModel'; -import { ContentModelEditorCore } from '../../../lib/publicTypes/ContentModelEditorCore'; -import { createContentModel } from '../../../lib/editor/coreApi/createContentModel'; +import { createContentModel } from '../../lib/coreApi/createContentModel'; +import { EditorCore } from 'roosterjs-editor-types'; +import { StandaloneEditorCore } from 'roosterjs-content-model-types'; const mockedEditorContext = 'EDITORCONTEXT' as any; const mockedContext = 'CONTEXT' as any; @@ -12,7 +13,7 @@ const mockedCachedMode = 'CACHEDMODEL' as any; const mockedClonedModel = 'CLONEDMODEL' as any; describe('createContentModel', () => { - let core: ContentModelEditorCore; + let core: StandaloneEditorCore & EditorCore; let createEditorContext: jasmine.Spy; let getDOMSelection: jasmine.Spy; let domToContentModelSpy: jasmine.Spy; @@ -43,7 +44,7 @@ describe('createContentModel', () => { cachedModel: mockedCachedMode, }, lifecycle: {}, - } as any) as ContentModelEditorCore; + } as any) as StandaloneEditorCore & EditorCore; }); it('Reuse model, no cache, no shadow edit', () => { diff --git a/packages-content-model/roosterjs-content-model-editor/test/editor/coreApi/createEditorContextTest.ts b/packages-content-model/roosterjs-content-model-core/test/coreApi/createEditorContextTest.ts similarity index 92% rename from packages-content-model/roosterjs-content-model-editor/test/editor/coreApi/createEditorContextTest.ts rename to packages-content-model/roosterjs-content-model-core/test/coreApi/createEditorContextTest.ts index 6a4fbc1bfa7..f9fd8365aac 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/editor/coreApi/createEditorContextTest.ts +++ b/packages-content-model/roosterjs-content-model-core/test/coreApi/createEditorContextTest.ts @@ -1,5 +1,6 @@ -import { ContentModelEditorCore } from '../../../lib/publicTypes/ContentModelEditorCore'; -import { createEditorContext } from '../../../lib/editor/coreApi/createEditorContext'; +import { createEditorContext } from '../../lib/coreApi/createEditorContext'; +import { EditorCore } from 'roosterjs-editor-types'; +import { StandaloneEditorCore } from 'roosterjs-content-model-types'; describe('createEditorContext', () => { it('create a normal context', () => { @@ -28,7 +29,7 @@ describe('createEditorContext', () => { }, darkColorHandler, cache: {}, - } as any) as ContentModelEditorCore; + } as any) as StandaloneEditorCore & EditorCore; const context = createEditorContext(core); @@ -71,7 +72,7 @@ describe('createEditorContext', () => { cache: { domIndexer, }, - } as any) as ContentModelEditorCore; + } as any) as StandaloneEditorCore & EditorCore; const context = createEditorContext(core); @@ -87,7 +88,7 @@ describe('createEditorContext', () => { }); describe('createEditorContext - checkZoomScale', () => { - let core: ContentModelEditorCore; + let core: StandaloneEditorCore & EditorCore; let div: any; let getComputedStyleSpy: jasmine.Spy; let getBoundingClientRectSpy: jasmine.Spy; @@ -117,7 +118,7 @@ describe('createEditorContext - checkZoomScale', () => { }, darkColorHandler, cache: {}, - } as any) as ContentModelEditorCore; + } as any) as StandaloneEditorCore & EditorCore; }); it('Zoom scale = 1', () => { @@ -179,7 +180,7 @@ describe('createEditorContext - checkZoomScale', () => { }); describe('createEditorContext - checkRootDir', () => { - let core: ContentModelEditorCore; + let core: StandaloneEditorCore & EditorCore; let div: any; let getComputedStyleSpy: jasmine.Spy; let getBoundingClientRectSpy: jasmine.Spy; @@ -209,7 +210,7 @@ describe('createEditorContext - checkRootDir', () => { }, darkColorHandler, cache: {}, - } as any) as ContentModelEditorCore; + } as any) as StandaloneEditorCore & EditorCore; }); it('LTR CSS', () => { diff --git a/packages-content-model/roosterjs-content-model-editor/test/editor/coreApi/formatContentModelTest.ts b/packages-content-model/roosterjs-content-model-core/test/coreApi/formatContentModelTest.ts similarity index 97% rename from packages-content-model/roosterjs-content-model-editor/test/editor/coreApi/formatContentModelTest.ts rename to packages-content-model/roosterjs-content-model-core/test/coreApi/formatContentModelTest.ts index 7fcfbf2638a..b518e96e7e2 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/editor/coreApi/formatContentModelTest.ts +++ b/packages-content-model/roosterjs-content-model-core/test/coreApi/formatContentModelTest.ts @@ -1,12 +1,20 @@ -import { ChangeSource } from '../../../lib/publicTypes/ChangeSource'; -import { ColorTransformDirection, EntityOperation, PluginEventType } from 'roosterjs-editor-types'; -import { ContentModelDocument, ContentModelSegmentFormat } from 'roosterjs-content-model-types'; -import { ContentModelEditorCore } from '../../../lib/publicTypes/ContentModelEditorCore'; +import { ChangeSource } from '../../lib/constants/ChangeSource'; import { createImage } from 'roosterjs-content-model-dom'; -import { formatContentModel } from '../../../lib/editor/coreApi/formatContentModel'; +import { formatContentModel } from '../../lib/coreApi/formatContentModel'; +import { + ColorTransformDirection, + EditorCore, + EntityOperation, + PluginEventType, +} from 'roosterjs-editor-types'; +import { + ContentModelDocument, + ContentModelSegmentFormat, + StandaloneEditorCore, +} from 'roosterjs-content-model-types'; describe('formatContentModel', () => { - let core: ContentModelEditorCore; + let core: StandaloneEditorCore & EditorCore; let addUndoSnapshot: jasmine.Spy; let createContentModel: jasmine.Spy; let setContentModel: jasmine.Spy; @@ -48,7 +56,7 @@ describe('formatContentModel', () => { }, lifecycle: {}, cache: {}, - } as any) as ContentModelEditorCore; + } as any) as StandaloneEditorCore & EditorCore; }); it('Callback return false', () => { @@ -512,7 +520,7 @@ describe('formatContentModel', () => { }); }); - describe('Pending foramt', () => { + describe('Pending format', () => { const mockedStartContainer1 = 'CONTAINER1' as any; const mockedStartOffset1 = 'OFFSET1' as any; const mockedFormat1: ContentModelSegmentFormat = { fontSize: '10pt' }; diff --git a/packages-content-model/roosterjs-content-model-editor/test/editor/coreApi/setContentModelTest.ts b/packages-content-model/roosterjs-content-model-core/test/coreApi/setContentModelTest.ts similarity index 93% rename from packages-content-model/roosterjs-content-model-editor/test/editor/coreApi/setContentModelTest.ts rename to packages-content-model/roosterjs-content-model-core/test/coreApi/setContentModelTest.ts index c7d5198daef..f65e179a403 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/editor/coreApi/setContentModelTest.ts +++ b/packages-content-model/roosterjs-content-model-core/test/coreApi/setContentModelTest.ts @@ -1,7 +1,8 @@ import * as contentModelToDom from 'roosterjs-content-model-dom/lib/modelToDom/contentModelToDom'; import * as createModelToDomContext from 'roosterjs-content-model-dom/lib/modelToDom/context/createModelToDomContext'; -import { ContentModelEditorCore } from '../../../lib/publicTypes/ContentModelEditorCore'; -import { setContentModel } from '../../../lib/editor/coreApi/setContentModel'; +import { EditorCore } from 'roosterjs-editor-types'; +import { setContentModel } from '../../lib/coreApi/setContentModel'; +import { StandaloneEditorCore } from 'roosterjs-content-model-types'; const mockedRange = 'RANGE' as any; const mockedDoc = 'DOCUMENT' as any; @@ -12,7 +13,7 @@ const mockedDiv = { ownerDocument: mockedDoc } as any; const mockedConfig = 'CONFIG' as any; describe('setContentModel', () => { - let core: ContentModelEditorCore; + let core: StandaloneEditorCore & EditorCore; let contentModelToDomSpy: jasmine.Spy; let createEditorContext: jasmine.Spy; let createModelToDomContextSpy: jasmine.Spy; @@ -48,7 +49,7 @@ describe('setContentModel', () => { lifecycle: {}, defaultModelToDomConfig: mockedConfig, cache: {}, - } as any) as ContentModelEditorCore; + } as any) as StandaloneEditorCore & EditorCore; }); it('no default option, no shadow edit', () => { diff --git a/packages-content-model/roosterjs-content-model-editor/test/editor/coreApi/switchShadowEditTest.ts b/packages-content-model/roosterjs-content-model-core/test/coreApi/switchShadowEditTest.ts similarity index 90% rename from packages-content-model/roosterjs-content-model-editor/test/editor/coreApi/switchShadowEditTest.ts rename to packages-content-model/roosterjs-content-model-core/test/coreApi/switchShadowEditTest.ts index 4d679d7b833..effd9f25284 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/editor/coreApi/switchShadowEditTest.ts +++ b/packages-content-model/roosterjs-content-model-core/test/coreApi/switchShadowEditTest.ts @@ -1,13 +1,13 @@ -import * as iterateSelections from '../../../lib/modelApi/selection/iterateSelections'; -import { ContentModelEditorCore } from '../../../lib/publicTypes/ContentModelEditorCore'; -import { PluginEventType } from 'roosterjs-editor-types'; -import { switchShadowEdit } from '../../../lib/editor/coreApi/switchShadowEdit'; +import * as iterateSelections from '../../lib/publicApi/selection/iterateSelections'; +import { EditorCore, PluginEventType } from 'roosterjs-editor-types'; +import { StandaloneEditorCore } from 'roosterjs-content-model-types'; +import { switchShadowEdit } from '../../lib/coreApi/switchShadowEdit'; const mockedModel = 'MODEL' as any; const mockedCachedModel = 'CACHEMODEL' as any; describe('switchShadowEdit', () => { - let core: ContentModelEditorCore; + let core: StandaloneEditorCore & EditorCore; let createContentModel: jasmine.Spy; let setContentModel: jasmine.Spy; let getSelectionRange: jasmine.Spy; @@ -29,7 +29,7 @@ describe('switchShadowEdit', () => { lifecycle: {}, contentDiv: document.createElement('div'), cache: {}, - } as any) as ContentModelEditorCore; + } as any) as StandaloneEditorCore & EditorCore; }); describe('was off', () => { @@ -46,7 +46,7 @@ describe('switchShadowEdit', () => { { eventType: PluginEventType.EnteredShadowEdit, fragment: document.createDocumentFragment(), - selectionPath: undefined, + selectionPath: { start: [], end: [] }, }, false ); @@ -67,7 +67,7 @@ describe('switchShadowEdit', () => { { eventType: PluginEventType.EnteredShadowEdit, fragment: document.createDocumentFragment(), - selectionPath: undefined, + selectionPath: { start: [], end: [] }, }, false ); diff --git a/packages-content-model/roosterjs-content-model-core/test/editor/promoteToContentModelEditorCoreTest.ts b/packages-content-model/roosterjs-content-model-core/test/editor/promoteToContentModelEditorCoreTest.ts new file mode 100644 index 00000000000..3b9d35f8840 --- /dev/null +++ b/packages-content-model/roosterjs-content-model-core/test/editor/promoteToContentModelEditorCoreTest.ts @@ -0,0 +1,180 @@ +import * as createDomToModelContext from 'roosterjs-content-model-dom/lib/domToModel/context/createDomToModelContext'; +import * as createModelToDomContext from 'roosterjs-content-model-dom/lib/modelToDom/context/createModelToDomContext'; +import { ContentModelPluginState } from 'roosterjs-content-model-types'; +import { createContentModel } from '../../lib/coreApi/createContentModel'; +import { createEditorContext } from '../../lib/coreApi/createEditorContext'; +import { EditorCore } from 'roosterjs-editor-types'; +import { formatContentModel } from '../../lib/coreApi/formatContentModel'; +import { getDOMSelection } from '../../lib/coreApi/getDOMSelection'; +import { promoteToContentModelEditorCore } from '../../lib/editor/promoteToContentModelEditorCore'; +import { setContentModel } from '../../lib/coreApi/setContentModel'; +import { setDOMSelection } from '../../lib/coreApi/setDOMSelection'; +import { switchShadowEdit } from '../../lib/coreApi/switchShadowEdit'; +import { tablePreProcessor } from '../../lib/override/tablePreProcessor'; +import { + listItemMetadataApplier, + listLevelMetadataApplier, +} from '../../lib/metadata/updateListMetadata'; + +describe('promoteToContentModelEditorCore', () => { + let pluginState: ContentModelPluginState; + let core: EditorCore; + const mockedSwitchShadowEdit = 'SHADOWEDIT' as any; + const mockedDomToModelConfig = { + config: 'mockedDomToModelConfig', + } as any; + const mockedModelToDomConfig = { + config: 'mockedModelToDomConfig', + } as any; + + const baseResult: any = { + contentDiv: null!, + darkColorHandler: null!, + domEvent: null!, + edit: null!, + entity: null!, + getVisibleViewport: null!, + lifecycle: null!, + pendingFormatState: null!, + trustedHTMLHandler: null!, + undo: null!, + sizeTransformer: null!, + zoomScale: 1, + plugins: [], + }; + + beforeEach(() => { + pluginState = { + cache: {}, + copyPaste: { allowedCustomPasteType: [] }, + format: { + defaultFormat: {}, + pendingFormat: null, + }, + }; + core = { + ...baseResult, + api: { + switchShadowEdit: mockedSwitchShadowEdit, + } as any, + originalApi: { + switchShadowEdit: mockedSwitchShadowEdit, + } as any, + copyPaste: { allowedCustomPasteType: [] }, + }; + + spyOn(createDomToModelContext, 'createDomToModelConfig').and.returnValue( + mockedDomToModelConfig + ); + spyOn(createModelToDomContext, 'createModelToDomConfig').and.returnValue( + mockedModelToDomConfig + ); + }); + + it('No additional option', () => { + promoteToContentModelEditorCore(core, {}, pluginState); + + expect(core).toEqual({ + ...baseResult, + api: { + switchShadowEdit, + createEditorContext, + createContentModel, + setContentModel, + getDOMSelection, + setDOMSelection, + formatContentModel, + }, + originalApi: { + switchShadowEdit: mockedSwitchShadowEdit, + createEditorContext, + createContentModel, + setContentModel, + getDOMSelection, + setDOMSelection, + formatContentModel, + }, + defaultDomToModelOptions: [ + { processorOverride: { table: tablePreProcessor } }, + undefined, + ], + defaultModelToDomOptions: [ + { + metadataAppliers: { + listItem: listItemMetadataApplier, + listLevel: listLevelMetadataApplier, + }, + }, + undefined, + ], + defaultDomToModelConfig: mockedDomToModelConfig, + defaultModelToDomConfig: mockedModelToDomConfig, + format: { + defaultFormat: {}, + pendingFormat: null, + }, + cache: {}, + copyPaste: { allowedCustomPasteType: [] }, + environment: { isMac: false, isAndroid: false }, + } as any); + }); + + it('With additional option', () => { + const defaultDomToModelOptions = { a: '1' } as any; + const defaultModelToDomOptions = { b: '2' } as any; + const mockedPlugin = 'PLUGIN' as any; + const options = { + defaultDomToModelOptions, + defaultModelToDomOptions, + corePluginOverride: { + copyPaste: mockedPlugin, + }, + }; + + promoteToContentModelEditorCore(core, options, pluginState); + + expect(core).toEqual({ + ...baseResult, + api: { + switchShadowEdit, + createEditorContext, + createContentModel, + setContentModel, + getDOMSelection, + setDOMSelection, + formatContentModel, + }, + originalApi: { + switchShadowEdit: mockedSwitchShadowEdit, + createEditorContext, + createContentModel, + setContentModel, + getDOMSelection, + setDOMSelection, + formatContentModel, + }, + defaultDomToModelOptions: [ + { processorOverride: { table: tablePreProcessor } }, + defaultDomToModelOptions, + ], + defaultModelToDomOptions: [ + { + metadataAppliers: { + listItem: listItemMetadataApplier, + listLevel: listLevelMetadataApplier, + }, + }, + defaultModelToDomOptions, + ], + defaultDomToModelConfig: mockedDomToModelConfig, + defaultModelToDomConfig: mockedModelToDomConfig, + format: { + defaultFormat: {}, + pendingFormat: null, + }, + cache: {}, + copyPaste: { allowedCustomPasteType: [] }, + environment: { isMac: false, isAndroid: false }, + } as any); + }); +}); diff --git a/packages-content-model/roosterjs-content-model-editor/test/domUtils/metadata/handleListItemWithMetadataTest.ts b/packages-content-model/roosterjs-content-model-core/test/metadata/handleListItemWithMetadataTest.ts similarity index 99% rename from packages-content-model/roosterjs-content-model-editor/test/domUtils/metadata/handleListItemWithMetadataTest.ts rename to packages-content-model/roosterjs-content-model-core/test/metadata/handleListItemWithMetadataTest.ts index d86b1dc0ee0..3069b2e9100 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/domUtils/metadata/handleListItemWithMetadataTest.ts +++ b/packages-content-model/roosterjs-content-model-core/test/metadata/handleListItemWithMetadataTest.ts @@ -18,7 +18,7 @@ import { import { listItemMetadataApplier, listLevelMetadataApplier, -} from '../../../lib/domUtils/metadata/updateListMetadata'; +} from '../../lib/metadata/updateListMetadata'; describe('handleListItem with metadata', () => { let context: ModelToDomContext; diff --git a/packages-content-model/roosterjs-content-model-editor/test/domUtils/metadata/handleListWithMetadataTest.ts b/packages-content-model/roosterjs-content-model-core/test/metadata/handleListWithMetadataTest.ts similarity index 99% rename from packages-content-model/roosterjs-content-model-editor/test/domUtils/metadata/handleListWithMetadataTest.ts rename to packages-content-model/roosterjs-content-model-core/test/metadata/handleListWithMetadataTest.ts index 4936cfec9a6..cce69e71cfb 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/domUtils/metadata/handleListWithMetadataTest.ts +++ b/packages-content-model/roosterjs-content-model-core/test/metadata/handleListWithMetadataTest.ts @@ -9,7 +9,7 @@ import { import { listItemMetadataApplier, listLevelMetadataApplier, -} from '../../../lib/domUtils/metadata/updateListMetadata'; +} from '../../lib/metadata/updateListMetadata'; describe('handleList with metadata', () => { let context: ModelToDomContext; diff --git a/packages-content-model/roosterjs-content-model-editor/test/domUtils/metadata/updateImageMetadataTest.ts b/packages-content-model/roosterjs-content-model-core/test/metadata/updateImageMetadataTest.ts similarity index 98% rename from packages-content-model/roosterjs-content-model-editor/test/domUtils/metadata/updateImageMetadataTest.ts rename to packages-content-model/roosterjs-content-model-core/test/metadata/updateImageMetadataTest.ts index 7350d97afc7..d3f003d0991 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/domUtils/metadata/updateImageMetadataTest.ts +++ b/packages-content-model/roosterjs-content-model-core/test/metadata/updateImageMetadataTest.ts @@ -1,5 +1,5 @@ import { ContentModelImage, ImageMetadataFormat } from 'roosterjs-content-model-types'; -import { updateImageMetadata } from '../../../lib/domUtils/metadata/updateImageMetadata'; +import { updateImageMetadata } from '../../lib/metadata/updateImageMetadata'; describe('updateImageMetadataTest', () => { it('No value', () => { diff --git a/packages-content-model/roosterjs-content-model-editor/test/domUtils/metadata/updateListMetadataTest.ts b/packages-content-model/roosterjs-content-model-core/test/metadata/updateListMetadataTest.ts similarity index 99% rename from packages-content-model/roosterjs-content-model-editor/test/domUtils/metadata/updateListMetadataTest.ts rename to packages-content-model/roosterjs-content-model-core/test/metadata/updateListMetadataTest.ts index d5279e200a8..939fec274ed 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/domUtils/metadata/updateListMetadataTest.ts +++ b/packages-content-model/roosterjs-content-model-core/test/metadata/updateListMetadataTest.ts @@ -11,7 +11,7 @@ import { listItemMetadataApplier, listLevelMetadataApplier, updateListMetadata, -} from '../../../lib/domUtils/metadata/updateListMetadata'; +} from '../../lib/metadata/updateListMetadata'; describe('updateListMetadata', () => { it('No value', () => { diff --git a/packages-content-model/roosterjs-content-model-editor/test/domUtils/metadata/updateTableCellMetadataTest.ts b/packages-content-model/roosterjs-content-model-core/test/metadata/updateTableCellMetadataTest.ts similarity index 98% rename from packages-content-model/roosterjs-content-model-editor/test/domUtils/metadata/updateTableCellMetadataTest.ts rename to packages-content-model/roosterjs-content-model-core/test/metadata/updateTableCellMetadataTest.ts index c3a177e62c9..d5ecf9822ea 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/domUtils/metadata/updateTableCellMetadataTest.ts +++ b/packages-content-model/roosterjs-content-model-core/test/metadata/updateTableCellMetadataTest.ts @@ -1,5 +1,5 @@ import { ContentModelTableCell, TableCellMetadataFormat } from 'roosterjs-content-model-types'; -import { updateTableCellMetadata } from '../../../lib/domUtils/metadata/updateTableCellMetadata'; +import { updateTableCellMetadata } from '../../lib/metadata/updateTableCellMetadata'; describe('updateTableCellMetadata', () => { it('No value', () => { diff --git a/packages-content-model/roosterjs-content-model-editor/test/domUtils/metadata/updateTableMetadataTest.ts b/packages-content-model/roosterjs-content-model-core/test/metadata/updateTableMetadataTest.ts similarity index 98% rename from packages-content-model/roosterjs-content-model-editor/test/domUtils/metadata/updateTableMetadataTest.ts rename to packages-content-model/roosterjs-content-model-core/test/metadata/updateTableMetadataTest.ts index 9afb2b357a3..a4ecc891d51 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/domUtils/metadata/updateTableMetadataTest.ts +++ b/packages-content-model/roosterjs-content-model-core/test/metadata/updateTableMetadataTest.ts @@ -1,4 +1,4 @@ -import { updateTableMetadata } from '../../../lib/domUtils/metadata/updateTableMetadata'; +import { updateTableMetadata } from '../../lib/metadata/updateTableMetadata'; import { ContentModelTable, TableBorderFormat, diff --git a/packages-content-model/roosterjs-content-model-editor/test/editor/overrides/tablePreProcessorTest.ts b/packages-content-model/roosterjs-content-model-core/test/overrides/tablePreProcessorTest.ts similarity index 98% rename from packages-content-model/roosterjs-content-model-editor/test/editor/overrides/tablePreProcessorTest.ts rename to packages-content-model/roosterjs-content-model-core/test/overrides/tablePreProcessorTest.ts index 4dd8d30ef19..e759c7b4a19 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/editor/overrides/tablePreProcessorTest.ts +++ b/packages-content-model/roosterjs-content-model-core/test/overrides/tablePreProcessorTest.ts @@ -1,6 +1,6 @@ import * as tableProcessor from 'roosterjs-content-model-dom/lib/domToModel/processors/tableProcessor'; import { createContentModelDocument, createDomToModelContext } from 'roosterjs-content-model-dom'; -import { tablePreProcessor } from '../../../lib/editor/overrides/tablePreProcessor'; +import { tablePreProcessor } from '../../lib/override/tablePreProcessor'; describe('tablePreProcessor', () => { it('Table without metadata, use Entity', () => { diff --git a/packages-content-model/roosterjs-content-model-editor/test/publicApi/model/cloneModelTest.ts b/packages-content-model/roosterjs-content-model-core/test/publicApi/model/cloneModelTest.ts similarity index 100% rename from packages-content-model/roosterjs-content-model-editor/test/publicApi/model/cloneModelTest.ts rename to packages-content-model/roosterjs-content-model-core/test/publicApi/model/cloneModelTest.ts diff --git a/packages-content-model/roosterjs-content-model-core/test/publicApi/selection/getSelectionRootNodeTest.ts b/packages-content-model/roosterjs-content-model-core/test/publicApi/selection/getSelectionRootNodeTest.ts new file mode 100644 index 00000000000..cbb1d37affa --- /dev/null +++ b/packages-content-model/roosterjs-content-model-core/test/publicApi/selection/getSelectionRootNodeTest.ts @@ -0,0 +1,41 @@ +import { getSelectionRootNode } from '../../../lib/publicApi/selection/getSelectionRootNode'; + +describe('getSelectionRootNode', () => { + it('undefined input', () => { + const root = getSelectionRootNode(undefined); + + expect(root).toBeUndefined(); + }); + + it('range input', () => { + const mockedRoot = 'ROOT' as any; + const root = getSelectionRootNode({ + type: 'range', + range: { + commonAncestorContainer: mockedRoot, + } as any, + }); + + expect(root).toBe(mockedRoot); + }); + + it('table input', () => { + const mockedTable = 'TABLE' as any; + const root = getSelectionRootNode({ + type: 'table', + table: mockedTable, + } as any); + + expect(root).toBe(mockedTable); + }); + + it('image input', () => { + const mockedImage = 'IMAGE' as any; + const root = getSelectionRootNode({ + type: 'image', + image: mockedImage, + } as any); + + expect(root).toBe(mockedImage); + }); +}); diff --git a/packages-content-model/roosterjs-content-model-editor/test/modelApi/selection/iterateSelectionsTest.ts b/packages-content-model/roosterjs-content-model-core/test/publicApi/selection/iterateSelectionsTest.ts similarity index 99% rename from packages-content-model/roosterjs-content-model-editor/test/modelApi/selection/iterateSelectionsTest.ts rename to packages-content-model/roosterjs-content-model-core/test/publicApi/selection/iterateSelectionsTest.ts index a790c394993..9bb7a27769c 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/modelApi/selection/iterateSelectionsTest.ts +++ b/packages-content-model/roosterjs-content-model-core/test/publicApi/selection/iterateSelectionsTest.ts @@ -17,7 +17,7 @@ import { import { iterateSelections, IterateSelectionsCallback, -} from '../../../lib/modelApi/selection/iterateSelections'; +} from '../../../lib/publicApi/selection/iterateSelections'; describe('iterateSelections', () => { let callback: jasmine.Spy; diff --git a/packages-content-model/roosterjs-content-model-editor/lib/editor/corePlugins/ContentModelCopyPastePlugin.ts b/packages-content-model/roosterjs-content-model-editor/lib/editor/corePlugins/ContentModelCopyPastePlugin.ts index 37726ae9227..a9138f480f1 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/editor/corePlugins/ContentModelCopyPastePlugin.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/editor/corePlugins/ContentModelCopyPastePlugin.ts @@ -1,11 +1,9 @@ import paste from '../../publicApi/utils/paste'; import { addRangeToSelection } from '../../domUtils/addRangeToSelection'; -import { ChangeSource } from '../../publicTypes/ChangeSource'; -import { cloneModel } from '../../publicApi/model/cloneModel'; +import { ChangeSource, cloneModel, iterateSelections } from 'roosterjs-content-model-core'; import { ColorTransformDirection, PluginEventType } from 'roosterjs-editor-types'; import { deleteSelection } from '../../publicApi/selection/deleteSelection'; import { extractClipboardItems } from 'roosterjs-editor-dom'; -import { iterateSelections } from '../../modelApi/selection/iterateSelections'; import { contentModelToDom, createModelToDomContext, @@ -286,3 +284,12 @@ export const onNodeCreated: OnNodeCreated = (_, node): void => { node.removeAttribute('contenteditable'); } }; + +/** + * @internal + * Create a new instance of ContentModelCopyPastePlugin + * @param state The plugin state object + */ +export function createContentModelCopyPastePlugin(state: CopyPastePluginState) { + return new ContentModelCopyPastePlugin(state); +} diff --git a/packages-content-model/roosterjs-content-model-editor/lib/editor/createContentModelEditorCore.ts b/packages-content-model/roosterjs-content-model-editor/lib/editor/createContentModelEditorCore.ts index d17046e3a39..9f9aa638c80 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/editor/createContentModelEditorCore.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/editor/createContentModelEditorCore.ts @@ -1,25 +1,13 @@ -import ContentModelCopyPastePlugin from './corePlugins/ContentModelCopyPastePlugin'; import ContentModelTypeInContainerPlugin from './corePlugins/ContentModelTypeInContainerPlugin'; import { contentModelDomIndexer } from './utils/contentModelDomIndexer'; -import { createContentModel } from './coreApi/createContentModel'; import { createContentModelCachePlugin } from './corePlugins/ContentModelCachePlugin'; +import { createContentModelCopyPastePlugin } from './corePlugins/ContentModelCopyPastePlugin'; import { createContentModelFormatPlugin } from './corePlugins/ContentModelFormatPlugin'; -import { createDomToModelConfig, createModelToDomConfig } from 'roosterjs-content-model-dom'; -import { createEditorContext } from './coreApi/createEditorContext'; import { createEditorCore } from 'roosterjs-editor-core'; -import { formatContentModel } from './coreApi/formatContentModel'; -import { getDOMSelection } from './coreApi/getDOMSelection'; -import { setContentModel } from './coreApi/setContentModel'; -import { setDOMSelection } from './coreApi/setDOMSelection'; -import { switchShadowEdit } from './coreApi/switchShadowEdit'; -import { tablePreProcessor } from './overrides/tablePreProcessor'; -import { - listItemMetadataApplier, - listLevelMetadataApplier, -} from '../domUtils/metadata/updateListMetadata'; +import { promoteToContentModelEditorCore } from 'roosterjs-content-model-core'; import type { ContentModelEditorCore } from '../publicTypes/ContentModelEditorCore'; import type { ContentModelEditorOptions } from '../publicTypes/IContentModelEditor'; -import type { CoreCreator, EditorCore } from 'roosterjs-editor-types'; +import type { CoreCreator } from 'roosterjs-editor-types'; import type { ContentModelPluginState } from 'roosterjs-content-model-types'; /** @@ -39,92 +27,18 @@ export const createContentModelEditorCore: CoreCreator< ], corePluginOverride: { typeInContainer: new ContentModelTypeInContainerPlugin(), - copyPaste: new ContentModelCopyPastePlugin(pluginState.copyPaste), + copyPaste: createContentModelCopyPastePlugin(pluginState.copyPaste), ...options.corePluginOverride, }, }; const core = createEditorCore(contentDiv, modifiedOptions) as ContentModelEditorCore; - core.environment = {}; - promoteToContentModelEditorCore(core, modifiedOptions, pluginState); return core; }; -/** - * Creator Content Model Editor Core from Editor Core - * @param core The original EditorCore object - * @param options Options of this editor - */ -export function promoteToContentModelEditorCore( - core: EditorCore, - options: ContentModelEditorOptions, - pluginState: ContentModelPluginState -) { - const cmCore = core as ContentModelEditorCore; - - promoteCorePluginState(cmCore, pluginState); - promoteContentModelInfo(cmCore, options); - promoteCoreApi(cmCore); - promoteEnvironment(cmCore); -} - -function promoteCorePluginState( - cmCore: ContentModelEditorCore, - pluginState: ContentModelPluginState -) { - Object.assign(cmCore, pluginState); -} - -function promoteContentModelInfo( - cmCore: ContentModelEditorCore, - options: ContentModelEditorOptions -) { - cmCore.defaultDomToModelOptions = [ - { - processorOverride: { - table: tablePreProcessor, - }, - }, - options.defaultDomToModelOptions, - ]; - cmCore.defaultModelToDomOptions = [ - { - metadataAppliers: { - listItem: listItemMetadataApplier, - listLevel: listLevelMetadataApplier, - }, - }, - options.defaultModelToDomOptions, - ]; - cmCore.defaultDomToModelConfig = createDomToModelConfig(cmCore.defaultDomToModelOptions); - cmCore.defaultModelToDomConfig = createModelToDomConfig(cmCore.defaultModelToDomOptions); -} - -function promoteCoreApi(cmCore: ContentModelEditorCore) { - cmCore.api.createEditorContext = createEditorContext; - cmCore.api.createContentModel = createContentModel; - cmCore.api.setContentModel = setContentModel; - cmCore.api.switchShadowEdit = switchShadowEdit; - cmCore.api.getDOMSelection = getDOMSelection; - cmCore.api.setDOMSelection = setDOMSelection; - cmCore.api.formatContentModel = formatContentModel; - cmCore.originalApi.createEditorContext = createEditorContext; - cmCore.originalApi.createContentModel = createContentModel; - cmCore.originalApi.setContentModel = setContentModel; - cmCore.originalApi.getDOMSelection = getDOMSelection; - cmCore.originalApi.setDOMSelection = setDOMSelection; - cmCore.originalApi.formatContentModel = formatContentModel; -} - -function promoteEnvironment(cmCore: ContentModelEditorCore) { - // It is ok to use global window here since the environment should always be the same for all windows in one session - cmCore.environment.isMac = window.navigator.appVersion.indexOf('Mac') != -1; - cmCore.environment.isAndroid = /android/i.test(window.navigator.userAgent); -} - function getPluginState(options: ContentModelEditorOptions): ContentModelPluginState { const format = options.defaultFormat || {}; return { diff --git a/packages-content-model/roosterjs-content-model-editor/lib/index.ts b/packages-content-model/roosterjs-content-model-editor/lib/index.ts index eebb88ceb0b..75eef39b208 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/index.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/index.ts @@ -3,7 +3,6 @@ export { ContentModelEditorCore, } from './publicTypes/ContentModelEditorCore'; export { IContentModelEditor, ContentModelEditorOptions } from './publicTypes/IContentModelEditor'; -export { ChangeSource } from './publicTypes/ChangeSource'; export { default as insertTable } from './publicApi/table/insertTable'; export { default as formatTable } from './publicApi/table/formatTable'; @@ -54,7 +53,6 @@ export { default as setParagraphMargin } from './publicApi/block/setParagraphMar export { default as toggleCode } from './publicApi/segment/toggleCode'; export { default as paste } from './publicApi/utils/paste'; export { default as insertEntity } from './publicApi/entity/insertEntity'; -export { CachedElementHandler, CloneModelOptions, cloneModel } from './publicApi/model/cloneModel'; export { deleteSelection } from './publicApi/selection/deleteSelection'; export { default as ContentModelEditor } from './editor/ContentModelEditor'; @@ -65,14 +63,7 @@ export { default as ContentModelTypeInContainerPlugin } from './editor/corePlugi export { default as ContentModelCopyPastePlugin } from './editor/corePlugins/ContentModelCopyPastePlugin'; export { default as ContentModelCachePlugin } from './editor/corePlugins/ContentModelCachePlugin'; -export { - createContentModelEditorCore, - promoteToContentModelEditorCore, -} from './editor/createContentModelEditorCore'; +export { createContentModelEditorCore } from './editor/createContentModelEditorCore'; export { combineBorderValue, extractBorderValues } from './domUtils/borderValues'; -export { updateImageMetadata } from './domUtils/metadata/updateImageMetadata'; -export { updateTableCellMetadata } from './domUtils/metadata/updateTableCellMetadata'; -export { updateTableMetadata } from './domUtils/metadata/updateTableMetadata'; -export { updateListMetadata } from './domUtils/metadata/updateListMetadata'; export { isCharacterValue, isModifierKey } from './domUtils/eventUtils'; export { isPunctuation, isSpace, normalizeText } from './domUtils/stringUtil'; diff --git a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/common/clearModelFormat.ts b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/common/clearModelFormat.ts index d811a161638..31fdcac6e3d 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/common/clearModelFormat.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/common/clearModelFormat.ts @@ -2,9 +2,11 @@ import { adjustWordSelection } from '../selection/adjustWordSelection'; import { applyTableFormat } from '../table/applyTableFormat'; import { createFormatContainer } from 'roosterjs-content-model-dom'; import { getClosestAncestorBlockGroupIndex } from './getClosestAncestorBlockGroupIndex'; -import { iterateSelections } from '../selection/iterateSelections'; -import { updateTableCellMetadata } from '../../domUtils/metadata/updateTableCellMetadata'; -import { updateTableMetadata } from '../../domUtils/metadata/updateTableMetadata'; +import { + iterateSelections, + updateTableCellMetadata, + updateTableMetadata, +} from 'roosterjs-content-model-core'; import type { ContentModelBlock, ContentModelBlockGroup, diff --git a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/common/retrieveModelFormatState.ts b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/common/retrieveModelFormatState.ts index ca3fd514c40..8d9503034c2 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/common/retrieveModelFormatState.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/common/retrieveModelFormatState.ts @@ -1,8 +1,7 @@ import { extractBorderValues } from '../../domUtils/borderValues'; import { getClosestAncestorBlockGroupIndex } from './getClosestAncestorBlockGroupIndex'; import { isBold } from '../../publicApi/segment/toggleBold'; -import { iterateSelections } from '../selection/iterateSelections'; -import { updateTableMetadata } from '../../domUtils/metadata/updateTableMetadata'; +import { iterateSelections, updateTableMetadata } from 'roosterjs-content-model-core'; import type { ContentModelFormatState, ContentModelBlock, diff --git a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/edit/utils/deleteExpandedSelection.ts b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/edit/utils/deleteExpandedSelection.ts index 4c603e12271..6685245d6f8 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/edit/utils/deleteExpandedSelection.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/edit/utils/deleteExpandedSelection.ts @@ -1,8 +1,8 @@ import { createInsertPoint } from '../utils/createInsertPoint'; import { deleteBlock } from '../../../publicApi/block/deleteBlock'; import { deleteSegment } from '../../../publicApi/segment/deleteSegment'; -import { iterateSelections } from '../../selection/iterateSelections'; -import type { IterateSelectionsOption } from '../../selection/iterateSelections'; +import { iterateSelections } from 'roosterjs-content-model-core'; +import type { IterateSelectionsOption } from 'roosterjs-content-model-core'; import type { ContentModelDocument, DeleteSelectionContext, diff --git a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/format/applyPendingFormat.ts b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/format/applyPendingFormat.ts index 7fa99123c90..093ac7b93f6 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/format/applyPendingFormat.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/format/applyPendingFormat.ts @@ -1,4 +1,4 @@ -import { iterateSelections } from '../../modelApi/selection/iterateSelections'; +import { iterateSelections } from 'roosterjs-content-model-core'; import type { ContentModelSegmentFormat } from 'roosterjs-content-model-types'; import type { IContentModelEditor } from '../../publicTypes/IContentModelEditor'; import { diff --git a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/selection/adjustWordSelection.ts b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/selection/adjustWordSelection.ts index 9d4d3e2f8cf..741ce3e48bd 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/selection/adjustWordSelection.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/selection/adjustWordSelection.ts @@ -1,6 +1,6 @@ import { createText } from 'roosterjs-content-model-dom'; import { isPunctuation, isSpace } from '../../domUtils/stringUtil'; -import { iterateSelections } from '../../modelApi/selection/iterateSelections'; +import { iterateSelections } from 'roosterjs-content-model-core'; import type { ContentModelDocument, ContentModelParagraph, diff --git a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/selection/collectSelections.ts b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/selection/collectSelections.ts index 14c6abd8874..7180f208819 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/selection/collectSelections.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/selection/collectSelections.ts @@ -1,7 +1,7 @@ import { getClosestAncestorBlockGroupIndex } from '../common/getClosestAncestorBlockGroupIndex'; import { isBlockGroupOfType } from '../common/isBlockGroupOfType'; -import { iterateSelections } from './iterateSelections'; -import type { IterateSelectionsOption } from './iterateSelections'; +import { iterateSelections } from 'roosterjs-content-model-core'; +import type { IterateSelectionsOption } from 'roosterjs-content-model-core'; import type { ContentModelBlock, ContentModelBlockGroup, diff --git a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/alignTableCell.ts b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/alignTableCell.ts index ded7e3264af..296ccb034d5 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/alignTableCell.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/alignTableCell.ts @@ -1,5 +1,5 @@ import { getSelectedCells } from './getSelectedCells'; -import { updateTableCellMetadata } from '../../domUtils/metadata/updateTableCellMetadata'; +import { updateTableCellMetadata } from 'roosterjs-content-model-core'; import type { ContentModelTable, ContentModelTableCell, diff --git a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/applyTableFormat.ts b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/applyTableFormat.ts index b41efeef019..dcc44fcdfe3 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/applyTableFormat.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/applyTableFormat.ts @@ -2,8 +2,7 @@ import { BorderKeys } from 'roosterjs-content-model-dom'; import { combineBorderValue, extractBorderValues } from '../../domUtils/borderValues'; import { setTableCellBackgroundColor } from './setTableCellBackgroundColor'; import { TableBorderFormat } from 'roosterjs-content-model-types'; -import { updateTableCellMetadata } from '../../domUtils/metadata/updateTableCellMetadata'; -import { updateTableMetadata } from '../../domUtils/metadata/updateTableMetadata'; +import { updateTableCellMetadata, updateTableMetadata } from 'roosterjs-content-model-core'; import type { BorderFormat, ContentModelTable, diff --git a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/setTableCellBackgroundColor.ts b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/setTableCellBackgroundColor.ts index 9307566a3cd..895940744b5 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/setTableCellBackgroundColor.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/modelApi/table/setTableCellBackgroundColor.ts @@ -1,4 +1,4 @@ -import { updateTableCellMetadata } from '../../domUtils/metadata/updateTableCellMetadata'; +import { updateTableCellMetadata } from 'roosterjs-content-model-core'; import type { ContentModelTableCell } from 'roosterjs-content-model-types'; // Using the HSL (hue, saturation and lightness) representation for RGB color values. diff --git a/packages-content-model/roosterjs-content-model-editor/lib/publicApi/entity/insertEntity.ts b/packages-content-model/roosterjs-content-model-editor/lib/publicApi/entity/insertEntity.ts index 408be04505e..964c4e59837 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/publicApi/entity/insertEntity.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/publicApi/entity/insertEntity.ts @@ -1,4 +1,4 @@ -import { ChangeSource } from '../../publicTypes/ChangeSource'; +import { ChangeSource } from 'roosterjs-content-model-core'; import { createEntity, normalizeContentModel } from 'roosterjs-content-model-dom'; import { insertEntityModel } from '../../modelApi/entity/insertEntityModel'; import type { diff --git a/packages-content-model/roosterjs-content-model-editor/lib/publicApi/format/getFormatState.ts b/packages-content-model/roosterjs-content-model-editor/lib/publicApi/format/getFormatState.ts index 5ee2fec8d02..deebd5dac76 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/publicApi/format/getFormatState.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/publicApi/format/getFormatState.ts @@ -1,4 +1,4 @@ -import { getSelectionRootNode } from '../../modelApi/selection/getSelectionRootNode'; +import { getSelectionRootNode } from 'roosterjs-content-model-core'; import { retrieveModelFormatState } from '../../modelApi/common/retrieveModelFormatState'; import type { IContentModelEditor } from '../../publicTypes/IContentModelEditor'; import type { diff --git a/packages-content-model/roosterjs-content-model-editor/lib/publicApi/image/changeImage.ts b/packages-content-model/roosterjs-content-model-editor/lib/publicApi/image/changeImage.ts index 20187fd008b..fcad8e95237 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/publicApi/image/changeImage.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/publicApi/image/changeImage.ts @@ -1,7 +1,7 @@ import formatImageWithContentModel from '../utils/formatImageWithContentModel'; import { PluginEventType } from 'roosterjs-editor-types'; import { readFile } from '../../domUtils/readFile'; -import { updateImageMetadata } from '../../domUtils/metadata/updateImageMetadata'; +import { updateImageMetadata } from 'roosterjs-content-model-core'; import type { ContentModelImage } from 'roosterjs-content-model-types'; import type { IContentModelEditor } from '../../publicTypes/IContentModelEditor'; diff --git a/packages-content-model/roosterjs-content-model-editor/lib/publicApi/link/insertLink.ts b/packages-content-model/roosterjs-content-model-editor/lib/publicApi/link/insertLink.ts index dd41b78dc34..2e1df2c3605 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/publicApi/link/insertLink.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/publicApi/link/insertLink.ts @@ -1,5 +1,5 @@ import getSelectedSegments from '../selection/getSelectedSegments'; -import { ChangeSource } from '../../publicTypes/ChangeSource'; +import { ChangeSource } from 'roosterjs-content-model-core'; import { HtmlSanitizer, matchLink } from 'roosterjs-editor-dom'; import { mergeModel } from '../../modelApi/common/mergeModel'; import type { ContentModelLink } from 'roosterjs-content-model-types'; diff --git a/packages-content-model/roosterjs-content-model-editor/lib/publicApi/list/setListStyle.ts b/packages-content-model/roosterjs-content-model-editor/lib/publicApi/list/setListStyle.ts index 15a101351b0..f9d9d7beee4 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/publicApi/list/setListStyle.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/publicApi/list/setListStyle.ts @@ -1,6 +1,6 @@ import { findListItemsInSameThread } from '../../modelApi/list/findListItemsInSameThread'; import { getFirstSelectedListItem } from '../../modelApi/selection/collectSelections'; -import { updateListMetadata } from '../../domUtils/metadata/updateListMetadata'; +import { updateListMetadata } from 'roosterjs-content-model-core'; import type { IContentModelEditor } from '../../publicTypes/IContentModelEditor'; import type { ListMetadataFormat } from 'roosterjs-content-model-types'; diff --git a/packages-content-model/roosterjs-content-model-editor/lib/publicApi/table/applyTableBorderFormat.ts b/packages-content-model/roosterjs-content-model-editor/lib/publicApi/table/applyTableBorderFormat.ts index 43d7fb5cb71..46a4b063a3d 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/publicApi/table/applyTableBorderFormat.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/publicApi/table/applyTableBorderFormat.ts @@ -2,7 +2,7 @@ import { extractBorderValues } from '../../domUtils/borderValues'; import { getFirstSelectedTable } from '../../modelApi/selection/collectSelections'; import { getSelectedCells } from '../../modelApi/table/getSelectedCells'; import { parseValueWithUnit } from 'roosterjs-content-model-dom'; -import { updateTableCellMetadata } from '../../domUtils/metadata/updateTableCellMetadata'; +import { updateTableCellMetadata } from 'roosterjs-content-model-core'; import type { IContentModelEditor } from '../../publicTypes/IContentModelEditor'; import type { Border, diff --git a/packages-content-model/roosterjs-content-model-editor/lib/publicApi/table/formatTable.ts b/packages-content-model/roosterjs-content-model-editor/lib/publicApi/table/formatTable.ts index 92a5e2b4044..7e3446851ab 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/publicApi/table/formatTable.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/publicApi/table/formatTable.ts @@ -1,6 +1,6 @@ import { applyTableFormat } from '../../modelApi/table/applyTableFormat'; import { getFirstSelectedTable } from '../../modelApi/selection/collectSelections'; -import { updateTableCellMetadata } from '../../domUtils/metadata/updateTableCellMetadata'; +import { updateTableCellMetadata } from 'roosterjs-content-model-core'; import type { IContentModelEditor } from '../../publicTypes/IContentModelEditor'; import type { TableMetadataFormat } from 'roosterjs-content-model-types'; diff --git a/packages-content-model/roosterjs-content-model-editor/lib/publicApi/utils/paste.ts b/packages-content-model/roosterjs-content-model-editor/lib/publicApi/utils/paste.ts index a9363711383..f66cf488248 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/publicApi/utils/paste.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/publicApi/utils/paste.ts @@ -1,5 +1,5 @@ import getSelectedSegments from '../selection/getSelectedSegments'; -import { ChangeSource } from '../../publicTypes/ChangeSource'; +import { ChangeSource } from 'roosterjs-content-model-core'; import { GetContentMode, PasteType as OldPasteType, PluginEventType } from 'roosterjs-editor-types'; import { mergeModel } from '../../modelApi/common/mergeModel'; import type { diff --git a/packages-content-model/roosterjs-content-model-editor/package.json b/packages-content-model/roosterjs-content-model-editor/package.json index 00f04bf6314..6debbfeb1cb 100644 --- a/packages-content-model/roosterjs-content-model-editor/package.json +++ b/packages-content-model/roosterjs-content-model-editor/package.json @@ -6,6 +6,7 @@ "roosterjs-editor-types": "", "roosterjs-editor-dom": "", "roosterjs-editor-core": "", + "roosterjs-content-model-core": "", "roosterjs-content-model-dom": "", "roosterjs-content-model-types": "" }, diff --git a/packages-content-model/roosterjs-content-model-editor/test/editor/createContentModelEditorCoreTest.ts b/packages-content-model/roosterjs-content-model-editor/test/editor/createContentModelEditorCoreTest.ts index 81bf05c5caa..c14a760dda6 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/editor/createContentModelEditorCoreTest.ts +++ b/packages-content-model/roosterjs-content-model-editor/test/editor/createContentModelEditorCoreTest.ts @@ -1,42 +1,25 @@ import * as ContentModelCachePlugin from '../../lib/editor/corePlugins/ContentModelCachePlugin'; +import * as ContentModelCopyPastePlugin from '../../lib/editor/corePlugins/ContentModelCopyPastePlugin'; import * as ContentModelFormatPlugin from '../../lib/editor/corePlugins/ContentModelFormatPlugin'; -import * as createDomToModelContext from 'roosterjs-content-model-dom/lib/domToModel/context/createDomToModelContext'; import * as createEditorCore from 'roosterjs-editor-core/lib/editor/createEditorCore'; -import * as createModelToDomContext from 'roosterjs-content-model-dom/lib/modelToDom/context/createModelToDomContext'; +import * as promoteToContentModelEditorCore from 'roosterjs-content-model-core/lib/editor/promoteToContentModelEditorCore'; import ContentModelTypeInContainerPlugin from '../../lib/editor/corePlugins/ContentModelTypeInContainerPlugin'; import { contentModelDomIndexer } from '../../lib/editor/utils/contentModelDomIndexer'; import { ContentModelEditorOptions } from '../../lib/publicTypes/IContentModelEditor'; -import { createContentModel } from '../../lib/editor/coreApi/createContentModel'; import { createContentModelEditorCore } from '../../lib/editor/createContentModelEditorCore'; -import { createEditorContext } from '../../lib/editor/coreApi/createEditorContext'; -import { formatContentModel } from '../../lib/editor/coreApi/formatContentModel'; -import { getDOMSelection } from '../../lib/editor/coreApi/getDOMSelection'; -import { setContentModel } from '../../lib/editor/coreApi/setContentModel'; -import { setDOMSelection } from '../../lib/editor/coreApi/setDOMSelection'; -import { switchShadowEdit } from '../../lib/editor/coreApi/switchShadowEdit'; -import { tablePreProcessor } from '../../lib/editor/overrides/tablePreProcessor'; -import { - listItemMetadataApplier, - listLevelMetadataApplier, -} from '../../lib/domUtils/metadata/updateListMetadata'; const mockedSwitchShadowEdit = 'SHADOWEDIT' as any; -const mockedDomToModelConfig = { - config: 'mockedDomToModelConfig', -} as any; -const mockedModelToDomConfig = { - config: 'mockedModelToDomConfig', -} as any; const mockedFormatPlugin = 'FORMATPLUGIN' as any; const mockedCachePlugin = 'CACHPLUGIN' as any; +const mockedCopyPastePlugin = 'COPYPASTE' as any; +const mockedCopyPastePlugin2 = 'COPYPASTE2' as any; describe('createContentModelEditorCore', () => { let createEditorCoreSpy: jasmine.Spy; + let promoteToContentModelEditorCoreSpy: jasmine.Spy; let mockedCore: any; let contentDiv: any; - let copyPastePlugin = 'copyPastePlugin' as any; - beforeEach(() => { contentDiv = { style: {}, @@ -58,73 +41,34 @@ describe('createContentModelEditorCore', () => { createEditorCoreSpy = spyOn(createEditorCore, 'createEditorCore').and.returnValue( mockedCore ); + promoteToContentModelEditorCoreSpy = spyOn( + promoteToContentModelEditorCore, + 'promoteToContentModelEditorCore' + ); spyOn(ContentModelFormatPlugin, 'createContentModelFormatPlugin').and.returnValue( mockedFormatPlugin ); spyOn(ContentModelCachePlugin, 'createContentModelCachePlugin').and.returnValue( mockedCachePlugin ); - - spyOn(createDomToModelContext, 'createDomToModelConfig').and.returnValue( - mockedDomToModelConfig - ); - spyOn(createModelToDomContext, 'createModelToDomConfig').and.returnValue( - mockedModelToDomConfig + spyOn(ContentModelCopyPastePlugin, 'createContentModelCopyPastePlugin').and.returnValue( + mockedCopyPastePlugin ); }); it('No additional option', () => { - const options = { - corePluginOverride: { - copyPaste: copyPastePlugin, - }, - }; - const core = createContentModelEditorCore(contentDiv, options); + const core = createContentModelEditorCore(contentDiv, {}); - expect(createEditorCoreSpy).toHaveBeenCalledWith(contentDiv, { + const expectedOptions = { plugins: [mockedCachePlugin, mockedFormatPlugin], corePluginOverride: { typeInContainer: new ContentModelTypeInContainerPlugin(), - copyPaste: copyPastePlugin, - }, - }); - expect(core).toEqual({ - lifecycle: { - experimentalFeatures: [], - }, - api: { - switchShadowEdit, - createEditorContext, - createContentModel, - setContentModel, - getDOMSelection, - setDOMSelection, - formatContentModel, - }, - originalApi: { - a: 'b', - createEditorContext, - createContentModel, - setContentModel, - getDOMSelection, - setDOMSelection, - formatContentModel, + copyPaste: mockedCopyPastePlugin, }, - defaultDomToModelOptions: [ - { processorOverride: { table: tablePreProcessor } }, - undefined, - ], - defaultModelToDomOptions: [ - { - metadataAppliers: { - listItem: listItemMetadataApplier, - listLevel: listLevelMetadataApplier, - }, - }, - undefined, - ], - defaultDomToModelConfig: mockedDomToModelConfig, - defaultModelToDomConfig: mockedModelToDomConfig, + }; + const expectedPluginState: any = { + cache: { domIndexer: undefined }, + copyPaste: { allowedCustomPasteType: [] }, format: { defaultFormat: { fontWeight: undefined, @@ -137,13 +81,14 @@ describe('createContentModelEditorCore', () => { }, pendingFormat: null, }, - contentDiv: { - style: {}, - }, - cache: { domIndexer: undefined }, - copyPaste: { allowedCustomPasteType: [] }, - environment: { isMac: false, isAndroid: false }, - } as any); + }; + + expect(createEditorCoreSpy).toHaveBeenCalledWith(contentDiv, expectedOptions); + expect(promoteToContentModelEditorCoreSpy).toHaveBeenCalledWith( + core, + expectedOptions, + expectedPluginState + ); }); it('With additional option', () => { @@ -154,58 +99,23 @@ describe('createContentModelEditorCore', () => { defaultDomToModelOptions, defaultModelToDomOptions, corePluginOverride: { - copyPaste: copyPastePlugin, + copyPaste: mockedCopyPastePlugin2, }, }; const core = createContentModelEditorCore(contentDiv, options); - expect(createEditorCoreSpy).toHaveBeenCalledWith(contentDiv, { + const expectedOptions = { defaultDomToModelOptions, defaultModelToDomOptions, plugins: [mockedCachePlugin, mockedFormatPlugin], corePluginOverride: { typeInContainer: new ContentModelTypeInContainerPlugin(), - copyPaste: copyPastePlugin, - }, - }); - - expect(core).toEqual({ - lifecycle: { - experimentalFeatures: [], - }, - api: { - switchShadowEdit, - createEditorContext, - createContentModel, - setContentModel, - getDOMSelection, - setDOMSelection, - formatContentModel, - }, - originalApi: { - a: 'b', - createEditorContext, - createContentModel, - setContentModel, - getDOMSelection, - setDOMSelection, - formatContentModel, + copyPaste: mockedCopyPastePlugin2, }, - defaultDomToModelOptions: [ - { processorOverride: { table: tablePreProcessor } }, - defaultDomToModelOptions, - ], - defaultModelToDomOptions: [ - { - metadataAppliers: { - listItem: listItemMetadataApplier, - listLevel: listLevelMetadataApplier, - }, - }, - defaultModelToDomOptions, - ], - defaultDomToModelConfig: mockedDomToModelConfig, - defaultModelToDomConfig: mockedModelToDomConfig, + }; + const expectedPluginState: any = { + cache: { domIndexer: undefined }, + copyPaste: { allowedCustomPasteType: [] }, format: { defaultFormat: { fontWeight: undefined, @@ -218,22 +128,18 @@ describe('createContentModelEditorCore', () => { }, pendingFormat: null, }, - contentDiv: { - style: {}, - }, - cache: { - domIndexer: undefined, - }, - copyPaste: { allowedCustomPasteType: [] }, - environment: { isMac: false, isAndroid: false }, - } as any); + }; + + expect(createEditorCoreSpy).toHaveBeenCalledWith(contentDiv, expectedOptions); + expect(promoteToContentModelEditorCoreSpy).toHaveBeenCalledWith( + core, + expectedOptions, + expectedPluginState + ); }); it('With default format', () => { const options = { - corePluginOverride: { - copyPaste: copyPastePlugin, - }, defaultFormat: { bold: true, italic: true, @@ -247,11 +153,11 @@ describe('createContentModelEditorCore', () => { const core = createContentModelEditorCore(contentDiv, options); - expect(createEditorCoreSpy).toHaveBeenCalledWith(contentDiv, { + const expectedOptions = { plugins: [mockedCachePlugin, mockedFormatPlugin], corePluginOverride: { typeInContainer: new ContentModelTypeInContainerPlugin(), - copyPaste: copyPastePlugin, + copyPaste: mockedCopyPastePlugin, }, defaultFormat: { bold: true, @@ -262,44 +168,10 @@ describe('createContentModelEditorCore', () => { textColor: 'red', backgroundColor: 'blue', }, - }); - expect(core).toEqual({ - lifecycle: { - experimentalFeatures: [], - }, - api: { - switchShadowEdit, - createEditorContext, - createContentModel, - setContentModel, - getDOMSelection, - setDOMSelection, - formatContentModel, - }, - originalApi: { - a: 'b', - createEditorContext, - createContentModel, - setContentModel, - getDOMSelection, - setDOMSelection, - formatContentModel, - }, - defaultDomToModelOptions: [ - { processorOverride: { table: tablePreProcessor } }, - undefined, - ], - defaultModelToDomOptions: [ - { - metadataAppliers: { - listItem: listItemMetadataApplier, - listLevel: listLevelMetadataApplier, - }, - }, - undefined, - ], - defaultDomToModelConfig: mockedDomToModelConfig, - defaultModelToDomConfig: mockedModelToDomConfig, + }; + const expectedPluginState: any = { + cache: { domIndexer: undefined }, + copyPaste: { allowedCustomPasteType: [] }, format: { defaultFormat: { fontWeight: 'bold', @@ -312,145 +184,34 @@ describe('createContentModelEditorCore', () => { }, pendingFormat: null, }, - contentDiv: { - style: {}, - }, - cache: { domIndexer: undefined }, - copyPaste: { allowedCustomPasteType: [] }, - environment: { isMac: false, isAndroid: false }, - } as any); - }); - - it('Reuse model', () => { - const options = { - corePluginOverride: { - copyPaste: copyPastePlugin, - }, }; - const core = createContentModelEditorCore(contentDiv, options); - - expect(createEditorCoreSpy).toHaveBeenCalledWith(contentDiv, { - plugins: [mockedCachePlugin, mockedFormatPlugin], - corePluginOverride: { - typeInContainer: new ContentModelTypeInContainerPlugin(), - copyPaste: copyPastePlugin, - }, - }); - expect(core).toEqual({ - lifecycle: { - experimentalFeatures: [], - }, - api: { - switchShadowEdit: switchShadowEdit, - createEditorContext, - createContentModel, - setContentModel, - getDOMSelection, - setDOMSelection, - formatContentModel, - }, - originalApi: { - a: 'b', - createEditorContext, - createContentModel, - setContentModel, - getDOMSelection, - setDOMSelection, - formatContentModel, - }, - defaultDomToModelOptions: [ - { processorOverride: { table: tablePreProcessor } }, - undefined, - ], - defaultModelToDomOptions: [ - { - metadataAppliers: { - listItem: listItemMetadataApplier, - listLevel: listLevelMetadataApplier, - }, - }, - undefined, - ], - format: { - defaultFormat: { - fontWeight: undefined, - italic: undefined, - underline: undefined, - fontFamily: undefined, - fontSize: undefined, - textColor: undefined, - backgroundColor: undefined, - }, - pendingFormat: null, - }, - defaultDomToModelConfig: mockedDomToModelConfig, - defaultModelToDomConfig: mockedModelToDomConfig, - - contentDiv: { - style: {}, - }, - cache: { domIndexer: undefined }, - copyPaste: { allowedCustomPasteType: [] }, - environment: { isMac: false, isAndroid: false }, - } as any); + expect(createEditorCoreSpy).toHaveBeenCalledWith(contentDiv, expectedOptions); + expect(promoteToContentModelEditorCoreSpy).toHaveBeenCalledWith( + core, + expectedOptions, + expectedPluginState + ); }); it('Allow dom indexer', () => { const options: ContentModelEditorOptions = { - corePluginOverride: { - copyPaste: copyPastePlugin, - }, cacheModel: true, }; const core = createContentModelEditorCore(contentDiv, options); - expect(createEditorCoreSpy).toHaveBeenCalledWith(contentDiv, { + const expectedOptions = { plugins: [mockedCachePlugin, mockedFormatPlugin], corePluginOverride: { typeInContainer: new ContentModelTypeInContainerPlugin(), - copyPaste: copyPastePlugin, + copyPaste: mockedCopyPastePlugin, }, cacheModel: true, - }); - expect(core).toEqual({ - lifecycle: { - experimentalFeatures: [], - }, - api: { - switchShadowEdit, - createEditorContext, - createContentModel, - setContentModel, - getDOMSelection, - setDOMSelection, - formatContentModel, - }, - originalApi: { - a: 'b', - createEditorContext, - createContentModel, - setContentModel, - getDOMSelection, - setDOMSelection, - formatContentModel, - }, - defaultDomToModelOptions: [ - { processorOverride: { table: tablePreProcessor } }, - undefined, - ], - defaultModelToDomOptions: [ - { - metadataAppliers: { - listItem: listItemMetadataApplier, - listLevel: listLevelMetadataApplier, - }, - }, - undefined, - ], - defaultDomToModelConfig: mockedDomToModelConfig, - defaultModelToDomConfig: mockedModelToDomConfig, + }; + const expectedPluginState: any = { + cache: { domIndexer: contentModelDomIndexer }, + copyPaste: { allowedCustomPasteType: [] }, format: { defaultFormat: { fontWeight: undefined, @@ -463,12 +224,13 @@ describe('createContentModelEditorCore', () => { }, pendingFormat: null, }, - contentDiv: { - style: {}, - }, - cache: { domIndexer: contentModelDomIndexer }, - copyPaste: { allowedCustomPasteType: [] }, - environment: { isMac: false, isAndroid: false }, - } as any); + }; + + expect(createEditorCoreSpy).toHaveBeenCalledWith(contentDiv, expectedOptions); + expect(promoteToContentModelEditorCoreSpy).toHaveBeenCalledWith( + core, + expectedOptions, + expectedPluginState + ); }); }); diff --git a/packages-content-model/roosterjs-content-model-editor/test/editor/plugins/ContentModelCopyPastePluginTest.ts b/packages-content-model/roosterjs-content-model-editor/test/editor/plugins/ContentModelCopyPastePluginTest.ts index ff1cd7a4bf5..8fa3ddd0c3f 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/editor/plugins/ContentModelCopyPastePluginTest.ts +++ b/packages-content-model/roosterjs-content-model-editor/test/editor/plugins/ContentModelCopyPastePluginTest.ts @@ -1,9 +1,9 @@ import * as addRangeToSelection from '../../../lib/domUtils/addRangeToSelection'; -import * as cloneModelFile from '../../../lib/publicApi/model/cloneModel'; +import * as cloneModelFile from 'roosterjs-content-model-core/lib/publicApi/model/cloneModel'; import * as contentModelToDomFile from 'roosterjs-content-model-dom/lib/modelToDom/contentModelToDom'; import * as deleteSelectionsFile from '../../../lib/publicApi/selection/deleteSelection'; import * as extractClipboardItemsFile from 'roosterjs-editor-dom/lib/clipboard/extractClipboardItems'; -import * as iterateSelectionsFile from '../../../lib/modelApi/selection/iterateSelections'; +import * as iterateSelectionsFile from 'roosterjs-content-model-core/lib/publicApi/selection/iterateSelections'; import * as normalizeContentModel from 'roosterjs-content-model-dom/lib/modelApi/common/normalizeContentModel'; import * as PasteFile from '../../../lib/publicApi/utils/paste'; import { createModelToDomContext } from 'roosterjs-content-model-dom'; diff --git a/packages-content-model/roosterjs-content-model-editor/test/modelApi/common/retrieveModelFormatStateTest.ts b/packages-content-model/roosterjs-content-model-editor/test/modelApi/common/retrieveModelFormatStateTest.ts index 1b916ed32c8..ef22256bc4f 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/modelApi/common/retrieveModelFormatStateTest.ts +++ b/packages-content-model/roosterjs-content-model-editor/test/modelApi/common/retrieveModelFormatStateTest.ts @@ -1,4 +1,4 @@ -import * as iterateSelections from '../../../lib/modelApi/selection/iterateSelections'; +import * as iterateSelections from 'roosterjs-content-model-core/lib/publicApi/selection/iterateSelections'; import { applyTableFormat } from '../../../lib/modelApi/table/applyTableFormat'; import { ContentModelFormatState, ContentModelSegmentFormat } from 'roosterjs-content-model-types'; import { retrieveModelFormatState } from '../../../lib/modelApi/common/retrieveModelFormatState'; diff --git a/packages-content-model/roosterjs-content-model-editor/test/modelApi/format/applyPendingFormatTest.ts b/packages-content-model/roosterjs-content-model-editor/test/modelApi/format/applyPendingFormatTest.ts index d827fe32175..e6a9d10837a 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/modelApi/format/applyPendingFormatTest.ts +++ b/packages-content-model/roosterjs-content-model-editor/test/modelApi/format/applyPendingFormatTest.ts @@ -1,4 +1,4 @@ -import * as iterateSelections from '../../../lib/modelApi/selection/iterateSelections'; +import * as iterateSelections from 'roosterjs-content-model-core/lib/publicApi/selection/iterateSelections'; import * as normalizeContentModel from 'roosterjs-content-model-dom/lib/modelApi/common/normalizeContentModel'; import { applyPendingFormat } from '../../../lib/modelApi/format/applyPendingFormat'; import { IContentModelEditor } from '../../../lib/publicTypes/IContentModelEditor'; diff --git a/packages-content-model/roosterjs-content-model-editor/test/modelApi/selection/collectSelectionsTest.ts b/packages-content-model/roosterjs-content-model-editor/test/modelApi/selection/collectSelectionsTest.ts index 4bf8312389f..8f31a71a522 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/modelApi/selection/collectSelectionsTest.ts +++ b/packages-content-model/roosterjs-content-model-editor/test/modelApi/selection/collectSelectionsTest.ts @@ -1,4 +1,4 @@ -import * as iterateSelections from '../../../lib/modelApi/selection/iterateSelections'; +import * as iterateSelections from 'roosterjs-content-model-core/lib/publicApi/selection/iterateSelections'; import { ContentModelBlock, ContentModelBlockGroup, diff --git a/packages-content-model/roosterjs-content-model-editor/test/publicApi/entity/insertEntityTest.ts b/packages-content-model/roosterjs-content-model-editor/test/publicApi/entity/insertEntityTest.ts index d9217e1c383..95bfbf5d206 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/publicApi/entity/insertEntityTest.ts +++ b/packages-content-model/roosterjs-content-model-editor/test/publicApi/entity/insertEntityTest.ts @@ -1,7 +1,7 @@ import * as insertEntityModel from '../../../lib/modelApi/entity/insertEntityModel'; import * as normalizeContentModel from 'roosterjs-content-model-dom/lib/modelApi/common/normalizeContentModel'; import insertEntity from '../../../lib/publicApi/entity/insertEntity'; -import { ChangeSource } from '../../../lib/publicTypes/ChangeSource'; +import { ChangeSource } from 'roosterjs-content-model-core'; import { IContentModelEditor } from '../../../lib/publicTypes/IContentModelEditor'; import { FormatWithContentModelContext, diff --git a/packages-content-model/roosterjs-content-model-editor/test/publicApi/format/getFormatStateTest.ts b/packages-content-model/roosterjs-content-model-editor/test/publicApi/format/getFormatStateTest.ts index 05057a68839..b1800c8e780 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/publicApi/format/getFormatStateTest.ts +++ b/packages-content-model/roosterjs-content-model-editor/test/publicApi/format/getFormatStateTest.ts @@ -1,4 +1,4 @@ -import * as getSelectionRootNode from '../../../lib/modelApi/selection/getSelectionRootNode'; +import * as getSelectionRootNode from 'roosterjs-content-model-core/lib/publicApi/selection/getSelectionRootNode'; import * as retrieveModelFormatState from '../../../lib/modelApi/common/retrieveModelFormatState'; import { ContentModelFormatState, DomToModelContext } from 'roosterjs-content-model-types'; import { IContentModelEditor } from '../../../lib/publicTypes/IContentModelEditor'; diff --git a/packages-content-model/roosterjs-content-model-editor/test/publicApi/link/insertLinkTest.ts b/packages-content-model/roosterjs-content-model-editor/test/publicApi/link/insertLinkTest.ts index f627da244a7..dafb43b835b 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/publicApi/link/insertLinkTest.ts +++ b/packages-content-model/roosterjs-content-model-editor/test/publicApi/link/insertLinkTest.ts @@ -1,6 +1,6 @@ import ContentModelEditor from '../../../lib/editor/ContentModelEditor'; import insertLink from '../../../lib/publicApi/link/insertLink'; -import { ChangeSource } from '../../../lib/publicTypes/ChangeSource'; +import { ChangeSource } from 'roosterjs-content-model-core'; import { IContentModelEditor } from '../../../lib/publicTypes/IContentModelEditor'; import { PluginEventType } from 'roosterjs-editor-types'; import { diff --git a/packages-content-model/roosterjs-content-model-editor/test/publicApi/selection/getSelectedSegmentsTest.ts b/packages-content-model/roosterjs-content-model-editor/test/publicApi/selection/getSelectedSegmentsTest.ts index 0fb7ee2c42b..2e9fa06beba 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/publicApi/selection/getSelectedSegmentsTest.ts +++ b/packages-content-model/roosterjs-content-model-editor/test/publicApi/selection/getSelectedSegmentsTest.ts @@ -1,4 +1,4 @@ -import * as iterateSelections from '../../../lib/modelApi/selection/iterateSelections'; +import * as iterateSelections from 'roosterjs-content-model-core/lib/publicApi/selection/iterateSelections'; import getSelectedSegments from '../../../lib/publicApi/selection/getSelectedSegments'; import { ContentModelBlock, diff --git a/packages-content-model/roosterjs-content-model-plugins/lib/edit/keyboardDelete.ts b/packages-content-model/roosterjs-content-model-plugins/lib/edit/keyboardDelete.ts index a68e2f8140f..7a72552d91c 100644 --- a/packages-content-model/roosterjs-content-model-plugins/lib/edit/keyboardDelete.ts +++ b/packages-content-model/roosterjs-content-model-plugins/lib/edit/keyboardDelete.ts @@ -1,5 +1,6 @@ -import { ChangeSource, deleteSelection, isModifierKey } from 'roosterjs-content-model-editor'; +import { ChangeSource } from 'roosterjs-content-model-core'; import { deleteAllSegmentBefore } from './deleteSteps/deleteAllSegmentBefore'; +import { deleteSelection, isModifierKey } from 'roosterjs-content-model-editor'; import { isNodeOfType } from 'roosterjs-content-model-dom'; import { handleKeyboardEventResult, diff --git a/packages-content-model/roosterjs-content-model-plugins/package.json b/packages-content-model/roosterjs-content-model-plugins/package.json index 1af019fc5c2..e17cccbee0c 100644 --- a/packages-content-model/roosterjs-content-model-plugins/package.json +++ b/packages-content-model/roosterjs-content-model-plugins/package.json @@ -6,6 +6,7 @@ "roosterjs-editor-types": "", "roosterjs-editor-dom": "", "roosterjs-editor-core": "", + "roosterjs-content-model-core": "", "roosterjs-content-model-editor": "", "roosterjs-content-model-dom": "", "roosterjs-content-model-types": "" diff --git a/packages-content-model/roosterjs-content-model-plugins/test/edit/keyboardDeleteTest.ts b/packages-content-model/roosterjs-content-model-plugins/test/edit/keyboardDeleteTest.ts index 403e30d55af..868f433ab1c 100644 --- a/packages-content-model/roosterjs-content-model-plugins/test/edit/keyboardDeleteTest.ts +++ b/packages-content-model/roosterjs-content-model-plugins/test/edit/keyboardDeleteTest.ts @@ -1,10 +1,11 @@ import * as deleteSelection from 'roosterjs-content-model-editor/lib/publicApi/selection/deleteSelection'; import * as handleKeyboardEventResult from '../../lib/edit/handleKeyboardEventCommon'; -import { ChangeSource, IContentModelEditor } from 'roosterjs-content-model-editor'; +import { ChangeSource } from 'roosterjs-content-model-core'; import { ContentModelDocument, DOMSelection } from 'roosterjs-content-model-types'; import { deleteAllSegmentBefore } from '../../lib/edit/deleteSteps/deleteAllSegmentBefore'; import { DeleteResult, DeleteSelectionStep } from 'roosterjs-content-model-types'; import { editingTestCommon } from './editingTestCommon'; +import { IContentModelEditor } from 'roosterjs-content-model-editor'; import { keyboardDelete } from '../../lib/edit/keyboardDelete'; import { Keys } from 'roosterjs-editor-types'; import { diff --git a/packages-content-model/roosterjs-content-model-plugins/test/paste/e2e/cmPasteFromWordTest.ts b/packages-content-model/roosterjs-content-model-plugins/test/paste/e2e/cmPasteFromWordTest.ts index ec029e34767..c364736e4b8 100644 --- a/packages-content-model/roosterjs-content-model-plugins/test/paste/e2e/cmPasteFromWordTest.ts +++ b/packages-content-model/roosterjs-content-model-plugins/test/paste/e2e/cmPasteFromWordTest.ts @@ -1,8 +1,9 @@ import * as wordFile from '../../../lib/paste/WordDesktop/processPastedContentFromWordDesktop'; import { ClipboardData } from 'roosterjs-editor-types'; -import { cloneModel, IContentModelEditor, paste } from 'roosterjs-content-model-editor'; +import { cloneModel } from 'roosterjs-content-model-core'; import { DomToModelOption } from 'roosterjs-content-model-types'; import { expectEqual, initEditor } from './testUtils'; +import { IContentModelEditor, paste } from 'roosterjs-content-model-editor'; import { itChromeOnly } from 'roosterjs-editor-dom/test/DomTestHelper'; import { tableProcessor } from 'roosterjs-content-model-dom'; diff --git a/packages-content-model/roosterjs-content-model-plugins/test/paste/e2e/testUtils.ts b/packages-content-model/roosterjs-content-model-plugins/test/paste/e2e/testUtils.ts index 89b2b719981..025c0d7882e 100644 --- a/packages-content-model/roosterjs-content-model-plugins/test/paste/e2e/testUtils.ts +++ b/packages-content-model/roosterjs-content-model-plugins/test/paste/e2e/testUtils.ts @@ -1,10 +1,10 @@ +import { cloneModel } from 'roosterjs-content-model-core'; import { ContentModelDocument } from 'roosterjs-content-model-types'; import { ContentModelPastePlugin } from '../../../lib/paste/ContentModelPastePlugin'; import { ContentModelEditorOptions, ContentModelEditor, IContentModelEditor, - cloneModel, } from 'roosterjs-content-model-editor'; export function initEditor(id: string): IContentModelEditor { diff --git a/packages-content-model/roosterjs-content-model-plugins/test/paste/processPastedContentFromWacTest.ts b/packages-content-model/roosterjs-content-model-plugins/test/paste/processPastedContentFromWacTest.ts index 36330c28ba6..e505f48d5a0 100644 --- a/packages-content-model/roosterjs-content-model-plugins/test/paste/processPastedContentFromWacTest.ts +++ b/packages-content-model/roosterjs-content-model-plugins/test/paste/processPastedContentFromWacTest.ts @@ -6,7 +6,7 @@ import { processPastedContentWacComponents } from '../../lib/paste/WacComponents import { listItemMetadataApplier, listLevelMetadataApplier, -} from 'roosterjs-content-model-editor/lib/domUtils/metadata/updateListMetadata'; +} from 'roosterjs-content-model-core/lib/metadata/updateListMetadata'; import { contentModelToDom, diff --git a/packages-content-model/roosterjs-content-model-plugins/test/paste/processPastedContentFromWordDesktopTest.ts b/packages-content-model/roosterjs-content-model-plugins/test/paste/processPastedContentFromWordDesktopTest.ts index 1e47fe03eb2..8c063b74d74 100644 --- a/packages-content-model/roosterjs-content-model-plugins/test/paste/processPastedContentFromWordDesktopTest.ts +++ b/packages-content-model/roosterjs-content-model-plugins/test/paste/processPastedContentFromWordDesktopTest.ts @@ -5,7 +5,7 @@ import { processPastedContentFromWordDesktop } from '../../lib/paste/WordDesktop import { listItemMetadataApplier, listLevelMetadataApplier, -} from 'roosterjs-content-model-editor/lib/domUtils/metadata/updateListMetadata'; +} from 'roosterjs-content-model-core/lib/metadata/updateListMetadata'; import { contentModelToDom, createDomToModelContext, diff --git a/packages-content-model/roosterjs-content-model-types/lib/editor/StandaloneEditorCore.ts b/packages-content-model/roosterjs-content-model-types/lib/editor/StandaloneEditorCore.ts index 51b2f142d30..8be1e5cf3d1 100644 --- a/packages-content-model/roosterjs-content-model-types/lib/editor/StandaloneEditorCore.ts +++ b/packages-content-model/roosterjs-content-model-types/lib/editor/StandaloneEditorCore.ts @@ -1,4 +1,4 @@ -import type { EditorCore } from 'roosterjs-editor-types'; +import type { EditorCore, SwitchShadowEdit } from 'roosterjs-editor-types'; import type { ContentModelDocument } from '../group/ContentModelDocument'; import type { ContentModelPluginState } from '../pluginState/ContentModelPluginState'; import type { DOMSelection } from '../selection/DOMSelection'; @@ -125,6 +125,9 @@ export interface StandaloneCoreApiMap { * @param options More options, see FormatWithContentModelOptions */ formatContentModel: FormatContentModel; + + // TODO: This is copied from legacy editor core, will be ported to use new types later + switchShadowEdit: SwitchShadowEdit; } /**