@portabletext/editor 1.0.10 → 1.0.12
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/lib/index.esm.js +203 -202
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +199 -198
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +203 -202
- package/lib/index.mjs.map +1 -1
- package/package.json +20 -18
- package/src/editor/__tests__/PortableTextEditor.test.tsx +15 -1
- package/src/editor/__tests__/handleClick.test.tsx +40 -20
- package/src/editor/__tests__/insert-block.test.tsx +229 -0
- package/src/editor/__tests__/utils.ts +14 -15
- package/src/editor/plugins/__tests__/withEditableAPIDelete.test.tsx +62 -20
- package/src/editor/plugins/__tests__/withEditableAPIGetFragment.test.tsx +19 -0
- package/src/editor/plugins/__tests__/withEditableAPIInsert.test.tsx +259 -134
- package/src/editor/plugins/__tests__/withHotkeys.test.tsx +1 -1
- package/src/editor/plugins/__tests__/withInsertBreak.test.tsx +18 -2
- package/src/editor/plugins/__tests__/withPortableTextMarkModel.test.tsx +176 -154
- package/src/editor/plugins/__tests__/withUndoRedo.test.tsx +17 -0
- package/src/editor/plugins/createWithEditableAPI.ts +41 -10
- package/src/editor/plugins/createWithObjectKeys.ts +23 -8
- package/src/editor/plugins/createWithPortableTextMarkModel.ts +51 -1
- package/src/editor/plugins/createWithUndoRedo.ts +5 -7
- package/src/utils/__tests__/values.test.ts +1 -0
- package/src/utils/withPreserveKeys.ts +7 -0
package/lib/index.esm.js
CHANGED
|
@@ -5,7 +5,7 @@ import { useRef, useState, useMemo, useEffect, useCallback, createContext, useCo
|
|
|
5
5
|
import { Editor, Element as Element$1, Range, Point, Text, Path, Transforms, Node, Operation, createEditor } from "slate";
|
|
6
6
|
import { useSlateStatic, ReactEditor, useSelected, withReact, Slate, useSlate, Editable } from "slate-react";
|
|
7
7
|
import debug$m from "debug";
|
|
8
|
-
import { isKeySegment, isPortableTextSpan, isPortableTextTextBlock, isPortableTextListBlock } from "@sanity/types";
|
|
8
|
+
import { isKeySegment, isPortableTextSpan as isPortableTextSpan$1, isPortableTextTextBlock, isPortableTextListBlock } from "@sanity/types";
|
|
9
9
|
import { styled } from "styled-components";
|
|
10
10
|
import uniq from "lodash/uniq.js";
|
|
11
11
|
import { Subject } from "rxjs";
|
|
@@ -185,8 +185,7 @@ function fromSlateValue(value, textBlockType, keyMap = {}) {
|
|
|
185
185
|
});
|
|
186
186
|
}
|
|
187
187
|
function isEqualToEmptyEditor(children, schemaTypes) {
|
|
188
|
-
|
|
189
|
-
return children === void 0 || children && Array.isArray(children) && children.length === 0 || children && Array.isArray(children) && children.length === 1 && Element$1.isElement(children[0]) && children[0]._type === schemaTypes.block.name && "style" in children[0] && children[0].style === schemaTypes.styles[0].value && !("listItem" in children[0]) && Array.isArray(children[0].children) && children[0].children.length === 1 && Text.isText(children[0].children[0]) && children[0].children[0]._type === "span" && !((_a = children[0].children[0].marks) != null && _a.join("")) && children[0].children[0].text === "";
|
|
188
|
+
return children === void 0 || children && Array.isArray(children) && children.length === 0 || children && Array.isArray(children) && children.length === 1 && Element$1.isElement(children[0]) && children[0]._type === schemaTypes.block.name && "style" in children[0] && children[0].style === schemaTypes.styles[0].value && !("listItem" in children[0]) && Array.isArray(children[0].children) && children[0].children.length === 1 && Text.isText(children[0].children[0]) && children[0].children[0]._type === "span" && !children[0].children[0].marks?.join("") && children[0].children[0].text === "";
|
|
190
189
|
}
|
|
191
190
|
const IS_PROCESSING_REMOTE_CHANGES = /* @__PURE__ */ new WeakMap(), IS_PROCESSING_LOCAL_CHANGES = /* @__PURE__ */ new WeakMap(), IS_DRAGGING = /* @__PURE__ */ new WeakMap(), IS_DRAGGING_BLOCK_ELEMENT = /* @__PURE__ */ new WeakMap(), IS_DRAGGING_ELEMENT_TARGET = /* @__PURE__ */ new WeakMap(), IS_DRAGGING_BLOCK_TARGET_POSITION = /* @__PURE__ */ new WeakMap(), KEY_TO_SLATE_ELEMENT = /* @__PURE__ */ new WeakMap(), KEY_TO_VALUE_ELEMENT = /* @__PURE__ */ new WeakMap(), SLATE_TO_PORTABLE_TEXT_RANGE = /* @__PURE__ */ new WeakMap(), DefaultObject = (props) => /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("pre", { children: JSON.stringify(props.value, null, 2) }) }), DefaultBlockObject = styled.div`
|
|
192
191
|
user-select: none;
|
|
@@ -655,13 +654,12 @@ function DefaultAnnotation(props) {
|
|
|
655
654
|
return /* @__PURE__ */ jsx("span", { style: { color: "blue" }, onClick: handleClick, children: props.children });
|
|
656
655
|
}
|
|
657
656
|
function getPortableTextMemberSchemaTypes(portableTextType) {
|
|
658
|
-
var _a, _b, _c;
|
|
659
657
|
if (!portableTextType)
|
|
660
658
|
throw new Error("Parameter 'portabletextType' missing (required)");
|
|
661
|
-
const blockType =
|
|
659
|
+
const blockType = portableTextType.of?.find(findBlockType);
|
|
662
660
|
if (!blockType)
|
|
663
661
|
throw new Error("Block type is not defined in this schema (required)");
|
|
664
|
-
const childrenField =
|
|
662
|
+
const childrenField = blockType.fields?.find((field) => field.name === "children");
|
|
665
663
|
if (!childrenField)
|
|
666
664
|
throw new Error("Children field for block type found in schema (required)");
|
|
667
665
|
const ofType = childrenField.type.of;
|
|
@@ -670,7 +668,7 @@ function getPortableTextMemberSchemaTypes(portableTextType) {
|
|
|
670
668
|
const spanType = ofType.find((memberType) => memberType.name === "span");
|
|
671
669
|
if (!spanType)
|
|
672
670
|
throw new Error("Span type not found in schema (required)");
|
|
673
|
-
const inlineObjectTypes = ofType.filter((memberType) => memberType.name !== "span") || [], blockObjectTypes =
|
|
671
|
+
const inlineObjectTypes = ofType.filter((memberType) => memberType.name !== "span") || [], blockObjectTypes = portableTextType.of?.filter((field) => field.name !== blockType.name) || [];
|
|
674
672
|
return {
|
|
675
673
|
styles: resolveEnabledStyles(blockType),
|
|
676
674
|
decorators: resolveEnabledDecorators(spanType),
|
|
@@ -684,11 +682,10 @@ function getPortableTextMemberSchemaTypes(portableTextType) {
|
|
|
684
682
|
};
|
|
685
683
|
}
|
|
686
684
|
function resolveEnabledStyles(blockType) {
|
|
687
|
-
|
|
688
|
-
const styleField = (_a = blockType.fields) == null ? void 0 : _a.find((btField) => btField.name === "style");
|
|
685
|
+
const styleField = blockType.fields?.find((btField) => btField.name === "style");
|
|
689
686
|
if (!styleField)
|
|
690
687
|
throw new Error("A field with name 'style' is not defined in the block type (required).");
|
|
691
|
-
const textStyles =
|
|
688
|
+
const textStyles = styleField.type.options?.list && styleField.type.options.list?.filter((style) => style.value);
|
|
692
689
|
if (!textStyles || textStyles.length === 0)
|
|
693
690
|
throw new Error(
|
|
694
691
|
"The style fields need at least one style defined. I.e: {title: 'Normal', value: 'normal'}."
|
|
@@ -699,11 +696,10 @@ function resolveEnabledDecorators(spanType) {
|
|
|
699
696
|
return spanType.decorators;
|
|
700
697
|
}
|
|
701
698
|
function resolveEnabledListItems(blockType) {
|
|
702
|
-
|
|
703
|
-
const listField = (_a = blockType.fields) == null ? void 0 : _a.find((btField) => btField.name === "listItem");
|
|
699
|
+
const listField = blockType.fields?.find((btField) => btField.name === "listItem");
|
|
704
700
|
if (!listField)
|
|
705
701
|
throw new Error("A field with name 'listItem' is not defined in the block type (required).");
|
|
706
|
-
const listItems =
|
|
702
|
+
const listItems = listField.type.options?.list && listField.type.options.list.filter((list) => list.value);
|
|
707
703
|
if (!listItems)
|
|
708
704
|
throw new Error("The list field need at least to be an empty array");
|
|
709
705
|
return listItems;
|
|
@@ -781,7 +777,7 @@ function createOperationToPatches(types) {
|
|
|
781
777
|
function insertNodePatch(editor, operation, beforeValue) {
|
|
782
778
|
const block = beforeValue[operation.path[0]], isTextBlock = editor.isTextBlock(block);
|
|
783
779
|
if (operation.path.length === 1) {
|
|
784
|
-
const position = operation.path[0] === 0 ? "before" : "after", beforeBlock = beforeValue[operation.path[0] - 1], targetKey = operation.path[0] === 0 ? block
|
|
780
|
+
const position = operation.path[0] === 0 ? "before" : "after", beforeBlock = beforeValue[operation.path[0] - 1], targetKey = operation.path[0] === 0 ? block?._key : beforeBlock?._key;
|
|
785
781
|
return targetKey ? [
|
|
786
782
|
insert([fromSlateValue([operation.node], textBlockName)[0]], position, [
|
|
787
783
|
{ _key: targetKey }
|
|
@@ -883,7 +879,7 @@ function createOperationToPatches(types) {
|
|
|
883
879
|
function mergeNodePatch(editor, operation, beforeValue) {
|
|
884
880
|
const patches = [], block = beforeValue[operation.path[0]], targetBlock = editor.children[operation.path[0]];
|
|
885
881
|
if (operation.path.length === 1)
|
|
886
|
-
if (block
|
|
882
|
+
if (block?._key) {
|
|
887
883
|
const newBlock = fromSlateValue([editor.children[operation.path[0] - 1]], textBlockName)[0];
|
|
888
884
|
patches.push(set(newBlock, [{ _key: newBlock._key }])), patches.push(unset([{ _key: block._key }]));
|
|
889
885
|
} else
|
|
@@ -981,7 +977,6 @@ function createWithEditableAPI(portableTextEditor, types, keyGenerator) {
|
|
|
981
977
|
}
|
|
982
978
|
},
|
|
983
979
|
insertChild: (type, value) => {
|
|
984
|
-
var _a;
|
|
985
980
|
if (!editor.selection)
|
|
986
981
|
throw new Error("The editor has no selection");
|
|
987
982
|
const [focusBlock] = Array.from(
|
|
@@ -1013,16 +1008,13 @@ function createWithEditableAPI(portableTextEditor, types, keyGenerator) {
|
|
|
1013
1008
|
return isSpanNode && focusNode._type !== types.span.name && (debug$j("Inserting span child next to inline object child, moving selection + 1"), editor.move({ distance: 1, unit: "character" })), Transforms.insertNodes(editor, child, {
|
|
1014
1009
|
select: !0,
|
|
1015
1010
|
at: editor.selection
|
|
1016
|
-
}), editor.onChange(),
|
|
1011
|
+
}), editor.onChange(), toPortableTextRange(
|
|
1017
1012
|
fromSlateValue(editor.children, types.block.name, KEY_TO_VALUE_ELEMENT.get(editor)),
|
|
1018
1013
|
editor.selection,
|
|
1019
1014
|
types
|
|
1020
|
-
)
|
|
1015
|
+
)?.focus.path || [];
|
|
1021
1016
|
},
|
|
1022
1017
|
insertBlock: (type, value) => {
|
|
1023
|
-
var _a;
|
|
1024
|
-
if (!editor.selection)
|
|
1025
|
-
throw new Error("The editor has no selection");
|
|
1026
1018
|
const block = toSlateValue(
|
|
1027
1019
|
[
|
|
1028
1020
|
{
|
|
@@ -1032,17 +1024,32 @@ function createWithEditableAPI(portableTextEditor, types, keyGenerator) {
|
|
|
1032
1024
|
}
|
|
1033
1025
|
],
|
|
1034
1026
|
portableTextEditor
|
|
1035
|
-
)[0]
|
|
1027
|
+
)[0];
|
|
1028
|
+
if (!editor.selection) {
|
|
1029
|
+
const lastBlock = Array.from(
|
|
1030
|
+
Editor.nodes(editor, {
|
|
1031
|
+
match: (n) => !Editor.isEditor(n),
|
|
1032
|
+
at: [],
|
|
1033
|
+
reverse: !0
|
|
1034
|
+
})
|
|
1035
|
+
)[0];
|
|
1036
|
+
return Editor.insertNode(editor, block), lastBlock && isEqualToEmptyEditor([lastBlock[0]], types) && Transforms.removeNodes(editor, { at: lastBlock[1] }), editor.onChange(), toPortableTextRange(
|
|
1037
|
+
fromSlateValue(editor.children, types.block.name, KEY_TO_VALUE_ELEMENT.get(editor)),
|
|
1038
|
+
editor.selection,
|
|
1039
|
+
types
|
|
1040
|
+
)?.focus.path ?? [];
|
|
1041
|
+
}
|
|
1042
|
+
const focusBlock = Array.from(
|
|
1036
1043
|
Editor.nodes(editor, {
|
|
1037
1044
|
at: editor.selection.focus.path.slice(0, 1),
|
|
1038
1045
|
match: (n) => n._type === types.block.name
|
|
1039
1046
|
})
|
|
1040
|
-
)[0]
|
|
1041
|
-
return focusBlock && isEqualToEmptyEditor([focusBlock], types) && Transforms.removeNodes(editor, { at:
|
|
1047
|
+
)[0];
|
|
1048
|
+
return Editor.insertNode(editor, block), focusBlock && isEqualToEmptyEditor([focusBlock[0]], types) && Transforms.removeNodes(editor, { at: focusBlock[1] }), editor.onChange(), toPortableTextRange(
|
|
1042
1049
|
fromSlateValue(editor.children, types.block.name, KEY_TO_VALUE_ELEMENT.get(editor)),
|
|
1043
1050
|
editor.selection,
|
|
1044
1051
|
types
|
|
1045
|
-
)
|
|
1052
|
+
)?.focus.path || [];
|
|
1046
1053
|
},
|
|
1047
1054
|
hasBlockStyle: (style) => {
|
|
1048
1055
|
try {
|
|
@@ -1098,7 +1105,6 @@ function createWithEditableAPI(portableTextEditor, types, keyGenerator) {
|
|
|
1098
1105
|
return node;
|
|
1099
1106
|
},
|
|
1100
1107
|
activeAnnotations: () => {
|
|
1101
|
-
var _a;
|
|
1102
1108
|
if (!editor.selection || editor.selection.focus.path.length < 2)
|
|
1103
1109
|
return [];
|
|
1104
1110
|
try {
|
|
@@ -1108,9 +1114,9 @@ function createWithEditableAPI(portableTextEditor, types, keyGenerator) {
|
|
|
1108
1114
|
});
|
|
1109
1115
|
for (const [span, path] of spans) {
|
|
1110
1116
|
const [block] = Editor.node(editor, path, { depth: 1 });
|
|
1111
|
-
editor.isTextBlock(block) &&
|
|
1117
|
+
editor.isTextBlock(block) && block.markDefs?.forEach((def) => {
|
|
1112
1118
|
Text.isText(span) && span.marks && Array.isArray(span.marks) && span.marks.includes(def._key) && activeAnnotations.push(def);
|
|
1113
|
-
})
|
|
1119
|
+
});
|
|
1114
1120
|
}
|
|
1115
1121
|
return activeAnnotations;
|
|
1116
1122
|
} catch {
|
|
@@ -1127,28 +1133,17 @@ function createWithEditableAPI(portableTextEditor, types, keyGenerator) {
|
|
|
1127
1133
|
match: (node) => Text.isText(node)
|
|
1128
1134
|
})
|
|
1129
1135
|
];
|
|
1130
|
-
if (spans.some(
|
|
1131
|
-
([span]) =>
|
|
1132
|
-
var _a;
|
|
1133
|
-
return !isPortableTextSpan(span) || !span.marks || ((_a = span.marks) == null ? void 0 : _a.length) === 0;
|
|
1134
|
-
}
|
|
1136
|
+
if (spans.length === 0 || spans.some(
|
|
1137
|
+
([span]) => !isPortableTextSpan$1(span) || !span.marks || span.marks?.length === 0
|
|
1135
1138
|
))
|
|
1136
1139
|
return !1;
|
|
1137
1140
|
const selectionMarkDefs = spans.reduce((accMarkDefs, [, path]) => {
|
|
1138
1141
|
const [block] = Editor.node(editor, path, { depth: 1 });
|
|
1139
1142
|
return editor.isTextBlock(block) && block.markDefs ? [...accMarkDefs, ...block.markDefs] : accMarkDefs;
|
|
1140
1143
|
}, []);
|
|
1141
|
-
return spans.every(([span]) =>
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
const spanMarkDefs = (_a = span.marks) == null ? void 0 : _a.map(
|
|
1145
|
-
(markKey) => {
|
|
1146
|
-
var _a2;
|
|
1147
|
-
return (_a2 = selectionMarkDefs.find((def) => (def == null ? void 0 : def._key) === markKey)) == null ? void 0 : _a2._type;
|
|
1148
|
-
}
|
|
1149
|
-
);
|
|
1150
|
-
return spanMarkDefs == null ? void 0 : spanMarkDefs.includes(annotationType);
|
|
1151
|
-
});
|
|
1144
|
+
return spans.every(([span]) => isPortableTextSpan$1(span) ? span.marks?.map(
|
|
1145
|
+
(markKey) => selectionMarkDefs.find((def) => def?._key === markKey)?._type
|
|
1146
|
+
)?.includes(annotationType) : !1);
|
|
1152
1147
|
} catch {
|
|
1153
1148
|
return !1;
|
|
1154
1149
|
}
|
|
@@ -1208,7 +1203,7 @@ function createWithEditableAPI(portableTextEditor, types, keyGenerator) {
|
|
|
1208
1203
|
if (!(range && range.anchor.path.length > 0 && range.focus.path.length > 0))
|
|
1209
1204
|
throw new Error("Invalid range");
|
|
1210
1205
|
if (range) {
|
|
1211
|
-
if (!
|
|
1206
|
+
if (!options?.mode || options?.mode === "selected") {
|
|
1212
1207
|
debug$j("Deleting content in selection"), Transforms.delete(editor, {
|
|
1213
1208
|
at: range,
|
|
1214
1209
|
hanging: !0,
|
|
@@ -1216,11 +1211,11 @@ function createWithEditableAPI(portableTextEditor, types, keyGenerator) {
|
|
|
1216
1211
|
}), editor.onChange();
|
|
1217
1212
|
return;
|
|
1218
1213
|
}
|
|
1219
|
-
|
|
1214
|
+
options?.mode === "blocks" && (debug$j("Deleting blocks touched by selection"), Transforms.removeNodes(editor, {
|
|
1220
1215
|
at: range,
|
|
1221
1216
|
voids: !0,
|
|
1222
1217
|
match: (node) => editor.isTextBlock(node) || !editor.isTextBlock(node) && Element$1.isElement(node)
|
|
1223
|
-
})),
|
|
1218
|
+
})), options?.mode === "children" && (debug$j("Deleting children touched by selection"), Transforms.removeNodes(editor, {
|
|
1224
1219
|
at: range,
|
|
1225
1220
|
voids: !0,
|
|
1226
1221
|
match: (node) => node._type === types.span.name || // Text children
|
|
@@ -1319,6 +1314,10 @@ function withPreserveKeys(editor, fn) {
|
|
|
1319
1314
|
const prev = isPreservingKeys(editor);
|
|
1320
1315
|
PRESERVE_KEYS.set(editor, !0), fn(), PRESERVE_KEYS.set(editor, prev);
|
|
1321
1316
|
}
|
|
1317
|
+
function withoutPreserveKeys(editor, fn) {
|
|
1318
|
+
const prev = isPreservingKeys(editor);
|
|
1319
|
+
PRESERVE_KEYS.set(editor, !1), fn(), PRESERVE_KEYS.set(editor, prev);
|
|
1320
|
+
}
|
|
1322
1321
|
function isPreservingKeys(editor) {
|
|
1323
1322
|
return PRESERVE_KEYS.get(editor);
|
|
1324
1323
|
}
|
|
@@ -1329,17 +1328,27 @@ function createWithObjectKeys(schemaTypes, keyGenerator) {
|
|
|
1329
1328
|
return editor.apply = (operation) => {
|
|
1330
1329
|
if (operation.type === "split_node") {
|
|
1331
1330
|
const withNewKey = !isPreservingKeys(editor) || !("_key" in operation.properties);
|
|
1332
|
-
|
|
1333
|
-
...operation
|
|
1334
|
-
|
|
1335
|
-
|
|
1331
|
+
apply2({
|
|
1332
|
+
...operation,
|
|
1333
|
+
properties: {
|
|
1334
|
+
...operation.properties,
|
|
1335
|
+
...withNewKey ? { _key: keyGenerator() } : {}
|
|
1336
|
+
}
|
|
1337
|
+
});
|
|
1338
|
+
return;
|
|
1336
1339
|
}
|
|
1337
1340
|
if (operation.type === "insert_node") {
|
|
1338
1341
|
const withNewKey = !isPreservingKeys(editor) || !("_key" in operation.node);
|
|
1339
|
-
Editor.isEditor(operation.node)
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1342
|
+
if (!Editor.isEditor(operation.node)) {
|
|
1343
|
+
apply2({
|
|
1344
|
+
...operation,
|
|
1345
|
+
node: {
|
|
1346
|
+
...operation.node,
|
|
1347
|
+
...withNewKey ? { _key: keyGenerator() } : {}
|
|
1348
|
+
}
|
|
1349
|
+
});
|
|
1350
|
+
return;
|
|
1351
|
+
}
|
|
1343
1352
|
}
|
|
1344
1353
|
apply2(operation);
|
|
1345
1354
|
}, editor.normalizeNode = (entry) => {
|
|
@@ -2227,7 +2236,7 @@ function findBlockAndChildFromPath(editor, path) {
|
|
|
2227
2236
|
const isMatch = isKeyedSegment(path[2]) ? node._key === path[2]._key : index === path[2];
|
|
2228
2237
|
return isMatch && (childIndex = index), isMatch;
|
|
2229
2238
|
});
|
|
2230
|
-
return child ? { block, child, blockPath, childPath: blockPath
|
|
2239
|
+
return child ? { block, child, blockPath, childPath: blockPath?.concat(childIndex) } : { block, blockPath, child: void 0, childPath: void 0 };
|
|
2231
2240
|
}
|
|
2232
2241
|
function withRemoteChanges(editor, fn) {
|
|
2233
2242
|
const prev = isChangingRemotely(editor) || !1;
|
|
@@ -2316,11 +2325,12 @@ function createWithUndoRedo(options) {
|
|
|
2316
2325
|
)
|
|
2317
2326
|
);
|
|
2318
2327
|
});
|
|
2328
|
+
const reversedOperations = transformedOperations.map(Operation.inverse).reverse();
|
|
2319
2329
|
try {
|
|
2320
2330
|
Editor.withoutNormalizing(editor, () => {
|
|
2321
2331
|
withPreserveKeys(editor, () => {
|
|
2322
2332
|
withoutSaving(editor, () => {
|
|
2323
|
-
|
|
2333
|
+
reversedOperations.forEach((op) => {
|
|
2324
2334
|
editor.apply(op);
|
|
2325
2335
|
});
|
|
2326
2336
|
});
|
|
@@ -2393,14 +2403,13 @@ function transformOperation(editor, patch, operation, snapshot, previousSnapshot
|
|
|
2393
2403
|
if (patch.type === "diffMatchPatch") {
|
|
2394
2404
|
const operationTargetBlock = findOperationTargetBlock(editor, transformedOperation);
|
|
2395
2405
|
return !operationTargetBlock || !isEqual({ _key: operationTargetBlock._key }, patch.path[0]) ? [transformedOperation] : (parse(patch.value).forEach((diffPatch) => {
|
|
2396
|
-
var _a, _b, _c, _d;
|
|
2397
2406
|
let adjustOffsetBy = 0, changedOffset = diffPatch.utf8Start1;
|
|
2398
2407
|
const { diffs } = diffPatch;
|
|
2399
2408
|
if (diffs.forEach((diff2, index) => {
|
|
2400
2409
|
const [diffType, text] = diff2;
|
|
2401
2410
|
diffType === DIFF_INSERT ? (adjustOffsetBy += text.length, changedOffset += text.length) : diffType === DIFF_DELETE ? (adjustOffsetBy -= text.length, changedOffset -= text.length) : diffType === DIFF_EQUAL && (diffs.slice(index).every(([dType]) => dType === DIFF_EQUAL) || (changedOffset += text.length));
|
|
2402
2411
|
}), transformedOperation.type === "insert_text" && changedOffset < transformedOperation.offset && (transformedOperation.offset += adjustOffsetBy), transformedOperation.type === "remove_text" && changedOffset <= transformedOperation.offset - transformedOperation.text.length && (transformedOperation.offset += adjustOffsetBy), transformedOperation.type === "set_selection") {
|
|
2403
|
-
const currentFocus =
|
|
2412
|
+
const currentFocus = transformedOperation.properties?.focus ? { ...transformedOperation.properties.focus } : void 0, currentAnchor = transformedOperation?.properties?.anchor ? { ...transformedOperation.properties.anchor } : void 0, newFocus = transformedOperation?.newProperties?.focus ? { ...transformedOperation.newProperties.focus } : void 0, newAnchor = transformedOperation?.newProperties?.anchor ? { ...transformedOperation.newProperties.anchor } : void 0;
|
|
2404
2413
|
(currentFocus && currentAnchor || newFocus && newAnchor) && ([currentFocus, currentAnchor, newFocus, newAnchor].forEach((point) => {
|
|
2405
2414
|
point && changedOffset < point.offset && (point.offset += adjustOffsetBy);
|
|
2406
2415
|
}), currentFocus && currentAnchor && (transformedOperation.properties = {
|
|
@@ -2416,14 +2425,13 @@ function transformOperation(editor, patch, operation, snapshot, previousSnapshot
|
|
|
2416
2425
|
return [transformedOperation];
|
|
2417
2426
|
}
|
|
2418
2427
|
function adjustBlockPath(operation, level, blockIndex) {
|
|
2419
|
-
var _a, _b, _c, _d;
|
|
2420
2428
|
const transformedOperation = { ...operation };
|
|
2421
2429
|
if (blockIndex >= 0 && transformedOperation.type !== "set_selection" && Array.isArray(transformedOperation.path) && transformedOperation.path[0] >= blockIndex + level && transformedOperation.path[0] + level > -1) {
|
|
2422
2430
|
const newPath = [transformedOperation.path[0] + level, ...transformedOperation.path.slice(1)];
|
|
2423
2431
|
transformedOperation.path = newPath;
|
|
2424
2432
|
}
|
|
2425
2433
|
if (transformedOperation.type === "set_selection") {
|
|
2426
|
-
const currentFocus =
|
|
2434
|
+
const currentFocus = transformedOperation.properties?.focus ? { ...transformedOperation.properties.focus } : void 0, currentAnchor = transformedOperation?.properties?.anchor ? { ...transformedOperation.properties.anchor } : void 0, newFocus = transformedOperation?.newProperties?.focus ? { ...transformedOperation.newProperties.focus } : void 0, newAnchor = transformedOperation?.newProperties?.anchor ? { ...transformedOperation.newProperties.anchor } : void 0;
|
|
2427
2435
|
(currentFocus && currentAnchor || newFocus && newAnchor) && ([currentFocus, currentAnchor, newFocus, newAnchor].forEach((point) => {
|
|
2428
2436
|
point && point.path[0] >= blockIndex + level && point.path[0] + level > -1 && (point.path = [point.path[0] + level, ...point.path.slice(1)]);
|
|
2429
2437
|
}), currentFocus && currentAnchor && (transformedOperation.properties = {
|
|
@@ -2721,6 +2729,21 @@ function createWithPortableTextLists(types) {
|
|
|
2721
2729
|
}, editor;
|
|
2722
2730
|
};
|
|
2723
2731
|
}
|
|
2732
|
+
function isPortableTextSpan(node) {
|
|
2733
|
+
return node._type === "span" && "text" in node && typeof node.text == "string" && (typeof node.marks > "u" || Array.isArray(node.marks) && node.marks.every((mark) => typeof mark == "string"));
|
|
2734
|
+
}
|
|
2735
|
+
function isPortableTextBlock(node) {
|
|
2736
|
+
return (
|
|
2737
|
+
// A block doesn't _have_ to be named 'block' - to differentiate between
|
|
2738
|
+
// allowed child types and marks, one might name them differently
|
|
2739
|
+
typeof node._type == "string" && // Toolkit-types like nested spans are @-prefixed
|
|
2740
|
+
node._type[0] !== "@" && // `markDefs` isn't _required_ per say, but if it's there, it needs to be an array
|
|
2741
|
+
(!("markDefs" in node) || !node.markDefs || Array.isArray(node.markDefs) && // Every mark definition needs to have an `_key` to be mappable in child spans
|
|
2742
|
+
node.markDefs.every((def) => typeof def._key == "string")) && // `children` is required and needs to be an array
|
|
2743
|
+
"children" in node && Array.isArray(node.children) && // All children are objects with `_type` (usually spans, but can contain other stuff)
|
|
2744
|
+
node.children.every((child) => typeof child == "object" && "_type" in child)
|
|
2745
|
+
);
|
|
2746
|
+
}
|
|
2724
2747
|
const debug$c = debugWithName("plugin:withPortableTextMarkModel");
|
|
2725
2748
|
function createWithPortableTextMarkModel(types, change$) {
|
|
2726
2749
|
return function(editor) {
|
|
@@ -2748,10 +2771,7 @@ function createWithPortableTextMarkModel(types, change$) {
|
|
|
2748
2771
|
);
|
|
2749
2772
|
if (annotationMarks.length > 0) {
|
|
2750
2773
|
const [block] = Editor.node(editor, Path.parent(path)), orphanedMarks = editor.isTextBlock(block) && annotationMarks.filter(
|
|
2751
|
-
(mark) =>
|
|
2752
|
-
var _a;
|
|
2753
|
-
return !((_a = block.markDefs) != null && _a.find((def) => def._key === mark));
|
|
2754
|
-
}
|
|
2774
|
+
(mark) => !block.markDefs?.find((def) => def._key === mark)
|
|
2755
2775
|
) || [];
|
|
2756
2776
|
orphanedMarks.length > 0 && (debug$c("Removing orphaned .marks from span node"), Transforms.setNodes(
|
|
2757
2777
|
editor,
|
|
@@ -2803,10 +2823,9 @@ function createWithPortableTextMarkModel(types, change$) {
|
|
|
2803
2823
|
), editor.onChange());
|
|
2804
2824
|
}
|
|
2805
2825
|
}, editor.apply = (op) => {
|
|
2806
|
-
var _a, _b;
|
|
2807
2826
|
if (op.type === "insert_text") {
|
|
2808
2827
|
const { selection } = editor;
|
|
2809
|
-
if (selection && Range.isCollapsed(selection) &&
|
|
2828
|
+
if (selection && Range.isCollapsed(selection) && Editor.marks(editor)?.marks?.some((mark) => !decorators.includes(mark))) {
|
|
2810
2829
|
const [node] = Array.from(
|
|
2811
2830
|
Editor.nodes(editor, {
|
|
2812
2831
|
mode: "lowest",
|
|
@@ -2832,6 +2851,32 @@ function createWithPortableTextMarkModel(types, change$) {
|
|
|
2832
2851
|
}
|
|
2833
2852
|
}
|
|
2834
2853
|
}
|
|
2854
|
+
if (op.type === "remove_text") {
|
|
2855
|
+
const node = Array.from(
|
|
2856
|
+
Editor.nodes(editor, {
|
|
2857
|
+
mode: "lowest",
|
|
2858
|
+
at: { path: op.path, offset: op.offset },
|
|
2859
|
+
match: (n) => n._type === types.span.name,
|
|
2860
|
+
voids: !1
|
|
2861
|
+
})
|
|
2862
|
+
)[0][0], block = Editor.node(editor, Path.parent(op.path))[0];
|
|
2863
|
+
if (node && isPortableTextSpan(node) && block && isPortableTextBlock(block)) {
|
|
2864
|
+
const markDefs = block.markDefs ?? [], nodeHasAnnotations = (node.marks ?? []).some(
|
|
2865
|
+
(mark) => markDefs.find((markDef) => markDef._key === mark)
|
|
2866
|
+
), deletingPartOfTheNode = op.offset !== 0, deletingFromTheEnd = op.offset + op.text.length === node.text.length;
|
|
2867
|
+
if (nodeHasAnnotations && deletingPartOfTheNode && deletingFromTheEnd) {
|
|
2868
|
+
Editor.withoutNormalizing(editor, () => {
|
|
2869
|
+
withoutPreserveKeys(editor, () => {
|
|
2870
|
+
Transforms.splitNodes(editor, {
|
|
2871
|
+
match: Text.isText,
|
|
2872
|
+
at: { path: op.path, offset: op.offset }
|
|
2873
|
+
});
|
|
2874
|
+
}), Transforms.removeNodes(editor, { at: Path.next(op.path) });
|
|
2875
|
+
}), editor.onChange();
|
|
2876
|
+
return;
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2879
|
+
}
|
|
2835
2880
|
apply2(op);
|
|
2836
2881
|
}, editor.addMark = (mark) => {
|
|
2837
2882
|
if (editor.selection) {
|
|
@@ -2840,10 +2885,7 @@ function createWithPortableTextMarkModel(types, change$) {
|
|
|
2840
2885
|
const splitTextNodes = [
|
|
2841
2886
|
...Editor.nodes(editor, { at: editor.selection, match: Text.isText })
|
|
2842
2887
|
];
|
|
2843
|
-
if (splitTextNodes.every((node) =>
|
|
2844
|
-
var _a;
|
|
2845
|
-
return (_a = node[0].marks) == null ? void 0 : _a.includes(mark);
|
|
2846
|
-
}))
|
|
2888
|
+
if (splitTextNodes.every((node) => node[0].marks?.includes(mark)))
|
|
2847
2889
|
return editor.removeMark(mark), editor;
|
|
2848
2890
|
Editor.withoutNormalizing(editor, () => {
|
|
2849
2891
|
splitTextNodes.forEach(([node, path]) => {
|
|
@@ -2912,9 +2954,8 @@ function createWithPortableTextMarkModel(types, change$) {
|
|
|
2912
2954
|
Editor.nodes(editor, { match: Text.isText, at: editor.selection })
|
|
2913
2955
|
);
|
|
2914
2956
|
return Range.isExpanded(editor.selection) ? selectedNodes.every((n) => {
|
|
2915
|
-
var _a;
|
|
2916
2957
|
const [node] = n;
|
|
2917
|
-
return
|
|
2958
|
+
return node.marks?.includes(mark);
|
|
2918
2959
|
}) : ({
|
|
2919
2960
|
...Editor.marks(editor) || {}
|
|
2920
2961
|
}.marks || []).includes(mark);
|
|
@@ -2974,7 +3015,7 @@ function createWithSchemaTypes({
|
|
|
2974
3015
|
keyGenerator
|
|
2975
3016
|
}) {
|
|
2976
3017
|
return function(editor) {
|
|
2977
|
-
editor.isTextBlock = (value) => isPortableTextTextBlock(value) && value._type === schemaTypes.block.name, editor.isTextSpan = (value) => isPortableTextSpan(value) && value._type == schemaTypes.span.name, editor.isListBlock = (value) => isPortableTextListBlock(value) && value._type === schemaTypes.block.name, editor.isVoid = (element) => schemaTypes.block.name !== element._type && (schemaTypes.blockObjects.map((obj) => obj.name).includes(element._type) || schemaTypes.inlineObjects.map((obj) => obj.name).includes(element._type)), editor.isInline = (element) => schemaTypes.inlineObjects.map((obj) => obj.name).includes(element._type) && "__inline" in element && element.__inline === !0;
|
|
3018
|
+
editor.isTextBlock = (value) => isPortableTextTextBlock(value) && value._type === schemaTypes.block.name, editor.isTextSpan = (value) => isPortableTextSpan$1(value) && value._type == schemaTypes.span.name, editor.isListBlock = (value) => isPortableTextListBlock(value) && value._type === schemaTypes.block.name, editor.isVoid = (element) => schemaTypes.block.name !== element._type && (schemaTypes.blockObjects.map((obj) => obj.name).includes(element._type) || schemaTypes.inlineObjects.map((obj) => obj.name).includes(element._type)), editor.isInline = (element) => schemaTypes.inlineObjects.map((obj) => obj.name).includes(element._type) && "__inline" in element && element.__inline === !0;
|
|
2978
3019
|
const { normalizeNode } = editor;
|
|
2979
3020
|
return editor.normalizeNode = (entry) => {
|
|
2980
3021
|
const [node, path] = entry;
|
|
@@ -3047,7 +3088,6 @@ function createWithHotkeys(types, portableTextEditor, hotkeysFromOptions) {
|
|
|
3047
3088
|
const reservedHotkeys = ["enter", "tab", "shift", "delete", "end"], activeHotkeys = hotkeysFromOptions || DEFAULT_HOTKEYS;
|
|
3048
3089
|
return function(editor) {
|
|
3049
3090
|
return editor.pteWithHotKeys = (event) => {
|
|
3050
|
-
var _a, _b, _c, _d, _e, _f;
|
|
3051
3091
|
Object.keys(activeHotkeys).forEach((cat) => {
|
|
3052
3092
|
if (cat === "marks")
|
|
3053
3093
|
for (const hotkey in activeHotkeys[cat]) {
|
|
@@ -3094,7 +3134,7 @@ function createWithHotkeys(types, portableTextEditor, hotkeysFromOptions) {
|
|
|
3094
3134
|
}
|
|
3095
3135
|
}
|
|
3096
3136
|
if (isBackspace && editor.selection && editor.selection.focus.path[0] === 0 && Range.isCollapsed(editor.selection)) {
|
|
3097
|
-
const focusBlock = Node.descendant(editor, editor.selection.focus.path.slice(0, 1)), nextPath = Path.next(editor.selection.focus.path.slice(0, 1)), nextBlock = Node.has(editor, nextPath), isTextBlock = isPortableTextTextBlock(focusBlock), isEmptyFocusBlock = isTextBlock && focusBlock.children.length === 1 &&
|
|
3137
|
+
const focusBlock = Node.descendant(editor, editor.selection.focus.path.slice(0, 1)), nextPath = Path.next(editor.selection.focus.path.slice(0, 1)), nextBlock = Node.has(editor, nextPath), isTextBlock = isPortableTextTextBlock(focusBlock), isEmptyFocusBlock = isTextBlock && focusBlock.children.length === 1 && focusBlock.children?.[0]?.text === "";
|
|
3098
3138
|
if (nextBlock && isTextBlock && isEmptyFocusBlock) {
|
|
3099
3139
|
event.preventDefault(), event.stopPropagation(), Transforms.removeNodes(editor, { match: (n) => n === focusBlock }), editor.onChange();
|
|
3100
3140
|
return;
|
|
@@ -3104,7 +3144,7 @@ function createWithHotkeys(types, portableTextEditor, hotkeysFromOptions) {
|
|
|
3104
3144
|
const prevPath = Path.previous(editor.selection.focus.path.slice(0, 1)), prevBlock = Node.descendant(editor, prevPath), focusBlock = Node.descendant(editor, editor.selection.focus.path.slice(0, 1));
|
|
3105
3145
|
if (prevBlock && focusBlock && Editor.isVoid(editor, prevBlock) && editor.selection.focus.offset === 0) {
|
|
3106
3146
|
debug$8("Preventing deleting void block above"), event.preventDefault(), event.stopPropagation();
|
|
3107
|
-
const isTextBlock = isPortableTextTextBlock(focusBlock), isEmptyFocusBlock = isTextBlock && focusBlock.children.length === 1 &&
|
|
3147
|
+
const isTextBlock = isPortableTextTextBlock(focusBlock), isEmptyFocusBlock = isTextBlock && focusBlock.children.length === 1 && focusBlock.children?.[0]?.text === "";
|
|
3108
3148
|
if (!isTextBlock || isEmptyFocusBlock) {
|
|
3109
3149
|
Transforms.removeNodes(editor, { match: (n) => n === focusBlock }), Transforms.select(editor, prevPath), editor.onChange();
|
|
3110
3150
|
return;
|
|
@@ -3120,17 +3160,17 @@ function createWithHotkeys(types, portableTextEditor, hotkeysFromOptions) {
|
|
|
3120
3160
|
const nextBlock = Node.descendant(
|
|
3121
3161
|
editor,
|
|
3122
3162
|
Path.next(editor.selection.focus.path.slice(0, 1))
|
|
3123
|
-
), focusBlockPath = editor.selection.focus.path.slice(0, 1), focusBlock = Node.descendant(editor, focusBlockPath), isEmptyFocusBlock = isPortableTextTextBlock(focusBlock) && focusBlock.children.length === 1 &&
|
|
3163
|
+
), focusBlockPath = editor.selection.focus.path.slice(0, 1), focusBlock = Node.descendant(editor, focusBlockPath), isEmptyFocusBlock = isPortableTextTextBlock(focusBlock) && focusBlock.children.length === 1 && focusBlock.children?.[0]?.text === "";
|
|
3124
3164
|
if (nextBlock && focusBlock && !Editor.isVoid(editor, focusBlock) && Editor.isVoid(editor, nextBlock) && isEmptyFocusBlock) {
|
|
3125
3165
|
debug$8("Preventing deleting void block below"), event.preventDefault(), event.stopPropagation(), Transforms.removeNodes(editor, { match: (n) => n === focusBlock }), Transforms.select(editor, focusBlockPath), editor.onChange();
|
|
3126
3166
|
return;
|
|
3127
3167
|
}
|
|
3128
3168
|
}
|
|
3129
3169
|
if ((isTab || isShiftTab) && editor.selection) {
|
|
3130
|
-
const [focusChild] = Editor.node(editor, editor.selection.focus, { depth: 2 }), [focusBlock] = isPortableTextSpan(focusChild) ? Editor.node(editor, editor.selection.focus, { depth: 1 }) : [], hasAnnotationFocus = focusChild && isPortableTextTextBlock(focusBlock) && isPortableTextSpan(focusChild) && (focusChild.marks || []).filter(
|
|
3170
|
+
const [focusChild] = Editor.node(editor, editor.selection.focus, { depth: 2 }), [focusBlock] = isPortableTextSpan$1(focusChild) ? Editor.node(editor, editor.selection.focus, { depth: 1 }) : [], hasAnnotationFocus = focusChild && isPortableTextTextBlock(focusBlock) && isPortableTextSpan$1(focusChild) && (focusChild.marks || []).filter(
|
|
3131
3171
|
(m) => (focusBlock.markDefs || []).map((def) => def._key).includes(m)
|
|
3132
3172
|
).length > 0, [start] = Range.edges(editor.selection), atStartOfNode = Editor.isStart(editor, start, start.path);
|
|
3133
|
-
focusChild && isPortableTextSpan(focusChild) && (!hasAnnotationFocus || atStartOfNode) && editor.pteIncrementBlockLevels(isShiftTab) && event.preventDefault();
|
|
3173
|
+
focusChild && isPortableTextSpan$1(focusChild) && (!hasAnnotationFocus || atStartOfNode) && editor.pteIncrementBlockLevels(isShiftTab) && event.preventDefault();
|
|
3134
3174
|
}
|
|
3135
3175
|
if (isEnter && !isShiftEnter && editor.selection) {
|
|
3136
3176
|
const focusBlockPath = editor.selection.focus.path.slice(0, 1), focusBlock = Node.descendant(editor, focusBlockPath);
|
|
@@ -3425,13 +3465,7 @@ function validateValue(value, types, keyGenerator) {
|
|
|
3425
3465
|
const debug$7 = debugWithName("plugin:withInsertData");
|
|
3426
3466
|
function createWithInsertData(change$, schemaTypes, keyGenerator) {
|
|
3427
3467
|
return function(editor) {
|
|
3428
|
-
const blockTypeName = schemaTypes.block.name, spanTypeName = schemaTypes.span.name, whitespaceOnPasteMode = schemaTypes.block.options.unstable_whitespaceOnPasteMode, toPlainText = (blocks) => blocks.map((block) => {
|
|
3429
|
-
var _a;
|
|
3430
|
-
return editor.isTextBlock(block) ? block.children.map((child) => {
|
|
3431
|
-
var _a2;
|
|
3432
|
-
return child._type === spanTypeName ? child.text : `[${((_a2 = schemaTypes.inlineObjects.find((t) => t.name === child._type)) == null ? void 0 : _a2.title) || "Object"}]`;
|
|
3433
|
-
}).join("") : `[${((_a = schemaTypes.blockObjects.find((t) => t.name === block._type)) == null ? void 0 : _a.title) || "Object"}]`;
|
|
3434
|
-
}).join(`
|
|
3468
|
+
const blockTypeName = schemaTypes.block.name, spanTypeName = schemaTypes.span.name, whitespaceOnPasteMode = schemaTypes.block.options.unstable_whitespaceOnPasteMode, toPlainText = (blocks) => blocks.map((block) => editor.isTextBlock(block) ? block.children.map((child) => child._type === spanTypeName ? child.text : `[${schemaTypes.inlineObjects.find((t) => t.name === child._type)?.title || "Object"}]`).join("") : `[${schemaTypes.blockObjects.find((t) => t.name === block._type)?.title || "Object"}]`).join(`
|
|
3435
3469
|
|
|
3436
3470
|
`);
|
|
3437
3471
|
return editor.setFragmentData = (data, originEvent) => {
|
|
@@ -3463,7 +3497,6 @@ function createWithInsertData(change$, schemaTypes, keyGenerator) {
|
|
|
3463
3497
|
const fragment = editor.getFragment(), portableText = fromSlateValue(fragment, blockTypeName), asJSON = JSON.stringify(portableText), asPlainText = toPlainText(portableText);
|
|
3464
3498
|
data.clearData(), data.setData("text/plain", asPlainText), data.setData("text/html", asHTML), data.setData("application/json", asJSON), data.setData("application/x-portable-text", asJSON), debug$7("text", asPlainText), data.setData("application/x-portable-text-event-origin", originEvent || "external"), debug$7("Set fragment data", asJSON, asHTML);
|
|
3465
3499
|
}, editor.insertPortableTextData = (data) => {
|
|
3466
|
-
var _a, _b;
|
|
3467
3500
|
if (!editor.selection)
|
|
3468
3501
|
return !1;
|
|
3469
3502
|
const pText = data.getData("application/x-portable-text"), origin = data.getData("application/x-portable-text-event-origin");
|
|
@@ -3477,8 +3510,8 @@ function createWithInsertData(change$, schemaTypes, keyGenerator) {
|
|
|
3477
3510
|
spanTypeName,
|
|
3478
3511
|
schemaTypes
|
|
3479
3512
|
), validation = validateValue(parsed, schemaTypes, keyGenerator);
|
|
3480
|
-
if (!validation.valid && !
|
|
3481
|
-
const errorDescription = `${
|
|
3513
|
+
if (!validation.valid && !validation.resolution?.autoResolve) {
|
|
3514
|
+
const errorDescription = `${validation.resolution?.description}`;
|
|
3482
3515
|
return change$.next({
|
|
3483
3516
|
type: "error",
|
|
3484
3517
|
level: "warning",
|
|
@@ -3492,7 +3525,6 @@ function createWithInsertData(change$, schemaTypes, keyGenerator) {
|
|
|
3492
3525
|
}
|
|
3493
3526
|
return !1;
|
|
3494
3527
|
}, editor.insertTextOrHTMLData = (data) => {
|
|
3495
|
-
var _a;
|
|
3496
3528
|
if (!editor.selection)
|
|
3497
3529
|
return debug$7("No selection, not inserting"), !1;
|
|
3498
3530
|
change$.next({ type: "loading", isLoading: !0 });
|
|
@@ -3518,7 +3550,7 @@ function createWithInsertData(change$, schemaTypes, keyGenerator) {
|
|
|
3518
3550
|
const validation = validateValue(portableText, schemaTypes, keyGenerator);
|
|
3519
3551
|
if (!validation.valid) {
|
|
3520
3552
|
const errorDescription = `Could not validate the resulting portable text to insert.
|
|
3521
|
-
${
|
|
3553
|
+
${validation.resolution?.description}
|
|
3522
3554
|
Try to insert as plain text (shift-paste) instead.`;
|
|
3523
3555
|
return change$.next({
|
|
3524
3556
|
type: "error",
|
|
@@ -3783,15 +3815,14 @@ function useSyncValue(props) {
|
|
|
3783
3815
|
isChanged = !0;
|
|
3784
3816
|
}
|
|
3785
3817
|
slateValueFromProps.forEach((currentBlock, currentBlockIndex) => {
|
|
3786
|
-
var _a, _b, _c, _d, _e;
|
|
3787
3818
|
const oldBlock = slateEditor.children[currentBlockIndex];
|
|
3788
3819
|
if (oldBlock && !isEqual(currentBlock, oldBlock) && isValid) {
|
|
3789
3820
|
const validationValue = [value[currentBlockIndex]], validation = validateValue(validationValue, schemaTypes, keyGenerator);
|
|
3790
|
-
!validation.valid &&
|
|
3791
|
-
`${validation.resolution.action} for block with _key '${validationValue[0]._key}'. ${
|
|
3821
|
+
!validation.valid && validation.resolution?.autoResolve && validation.resolution?.patches.length > 0 && !readOnly && previousValue.current && previousValue.current !== value && (console.warn(
|
|
3822
|
+
`${validation.resolution.action} for block with _key '${validationValue[0]._key}'. ${validation.resolution?.description}`
|
|
3792
3823
|
), validation.resolution.patches.forEach((patch) => {
|
|
3793
3824
|
change$.next({ type: "patch", patch });
|
|
3794
|
-
})), validation.valid ||
|
|
3825
|
+
})), validation.valid || validation.resolution?.autoResolve ? (oldBlock._key === currentBlock._key ? (debug$5.enabled && debug$5("Updating block", oldBlock, currentBlock), _updateBlock(slateEditor, currentBlock, oldBlock, currentBlockIndex)) : (debug$5.enabled && debug$5("Replacing block", oldBlock, currentBlock), _replaceBlock(slateEditor, currentBlock, currentBlockIndex)), isChanged = !0) : (change$.next({
|
|
3795
3826
|
type: "invalidValue",
|
|
3796
3827
|
resolution: validation.resolution,
|
|
3797
3828
|
value
|
|
@@ -3802,7 +3833,7 @@ function useSyncValue(props) {
|
|
|
3802
3833
|
debug$5.enabled && debug$5(
|
|
3803
3834
|
"Validating and inserting new block in the end of the value",
|
|
3804
3835
|
currentBlock
|
|
3805
|
-
), validation.valid ||
|
|
3836
|
+
), validation.valid || validation.resolution?.autoResolve ? withPreserveKeys(slateEditor, () => {
|
|
3806
3837
|
Transforms.insertNodes(slateEditor, currentBlock, {
|
|
3807
3838
|
at: [currentBlockIndex]
|
|
3808
3839
|
});
|
|
@@ -3872,9 +3903,9 @@ function _updateBlock(slateEditor, currentBlock, oldBlock, currentBlockIndex) {
|
|
|
3872
3903
|
}));
|
|
3873
3904
|
}
|
|
3874
3905
|
), currentBlock.children.forEach((currentBlockChild, currentBlockChildIndex) => {
|
|
3875
|
-
const oldBlockChild = oldBlock.children[currentBlockChildIndex], isChildChanged = !isEqual(currentBlockChild, oldBlockChild), isTextChanged = !isEqual(currentBlockChild.text, oldBlockChild
|
|
3906
|
+
const oldBlockChild = oldBlock.children[currentBlockChildIndex], isChildChanged = !isEqual(currentBlockChild, oldBlockChild), isTextChanged = !isEqual(currentBlockChild.text, oldBlockChild?.text), path = [currentBlockIndex, currentBlockChildIndex];
|
|
3876
3907
|
if (isChildChanged)
|
|
3877
|
-
if (currentBlockChild._key ===
|
|
3908
|
+
if (currentBlockChild._key === oldBlockChild?._key) {
|
|
3878
3909
|
debug$5("Updating changed child", currentBlockChild, oldBlockChild), Transforms.setNodes(slateEditor, currentBlockChild, {
|
|
3879
3910
|
at: path
|
|
3880
3911
|
});
|
|
@@ -3990,16 +4021,22 @@ function PortableTextEditorSelectionProvider(props) {
|
|
|
3990
4021
|
};
|
|
3991
4022
|
}, [change$]), /* @__PURE__ */ jsx(PortableTextEditorSelectionContext.Provider, { value: selection, children: props.children });
|
|
3992
4023
|
}
|
|
3993
|
-
var __defProp = Object.defineProperty, __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __publicField = (obj, key, value) => __defNormalProp(obj, typeof key != "symbol" ? key + "" : key, value);
|
|
3994
4024
|
const debug$2 = debugWithName("component:PortableTextEditor");
|
|
3995
4025
|
class PortableTextEditor extends Component {
|
|
4026
|
+
/**
|
|
4027
|
+
* An observable of all the editor changes.
|
|
4028
|
+
*/
|
|
4029
|
+
change$ = new Subject();
|
|
4030
|
+
/**
|
|
4031
|
+
* A lookup table for all the relevant schema types for this portable text type.
|
|
4032
|
+
*/
|
|
4033
|
+
schemaTypes;
|
|
4034
|
+
/**
|
|
4035
|
+
* The editor API (currently implemented with Slate).
|
|
4036
|
+
*/
|
|
4037
|
+
editable;
|
|
3996
4038
|
constructor(props) {
|
|
3997
|
-
if (super(props),
|
|
3998
|
-
this.editable = { ...this.editable, ...editable };
|
|
3999
|
-
}), __publicField(this, "getValue", () => {
|
|
4000
|
-
if (this.editable)
|
|
4001
|
-
return this.editable.getValue();
|
|
4002
|
-
}), !props.schemaType)
|
|
4039
|
+
if (super(props), !props.schemaType)
|
|
4003
4040
|
throw new Error('PortableTextEditor: missing "schemaType" property');
|
|
4004
4041
|
props.incomingPatches$ && console.warn("The prop 'incomingPatches$' is deprecated and renamed to 'patches$'"), this.change$.next({ type: "loading", isLoading: !0 }), this.schemaTypes = getPortableTextMemberSchemaTypes(
|
|
4005
4042
|
props.schemaType.hasOwnProperty("jsonType") ? props.schemaType : compileType(props.schemaType)
|
|
@@ -4010,6 +4047,13 @@ class PortableTextEditor extends Component {
|
|
|
4010
4047
|
this.props.schemaType.hasOwnProperty("jsonType") ? this.props.schemaType : compileType(this.props.schemaType)
|
|
4011
4048
|
)), this.props.editorRef !== prevProps.editorRef && this.props.editorRef && (this.props.editorRef.current = this);
|
|
4012
4049
|
}
|
|
4050
|
+
setEditable = (editable) => {
|
|
4051
|
+
this.editable = { ...this.editable, ...editable };
|
|
4052
|
+
};
|
|
4053
|
+
getValue = () => {
|
|
4054
|
+
if (this.editable)
|
|
4055
|
+
return this.editable.getValue();
|
|
4056
|
+
};
|
|
4013
4057
|
render() {
|
|
4014
4058
|
const { onChange, value, children, patches$, incomingPatches$ } = this.props, { change$ } = this, _patches$ = incomingPatches$ || patches$, maxBlocks = typeof this.props.maxBlocks > "u" ? void 0 : parseInt(this.props.maxBlocks.toString(), 10) || void 0, readOnly = !!this.props.readOnly, keyGenerator = this.props.keyGenerator || defaultKeyGenerator;
|
|
4015
4059
|
return /* @__PURE__ */ jsx(
|
|
@@ -4035,99 +4079,59 @@ class PortableTextEditor extends Component {
|
|
|
4035
4079
|
}
|
|
4036
4080
|
);
|
|
4037
4081
|
}
|
|
4082
|
+
// Static API methods
|
|
4083
|
+
static activeAnnotations = (editor) => editor && editor.editable ? editor.editable.activeAnnotations() : [];
|
|
4084
|
+
static isAnnotationActive = (editor, annotationType) => editor && editor.editable ? editor.editable.isAnnotationActive(annotationType) : !1;
|
|
4085
|
+
static addAnnotation = (editor, type, value) => editor.editable?.addAnnotation(type, value);
|
|
4086
|
+
static blur = (editor) => {
|
|
4087
|
+
debug$2("Host blurred"), editor.editable?.blur();
|
|
4088
|
+
};
|
|
4089
|
+
static delete = (editor, selection, options) => editor.editable?.delete(selection, options);
|
|
4090
|
+
static findDOMNode = (editor, element) => editor.editable?.findDOMNode(element);
|
|
4091
|
+
static findByPath = (editor, path) => editor.editable?.findByPath(path) || [];
|
|
4092
|
+
static focus = (editor) => {
|
|
4093
|
+
debug$2("Host requesting focus"), editor.editable?.focus();
|
|
4094
|
+
};
|
|
4095
|
+
static focusBlock = (editor) => editor.editable?.focusBlock();
|
|
4096
|
+
static focusChild = (editor) => editor.editable?.focusChild();
|
|
4097
|
+
static getSelection = (editor) => editor.editable ? editor.editable.getSelection() : null;
|
|
4098
|
+
static getValue = (editor) => editor.editable?.getValue();
|
|
4099
|
+
static hasBlockStyle = (editor, blockStyle) => editor.editable?.hasBlockStyle(blockStyle);
|
|
4100
|
+
static hasListStyle = (editor, listStyle) => editor.editable?.hasListStyle(listStyle);
|
|
4101
|
+
static isCollapsedSelection = (editor) => editor.editable?.isCollapsedSelection();
|
|
4102
|
+
static isExpandedSelection = (editor) => editor.editable?.isExpandedSelection();
|
|
4103
|
+
static isMarkActive = (editor, mark) => editor.editable?.isMarkActive(mark);
|
|
4104
|
+
static insertChild = (editor, type, value) => (debug$2("Host inserting child"), editor.editable?.insertChild(type, value));
|
|
4105
|
+
static insertBlock = (editor, type, value) => editor.editable?.insertBlock(type, value);
|
|
4106
|
+
static insertBreak = (editor) => editor.editable?.insertBreak();
|
|
4107
|
+
static isVoid = (editor, element) => editor.editable?.isVoid(element);
|
|
4108
|
+
static isObjectPath = (editor, path) => {
|
|
4109
|
+
if (!path || !Array.isArray(path)) return !1;
|
|
4110
|
+
const isChildObjectEditPath = path.length > 3 && path[1] === "children";
|
|
4111
|
+
return path.length > 1 && path[1] !== "children" || isChildObjectEditPath;
|
|
4112
|
+
};
|
|
4113
|
+
static marks = (editor) => editor.editable?.marks();
|
|
4114
|
+
static select = (editor, selection) => {
|
|
4115
|
+
debug$2("Host setting selection", selection), editor.editable?.select(selection);
|
|
4116
|
+
};
|
|
4117
|
+
static removeAnnotation = (editor, type) => editor.editable?.removeAnnotation(type);
|
|
4118
|
+
static toggleBlockStyle = (editor, blockStyle) => (debug$2("Host is toggling block style"), editor.editable?.toggleBlockStyle(blockStyle));
|
|
4119
|
+
static toggleList = (editor, listStyle) => editor.editable?.toggleList(listStyle);
|
|
4120
|
+
static toggleMark = (editor, mark) => {
|
|
4121
|
+
debug$2("Host toggling mark", mark), editor.editable?.toggleMark(mark);
|
|
4122
|
+
};
|
|
4123
|
+
static getFragment = (editor) => (debug$2("Host getting fragment"), editor.editable?.getFragment());
|
|
4124
|
+
static undo = (editor) => {
|
|
4125
|
+
debug$2("Host undoing"), editor.editable?.undo();
|
|
4126
|
+
};
|
|
4127
|
+
static redo = (editor) => {
|
|
4128
|
+
debug$2("Host redoing"), editor.editable?.redo();
|
|
4129
|
+
};
|
|
4130
|
+
static isSelectionsOverlapping = (editor, selectionA, selectionB) => editor.editable?.isSelectionsOverlapping(selectionA, selectionB);
|
|
4038
4131
|
}
|
|
4039
|
-
__publicField(PortableTextEditor, "activeAnnotations", (editor) => editor && editor.editable ? editor.editable.activeAnnotations() : []), __publicField(PortableTextEditor, "isAnnotationActive", (editor, annotationType) => editor && editor.editable ? editor.editable.isAnnotationActive(annotationType) : !1), __publicField(PortableTextEditor, "addAnnotation", (editor, type, value) => {
|
|
4040
|
-
var _a;
|
|
4041
|
-
return (_a = editor.editable) == null ? void 0 : _a.addAnnotation(type, value);
|
|
4042
|
-
}), __publicField(PortableTextEditor, "blur", (editor) => {
|
|
4043
|
-
var _a;
|
|
4044
|
-
debug$2("Host blurred"), (_a = editor.editable) == null || _a.blur();
|
|
4045
|
-
}), __publicField(PortableTextEditor, "delete", (editor, selection, options) => {
|
|
4046
|
-
var _a;
|
|
4047
|
-
return (_a = editor.editable) == null ? void 0 : _a.delete(selection, options);
|
|
4048
|
-
}), __publicField(PortableTextEditor, "findDOMNode", (editor, element) => {
|
|
4049
|
-
var _a;
|
|
4050
|
-
return (_a = editor.editable) == null ? void 0 : _a.findDOMNode(element);
|
|
4051
|
-
}), __publicField(PortableTextEditor, "findByPath", (editor, path) => {
|
|
4052
|
-
var _a;
|
|
4053
|
-
return ((_a = editor.editable) == null ? void 0 : _a.findByPath(path)) || [];
|
|
4054
|
-
}), __publicField(PortableTextEditor, "focus", (editor) => {
|
|
4055
|
-
var _a;
|
|
4056
|
-
debug$2("Host requesting focus"), (_a = editor.editable) == null || _a.focus();
|
|
4057
|
-
}), __publicField(PortableTextEditor, "focusBlock", (editor) => {
|
|
4058
|
-
var _a;
|
|
4059
|
-
return (_a = editor.editable) == null ? void 0 : _a.focusBlock();
|
|
4060
|
-
}), __publicField(PortableTextEditor, "focusChild", (editor) => {
|
|
4061
|
-
var _a;
|
|
4062
|
-
return (_a = editor.editable) == null ? void 0 : _a.focusChild();
|
|
4063
|
-
}), __publicField(PortableTextEditor, "getSelection", (editor) => editor.editable ? editor.editable.getSelection() : null), __publicField(PortableTextEditor, "getValue", (editor) => {
|
|
4064
|
-
var _a;
|
|
4065
|
-
return (_a = editor.editable) == null ? void 0 : _a.getValue();
|
|
4066
|
-
}), __publicField(PortableTextEditor, "hasBlockStyle", (editor, blockStyle) => {
|
|
4067
|
-
var _a;
|
|
4068
|
-
return (_a = editor.editable) == null ? void 0 : _a.hasBlockStyle(blockStyle);
|
|
4069
|
-
}), __publicField(PortableTextEditor, "hasListStyle", (editor, listStyle) => {
|
|
4070
|
-
var _a;
|
|
4071
|
-
return (_a = editor.editable) == null ? void 0 : _a.hasListStyle(listStyle);
|
|
4072
|
-
}), __publicField(PortableTextEditor, "isCollapsedSelection", (editor) => {
|
|
4073
|
-
var _a;
|
|
4074
|
-
return (_a = editor.editable) == null ? void 0 : _a.isCollapsedSelection();
|
|
4075
|
-
}), __publicField(PortableTextEditor, "isExpandedSelection", (editor) => {
|
|
4076
|
-
var _a;
|
|
4077
|
-
return (_a = editor.editable) == null ? void 0 : _a.isExpandedSelection();
|
|
4078
|
-
}), __publicField(PortableTextEditor, "isMarkActive", (editor, mark) => {
|
|
4079
|
-
var _a;
|
|
4080
|
-
return (_a = editor.editable) == null ? void 0 : _a.isMarkActive(mark);
|
|
4081
|
-
}), __publicField(PortableTextEditor, "insertChild", (editor, type, value) => {
|
|
4082
|
-
var _a;
|
|
4083
|
-
return debug$2("Host inserting child"), (_a = editor.editable) == null ? void 0 : _a.insertChild(type, value);
|
|
4084
|
-
}), __publicField(PortableTextEditor, "insertBlock", (editor, type, value) => {
|
|
4085
|
-
var _a;
|
|
4086
|
-
return (_a = editor.editable) == null ? void 0 : _a.insertBlock(type, value);
|
|
4087
|
-
}), __publicField(PortableTextEditor, "insertBreak", (editor) => {
|
|
4088
|
-
var _a;
|
|
4089
|
-
return (_a = editor.editable) == null ? void 0 : _a.insertBreak();
|
|
4090
|
-
}), __publicField(PortableTextEditor, "isVoid", (editor, element) => {
|
|
4091
|
-
var _a;
|
|
4092
|
-
return (_a = editor.editable) == null ? void 0 : _a.isVoid(element);
|
|
4093
|
-
}), __publicField(PortableTextEditor, "isObjectPath", (editor, path) => {
|
|
4094
|
-
if (!path || !Array.isArray(path)) return !1;
|
|
4095
|
-
const isChildObjectEditPath = path.length > 3 && path[1] === "children";
|
|
4096
|
-
return path.length > 1 && path[1] !== "children" || isChildObjectEditPath;
|
|
4097
|
-
}), __publicField(PortableTextEditor, "marks", (editor) => {
|
|
4098
|
-
var _a;
|
|
4099
|
-
return (_a = editor.editable) == null ? void 0 : _a.marks();
|
|
4100
|
-
}), __publicField(PortableTextEditor, "select", (editor, selection) => {
|
|
4101
|
-
var _a;
|
|
4102
|
-
debug$2("Host setting selection", selection), (_a = editor.editable) == null || _a.select(selection);
|
|
4103
|
-
}), __publicField(PortableTextEditor, "removeAnnotation", (editor, type) => {
|
|
4104
|
-
var _a;
|
|
4105
|
-
return (_a = editor.editable) == null ? void 0 : _a.removeAnnotation(type);
|
|
4106
|
-
}), __publicField(PortableTextEditor, "toggleBlockStyle", (editor, blockStyle) => {
|
|
4107
|
-
var _a;
|
|
4108
|
-
return debug$2("Host is toggling block style"), (_a = editor.editable) == null ? void 0 : _a.toggleBlockStyle(blockStyle);
|
|
4109
|
-
}), __publicField(PortableTextEditor, "toggleList", (editor, listStyle) => {
|
|
4110
|
-
var _a;
|
|
4111
|
-
return (_a = editor.editable) == null ? void 0 : _a.toggleList(listStyle);
|
|
4112
|
-
}), __publicField(PortableTextEditor, "toggleMark", (editor, mark) => {
|
|
4113
|
-
var _a;
|
|
4114
|
-
debug$2("Host toggling mark", mark), (_a = editor.editable) == null || _a.toggleMark(mark);
|
|
4115
|
-
}), __publicField(PortableTextEditor, "getFragment", (editor) => {
|
|
4116
|
-
var _a;
|
|
4117
|
-
return debug$2("Host getting fragment"), (_a = editor.editable) == null ? void 0 : _a.getFragment();
|
|
4118
|
-
}), __publicField(PortableTextEditor, "undo", (editor) => {
|
|
4119
|
-
var _a;
|
|
4120
|
-
debug$2("Host undoing"), (_a = editor.editable) == null || _a.undo();
|
|
4121
|
-
}), __publicField(PortableTextEditor, "redo", (editor) => {
|
|
4122
|
-
var _a;
|
|
4123
|
-
debug$2("Host redoing"), (_a = editor.editable) == null || _a.redo();
|
|
4124
|
-
}), __publicField(PortableTextEditor, "isSelectionsOverlapping", (editor, selectionA, selectionB) => {
|
|
4125
|
-
var _a;
|
|
4126
|
-
return (_a = editor.editable) == null ? void 0 : _a.isSelectionsOverlapping(selectionA, selectionB);
|
|
4127
|
-
});
|
|
4128
4132
|
const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (props) => {
|
|
4129
4133
|
const { attributes, children, leaf, schemaTypes, renderChild, renderDecorator, renderAnnotation } = props, spanRef = useRef(null), portableTextEditor = usePortableTextEditor(), blockSelected = useSelected(), [focused, setFocused] = useState(!1), [selected, setSelected] = useState(!1), block = children.props.parent, path = useMemo(
|
|
4130
|
-
() => block ? [{ _key: block
|
|
4134
|
+
() => block ? [{ _key: block?._key }, "children", { _key: leaf._key }] : [],
|
|
4131
4135
|
[block, leaf._key]
|
|
4132
4136
|
), decoratorValues = useMemo(
|
|
4133
4137
|
() => schemaTypes.decorators.map((dec) => dec.value),
|
|
@@ -4137,10 +4141,7 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
|
|
|
4137
4141
|
[decoratorValues, leaf.marks]
|
|
4138
4142
|
), annotationMarks = Array.isArray(leaf.marks) ? leaf.marks : EMPTY_MARKS, annotations = useMemo(
|
|
4139
4143
|
() => annotationMarks.map(
|
|
4140
|
-
(mark) =>
|
|
4141
|
-
var _a;
|
|
4142
|
-
return !decoratorValues.includes(mark) && ((_a = block == null ? void 0 : block.markDefs) == null ? void 0 : _a.find((def) => def._key === mark));
|
|
4143
|
-
}
|
|
4144
|
+
(mark) => !decoratorValues.includes(mark) && block?.markDefs?.find((def) => def._key === mark)
|
|
4144
4145
|
).filter(Boolean),
|
|
4145
4146
|
[annotationMarks, block, decoratorValues]
|
|
4146
4147
|
), shouldTrackSelectionAndFocus = annotations.length > 0 && blockSelected;
|
|
@@ -4451,7 +4452,7 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
|
|
|
4451
4452
|
debug("Pasting normally"), slateEditor.insertData(event.clipboardData);
|
|
4452
4453
|
return;
|
|
4453
4454
|
}
|
|
4454
|
-
const value = PortableTextEditor.getValue(portableTextEditor),
|
|
4455
|
+
const value = PortableTextEditor.getValue(portableTextEditor), path = toPortableTextRange(value, slateEditor.selection, schemaTypes)?.focus.path || [], onPasteResult = onPaste({ event, value, path, schemaTypes });
|
|
4455
4456
|
onPasteResult === void 0 ? (debug("No result from custom paste handler, pasting normally"), slateEditor.insertData(event.clipboardData)) : (change$.next({ type: "loading", isLoading: !0 }), Promise.resolve(onPasteResult).then((result) => {
|
|
4456
4457
|
debug("Custom paste function from client resolved", result), !result || !result.insert ? (debug("No result from custom paste handler, pasting normally"), slateEditor.insertData(event.clipboardData)) : result.insert ? slateEditor.insertFragment(
|
|
4457
4458
|
toSlateValue(result.insert, { schemaTypes })
|
|
@@ -4507,7 +4508,7 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
|
|
|
4507
4508
|
const existingDOMRange = domSelection.getRangeAt(0);
|
|
4508
4509
|
try {
|
|
4509
4510
|
const newDOMRange = ReactEditor.toDOMRange(slateEditor, slateEditor.selection);
|
|
4510
|
-
(newDOMRange.startOffset !== existingDOMRange.startOffset || newDOMRange.endOffset !== existingDOMRange.endOffset) && (debug("DOM range out of sync, validating selection"), domSelection
|
|
4511
|
+
(newDOMRange.startOffset !== existingDOMRange.startOffset || newDOMRange.endOffset !== existingDOMRange.endOffset) && (debug("DOM range out of sync, validating selection"), domSelection?.removeAllRanges(), domSelection.addRange(newDOMRange));
|
|
4511
4512
|
} catch {
|
|
4512
4513
|
debug("Could not resolve selection, selecting top document"), Transforms.deselect(slateEditor), slateEditor.children.length > 0 && Transforms.select(slateEditor, [0, 0]), slateEditor.onChange();
|
|
4513
4514
|
}
|