roosterjs-editor-adapter 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +25 -0
- package/README.md +262 -0
- package/lib/corePlugins/BridgePlugin.d.ts +73 -0
- package/lib/corePlugins/BridgePlugin.js +124 -0
- package/lib/corePlugins/BridgePlugin.js.map +1 -0
- package/lib/corePlugins/EditPlugin.d.ts +6 -0
- package/lib/corePlugins/EditPlugin.js +89 -0
- package/lib/corePlugins/EditPlugin.js.map +1 -0
- package/lib/editor/DarkColorHandlerImpl.d.ts +6 -0
- package/lib/editor/DarkColorHandlerImpl.js +134 -0
- package/lib/editor/DarkColorHandlerImpl.js.map +1 -0
- package/lib/editor/EditorAdapter.d.ts +341 -0
- package/lib/editor/EditorAdapter.js +843 -0
- package/lib/editor/EditorAdapter.js.map +1 -0
- package/lib/editor/utils/buildRangeEx.d.ts +5 -0
- package/lib/editor/utils/buildRangeEx.js +81 -0
- package/lib/editor/utils/buildRangeEx.js.map +1 -0
- package/lib/editor/utils/eventConverter.d.ts +15 -0
- package/lib/editor/utils/eventConverter.js +463 -0
- package/lib/editor/utils/eventConverter.js.map +1 -0
- package/lib/editor/utils/insertNode.d.ts +7 -0
- package/lib/editor/utils/insertNode.js +147 -0
- package/lib/editor/utils/insertNode.js.map +1 -0
- package/lib/editor/utils/selectionConverter.d.ts +10 -0
- package/lib/editor/utils/selectionConverter.js +79 -0
- package/lib/editor/utils/selectionConverter.js.map +1 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +6 -0
- package/lib/index.js.map +1 -0
- package/lib/publicTypes/BeforePasteAdapterEvent.d.ts +15 -0
- package/lib/publicTypes/BeforePasteAdapterEvent.js +3 -0
- package/lib/publicTypes/BeforePasteAdapterEvent.js.map +1 -0
- package/lib/publicTypes/EditorAdapterOptions.d.ts +20 -0
- package/lib/publicTypes/EditorAdapterOptions.js +3 -0
- package/lib/publicTypes/EditorAdapterOptions.js.map +1 -0
- package/lib-amd/corePlugins/BridgePlugin.d.ts +73 -0
- package/lib-amd/corePlugins/BridgePlugin.js +122 -0
- package/lib-amd/corePlugins/BridgePlugin.js.map +1 -0
- package/lib-amd/corePlugins/EditPlugin.d.ts +6 -0
- package/lib-amd/corePlugins/EditPlugin.js +90 -0
- package/lib-amd/corePlugins/EditPlugin.js.map +1 -0
- package/lib-amd/editor/DarkColorHandlerImpl.d.ts +6 -0
- package/lib-amd/editor/DarkColorHandlerImpl.js +135 -0
- package/lib-amd/editor/DarkColorHandlerImpl.js.map +1 -0
- package/lib-amd/editor/EditorAdapter.d.ts +341 -0
- package/lib-amd/editor/EditorAdapter.js +836 -0
- package/lib-amd/editor/EditorAdapter.js.map +1 -0
- package/lib-amd/editor/utils/buildRangeEx.d.ts +5 -0
- package/lib-amd/editor/utils/buildRangeEx.js +82 -0
- package/lib-amd/editor/utils/buildRangeEx.js.map +1 -0
- package/lib-amd/editor/utils/eventConverter.d.ts +15 -0
- package/lib-amd/editor/utils/eventConverter.js +463 -0
- package/lib-amd/editor/utils/eventConverter.js.map +1 -0
- package/lib-amd/editor/utils/insertNode.d.ts +7 -0
- package/lib-amd/editor/utils/insertNode.js +148 -0
- package/lib-amd/editor/utils/insertNode.js.map +1 -0
- package/lib-amd/editor/utils/selectionConverter.d.ts +10 -0
- package/lib-amd/editor/utils/selectionConverter.js +79 -0
- package/lib-amd/editor/utils/selectionConverter.js.map +1 -0
- package/lib-amd/index.d.ts +3 -0
- package/lib-amd/index.js +7 -0
- package/lib-amd/index.js.map +1 -0
- package/lib-amd/publicTypes/BeforePasteAdapterEvent.d.ts +15 -0
- package/lib-amd/publicTypes/BeforePasteAdapterEvent.js +5 -0
- package/lib-amd/publicTypes/BeforePasteAdapterEvent.js.map +1 -0
- package/lib-amd/publicTypes/EditorAdapterOptions.d.ts +20 -0
- package/lib-amd/publicTypes/EditorAdapterOptions.js +5 -0
- package/lib-amd/publicTypes/EditorAdapterOptions.js.map +1 -0
- package/lib-mjs/corePlugins/BridgePlugin.d.ts +73 -0
- package/lib-mjs/corePlugins/BridgePlugin.js +120 -0
- package/lib-mjs/corePlugins/BridgePlugin.js.map +1 -0
- package/lib-mjs/corePlugins/EditPlugin.d.ts +6 -0
- package/lib-mjs/corePlugins/EditPlugin.js +85 -0
- package/lib-mjs/corePlugins/EditPlugin.js.map +1 -0
- package/lib-mjs/editor/DarkColorHandlerImpl.d.ts +6 -0
- package/lib-mjs/editor/DarkColorHandlerImpl.js +130 -0
- package/lib-mjs/editor/DarkColorHandlerImpl.js.map +1 -0
- package/lib-mjs/editor/EditorAdapter.d.ts +341 -0
- package/lib-mjs/editor/EditorAdapter.js +840 -0
- package/lib-mjs/editor/EditorAdapter.js.map +1 -0
- package/lib-mjs/editor/utils/buildRangeEx.d.ts +5 -0
- package/lib-mjs/editor/utils/buildRangeEx.js +77 -0
- package/lib-mjs/editor/utils/buildRangeEx.js.map +1 -0
- package/lib-mjs/editor/utils/eventConverter.d.ts +15 -0
- package/lib-mjs/editor/utils/eventConverter.js +458 -0
- package/lib-mjs/editor/utils/eventConverter.js.map +1 -0
- package/lib-mjs/editor/utils/insertNode.d.ts +7 -0
- package/lib-mjs/editor/utils/insertNode.js +143 -0
- package/lib-mjs/editor/utils/insertNode.js.map +1 -0
- package/lib-mjs/editor/utils/selectionConverter.d.ts +10 -0
- package/lib-mjs/editor/utils/selectionConverter.js +74 -0
- package/lib-mjs/editor/utils/selectionConverter.js.map +1 -0
- package/lib-mjs/index.d.ts +3 -0
- package/lib-mjs/index.js +2 -0
- package/lib-mjs/index.js.map +1 -0
- package/lib-mjs/publicTypes/BeforePasteAdapterEvent.d.ts +15 -0
- package/lib-mjs/publicTypes/BeforePasteAdapterEvent.js +2 -0
- package/lib-mjs/publicTypes/BeforePasteAdapterEvent.js.map +1 -0
- package/lib-mjs/publicTypes/EditorAdapterOptions.d.ts +20 -0
- package/lib-mjs/publicTypes/EditorAdapterOptions.js +2 -0
- package/lib-mjs/publicTypes/EditorAdapterOptions.js.map +1 -0
- package/package.json +21 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.insertNode = void 0;
|
|
4
|
+
var roosterjs_editor_dom_1 = require("roosterjs-editor-dom");
|
|
5
|
+
function getInitialRange(selection, option) {
|
|
6
|
+
// Selection start replaces based on the current selection.
|
|
7
|
+
// Range inserts based on a provided range.
|
|
8
|
+
// Both have the potential to use the current selection to restore cursor position
|
|
9
|
+
// So in both cases we need to store the selection state.
|
|
10
|
+
var range = (selection === null || selection === void 0 ? void 0 : selection.type) == 'range' ? selection.range : null;
|
|
11
|
+
var rangeToRestore = null;
|
|
12
|
+
if (option.position == 5 /* Range */) {
|
|
13
|
+
rangeToRestore = range;
|
|
14
|
+
range = option.range;
|
|
15
|
+
}
|
|
16
|
+
else if (range) {
|
|
17
|
+
rangeToRestore = range.cloneRange();
|
|
18
|
+
}
|
|
19
|
+
return { range: range, rangeToRestore: rangeToRestore };
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* @internal
|
|
23
|
+
* Insert a DOM node into editor content
|
|
24
|
+
*/
|
|
25
|
+
function insertNode(contentDiv, selection, node, option) {
|
|
26
|
+
var _a, _b;
|
|
27
|
+
switch (option.position) {
|
|
28
|
+
case 0 /* Begin */:
|
|
29
|
+
case 1 /* End */: {
|
|
30
|
+
var isBegin = option.position == 0 /* Begin */;
|
|
31
|
+
var block = (0, roosterjs_editor_dom_1.getFirstLastBlockElement)(contentDiv, isBegin);
|
|
32
|
+
var insertedNode_1;
|
|
33
|
+
if (block) {
|
|
34
|
+
var refNode = isBegin ? block.getStartNode() : block.getEndNode();
|
|
35
|
+
if (option.insertOnNewLine ||
|
|
36
|
+
refNode.nodeType == 3 /* Text */ ||
|
|
37
|
+
(0, roosterjs_editor_dom_1.isVoidHtmlElement)(refNode)) {
|
|
38
|
+
// For insert on new line, or refNode is text or void html element (HR, BR etc.)
|
|
39
|
+
// which cannot have children, i.e. <div>hello<br>world</div>. 'hello', 'world' are the
|
|
40
|
+
// first and last node. Insert before 'hello' or after 'world', but still inside DIV
|
|
41
|
+
if ((0, roosterjs_editor_dom_1.safeInstanceOf)(node, 'DocumentFragment')) {
|
|
42
|
+
// if the node to be inserted is DocumentFragment, use its childNodes as insertedNode
|
|
43
|
+
// because insertBefore() returns an empty DocumentFragment
|
|
44
|
+
insertedNode_1 = (0, roosterjs_editor_dom_1.toArray)(node.childNodes);
|
|
45
|
+
(_a = refNode.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(node, isBegin ? refNode : refNode.nextSibling);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
insertedNode_1 = (_b = refNode.parentNode) === null || _b === void 0 ? void 0 : _b.insertBefore(node, isBegin ? refNode : refNode.nextSibling);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
// if the refNode can have child, use appendChild (which is like to insert as first/last child)
|
|
53
|
+
// i.e. <div>hello</div>, the content will be inserted before/after hello
|
|
54
|
+
insertedNode_1 = refNode.insertBefore(node, isBegin ? refNode.firstChild : null);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
// No first block, this can happen when editor is empty. Use appendChild to insert the content in contentDiv
|
|
59
|
+
insertedNode_1 = contentDiv.appendChild(node);
|
|
60
|
+
}
|
|
61
|
+
// Final check to see if the inserted node is a block. If not block and the ask is to insert on new line,
|
|
62
|
+
// add a DIV wrapping
|
|
63
|
+
if (insertedNode_1 && option.insertOnNewLine) {
|
|
64
|
+
var nodes = Array.isArray(insertedNode_1) ? insertedNode_1 : [insertedNode_1];
|
|
65
|
+
if (!(0, roosterjs_editor_dom_1.isBlockElement)(nodes[0]) || !(0, roosterjs_editor_dom_1.isBlockElement)(nodes[nodes.length - 1])) {
|
|
66
|
+
(0, roosterjs_editor_dom_1.wrap)(nodes);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
case 2 /* DomEnd */:
|
|
72
|
+
// Use appendChild to insert the node at the end of the content div.
|
|
73
|
+
var insertedNode = contentDiv.appendChild(node);
|
|
74
|
+
// Final check to see if the inserted node is a block. If not block and the ask is to insert on new line,
|
|
75
|
+
// add a DIV wrapping
|
|
76
|
+
if (insertedNode && option.insertOnNewLine && !(0, roosterjs_editor_dom_1.isBlockElement)(insertedNode)) {
|
|
77
|
+
(0, roosterjs_editor_dom_1.wrap)(insertedNode);
|
|
78
|
+
}
|
|
79
|
+
break;
|
|
80
|
+
case 5 /* Range */:
|
|
81
|
+
case 3 /* SelectionStart */:
|
|
82
|
+
var _c = getInitialRange(selection, option), range = _c.range, rangeToRestore = _c.rangeToRestore;
|
|
83
|
+
if (!range) {
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
// if to replace the selection and the selection is not collapsed, remove the the content at selection first
|
|
87
|
+
if (option.replaceSelection && !range.collapsed) {
|
|
88
|
+
range.deleteContents();
|
|
89
|
+
}
|
|
90
|
+
var pos = roosterjs_editor_dom_1.Position.getStart(range);
|
|
91
|
+
var blockElement = void 0;
|
|
92
|
+
if (option.insertOnNewLine && option.insertToRegionRoot) {
|
|
93
|
+
pos = adjustInsertPositionRegionRoot(contentDiv, range, pos);
|
|
94
|
+
}
|
|
95
|
+
else if (option.insertOnNewLine &&
|
|
96
|
+
(blockElement = (0, roosterjs_editor_dom_1.getBlockElementAtNode)(contentDiv, pos.normalize().node))) {
|
|
97
|
+
pos = adjustInsertPositionNewLine(blockElement, contentDiv, pos);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
pos = (0, roosterjs_editor_dom_1.adjustInsertPosition)(contentDiv, node, pos, range);
|
|
101
|
+
}
|
|
102
|
+
var nodeForCursor = node.nodeType == 11 /* DocumentFragment */ ? node.lastChild : node;
|
|
103
|
+
range = (0, roosterjs_editor_dom_1.createRange)(pos);
|
|
104
|
+
range.insertNode(node);
|
|
105
|
+
if (option.updateCursor && nodeForCursor) {
|
|
106
|
+
rangeToRestore = (0, roosterjs_editor_dom_1.createRange)(new roosterjs_editor_dom_1.Position(nodeForCursor, -3 /* After */).normalize());
|
|
107
|
+
}
|
|
108
|
+
return rangeToRestore
|
|
109
|
+
? {
|
|
110
|
+
type: 'range',
|
|
111
|
+
range: rangeToRestore,
|
|
112
|
+
isReverted: false,
|
|
113
|
+
}
|
|
114
|
+
: undefined;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
exports.insertNode = insertNode;
|
|
118
|
+
function adjustInsertPositionRegionRoot(contentDiv, range, position) {
|
|
119
|
+
var region = (0, roosterjs_editor_dom_1.getRegionsFromRange)(contentDiv, range, 0 /* Table */)[0];
|
|
120
|
+
var node = position.node;
|
|
121
|
+
if (region) {
|
|
122
|
+
if (node.nodeType == 3 /* Text */ && !position.isAtEnd) {
|
|
123
|
+
node = (0, roosterjs_editor_dom_1.splitTextNode)(node, position.offset, true /*returnFirstPart*/);
|
|
124
|
+
}
|
|
125
|
+
if (node != region.rootNode) {
|
|
126
|
+
while (node && node.parentNode != region.rootNode) {
|
|
127
|
+
(0, roosterjs_editor_dom_1.splitParentNode)(node, false /*splitBefore*/);
|
|
128
|
+
node = node.parentNode;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (node) {
|
|
132
|
+
position = new roosterjs_editor_dom_1.Position(node, -3 /* After */);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return position;
|
|
136
|
+
}
|
|
137
|
+
function adjustInsertPositionNewLine(blockElement, contentDiv, pos) {
|
|
138
|
+
var tempPos = new roosterjs_editor_dom_1.Position(blockElement.getEndNode(), -3 /* After */);
|
|
139
|
+
if ((0, roosterjs_editor_dom_1.safeInstanceOf)(tempPos.node, 'HTMLTableRowElement')) {
|
|
140
|
+
var div = contentDiv.ownerDocument.createElement('div');
|
|
141
|
+
var range = (0, roosterjs_editor_dom_1.createRange)(pos);
|
|
142
|
+
range.insertNode(div);
|
|
143
|
+
tempPos = new roosterjs_editor_dom_1.Position(div, 0 /* Begin */);
|
|
144
|
+
}
|
|
145
|
+
return tempPos;
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=insertNode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"insertNode.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-editor-adapter/lib/editor/utils/insertNode.ts"],"names":[],"mappings":"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","sourcesContent":["import { ContentPosition, NodeType, PositionType, RegionType } from 'roosterjs-editor-types';\r\nimport type { BlockElement, InsertOption, NodePosition } from 'roosterjs-editor-types';\r\nimport {\r\n createRange,\r\n getBlockElementAtNode,\r\n getFirstLastBlockElement,\r\n isBlockElement,\r\n isVoidHtmlElement,\r\n Position,\r\n safeInstanceOf,\r\n toArray,\r\n wrap,\r\n adjustInsertPosition,\r\n getRegionsFromRange,\r\n splitTextNode,\r\n splitParentNode,\r\n} from 'roosterjs-editor-dom';\r\nimport type { DOMSelection } from 'roosterjs-content-model-types';\r\n\r\nfunction getInitialRange(\r\n selection: DOMSelection | null,\r\n option: InsertOption\r\n): { range: Range | null; rangeToRestore: Range | null } {\r\n // Selection start replaces based on the current selection.\r\n // Range inserts based on a provided range.\r\n // Both have the potential to use the current selection to restore cursor position\r\n // So in both cases we need to store the selection state.\r\n let range = selection?.type == 'range' ? selection.range : null;\r\n let rangeToRestore = null;\r\n\r\n if (option.position == ContentPosition.Range) {\r\n rangeToRestore = range;\r\n range = option.range;\r\n } else if (range) {\r\n rangeToRestore = range.cloneRange();\r\n }\r\n\r\n return { range, rangeToRestore };\r\n}\r\n\r\n/**\r\n * @internal\r\n * Insert a DOM node into editor content\r\n */\r\nexport function insertNode(\r\n contentDiv: HTMLDivElement,\r\n selection: DOMSelection | null,\r\n node: Node,\r\n option: InsertOption\r\n): DOMSelection | undefined {\r\n switch (option.position) {\r\n case ContentPosition.Begin:\r\n case ContentPosition.End: {\r\n const isBegin = option.position == ContentPosition.Begin;\r\n const block = getFirstLastBlockElement(contentDiv, isBegin);\r\n let insertedNode: Node | Node[] | undefined;\r\n if (block) {\r\n const refNode = isBegin ? block.getStartNode() : block.getEndNode();\r\n if (\r\n option.insertOnNewLine ||\r\n refNode.nodeType == NodeType.Text ||\r\n isVoidHtmlElement(refNode)\r\n ) {\r\n // For insert on new line, or refNode is text or void html element (HR, BR etc.)\r\n // which cannot have children, i.e. <div>hello<br>world</div>. 'hello', 'world' are the\r\n // first and last node. Insert before 'hello' or after 'world', but still inside DIV\r\n if (safeInstanceOf(node, 'DocumentFragment')) {\r\n // if the node to be inserted is DocumentFragment, use its childNodes as insertedNode\r\n // because insertBefore() returns an empty DocumentFragment\r\n insertedNode = toArray(node.childNodes);\r\n refNode.parentNode?.insertBefore(\r\n node,\r\n isBegin ? refNode : refNode.nextSibling\r\n );\r\n } else {\r\n insertedNode = refNode.parentNode?.insertBefore(\r\n node,\r\n isBegin ? refNode : refNode.nextSibling\r\n );\r\n }\r\n } else {\r\n // if the refNode can have child, use appendChild (which is like to insert as first/last child)\r\n // i.e. <div>hello</div>, the content will be inserted before/after hello\r\n insertedNode = refNode.insertBefore(node, isBegin ? refNode.firstChild : null);\r\n }\r\n } else {\r\n // No first block, this can happen when editor is empty. Use appendChild to insert the content in contentDiv\r\n insertedNode = contentDiv.appendChild(node);\r\n }\r\n\r\n // Final check to see if the inserted node is a block. If not block and the ask is to insert on new line,\r\n // add a DIV wrapping\r\n if (insertedNode && option.insertOnNewLine) {\r\n const nodes = Array.isArray(insertedNode) ? insertedNode : [insertedNode];\r\n if (!isBlockElement(nodes[0]) || !isBlockElement(nodes[nodes.length - 1])) {\r\n wrap(nodes);\r\n }\r\n }\r\n\r\n break;\r\n }\r\n case ContentPosition.DomEnd:\r\n // Use appendChild to insert the node at the end of the content div.\r\n const insertedNode = contentDiv.appendChild(node);\r\n // Final check to see if the inserted node is a block. If not block and the ask is to insert on new line,\r\n // add a DIV wrapping\r\n if (insertedNode && option.insertOnNewLine && !isBlockElement(insertedNode)) {\r\n wrap(insertedNode);\r\n }\r\n break;\r\n case ContentPosition.Range:\r\n case ContentPosition.SelectionStart:\r\n let { range, rangeToRestore } = getInitialRange(selection, option);\r\n if (!range) {\r\n break;\r\n }\r\n\r\n // if to replace the selection and the selection is not collapsed, remove the the content at selection first\r\n if (option.replaceSelection && !range.collapsed) {\r\n range.deleteContents();\r\n }\r\n\r\n let pos: NodePosition = Position.getStart(range);\r\n let blockElement: BlockElement | null;\r\n\r\n if (option.insertOnNewLine && option.insertToRegionRoot) {\r\n pos = adjustInsertPositionRegionRoot(contentDiv, range, pos);\r\n } else if (\r\n option.insertOnNewLine &&\r\n (blockElement = getBlockElementAtNode(contentDiv, pos.normalize().node))\r\n ) {\r\n pos = adjustInsertPositionNewLine(blockElement, contentDiv, pos);\r\n } else {\r\n pos = adjustInsertPosition(contentDiv, node, pos, range);\r\n }\r\n\r\n const nodeForCursor =\r\n node.nodeType == NodeType.DocumentFragment ? node.lastChild : node;\r\n\r\n range = createRange(pos);\r\n range.insertNode(node);\r\n\r\n if (option.updateCursor && nodeForCursor) {\r\n rangeToRestore = createRange(\r\n new Position(nodeForCursor, PositionType.After).normalize()\r\n );\r\n }\r\n\r\n return rangeToRestore\r\n ? {\r\n type: 'range',\r\n range: rangeToRestore,\r\n isReverted: false,\r\n }\r\n : undefined;\r\n }\r\n}\r\n\r\nfunction adjustInsertPositionRegionRoot(\r\n contentDiv: HTMLDivElement,\r\n range: Range,\r\n position: NodePosition\r\n) {\r\n const region = getRegionsFromRange(contentDiv, range, RegionType.Table)[0];\r\n let node: Node | null = position.node;\r\n\r\n if (region) {\r\n if (node.nodeType == NodeType.Text && !position.isAtEnd) {\r\n node = splitTextNode(node as Text, position.offset, true /*returnFirstPart*/);\r\n }\r\n\r\n if (node != region.rootNode) {\r\n while (node && node.parentNode != region.rootNode) {\r\n splitParentNode(node, false /*splitBefore*/);\r\n node = node.parentNode;\r\n }\r\n }\r\n\r\n if (node) {\r\n position = new Position(node, PositionType.After);\r\n }\r\n }\r\n\r\n return position;\r\n}\r\n\r\nfunction adjustInsertPositionNewLine(\r\n blockElement: BlockElement,\r\n contentDiv: HTMLDivElement,\r\n pos: Position\r\n) {\r\n let tempPos = new Position(blockElement.getEndNode(), PositionType.After);\r\n if (safeInstanceOf(tempPos.node, 'HTMLTableRowElement')) {\r\n const div = contentDiv.ownerDocument.createElement('div');\r\n const range = createRange(pos);\r\n range.insertNode(div);\r\n tempPos = new Position(div, PositionType.Begin);\r\n }\r\n return tempPos;\r\n}\r\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { DOMSelection } from 'roosterjs-content-model-types';
|
|
2
|
+
import type { SelectionRangeEx } from 'roosterjs-editor-types';
|
|
3
|
+
/**
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export declare function convertRangeExToDomSelection(rangeEx: SelectionRangeEx | null): DOMSelection | null;
|
|
7
|
+
/**
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export declare function convertDomSelectionToRangeEx(selection: DOMSelection | null): SelectionRangeEx;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.convertDomSelectionToRangeEx = exports.convertRangeExToDomSelection = void 0;
|
|
4
|
+
var roosterjs_editor_dom_1 = require("roosterjs-editor-dom");
|
|
5
|
+
var roosterjs_content_model_core_1 = require("roosterjs-content-model-core");
|
|
6
|
+
// In theory, all functions below are not necessary. We keep these functions here only for compatibility with old IEditor interface
|
|
7
|
+
/**
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
function convertRangeExToDomSelection(rangeEx) {
|
|
11
|
+
switch (rangeEx === null || rangeEx === void 0 ? void 0 : rangeEx.type) {
|
|
12
|
+
case 2 /* ImageSelection */:
|
|
13
|
+
return {
|
|
14
|
+
type: 'image',
|
|
15
|
+
image: rangeEx.image,
|
|
16
|
+
};
|
|
17
|
+
case 0 /* Normal */:
|
|
18
|
+
return rangeEx.ranges.length > 0
|
|
19
|
+
? {
|
|
20
|
+
type: 'range',
|
|
21
|
+
range: rangeEx.ranges[0],
|
|
22
|
+
isReverted: false,
|
|
23
|
+
}
|
|
24
|
+
: null;
|
|
25
|
+
case 1 /* TableSelection */:
|
|
26
|
+
return rangeEx.coordinates
|
|
27
|
+
? {
|
|
28
|
+
type: 'table',
|
|
29
|
+
table: rangeEx.table,
|
|
30
|
+
firstColumn: rangeEx.coordinates.firstCell.x,
|
|
31
|
+
firstRow: rangeEx.coordinates.firstCell.y,
|
|
32
|
+
lastColumn: rangeEx.coordinates.lastCell.x,
|
|
33
|
+
lastRow: rangeEx.coordinates.lastCell.y,
|
|
34
|
+
}
|
|
35
|
+
: null;
|
|
36
|
+
default:
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.convertRangeExToDomSelection = convertRangeExToDomSelection;
|
|
41
|
+
/**
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
44
|
+
function convertDomSelectionToRangeEx(selection) {
|
|
45
|
+
switch (selection === null || selection === void 0 ? void 0 : selection.type) {
|
|
46
|
+
case 'image':
|
|
47
|
+
return {
|
|
48
|
+
type: 2 /* ImageSelection */,
|
|
49
|
+
image: selection.image,
|
|
50
|
+
areAllCollapsed: false,
|
|
51
|
+
ranges: [(0, roosterjs_editor_dom_1.createRange)(selection.image)],
|
|
52
|
+
};
|
|
53
|
+
case 'range':
|
|
54
|
+
return {
|
|
55
|
+
type: 0 /* Normal */,
|
|
56
|
+
ranges: [selection.range],
|
|
57
|
+
areAllCollapsed: selection.range.collapsed,
|
|
58
|
+
};
|
|
59
|
+
case 'table':
|
|
60
|
+
return {
|
|
61
|
+
type: 1 /* TableSelection */,
|
|
62
|
+
ranges: (0, roosterjs_content_model_core_1.createTableRanges)(selection),
|
|
63
|
+
areAllCollapsed: false,
|
|
64
|
+
table: selection.table,
|
|
65
|
+
coordinates: {
|
|
66
|
+
firstCell: { x: selection.firstColumn, y: selection.firstRow },
|
|
67
|
+
lastCell: { x: selection.lastColumn, y: selection.lastRow },
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
default:
|
|
71
|
+
return {
|
|
72
|
+
type: 0 /* Normal */,
|
|
73
|
+
ranges: [],
|
|
74
|
+
areAllCollapsed: true,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
exports.convertDomSelectionToRangeEx = convertDomSelectionToRangeEx;
|
|
79
|
+
//# sourceMappingURL=selectionConverter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectionConverter.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-editor-adapter/lib/editor/utils/selectionConverter.ts"],"names":[],"mappings":";;;AAAA,6DAAmD;AACnD,6EAAiE;AAKjE,mIAAmI;AAEnI;;GAEG;AACH,SAAgB,4BAA4B,CACxC,OAAgC;IAEhC,QAAQ,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,IAAI,EAAE;QACnB;YACI,OAAO;gBACH,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,OAAO,CAAC,KAAK;aACvB,CAAC;QAEN;YACI,OAAO,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;gBAC5B,CAAC,CAAC;oBACI,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;oBACxB,UAAU,EAAE,KAAK;iBACpB;gBACH,CAAC,CAAC,IAAI,CAAC;QAEf;YACI,OAAO,OAAO,CAAC,WAAW;gBACtB,CAAC,CAAC;oBACI,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE,OAAO,CAAC,KAAK;oBACpB,WAAW,EAAE,OAAO,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;oBAC5C,QAAQ,EAAE,OAAO,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;oBACzC,UAAU,EAAE,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;oBAC1C,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;iBAC1C;gBACH,CAAC,CAAC,IAAI,CAAC;QAEf;YACI,OAAO,IAAI,CAAC;KACnB;AACL,CAAC;AAlCD,oEAkCC;AAED;;GAEG;AACH,SAAgB,4BAA4B,CAAC,SAA8B;IACvE,QAAQ,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,IAAI,EAAE;QACrB,KAAK,OAAO;YACR,OAAO;gBACH,IAAI,wBAAoC;gBACxC,KAAK,EAAE,SAAS,CAAC,KAAK;gBACtB,eAAe,EAAE,KAAK;gBACtB,MAAM,EAAE,CAAC,IAAA,kCAAW,EAAC,SAAS,CAAC,KAAK,CAAC,CAAC;aACzC,CAAC;QAEN,KAAK,OAAO;YACR,OAAO;gBACH,IAAI,gBAA4B;gBAChC,MAAM,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC;gBACzB,eAAe,EAAE,SAAS,CAAC,KAAK,CAAC,SAAS;aAC7C,CAAC;QAEN,KAAK,OAAO;YACR,OAAO;gBACH,IAAI,wBAAoC;gBACxC,MAAM,EAAE,IAAA,gDAAiB,EAAC,SAAS,CAAC;gBACpC,eAAe,EAAE,KAAK;gBACtB,KAAK,EAAE,SAAS,CAAC,KAAK;gBACtB,WAAW,EAAE;oBACT,SAAS,EAAE,EAAE,CAAC,EAAE,SAAS,CAAC,WAAW,EAAE,CAAC,EAAE,SAAS,CAAC,QAAQ,EAAE;oBAC9D,QAAQ,EAAE,EAAE,CAAC,EAAE,SAAS,CAAC,UAAU,EAAE,CAAC,EAAE,SAAS,CAAC,OAAO,EAAE;iBAC9D;aACJ,CAAC;QAEN;YACI,OAAO;gBACH,IAAI,gBAA4B;gBAChC,MAAM,EAAE,EAAE;gBACV,eAAe,EAAE,IAAI;aACxB,CAAC;KACT;AACL,CAAC;AApCD,oEAoCC","sourcesContent":["import { createRange } from 'roosterjs-editor-dom';\r\nimport { createTableRanges } from 'roosterjs-content-model-core';\r\nimport { SelectionRangeTypes } from 'roosterjs-editor-types';\r\nimport type { DOMSelection } from 'roosterjs-content-model-types';\r\nimport type { SelectionRangeEx } from 'roosterjs-editor-types';\r\n\r\n// In theory, all functions below are not necessary. We keep these functions here only for compatibility with old IEditor interface\r\n\r\n/**\r\n * @internal\r\n */\r\nexport function convertRangeExToDomSelection(\r\n rangeEx: SelectionRangeEx | null\r\n): DOMSelection | null {\r\n switch (rangeEx?.type) {\r\n case SelectionRangeTypes.ImageSelection:\r\n return {\r\n type: 'image',\r\n image: rangeEx.image,\r\n };\r\n\r\n case SelectionRangeTypes.Normal:\r\n return rangeEx.ranges.length > 0\r\n ? {\r\n type: 'range',\r\n range: rangeEx.ranges[0],\r\n isReverted: false,\r\n }\r\n : null;\r\n\r\n case SelectionRangeTypes.TableSelection:\r\n return rangeEx.coordinates\r\n ? {\r\n type: 'table',\r\n table: rangeEx.table,\r\n firstColumn: rangeEx.coordinates.firstCell.x,\r\n firstRow: rangeEx.coordinates.firstCell.y,\r\n lastColumn: rangeEx.coordinates.lastCell.x,\r\n lastRow: rangeEx.coordinates.lastCell.y,\r\n }\r\n : null;\r\n\r\n default:\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * @internal\r\n */\r\nexport function convertDomSelectionToRangeEx(selection: DOMSelection | null): SelectionRangeEx {\r\n switch (selection?.type) {\r\n case 'image':\r\n return {\r\n type: SelectionRangeTypes.ImageSelection,\r\n image: selection.image,\r\n areAllCollapsed: false,\r\n ranges: [createRange(selection.image)],\r\n };\r\n\r\n case 'range':\r\n return {\r\n type: SelectionRangeTypes.Normal,\r\n ranges: [selection.range],\r\n areAllCollapsed: selection.range.collapsed,\r\n };\r\n\r\n case 'table':\r\n return {\r\n type: SelectionRangeTypes.TableSelection,\r\n ranges: createTableRanges(selection),\r\n areAllCollapsed: false,\r\n table: selection.table,\r\n coordinates: {\r\n firstCell: { x: selection.firstColumn, y: selection.firstRow },\r\n lastCell: { x: selection.lastColumn, y: selection.lastRow },\r\n },\r\n };\r\n\r\n default:\r\n return {\r\n type: SelectionRangeTypes.Normal,\r\n ranges: [],\r\n areAllCollapsed: true,\r\n };\r\n }\r\n}\r\n"]}
|
package/lib/index.d.ts
ADDED
package/lib/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EditorAdapter = void 0;
|
|
4
|
+
var EditorAdapter_1 = require("./editor/EditorAdapter");
|
|
5
|
+
Object.defineProperty(exports, "EditorAdapter", { enumerable: true, get: function () { return EditorAdapter_1.EditorAdapter; } });
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../packages/roosterjs-editor-adapter/lib/index.ts"],"names":[],"mappings":";;;AAGA,wDAAuD;AAA9C,8GAAA,aAAa,OAAA","sourcesContent":["export { EditorAdapterOptions } from './publicTypes/EditorAdapterOptions';\r\nexport { BeforePasteAdapterEvent } from './publicTypes/BeforePasteAdapterEvent';\r\n\r\nexport { EditorAdapter } from './editor/EditorAdapter';\r\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { BeforePasteEvent } from 'roosterjs-editor-types';
|
|
2
|
+
import type { DomToModelOptionForSanitizing, MergePastedContentFunc } from 'roosterjs-content-model-types';
|
|
3
|
+
/**
|
|
4
|
+
* A temporary event type to be compatible with both legacy plugin and EditorAdapter
|
|
5
|
+
*/
|
|
6
|
+
export interface BeforePasteAdapterEvent extends BeforePasteEvent {
|
|
7
|
+
/**
|
|
8
|
+
* domToModel Options to use when creating the content model from the paste fragment
|
|
9
|
+
*/
|
|
10
|
+
readonly domToModelOption: DomToModelOptionForSanitizing;
|
|
11
|
+
/**
|
|
12
|
+
* customizedMerge Customized merge function to use when merging the paste fragment into the editor
|
|
13
|
+
*/
|
|
14
|
+
customizedMerge?: MergePastedContentFunc;
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BeforePasteAdapterEvent.js","sourceRoot":"","sources":["../../../../packages/roosterjs-editor-adapter/lib/publicTypes/BeforePasteAdapterEvent.ts"],"names":[],"mappings":"","sourcesContent":["import type { BeforePasteEvent } from 'roosterjs-editor-types';\r\nimport type {\r\n DomToModelOptionForSanitizing,\r\n MergePastedContentFunc,\r\n} from 'roosterjs-content-model-types';\r\n\r\n/**\r\n * A temporary event type to be compatible with both legacy plugin and EditorAdapter\r\n */\r\nexport interface BeforePasteAdapterEvent extends BeforePasteEvent {\r\n /**\r\n * domToModel Options to use when creating the content model from the paste fragment\r\n */\r\n readonly domToModelOption: DomToModelOptionForSanitizing;\r\n\r\n /**\r\n * customizedMerge Customized merge function to use when merging the paste fragment into the editor\r\n */\r\n customizedMerge?: MergePastedContentFunc;\r\n}\r\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { StandaloneEditorOptions } from 'roosterjs-content-model-types';
|
|
2
|
+
import type { EditorPlugin, ExperimentalFeatures } from 'roosterjs-editor-types';
|
|
3
|
+
/**
|
|
4
|
+
* Options for editor adapter
|
|
5
|
+
*/
|
|
6
|
+
export interface EditorAdapterOptions extends StandaloneEditorOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Initial HTML content
|
|
9
|
+
* Default value is whatever already inside the editor content DIV
|
|
10
|
+
*/
|
|
11
|
+
initialContent?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Specify the enabled experimental features
|
|
14
|
+
*/
|
|
15
|
+
experimentalFeatures?: ExperimentalFeatures[];
|
|
16
|
+
/**
|
|
17
|
+
* Legacy plugins using IEditor interface
|
|
18
|
+
*/
|
|
19
|
+
legacyPlugins?: EditorPlugin[];
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EditorAdapterOptions.js","sourceRoot":"","sources":["../../../../packages/roosterjs-editor-adapter/lib/publicTypes/EditorAdapterOptions.ts"],"names":[],"mappings":"","sourcesContent":["import type { StandaloneEditorOptions } from 'roosterjs-content-model-types';\r\nimport type { EditorPlugin, ExperimentalFeatures } from 'roosterjs-editor-types';\r\n\r\n/**\r\n * Options for editor adapter\r\n */\r\nexport interface EditorAdapterOptions extends StandaloneEditorOptions {\r\n /**\r\n * Initial HTML content\r\n * Default value is whatever already inside the editor content DIV\r\n */\r\n initialContent?: string;\r\n\r\n /**\r\n * Specify the enabled experimental features\r\n */\r\n experimentalFeatures?: ExperimentalFeatures[];\r\n\r\n /**\r\n * Legacy plugins using IEditor interface\r\n */\r\n legacyPlugins?: EditorPlugin[];\r\n}\r\n"]}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { EditorPlugin as LegacyEditorPlugin, ContextMenuProvider as LegacyContextMenuProvider, IEditor as ILegacyEditor, ExperimentalFeatures, SizeTransformer, EditPluginState, CustomData, DarkColorHandler } from 'roosterjs-editor-types';
|
|
2
|
+
import type { ContextMenuProvider, IStandaloneEditor, PluginEvent } from 'roosterjs-content-model-types';
|
|
3
|
+
/**
|
|
4
|
+
* @internal
|
|
5
|
+
* Represents the core data structure of a editor adapter
|
|
6
|
+
*/
|
|
7
|
+
export interface EditorAdapterCore {
|
|
8
|
+
/**
|
|
9
|
+
* Custom data of this editor
|
|
10
|
+
*/
|
|
11
|
+
readonly customData: Record<string, CustomData>;
|
|
12
|
+
/**
|
|
13
|
+
* Enabled experimental features
|
|
14
|
+
*/
|
|
15
|
+
readonly experimentalFeatures: ExperimentalFeatures[];
|
|
16
|
+
/**
|
|
17
|
+
* Dark model handler for the editor, used for variable-based solution.
|
|
18
|
+
* If keep it null, editor will still use original dataset-based dark mode solution.
|
|
19
|
+
*/
|
|
20
|
+
readonly darkColorHandler: DarkColorHandler;
|
|
21
|
+
/**
|
|
22
|
+
* Plugin state of EditPlugin
|
|
23
|
+
*/
|
|
24
|
+
readonly edit: EditPluginState;
|
|
25
|
+
/**
|
|
26
|
+
* Context Menu providers
|
|
27
|
+
*/
|
|
28
|
+
readonly contextMenuProviders: LegacyContextMenuProvider<any>[];
|
|
29
|
+
/**
|
|
30
|
+
* @deprecated Use zoomScale instead
|
|
31
|
+
*/
|
|
32
|
+
readonly sizeTransformer: SizeTransformer;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* @internal
|
|
36
|
+
* Act as a bridge between Standalone editor and Content Model editor, translate Standalone editor event type to legacy event type
|
|
37
|
+
*/
|
|
38
|
+
export declare class BridgePlugin implements ContextMenuProvider<any> {
|
|
39
|
+
private onInitialize;
|
|
40
|
+
private experimentalFeatures;
|
|
41
|
+
private legacyPlugins;
|
|
42
|
+
private edit;
|
|
43
|
+
private contextMenuProviders;
|
|
44
|
+
private checkExclusivelyHandling;
|
|
45
|
+
constructor(onInitialize: (core: EditorAdapterCore) => ILegacyEditor, legacyPlugins?: LegacyEditorPlugin[], experimentalFeatures?: ExperimentalFeatures[]);
|
|
46
|
+
/**
|
|
47
|
+
* Get a friendly name of this plugin
|
|
48
|
+
*/
|
|
49
|
+
getName(): string;
|
|
50
|
+
/**
|
|
51
|
+
* Initialize this plugin. This should only be called from Editor
|
|
52
|
+
* @param editor Editor instance
|
|
53
|
+
*/
|
|
54
|
+
initialize(editor: IStandaloneEditor): void;
|
|
55
|
+
/**
|
|
56
|
+
* Dispose this plugin
|
|
57
|
+
*/
|
|
58
|
+
dispose(): void;
|
|
59
|
+
willHandleEventExclusively(event: PluginEvent): boolean;
|
|
60
|
+
onPluginEvent(event: PluginEvent): void;
|
|
61
|
+
/**
|
|
62
|
+
* A callback to return context menu items
|
|
63
|
+
* @param target Target node that triggered a ContextMenu event
|
|
64
|
+
* @returns An array of context menu items, or null means no items needed
|
|
65
|
+
*/
|
|
66
|
+
getContextMenuItems(target: Node): any[];
|
|
67
|
+
private createEditorCore;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* @internal Export for test only. This function is only used for compatibility from older build
|
|
71
|
+
|
|
72
|
+
*/
|
|
73
|
+
export declare function createSizeTransformer(editor: IStandaloneEditor): SizeTransformer;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
define(["require", "exports", "tslib", "../editor/DarkColorHandlerImpl", "./EditPlugin", "../editor/utils/eventConverter"], function (require, exports, tslib_1, DarkColorHandlerImpl_1, EditPlugin_1, eventConverter_1) {
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.createSizeTransformer = exports.BridgePlugin = void 0;
|
|
5
|
+
var ExclusivelyHandleEventPluginKey = '__ExclusivelyHandleEventPlugin';
|
|
6
|
+
/**
|
|
7
|
+
* @internal
|
|
8
|
+
* Act as a bridge between Standalone editor and Content Model editor, translate Standalone editor event type to legacy event type
|
|
9
|
+
*/
|
|
10
|
+
var BridgePlugin = /** @class */ (function () {
|
|
11
|
+
function BridgePlugin(onInitialize, legacyPlugins, experimentalFeatures) {
|
|
12
|
+
if (legacyPlugins === void 0) { legacyPlugins = []; }
|
|
13
|
+
if (experimentalFeatures === void 0) { experimentalFeatures = []; }
|
|
14
|
+
this.onInitialize = onInitialize;
|
|
15
|
+
this.experimentalFeatures = experimentalFeatures;
|
|
16
|
+
var editPlugin = (0, EditPlugin_1.createEditPlugin)();
|
|
17
|
+
this.legacyPlugins = (0, tslib_1.__spreadArray)([editPlugin], (0, tslib_1.__read)(legacyPlugins.filter(function (x) { return !!x; })), false);
|
|
18
|
+
this.edit = editPlugin.getState();
|
|
19
|
+
this.contextMenuProviders = this.legacyPlugins.filter(isContextMenuProvider);
|
|
20
|
+
this.checkExclusivelyHandling = this.legacyPlugins.some(function (plugin) { return plugin.willHandleEventExclusively; });
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get a friendly name of this plugin
|
|
24
|
+
*/
|
|
25
|
+
BridgePlugin.prototype.getName = function () {
|
|
26
|
+
return 'Bridge';
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Initialize this plugin. This should only be called from Editor
|
|
30
|
+
* @param editor Editor instance
|
|
31
|
+
*/
|
|
32
|
+
BridgePlugin.prototype.initialize = function (editor) {
|
|
33
|
+
var outerEditor = this.onInitialize(this.createEditorCore(editor));
|
|
34
|
+
this.legacyPlugins.forEach(function (plugin) { return plugin.initialize(outerEditor); });
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Dispose this plugin
|
|
38
|
+
*/
|
|
39
|
+
BridgePlugin.prototype.dispose = function () {
|
|
40
|
+
for (var i = this.legacyPlugins.length - 1; i >= 0; i--) {
|
|
41
|
+
var plugin = this.legacyPlugins[i];
|
|
42
|
+
plugin.dispose();
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
BridgePlugin.prototype.willHandleEventExclusively = function (event) {
|
|
46
|
+
var _a;
|
|
47
|
+
var oldEvent;
|
|
48
|
+
if (this.checkExclusivelyHandling && (oldEvent = (0, eventConverter_1.newEventToOldEvent)(event))) {
|
|
49
|
+
for (var i = 0; i < this.legacyPlugins.length; i++) {
|
|
50
|
+
var plugin = this.legacyPlugins[i];
|
|
51
|
+
if ((_a = plugin.willHandleEventExclusively) === null || _a === void 0 ? void 0 : _a.call(plugin, oldEvent)) {
|
|
52
|
+
if (!event.eventDataCache) {
|
|
53
|
+
event.eventDataCache = {};
|
|
54
|
+
}
|
|
55
|
+
event.eventDataCache[ExclusivelyHandleEventPluginKey] = plugin;
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return false;
|
|
61
|
+
};
|
|
62
|
+
BridgePlugin.prototype.onPluginEvent = function (event) {
|
|
63
|
+
var _a, _b;
|
|
64
|
+
var oldEvent = (0, eventConverter_1.newEventToOldEvent)(event);
|
|
65
|
+
if (oldEvent) {
|
|
66
|
+
var exclusivelyHandleEventPlugin = (_a = event.eventDataCache) === null || _a === void 0 ? void 0 : _a[ExclusivelyHandleEventPluginKey];
|
|
67
|
+
if (exclusivelyHandleEventPlugin) {
|
|
68
|
+
(_b = exclusivelyHandleEventPlugin.onPluginEvent) === null || _b === void 0 ? void 0 : _b.call(exclusivelyHandleEventPlugin, oldEvent);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
this.legacyPlugins.forEach(function (plugin) { var _a; return (_a = plugin.onPluginEvent) === null || _a === void 0 ? void 0 : _a.call(plugin, oldEvent); });
|
|
72
|
+
}
|
|
73
|
+
Object.assign(event, (0, eventConverter_1.oldEventToNewEvent)(oldEvent, event));
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* A callback to return context menu items
|
|
78
|
+
* @param target Target node that triggered a ContextMenu event
|
|
79
|
+
* @returns An array of context menu items, or null means no items needed
|
|
80
|
+
*/
|
|
81
|
+
BridgePlugin.prototype.getContextMenuItems = function (target) {
|
|
82
|
+
var allItems = [];
|
|
83
|
+
this.contextMenuProviders.forEach(function (provider) {
|
|
84
|
+
var _a;
|
|
85
|
+
var items = (_a = provider.getContextMenuItems(target)) !== null && _a !== void 0 ? _a : [];
|
|
86
|
+
if ((items === null || items === void 0 ? void 0 : items.length) > 0) {
|
|
87
|
+
if (allItems.length > 0) {
|
|
88
|
+
allItems.push(null);
|
|
89
|
+
}
|
|
90
|
+
allItems.push.apply(allItems, (0, tslib_1.__spreadArray)([], (0, tslib_1.__read)(items), false));
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
return allItems;
|
|
94
|
+
};
|
|
95
|
+
BridgePlugin.prototype.createEditorCore = function (editor) {
|
|
96
|
+
var _a;
|
|
97
|
+
return {
|
|
98
|
+
customData: {},
|
|
99
|
+
experimentalFeatures: (_a = this.experimentalFeatures) !== null && _a !== void 0 ? _a : [],
|
|
100
|
+
sizeTransformer: createSizeTransformer(editor),
|
|
101
|
+
darkColorHandler: (0, DarkColorHandlerImpl_1.createDarkColorHandler)(editor.getColorManager()),
|
|
102
|
+
edit: this.edit,
|
|
103
|
+
contextMenuProviders: this.contextMenuProviders,
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
return BridgePlugin;
|
|
107
|
+
}());
|
|
108
|
+
exports.BridgePlugin = BridgePlugin;
|
|
109
|
+
/**
|
|
110
|
+
* @internal Export for test only. This function is only used for compatibility from older build
|
|
111
|
+
|
|
112
|
+
*/
|
|
113
|
+
function createSizeTransformer(editor) {
|
|
114
|
+
return function (size) { return size / editor.getDOMHelper().calculateZoomScale(); };
|
|
115
|
+
}
|
|
116
|
+
exports.createSizeTransformer = createSizeTransformer;
|
|
117
|
+
function isContextMenuProvider(source) {
|
|
118
|
+
var _a;
|
|
119
|
+
return !!((_a = source) === null || _a === void 0 ? void 0 : _a.getContextMenuItems);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
//# sourceMappingURL=BridgePlugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BridgePlugin.js","sourceRoot":"","sources":["../../../../packages/roosterjs-editor-adapter/lib/corePlugins/BridgePlugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { createDarkColorHandler } from '../editor/DarkColorHandlerImpl';\r\nimport { createEditPlugin } from './EditPlugin';\r\nimport { newEventToOldEvent, oldEventToNewEvent } from '../editor/utils/eventConverter';\r\nimport type {\r\n EditorPlugin as LegacyEditorPlugin,\r\n PluginEvent as LegacyPluginEvent,\r\n ContextMenuProvider as LegacyContextMenuProvider,\r\n IEditor as ILegacyEditor,\r\n ExperimentalFeatures,\r\n SizeTransformer,\r\n EditPluginState,\r\n CustomData,\r\n DarkColorHandler,\r\n} from 'roosterjs-editor-types';\r\nimport type {\r\n ContextMenuProvider,\r\n IStandaloneEditor,\r\n PluginEvent,\r\n} from 'roosterjs-content-model-types';\r\n\r\nconst ExclusivelyHandleEventPluginKey = '__ExclusivelyHandleEventPlugin';\r\n\r\n/**\r\n * @internal\r\n * Represents the core data structure of a editor adapter\r\n */\r\nexport interface EditorAdapterCore {\r\n /**\r\n * Custom data of this editor\r\n */\r\n readonly customData: Record<string, CustomData>;\r\n\r\n /**\r\n * Enabled experimental features\r\n */\r\n readonly experimentalFeatures: ExperimentalFeatures[];\r\n\r\n /**\r\n * Dark model handler for the editor, used for variable-based solution.\r\n * If keep it null, editor will still use original dataset-based dark mode solution.\r\n */\r\n readonly darkColorHandler: DarkColorHandler;\r\n\r\n /**\r\n * Plugin state of EditPlugin\r\n */\r\n readonly edit: EditPluginState;\r\n\r\n /**\r\n * Context Menu providers\r\n */\r\n readonly contextMenuProviders: LegacyContextMenuProvider<any>[];\r\n\r\n /**\r\n * @deprecated Use zoomScale instead\r\n */\r\n readonly sizeTransformer: SizeTransformer;\r\n}\r\n\r\n/**\r\n * @internal\r\n * Act as a bridge between Standalone editor and Content Model editor, translate Standalone editor event type to legacy event type\r\n */\r\nexport class BridgePlugin implements ContextMenuProvider<any> {\r\n private legacyPlugins: LegacyEditorPlugin[];\r\n private edit: EditPluginState;\r\n private contextMenuProviders: LegacyContextMenuProvider<any>[];\r\n private checkExclusivelyHandling: boolean;\r\n\r\n constructor(\r\n private onInitialize: (core: EditorAdapterCore) => ILegacyEditor,\r\n legacyPlugins: LegacyEditorPlugin[] = [],\r\n private experimentalFeatures: ExperimentalFeatures[] = []\r\n ) {\r\n const editPlugin = createEditPlugin();\r\n\r\n this.legacyPlugins = [editPlugin, ...legacyPlugins.filter(x => !!x)];\r\n this.edit = editPlugin.getState();\r\n this.contextMenuProviders = this.legacyPlugins.filter(isContextMenuProvider);\r\n this.checkExclusivelyHandling = this.legacyPlugins.some(\r\n plugin => plugin.willHandleEventExclusively\r\n );\r\n }\r\n\r\n /**\r\n * Get a friendly name of this plugin\r\n */\r\n getName() {\r\n return 'Bridge';\r\n }\r\n\r\n /**\r\n * Initialize this plugin. This should only be called from Editor\r\n * @param editor Editor instance\r\n */\r\n initialize(editor: IStandaloneEditor) {\r\n const outerEditor = this.onInitialize(this.createEditorCore(editor));\r\n\r\n this.legacyPlugins.forEach(plugin => plugin.initialize(outerEditor));\r\n }\r\n\r\n /**\r\n * Dispose this plugin\r\n */\r\n dispose() {\r\n for (let i = this.legacyPlugins.length - 1; i >= 0; i--) {\r\n const plugin = this.legacyPlugins[i];\r\n\r\n plugin.dispose();\r\n }\r\n }\r\n\r\n willHandleEventExclusively(event: PluginEvent) {\r\n let oldEvent: LegacyPluginEvent | undefined;\r\n\r\n if (this.checkExclusivelyHandling && (oldEvent = newEventToOldEvent(event))) {\r\n for (let i = 0; i < this.legacyPlugins.length; i++) {\r\n const plugin = this.legacyPlugins[i];\r\n\r\n if (plugin.willHandleEventExclusively?.(oldEvent)) {\r\n if (!event.eventDataCache) {\r\n event.eventDataCache = {};\r\n }\r\n\r\n event.eventDataCache[ExclusivelyHandleEventPluginKey] = plugin;\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n onPluginEvent(event: PluginEvent) {\r\n const oldEvent = newEventToOldEvent(event);\r\n\r\n if (oldEvent) {\r\n const exclusivelyHandleEventPlugin = event.eventDataCache?.[\r\n ExclusivelyHandleEventPluginKey\r\n ] as LegacyEditorPlugin | undefined;\r\n\r\n if (exclusivelyHandleEventPlugin) {\r\n exclusivelyHandleEventPlugin.onPluginEvent?.(oldEvent);\r\n } else {\r\n this.legacyPlugins.forEach(plugin => plugin.onPluginEvent?.(oldEvent));\r\n }\r\n\r\n Object.assign(event, oldEventToNewEvent(oldEvent, event));\r\n }\r\n }\r\n\r\n /**\r\n * A callback to return context menu items\r\n * @param target Target node that triggered a ContextMenu event\r\n * @returns An array of context menu items, or null means no items needed\r\n */\r\n getContextMenuItems(target: Node): any[] {\r\n const allItems: any[] = [];\r\n\r\n this.contextMenuProviders.forEach(provider => {\r\n const items = provider.getContextMenuItems(target) ?? [];\r\n if (items?.length > 0) {\r\n if (allItems.length > 0) {\r\n allItems.push(null);\r\n }\r\n\r\n allItems.push(...items);\r\n }\r\n });\r\n\r\n return allItems;\r\n }\r\n\r\n private createEditorCore(editor: IStandaloneEditor): EditorAdapterCore {\r\n return {\r\n customData: {},\r\n experimentalFeatures: this.experimentalFeatures ?? [],\r\n sizeTransformer: createSizeTransformer(editor),\r\n darkColorHandler: createDarkColorHandler(editor.getColorManager()),\r\n edit: this.edit,\r\n contextMenuProviders: this.contextMenuProviders,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * @internal Export for test only. This function is only used for compatibility from older build\r\n\r\n */\r\nexport function createSizeTransformer(editor: IStandaloneEditor): SizeTransformer {\r\n return size => size / editor.getDOMHelper().calculateZoomScale();\r\n}\r\n\r\nfunction isContextMenuProvider(\r\n source: LegacyEditorPlugin\r\n): source is LegacyContextMenuProvider<any> {\r\n return !!(<LegacyContextMenuProvider<any>>source)?.getContextMenuItems;\r\n}\r\n"]}
|