@atlaskit/editor-plugin-paste 9.0.15 → 9.1.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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-paste
|
|
2
2
|
|
|
3
|
+
## 9.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`b749ce678d575`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/b749ce678d575) -
|
|
8
|
+
Preserve small text formatting across list and task list edits
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- Updated dependencies
|
|
13
|
+
|
|
14
|
+
## 9.0.16
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- Updated dependencies
|
|
19
|
+
|
|
3
20
|
## 9.0.15
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
|
@@ -32,7 +32,9 @@ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/
|
|
|
32
32
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
33
33
|
var _v = _interopRequireDefault(require("uuid/v4"));
|
|
34
34
|
var _analytics = require("@atlaskit/editor-common/analytics");
|
|
35
|
+
var _card = require("@atlaskit/editor-common/card");
|
|
35
36
|
var _coreUtils = require("@atlaskit/editor-common/core-utils");
|
|
37
|
+
var _lists = require("@atlaskit/editor-common/lists");
|
|
36
38
|
var _mark = require("@atlaskit/editor-common/mark");
|
|
37
39
|
var _nesting = require("@atlaskit/editor-common/nesting");
|
|
38
40
|
var _selection = require("@atlaskit/editor-common/selection");
|
|
@@ -48,7 +50,7 @@ var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equa
|
|
|
48
50
|
var _commands = require("../../editor-commands/commands");
|
|
49
51
|
var _pluginFactory = require("../plugin-factory");
|
|
50
52
|
var _edgeCases = require("./edge-cases");
|
|
51
|
-
var
|
|
53
|
+
var _lists2 = require("./edge-cases/lists");
|
|
52
54
|
var _index = require("./index");
|
|
53
55
|
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
54
56
|
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
@@ -172,7 +174,7 @@ function handlePasteIntoTaskOrDecisionOrPanel(slice, queueCardsFromChangedTr) {
|
|
|
172
174
|
var isFirstChildTaskNode = transformedSlice.content.firstChild.type === taskList || transformedSlice.content.firstChild.type === taskItem;
|
|
173
175
|
var tr = (0, _prosemirrorHistory.closeHistory)(state.tr);
|
|
174
176
|
if (panelNode && sliceHasTask && ((_slice$content$firstC3 = slice.content.firstChild) === null || _slice$content$firstC3 === void 0 ? void 0 : _slice$content$firstC3.type) === panel && (0, _index.isEmptyNode)(panelNode) && selection.$from.node() === selection.$to.node()) {
|
|
175
|
-
return Boolean((0,
|
|
177
|
+
return Boolean((0, _lists2.insertSliceInsideOfPanelNodeSelected)(panelNode)({
|
|
176
178
|
tr: tr,
|
|
177
179
|
slice: slice
|
|
178
180
|
}));
|
|
@@ -627,7 +629,11 @@ function insertAutoMacro(slice, macro, view, from, to) {
|
|
|
627
629
|
|
|
628
630
|
// replace the text with the macro as a separate transaction
|
|
629
631
|
// so the autoconversion generates 2 undo steps
|
|
630
|
-
|
|
632
|
+
var macroTr = (0, _prosemirrorHistory.closeHistory)(view.state.tr).replaceRangeWith(before, before + slice.size, macro).scrollIntoView();
|
|
633
|
+
(0, _card.addLinkMetadata)(view.state.selection, macroTr, {
|
|
634
|
+
inputMethod: _analytics.INPUT_METHOD.CLIPBOARD
|
|
635
|
+
});
|
|
636
|
+
view.dispatch(macroTr);
|
|
631
637
|
return true;
|
|
632
638
|
}
|
|
633
639
|
return false;
|
|
@@ -907,21 +913,32 @@ function getTopLevelMarkTypesInSlice(slice) {
|
|
|
907
913
|
return markTypes;
|
|
908
914
|
}
|
|
909
915
|
function handleParagraphBlockMarks(state, slice) {
|
|
916
|
+
var _findParentNodeOfType2;
|
|
910
917
|
if (slice.content.size === 0) {
|
|
911
918
|
return slice;
|
|
912
919
|
}
|
|
913
920
|
var schema = state.schema,
|
|
921
|
+
selection = state.selection,
|
|
914
922
|
$from = state.selection.$from;
|
|
923
|
+
var destinationListNode = (_findParentNodeOfType2 = (0, _utils2.findParentNodeOfType)([schema.nodes.bulletList, schema.nodes.orderedList])(selection)) === null || _findParentNodeOfType2 === void 0 ? void 0 : _findParentNodeOfType2.node;
|
|
924
|
+
var currentNode = typeof $from.node === 'function' ? $from.node() : undefined;
|
|
925
|
+
var isInNormalTaskContext = (currentNode === null || currentNode === void 0 ? void 0 : currentNode.type) === schema.nodes.taskItem || $from.parent.type === schema.nodes.taskItem;
|
|
926
|
+
var isInSmallTaskContext = schema.nodes.blockTaskItem && (currentNode === null || currentNode === void 0 ? void 0 : currentNode.type) === schema.nodes.blockTaskItem || schema.nodes.blockTaskItem && $from.parent.type === schema.nodes.blockTaskItem || schema.nodes.blockTaskItem && $from.parent.type === schema.nodes.paragraph && $from.depth > 0 && $from.node($from.depth - 1).type === schema.nodes.blockTaskItem;
|
|
927
|
+
var destinationBlockMarkAttrs = (0, _expValEquals.expValEquals)('platform_editor_small_font_size', 'isEnabled', true) && schema.marks.fontSize ? destinationListNode ? (0, _lists.getFirstParagraphBlockMarkAttrs)(destinationListNode, schema.marks.fontSize) : isInSmallTaskContext ? (0, _lists.getBlockMarkAttrs)($from.parent, schema.marks.fontSize) || (0, _lists.getFirstParagraphBlockMarkAttrs)(currentNode, schema.marks.fontSize) : false : false;
|
|
915
928
|
|
|
916
929
|
// If no paragraph in the slice contains marks, there's no need for special handling
|
|
930
|
+
// unless we're pasting into a small-text list and need to add the destination block mark.
|
|
917
931
|
// Note: this doesn't check for marks applied to lower level nodes such as text
|
|
918
|
-
if (!sliceHasTopLevelMarks(slice)) {
|
|
932
|
+
if (!sliceHasTopLevelMarks(slice) && !destinationBlockMarkAttrs) {
|
|
919
933
|
return slice;
|
|
920
934
|
}
|
|
935
|
+
var shouldNormalizeFontSizeForTarget = (0, _expValEquals.expValEquals)('platform_editor_small_font_size', 'isEnabled', true) && !!schema.marks.fontSize && (!!destinationListNode || isInNormalTaskContext || !!isInSmallTaskContext);
|
|
921
936
|
|
|
922
|
-
// If pasting a single paragraph into pre-existing content, match destination formatting
|
|
937
|
+
// If pasting a single paragraph into pre-existing content, match destination formatting.
|
|
938
|
+
// For bullet/ordered lists under small-text, we still need to normalize the paragraph block mark
|
|
939
|
+
// so pasted content adopts the destination list state.
|
|
923
940
|
var destinationHasContent = $from.parent.textContent.length > 0;
|
|
924
|
-
if (slice.content.childCount === 1 && destinationHasContent) {
|
|
941
|
+
if (slice.content.childCount === 1 && destinationHasContent && !shouldNormalizeFontSizeForTarget) {
|
|
925
942
|
return slice;
|
|
926
943
|
}
|
|
927
944
|
|
|
@@ -944,23 +961,16 @@ function handleParagraphBlockMarks(state, slice) {
|
|
|
944
961
|
} finally {
|
|
945
962
|
_iterator.f();
|
|
946
963
|
}
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
// another node), the first paragraph will only have its text content captured and pasted
|
|
950
|
-
// since openStart is 1. We decrement the open depth of the slice so it retains any block
|
|
951
|
-
// marks applied to it. We only care about the depth at the start of the selection so
|
|
952
|
-
// there's no need to change openEnd - the rest of the slice gets pasted correctly.
|
|
953
|
-
var openStart = Math.max(0, slice.openStart - 1);
|
|
954
|
-
return new _model.Slice(slice.content, openStart, slice.openEnd);
|
|
955
|
-
}
|
|
956
|
-
|
|
957
|
-
// If the paragraph or heading contains marks forbidden by the parent node
|
|
958
|
-
// (e.g. alignment/indentation), drop those marks from the slice
|
|
959
|
-
return (0, _utils.mapSlice)(slice, function (node) {
|
|
964
|
+
var fontSizeMarkType = shouldNormalizeFontSizeForTarget ? schema.marks.fontSize : undefined;
|
|
965
|
+
var normalizedContent = (0, _utils.mapSlice)(slice, function (node) {
|
|
960
966
|
if (node.type === schema.nodes.paragraph) {
|
|
961
|
-
|
|
967
|
+
var paragraphMarks = node.marks.filter(function (mark) {
|
|
962
968
|
return !forbiddenMarkTypes.includes(mark.type);
|
|
963
|
-
})
|
|
969
|
+
});
|
|
970
|
+
var normalizedMarks = fontSizeMarkType ? paragraphMarks.filter(function (mark) {
|
|
971
|
+
return mark.type !== fontSizeMarkType;
|
|
972
|
+
}) : paragraphMarks;
|
|
973
|
+
return schema.nodes.paragraph.createChecked(undefined, node.content, destinationBlockMarkAttrs && fontSizeMarkType ? normalizedMarks.concat(fontSizeMarkType.create(destinationBlockMarkAttrs)) : normalizedMarks);
|
|
964
974
|
} else if (node.type === schema.nodes.heading) {
|
|
965
975
|
// Preserve heading attributes to keep formatting
|
|
966
976
|
return schema.nodes.heading.createChecked(node.attrs, node.content, node.marks.filter(function (mark) {
|
|
@@ -969,6 +979,24 @@ function handleParagraphBlockMarks(state, slice) {
|
|
|
969
979
|
}
|
|
970
980
|
return node;
|
|
971
981
|
});
|
|
982
|
+
if (forbiddenMarkTypes.length === 0 && !shouldNormalizeFontSizeForTarget) {
|
|
983
|
+
// In a slice containing one or more paragraphs at the document level (not wrapped in
|
|
984
|
+
// another node), the first paragraph will only have its text content captured and pasted
|
|
985
|
+
// since openStart is 1. We decrement the open depth of the slice so it retains any block
|
|
986
|
+
// marks applied to it. We only care about the depth at the start of the selection so
|
|
987
|
+
// there's no need to change openEnd - the rest of the slice gets pasted correctly.
|
|
988
|
+
var openStart = Math.max(0, slice.openStart - 1);
|
|
989
|
+
return new _model.Slice(slice.content, openStart, slice.openEnd);
|
|
990
|
+
}
|
|
991
|
+
if (forbiddenMarkTypes.length === 0 && shouldNormalizeFontSizeForTarget) {
|
|
992
|
+
var _openStart = Math.max(0, slice.openStart - 1);
|
|
993
|
+
return new _model.Slice(normalizedContent.content, _openStart, slice.openEnd);
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
// If the paragraph or heading contains marks forbidden by the parent node
|
|
997
|
+
// (e.g. alignment/indentation), drop those marks from the slice. For lists under the small
|
|
998
|
+
// text experiment, also normalize fontSize to the destination list state.
|
|
999
|
+
return new _model.Slice(normalizedContent.content, slice.openStart, slice.openEnd);
|
|
972
1000
|
}
|
|
973
1001
|
|
|
974
1002
|
/**
|
|
@@ -1010,7 +1038,7 @@ function flattenNestedListInSlice(slice) {
|
|
|
1010
1038
|
}
|
|
1011
1039
|
function handleRichText(slice, queueCardsFromChangedTr) {
|
|
1012
1040
|
return function (state, dispatch) {
|
|
1013
|
-
var _slice$content, _slice$content2, _firstChildOfSlice$ty, _lastChildOfSlice$typ, _panelParentOverCurre;
|
|
1041
|
+
var _slice$content, _slice$content2, _findParentNodeOfType3, _firstChildOfSlice$ty, _lastChildOfSlice$typ, _panelParentOverCurre;
|
|
1014
1042
|
var _state$schema$nodes4 = state.schema.nodes,
|
|
1015
1043
|
codeBlock = _state$schema$nodes4.codeBlock,
|
|
1016
1044
|
heading = _state$schema$nodes4.heading,
|
|
@@ -1020,6 +1048,7 @@ function handleRichText(slice, queueCardsFromChangedTr) {
|
|
|
1020
1048
|
schema = state.schema;
|
|
1021
1049
|
var firstChildOfSlice = (_slice$content = slice.content) === null || _slice$content === void 0 ? void 0 : _slice$content.firstChild;
|
|
1022
1050
|
var lastChildOfSlice = (_slice$content2 = slice.content) === null || _slice$content2 === void 0 ? void 0 : _slice$content2.lastChild;
|
|
1051
|
+
var destinationListFontSizeAttrs = (0, _expValEquals.expValEquals)('platform_editor_small_font_size', 'isEnabled', true) ? (0, _lists.getFirstParagraphBlockMarkAttrs)((_findParentNodeOfType3 = (0, _utils2.findParentNodeOfType)([schema.nodes.bulletList, schema.nodes.orderedList])(selection)) === null || _findParentNodeOfType3 === void 0 ? void 0 : _findParentNodeOfType3.node, schema.marks.fontSize) : false;
|
|
1023
1052
|
|
|
1024
1053
|
// In case user is pasting inline code,
|
|
1025
1054
|
// any backtick ` immediately preceding it should be removed.
|
|
@@ -1104,6 +1133,12 @@ function handleRichText(slice, queueCardsFromChangedTr) {
|
|
|
1104
1133
|
}
|
|
1105
1134
|
}
|
|
1106
1135
|
}
|
|
1136
|
+
if ((0, _expValEquals.expValEquals)('platform_editor_small_font_size', 'isEnabled', true) && isSliceContentListNodes) {
|
|
1137
|
+
var containingList = (0, _utils2.findParentNodeOfTypeClosestToPos)(tr.doc.resolve(tr.mapping.map(selection.from)), [schema.nodes.bulletList, schema.nodes.orderedList]);
|
|
1138
|
+
if (containingList) {
|
|
1139
|
+
(0, _lists.reconcileBlockMarkForContainerAtPos)(tr, containingList.pos, schema.marks.fontSize, destinationListFontSizeAttrs);
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1107
1142
|
tr.setStoredMarks([]);
|
|
1108
1143
|
if (tr.selection.empty && tr.selection.$from.parent.type === codeBlock) {
|
|
1109
1144
|
tr.setSelection(_state.TextSelection.near(tr.selection.$from, 1));
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
2
2
|
import uuid from 'uuid/v4';
|
|
3
3
|
import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
4
|
+
import { addLinkMetadata } from '@atlaskit/editor-common/card';
|
|
4
5
|
import { insideTable } from '@atlaskit/editor-common/core-utils';
|
|
6
|
+
import { getBlockMarkAttrs, getFirstParagraphBlockMarkAttrs, reconcileBlockMarkForContainerAtPos } from '@atlaskit/editor-common/lists';
|
|
5
7
|
import { anyMarkActive } from '@atlaskit/editor-common/mark';
|
|
6
8
|
import { getParentOfTypeCount, getPositionAfterTopParentNodeOfType } from '@atlaskit/editor-common/nesting';
|
|
7
9
|
import { GapCursorSelection, Side } from '@atlaskit/editor-common/selection';
|
|
@@ -596,7 +598,11 @@ function insertAutoMacro(slice, macro, view, from, to) {
|
|
|
596
598
|
|
|
597
599
|
// replace the text with the macro as a separate transaction
|
|
598
600
|
// so the autoconversion generates 2 undo steps
|
|
599
|
-
|
|
601
|
+
const macroTr = closeHistory(view.state.tr).replaceRangeWith(before, before + slice.size, macro).scrollIntoView();
|
|
602
|
+
addLinkMetadata(view.state.selection, macroTr, {
|
|
603
|
+
inputMethod: INPUT_METHOD.CLIPBOARD
|
|
604
|
+
});
|
|
605
|
+
view.dispatch(macroTr);
|
|
600
606
|
return true;
|
|
601
607
|
}
|
|
602
608
|
return false;
|
|
@@ -893,25 +899,36 @@ function getTopLevelMarkTypesInSlice(slice) {
|
|
|
893
899
|
return markTypes;
|
|
894
900
|
}
|
|
895
901
|
export function handleParagraphBlockMarks(state, slice) {
|
|
902
|
+
var _findParentNodeOfType2;
|
|
896
903
|
if (slice.content.size === 0) {
|
|
897
904
|
return slice;
|
|
898
905
|
}
|
|
899
906
|
const {
|
|
900
907
|
schema,
|
|
908
|
+
selection,
|
|
901
909
|
selection: {
|
|
902
910
|
$from
|
|
903
911
|
}
|
|
904
912
|
} = state;
|
|
913
|
+
const destinationListNode = (_findParentNodeOfType2 = findParentNodeOfType([schema.nodes.bulletList, schema.nodes.orderedList])(selection)) === null || _findParentNodeOfType2 === void 0 ? void 0 : _findParentNodeOfType2.node;
|
|
914
|
+
const currentNode = typeof $from.node === 'function' ? $from.node() : undefined;
|
|
915
|
+
const isInNormalTaskContext = (currentNode === null || currentNode === void 0 ? void 0 : currentNode.type) === schema.nodes.taskItem || $from.parent.type === schema.nodes.taskItem;
|
|
916
|
+
const isInSmallTaskContext = schema.nodes.blockTaskItem && (currentNode === null || currentNode === void 0 ? void 0 : currentNode.type) === schema.nodes.blockTaskItem || schema.nodes.blockTaskItem && $from.parent.type === schema.nodes.blockTaskItem || schema.nodes.blockTaskItem && $from.parent.type === schema.nodes.paragraph && $from.depth > 0 && $from.node($from.depth - 1).type === schema.nodes.blockTaskItem;
|
|
917
|
+
const destinationBlockMarkAttrs = expValEquals('platform_editor_small_font_size', 'isEnabled', true) && schema.marks.fontSize ? destinationListNode ? getFirstParagraphBlockMarkAttrs(destinationListNode, schema.marks.fontSize) : isInSmallTaskContext ? getBlockMarkAttrs($from.parent, schema.marks.fontSize) || getFirstParagraphBlockMarkAttrs(currentNode, schema.marks.fontSize) : false : false;
|
|
905
918
|
|
|
906
919
|
// If no paragraph in the slice contains marks, there's no need for special handling
|
|
920
|
+
// unless we're pasting into a small-text list and need to add the destination block mark.
|
|
907
921
|
// Note: this doesn't check for marks applied to lower level nodes such as text
|
|
908
|
-
if (!sliceHasTopLevelMarks(slice)) {
|
|
922
|
+
if (!sliceHasTopLevelMarks(slice) && !destinationBlockMarkAttrs) {
|
|
909
923
|
return slice;
|
|
910
924
|
}
|
|
925
|
+
const shouldNormalizeFontSizeForTarget = expValEquals('platform_editor_small_font_size', 'isEnabled', true) && !!schema.marks.fontSize && (!!destinationListNode || isInNormalTaskContext || !!isInSmallTaskContext);
|
|
911
926
|
|
|
912
|
-
// If pasting a single paragraph into pre-existing content, match destination formatting
|
|
927
|
+
// If pasting a single paragraph into pre-existing content, match destination formatting.
|
|
928
|
+
// For bullet/ordered lists under small-text, we still need to normalize the paragraph block mark
|
|
929
|
+
// so pasted content adopts the destination list state.
|
|
913
930
|
const destinationHasContent = $from.parent.textContent.length > 0;
|
|
914
|
-
if (slice.content.childCount === 1 && destinationHasContent) {
|
|
931
|
+
if (slice.content.childCount === 1 && destinationHasContent && !shouldNormalizeFontSizeForTarget) {
|
|
915
932
|
return slice;
|
|
916
933
|
}
|
|
917
934
|
|
|
@@ -925,7 +942,19 @@ export function handleParagraphBlockMarks(state, slice) {
|
|
|
925
942
|
forbiddenMarkTypes.push(markType);
|
|
926
943
|
}
|
|
927
944
|
}
|
|
928
|
-
|
|
945
|
+
const fontSizeMarkType = shouldNormalizeFontSizeForTarget ? schema.marks.fontSize : undefined;
|
|
946
|
+
const normalizedContent = mapSlice(slice, node => {
|
|
947
|
+
if (node.type === schema.nodes.paragraph) {
|
|
948
|
+
const paragraphMarks = node.marks.filter(mark => !forbiddenMarkTypes.includes(mark.type));
|
|
949
|
+
const normalizedMarks = fontSizeMarkType ? paragraphMarks.filter(mark => mark.type !== fontSizeMarkType) : paragraphMarks;
|
|
950
|
+
return schema.nodes.paragraph.createChecked(undefined, node.content, destinationBlockMarkAttrs && fontSizeMarkType ? normalizedMarks.concat(fontSizeMarkType.create(destinationBlockMarkAttrs)) : normalizedMarks);
|
|
951
|
+
} else if (node.type === schema.nodes.heading) {
|
|
952
|
+
// Preserve heading attributes to keep formatting
|
|
953
|
+
return schema.nodes.heading.createChecked(node.attrs, node.content, node.marks.filter(mark => !forbiddenMarkTypes.includes(mark.type)));
|
|
954
|
+
}
|
|
955
|
+
return node;
|
|
956
|
+
});
|
|
957
|
+
if (forbiddenMarkTypes.length === 0 && !shouldNormalizeFontSizeForTarget) {
|
|
929
958
|
// In a slice containing one or more paragraphs at the document level (not wrapped in
|
|
930
959
|
// another node), the first paragraph will only have its text content captured and pasted
|
|
931
960
|
// since openStart is 1. We decrement the open depth of the slice so it retains any block
|
|
@@ -934,18 +963,15 @@ export function handleParagraphBlockMarks(state, slice) {
|
|
|
934
963
|
const openStart = Math.max(0, slice.openStart - 1);
|
|
935
964
|
return new Slice(slice.content, openStart, slice.openEnd);
|
|
936
965
|
}
|
|
966
|
+
if (forbiddenMarkTypes.length === 0 && shouldNormalizeFontSizeForTarget) {
|
|
967
|
+
const openStart = Math.max(0, slice.openStart - 1);
|
|
968
|
+
return new Slice(normalizedContent.content, openStart, slice.openEnd);
|
|
969
|
+
}
|
|
937
970
|
|
|
938
971
|
// If the paragraph or heading contains marks forbidden by the parent node
|
|
939
|
-
// (e.g. alignment/indentation), drop those marks from the slice
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
return schema.nodes.paragraph.createChecked(undefined, node.content, node.marks.filter(mark => !forbiddenMarkTypes.includes(mark.type)));
|
|
943
|
-
} else if (node.type === schema.nodes.heading) {
|
|
944
|
-
// Preserve heading attributes to keep formatting
|
|
945
|
-
return schema.nodes.heading.createChecked(node.attrs, node.content, node.marks.filter(mark => !forbiddenMarkTypes.includes(mark.type)));
|
|
946
|
-
}
|
|
947
|
-
return node;
|
|
948
|
-
});
|
|
972
|
+
// (e.g. alignment/indentation), drop those marks from the slice. For lists under the small
|
|
973
|
+
// text experiment, also normalize fontSize to the destination list state.
|
|
974
|
+
return new Slice(normalizedContent.content, slice.openStart, slice.openEnd);
|
|
949
975
|
}
|
|
950
976
|
|
|
951
977
|
/**
|
|
@@ -987,7 +1013,7 @@ export function flattenNestedListInSlice(slice) {
|
|
|
987
1013
|
}
|
|
988
1014
|
export function handleRichText(slice, queueCardsFromChangedTr) {
|
|
989
1015
|
return (state, dispatch) => {
|
|
990
|
-
var _slice$content, _slice$content2, _firstChildOfSlice$ty, _lastChildOfSlice$typ, _panelParentOverCurre;
|
|
1016
|
+
var _slice$content, _slice$content2, _findParentNodeOfType3, _firstChildOfSlice$ty, _lastChildOfSlice$typ, _panelParentOverCurre;
|
|
991
1017
|
const {
|
|
992
1018
|
codeBlock,
|
|
993
1019
|
heading,
|
|
@@ -1000,6 +1026,7 @@ export function handleRichText(slice, queueCardsFromChangedTr) {
|
|
|
1000
1026
|
} = state;
|
|
1001
1027
|
const firstChildOfSlice = (_slice$content = slice.content) === null || _slice$content === void 0 ? void 0 : _slice$content.firstChild;
|
|
1002
1028
|
const lastChildOfSlice = (_slice$content2 = slice.content) === null || _slice$content2 === void 0 ? void 0 : _slice$content2.lastChild;
|
|
1029
|
+
const destinationListFontSizeAttrs = expValEquals('platform_editor_small_font_size', 'isEnabled', true) ? getFirstParagraphBlockMarkAttrs((_findParentNodeOfType3 = findParentNodeOfType([schema.nodes.bulletList, schema.nodes.orderedList])(selection)) === null || _findParentNodeOfType3 === void 0 ? void 0 : _findParentNodeOfType3.node, schema.marks.fontSize) : false;
|
|
1003
1030
|
|
|
1004
1031
|
// In case user is pasting inline code,
|
|
1005
1032
|
// any backtick ` immediately preceding it should be removed.
|
|
@@ -1084,6 +1111,12 @@ export function handleRichText(slice, queueCardsFromChangedTr) {
|
|
|
1084
1111
|
}
|
|
1085
1112
|
}
|
|
1086
1113
|
}
|
|
1114
|
+
if (expValEquals('platform_editor_small_font_size', 'isEnabled', true) && isSliceContentListNodes) {
|
|
1115
|
+
const containingList = findParentNodeOfTypeClosestToPos(tr.doc.resolve(tr.mapping.map(selection.from)), [schema.nodes.bulletList, schema.nodes.orderedList]);
|
|
1116
|
+
if (containingList) {
|
|
1117
|
+
reconcileBlockMarkForContainerAtPos(tr, containingList.pos, schema.marks.fontSize, destinationListFontSizeAttrs);
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1087
1120
|
tr.setStoredMarks([]);
|
|
1088
1121
|
if (tr.selection.empty && tr.selection.$from.parent.type === codeBlock) {
|
|
1089
1122
|
tr.setSelection(TextSelection.near(tr.selection.$from, 1));
|
|
@@ -9,7 +9,9 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
9
9
|
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
10
10
|
import uuid from 'uuid/v4';
|
|
11
11
|
import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
12
|
+
import { addLinkMetadata } from '@atlaskit/editor-common/card';
|
|
12
13
|
import { insideTable } from '@atlaskit/editor-common/core-utils';
|
|
14
|
+
import { getBlockMarkAttrs, getFirstParagraphBlockMarkAttrs, reconcileBlockMarkForContainerAtPos } from '@atlaskit/editor-common/lists';
|
|
13
15
|
import { anyMarkActive } from '@atlaskit/editor-common/mark';
|
|
14
16
|
import { getParentOfTypeCount, getPositionAfterTopParentNodeOfType } from '@atlaskit/editor-common/nesting';
|
|
15
17
|
import { GapCursorSelection, Side } from '@atlaskit/editor-common/selection';
|
|
@@ -600,7 +602,11 @@ function insertAutoMacro(slice, macro, view, from, to) {
|
|
|
600
602
|
|
|
601
603
|
// replace the text with the macro as a separate transaction
|
|
602
604
|
// so the autoconversion generates 2 undo steps
|
|
603
|
-
|
|
605
|
+
var macroTr = closeHistory(view.state.tr).replaceRangeWith(before, before + slice.size, macro).scrollIntoView();
|
|
606
|
+
addLinkMetadata(view.state.selection, macroTr, {
|
|
607
|
+
inputMethod: INPUT_METHOD.CLIPBOARD
|
|
608
|
+
});
|
|
609
|
+
view.dispatch(macroTr);
|
|
604
610
|
return true;
|
|
605
611
|
}
|
|
606
612
|
return false;
|
|
@@ -880,21 +886,32 @@ function getTopLevelMarkTypesInSlice(slice) {
|
|
|
880
886
|
return markTypes;
|
|
881
887
|
}
|
|
882
888
|
export function handleParagraphBlockMarks(state, slice) {
|
|
889
|
+
var _findParentNodeOfType2;
|
|
883
890
|
if (slice.content.size === 0) {
|
|
884
891
|
return slice;
|
|
885
892
|
}
|
|
886
893
|
var schema = state.schema,
|
|
894
|
+
selection = state.selection,
|
|
887
895
|
$from = state.selection.$from;
|
|
896
|
+
var destinationListNode = (_findParentNodeOfType2 = findParentNodeOfType([schema.nodes.bulletList, schema.nodes.orderedList])(selection)) === null || _findParentNodeOfType2 === void 0 ? void 0 : _findParentNodeOfType2.node;
|
|
897
|
+
var currentNode = typeof $from.node === 'function' ? $from.node() : undefined;
|
|
898
|
+
var isInNormalTaskContext = (currentNode === null || currentNode === void 0 ? void 0 : currentNode.type) === schema.nodes.taskItem || $from.parent.type === schema.nodes.taskItem;
|
|
899
|
+
var isInSmallTaskContext = schema.nodes.blockTaskItem && (currentNode === null || currentNode === void 0 ? void 0 : currentNode.type) === schema.nodes.blockTaskItem || schema.nodes.blockTaskItem && $from.parent.type === schema.nodes.blockTaskItem || schema.nodes.blockTaskItem && $from.parent.type === schema.nodes.paragraph && $from.depth > 0 && $from.node($from.depth - 1).type === schema.nodes.blockTaskItem;
|
|
900
|
+
var destinationBlockMarkAttrs = expValEquals('platform_editor_small_font_size', 'isEnabled', true) && schema.marks.fontSize ? destinationListNode ? getFirstParagraphBlockMarkAttrs(destinationListNode, schema.marks.fontSize) : isInSmallTaskContext ? getBlockMarkAttrs($from.parent, schema.marks.fontSize) || getFirstParagraphBlockMarkAttrs(currentNode, schema.marks.fontSize) : false : false;
|
|
888
901
|
|
|
889
902
|
// If no paragraph in the slice contains marks, there's no need for special handling
|
|
903
|
+
// unless we're pasting into a small-text list and need to add the destination block mark.
|
|
890
904
|
// Note: this doesn't check for marks applied to lower level nodes such as text
|
|
891
|
-
if (!sliceHasTopLevelMarks(slice)) {
|
|
905
|
+
if (!sliceHasTopLevelMarks(slice) && !destinationBlockMarkAttrs) {
|
|
892
906
|
return slice;
|
|
893
907
|
}
|
|
908
|
+
var shouldNormalizeFontSizeForTarget = expValEquals('platform_editor_small_font_size', 'isEnabled', true) && !!schema.marks.fontSize && (!!destinationListNode || isInNormalTaskContext || !!isInSmallTaskContext);
|
|
894
909
|
|
|
895
|
-
// If pasting a single paragraph into pre-existing content, match destination formatting
|
|
910
|
+
// If pasting a single paragraph into pre-existing content, match destination formatting.
|
|
911
|
+
// For bullet/ordered lists under small-text, we still need to normalize the paragraph block mark
|
|
912
|
+
// so pasted content adopts the destination list state.
|
|
896
913
|
var destinationHasContent = $from.parent.textContent.length > 0;
|
|
897
|
-
if (slice.content.childCount === 1 && destinationHasContent) {
|
|
914
|
+
if (slice.content.childCount === 1 && destinationHasContent && !shouldNormalizeFontSizeForTarget) {
|
|
898
915
|
return slice;
|
|
899
916
|
}
|
|
900
917
|
|
|
@@ -917,23 +934,16 @@ export function handleParagraphBlockMarks(state, slice) {
|
|
|
917
934
|
} finally {
|
|
918
935
|
_iterator.f();
|
|
919
936
|
}
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
// another node), the first paragraph will only have its text content captured and pasted
|
|
923
|
-
// since openStart is 1. We decrement the open depth of the slice so it retains any block
|
|
924
|
-
// marks applied to it. We only care about the depth at the start of the selection so
|
|
925
|
-
// there's no need to change openEnd - the rest of the slice gets pasted correctly.
|
|
926
|
-
var openStart = Math.max(0, slice.openStart - 1);
|
|
927
|
-
return new Slice(slice.content, openStart, slice.openEnd);
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
// If the paragraph or heading contains marks forbidden by the parent node
|
|
931
|
-
// (e.g. alignment/indentation), drop those marks from the slice
|
|
932
|
-
return mapSlice(slice, function (node) {
|
|
937
|
+
var fontSizeMarkType = shouldNormalizeFontSizeForTarget ? schema.marks.fontSize : undefined;
|
|
938
|
+
var normalizedContent = mapSlice(slice, function (node) {
|
|
933
939
|
if (node.type === schema.nodes.paragraph) {
|
|
934
|
-
|
|
940
|
+
var paragraphMarks = node.marks.filter(function (mark) {
|
|
935
941
|
return !forbiddenMarkTypes.includes(mark.type);
|
|
936
|
-
})
|
|
942
|
+
});
|
|
943
|
+
var normalizedMarks = fontSizeMarkType ? paragraphMarks.filter(function (mark) {
|
|
944
|
+
return mark.type !== fontSizeMarkType;
|
|
945
|
+
}) : paragraphMarks;
|
|
946
|
+
return schema.nodes.paragraph.createChecked(undefined, node.content, destinationBlockMarkAttrs && fontSizeMarkType ? normalizedMarks.concat(fontSizeMarkType.create(destinationBlockMarkAttrs)) : normalizedMarks);
|
|
937
947
|
} else if (node.type === schema.nodes.heading) {
|
|
938
948
|
// Preserve heading attributes to keep formatting
|
|
939
949
|
return schema.nodes.heading.createChecked(node.attrs, node.content, node.marks.filter(function (mark) {
|
|
@@ -942,6 +952,24 @@ export function handleParagraphBlockMarks(state, slice) {
|
|
|
942
952
|
}
|
|
943
953
|
return node;
|
|
944
954
|
});
|
|
955
|
+
if (forbiddenMarkTypes.length === 0 && !shouldNormalizeFontSizeForTarget) {
|
|
956
|
+
// In a slice containing one or more paragraphs at the document level (not wrapped in
|
|
957
|
+
// another node), the first paragraph will only have its text content captured and pasted
|
|
958
|
+
// since openStart is 1. We decrement the open depth of the slice so it retains any block
|
|
959
|
+
// marks applied to it. We only care about the depth at the start of the selection so
|
|
960
|
+
// there's no need to change openEnd - the rest of the slice gets pasted correctly.
|
|
961
|
+
var openStart = Math.max(0, slice.openStart - 1);
|
|
962
|
+
return new Slice(slice.content, openStart, slice.openEnd);
|
|
963
|
+
}
|
|
964
|
+
if (forbiddenMarkTypes.length === 0 && shouldNormalizeFontSizeForTarget) {
|
|
965
|
+
var _openStart = Math.max(0, slice.openStart - 1);
|
|
966
|
+
return new Slice(normalizedContent.content, _openStart, slice.openEnd);
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
// If the paragraph or heading contains marks forbidden by the parent node
|
|
970
|
+
// (e.g. alignment/indentation), drop those marks from the slice. For lists under the small
|
|
971
|
+
// text experiment, also normalize fontSize to the destination list state.
|
|
972
|
+
return new Slice(normalizedContent.content, slice.openStart, slice.openEnd);
|
|
945
973
|
}
|
|
946
974
|
|
|
947
975
|
/**
|
|
@@ -983,7 +1011,7 @@ export function flattenNestedListInSlice(slice) {
|
|
|
983
1011
|
}
|
|
984
1012
|
export function handleRichText(slice, queueCardsFromChangedTr) {
|
|
985
1013
|
return function (state, dispatch) {
|
|
986
|
-
var _slice$content, _slice$content2, _firstChildOfSlice$ty, _lastChildOfSlice$typ, _panelParentOverCurre;
|
|
1014
|
+
var _slice$content, _slice$content2, _findParentNodeOfType3, _firstChildOfSlice$ty, _lastChildOfSlice$typ, _panelParentOverCurre;
|
|
987
1015
|
var _state$schema$nodes4 = state.schema.nodes,
|
|
988
1016
|
codeBlock = _state$schema$nodes4.codeBlock,
|
|
989
1017
|
heading = _state$schema$nodes4.heading,
|
|
@@ -993,6 +1021,7 @@ export function handleRichText(slice, queueCardsFromChangedTr) {
|
|
|
993
1021
|
schema = state.schema;
|
|
994
1022
|
var firstChildOfSlice = (_slice$content = slice.content) === null || _slice$content === void 0 ? void 0 : _slice$content.firstChild;
|
|
995
1023
|
var lastChildOfSlice = (_slice$content2 = slice.content) === null || _slice$content2 === void 0 ? void 0 : _slice$content2.lastChild;
|
|
1024
|
+
var destinationListFontSizeAttrs = expValEquals('platform_editor_small_font_size', 'isEnabled', true) ? getFirstParagraphBlockMarkAttrs((_findParentNodeOfType3 = findParentNodeOfType([schema.nodes.bulletList, schema.nodes.orderedList])(selection)) === null || _findParentNodeOfType3 === void 0 ? void 0 : _findParentNodeOfType3.node, schema.marks.fontSize) : false;
|
|
996
1025
|
|
|
997
1026
|
// In case user is pasting inline code,
|
|
998
1027
|
// any backtick ` immediately preceding it should be removed.
|
|
@@ -1077,6 +1106,12 @@ export function handleRichText(slice, queueCardsFromChangedTr) {
|
|
|
1077
1106
|
}
|
|
1078
1107
|
}
|
|
1079
1108
|
}
|
|
1109
|
+
if (expValEquals('platform_editor_small_font_size', 'isEnabled', true) && isSliceContentListNodes) {
|
|
1110
|
+
var containingList = findParentNodeOfTypeClosestToPos(tr.doc.resolve(tr.mapping.map(selection.from)), [schema.nodes.bulletList, schema.nodes.orderedList]);
|
|
1111
|
+
if (containingList) {
|
|
1112
|
+
reconcileBlockMarkForContainerAtPos(tr, containingList.pos, schema.marks.fontSize, destinationListFontSizeAttrs);
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1080
1115
|
tr.setStoredMarks([]);
|
|
1081
1116
|
if (tr.selection.empty && tr.selection.$from.parent.type === codeBlock) {
|
|
1082
1117
|
tr.setSelection(TextSelection.near(tr.selection.$from, 1));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-paste",
|
|
3
|
-
"version": "9.0
|
|
3
|
+
"version": "9.1.0",
|
|
4
4
|
"description": "Paste plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -36,27 +36,27 @@
|
|
|
36
36
|
"@atlaskit/editor-plugin-card": "^13.1.0",
|
|
37
37
|
"@atlaskit/editor-plugin-expand": "^9.1.0",
|
|
38
38
|
"@atlaskit/editor-plugin-feature-flags": "^7.0.0",
|
|
39
|
-
"@atlaskit/editor-plugin-list": "^10.
|
|
39
|
+
"@atlaskit/editor-plugin-list": "^10.2.0",
|
|
40
40
|
"@atlaskit/editor-plugin-media": "^10.1.0",
|
|
41
41
|
"@atlaskit/editor-plugin-mentions": "^10.0.0",
|
|
42
42
|
"@atlaskit/editor-prosemirror": "^7.3.0",
|
|
43
43
|
"@atlaskit/editor-tables": "^2.9.0",
|
|
44
44
|
"@atlaskit/flag": "^17.9.0",
|
|
45
45
|
"@atlaskit/icon": "^33.1.0",
|
|
46
|
-
"@atlaskit/insm": "^0.
|
|
46
|
+
"@atlaskit/insm": "^0.4.0",
|
|
47
47
|
"@atlaskit/media-client": "^36.0.0",
|
|
48
48
|
"@atlaskit/media-common": "^13.0.0",
|
|
49
49
|
"@atlaskit/platform-feature-flags": "^1.1.0",
|
|
50
50
|
"@atlaskit/prosemirror-history": "^0.2.0",
|
|
51
|
-
"@atlaskit/tmp-editor-statsig": "^
|
|
52
|
-
"@atlaskit/tokens": "^11.
|
|
51
|
+
"@atlaskit/tmp-editor-statsig": "^49.0.0",
|
|
52
|
+
"@atlaskit/tokens": "^11.4.0",
|
|
53
53
|
"@babel/runtime": "^7.0.0",
|
|
54
54
|
"lodash": "^4.17.21",
|
|
55
55
|
"react-intl-next": "npm:react-intl@^5.18.1",
|
|
56
56
|
"uuid": "^3.1.0"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
|
-
"@atlaskit/editor-common": "^112.
|
|
59
|
+
"@atlaskit/editor-common": "^112.13.0",
|
|
60
60
|
"react": "^18.2.0",
|
|
61
61
|
"react-dom": "^18.2.0"
|
|
62
62
|
},
|