@atlaskit/editor-plugin-paste 9.0.16 → 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,16 @@
|
|
|
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
|
+
|
|
3
14
|
## 9.0.16
|
|
4
15
|
|
|
5
16
|
### Patch Changes
|
|
@@ -34,6 +34,7 @@ var _v = _interopRequireDefault(require("uuid/v4"));
|
|
|
34
34
|
var _analytics = require("@atlaskit/editor-common/analytics");
|
|
35
35
|
var _card = require("@atlaskit/editor-common/card");
|
|
36
36
|
var _coreUtils = require("@atlaskit/editor-common/core-utils");
|
|
37
|
+
var _lists = require("@atlaskit/editor-common/lists");
|
|
37
38
|
var _mark = require("@atlaskit/editor-common/mark");
|
|
38
39
|
var _nesting = require("@atlaskit/editor-common/nesting");
|
|
39
40
|
var _selection = require("@atlaskit/editor-common/selection");
|
|
@@ -49,7 +50,7 @@ var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equa
|
|
|
49
50
|
var _commands = require("../../editor-commands/commands");
|
|
50
51
|
var _pluginFactory = require("../plugin-factory");
|
|
51
52
|
var _edgeCases = require("./edge-cases");
|
|
52
|
-
var
|
|
53
|
+
var _lists2 = require("./edge-cases/lists");
|
|
53
54
|
var _index = require("./index");
|
|
54
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; } } }; }
|
|
55
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; } }
|
|
@@ -173,7 +174,7 @@ function handlePasteIntoTaskOrDecisionOrPanel(slice, queueCardsFromChangedTr) {
|
|
|
173
174
|
var isFirstChildTaskNode = transformedSlice.content.firstChild.type === taskList || transformedSlice.content.firstChild.type === taskItem;
|
|
174
175
|
var tr = (0, _prosemirrorHistory.closeHistory)(state.tr);
|
|
175
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()) {
|
|
176
|
-
return Boolean((0,
|
|
177
|
+
return Boolean((0, _lists2.insertSliceInsideOfPanelNodeSelected)(panelNode)({
|
|
177
178
|
tr: tr,
|
|
178
179
|
slice: slice
|
|
179
180
|
}));
|
|
@@ -912,21 +913,32 @@ function getTopLevelMarkTypesInSlice(slice) {
|
|
|
912
913
|
return markTypes;
|
|
913
914
|
}
|
|
914
915
|
function handleParagraphBlockMarks(state, slice) {
|
|
916
|
+
var _findParentNodeOfType2;
|
|
915
917
|
if (slice.content.size === 0) {
|
|
916
918
|
return slice;
|
|
917
919
|
}
|
|
918
920
|
var schema = state.schema,
|
|
921
|
+
selection = state.selection,
|
|
919
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;
|
|
920
928
|
|
|
921
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.
|
|
922
931
|
// Note: this doesn't check for marks applied to lower level nodes such as text
|
|
923
|
-
if (!sliceHasTopLevelMarks(slice)) {
|
|
932
|
+
if (!sliceHasTopLevelMarks(slice) && !destinationBlockMarkAttrs) {
|
|
924
933
|
return slice;
|
|
925
934
|
}
|
|
935
|
+
var shouldNormalizeFontSizeForTarget = (0, _expValEquals.expValEquals)('platform_editor_small_font_size', 'isEnabled', true) && !!schema.marks.fontSize && (!!destinationListNode || isInNormalTaskContext || !!isInSmallTaskContext);
|
|
926
936
|
|
|
927
|
-
// 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.
|
|
928
940
|
var destinationHasContent = $from.parent.textContent.length > 0;
|
|
929
|
-
if (slice.content.childCount === 1 && destinationHasContent) {
|
|
941
|
+
if (slice.content.childCount === 1 && destinationHasContent && !shouldNormalizeFontSizeForTarget) {
|
|
930
942
|
return slice;
|
|
931
943
|
}
|
|
932
944
|
|
|
@@ -949,23 +961,16 @@ function handleParagraphBlockMarks(state, slice) {
|
|
|
949
961
|
} finally {
|
|
950
962
|
_iterator.f();
|
|
951
963
|
}
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
// another node), the first paragraph will only have its text content captured and pasted
|
|
955
|
-
// since openStart is 1. We decrement the open depth of the slice so it retains any block
|
|
956
|
-
// marks applied to it. We only care about the depth at the start of the selection so
|
|
957
|
-
// there's no need to change openEnd - the rest of the slice gets pasted correctly.
|
|
958
|
-
var openStart = Math.max(0, slice.openStart - 1);
|
|
959
|
-
return new _model.Slice(slice.content, openStart, slice.openEnd);
|
|
960
|
-
}
|
|
961
|
-
|
|
962
|
-
// If the paragraph or heading contains marks forbidden by the parent node
|
|
963
|
-
// (e.g. alignment/indentation), drop those marks from the slice
|
|
964
|
-
return (0, _utils.mapSlice)(slice, function (node) {
|
|
964
|
+
var fontSizeMarkType = shouldNormalizeFontSizeForTarget ? schema.marks.fontSize : undefined;
|
|
965
|
+
var normalizedContent = (0, _utils.mapSlice)(slice, function (node) {
|
|
965
966
|
if (node.type === schema.nodes.paragraph) {
|
|
966
|
-
|
|
967
|
+
var paragraphMarks = node.marks.filter(function (mark) {
|
|
967
968
|
return !forbiddenMarkTypes.includes(mark.type);
|
|
968
|
-
})
|
|
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);
|
|
969
974
|
} else if (node.type === schema.nodes.heading) {
|
|
970
975
|
// Preserve heading attributes to keep formatting
|
|
971
976
|
return schema.nodes.heading.createChecked(node.attrs, node.content, node.marks.filter(function (mark) {
|
|
@@ -974,6 +979,24 @@ function handleParagraphBlockMarks(state, slice) {
|
|
|
974
979
|
}
|
|
975
980
|
return node;
|
|
976
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);
|
|
977
1000
|
}
|
|
978
1001
|
|
|
979
1002
|
/**
|
|
@@ -1015,7 +1038,7 @@ function flattenNestedListInSlice(slice) {
|
|
|
1015
1038
|
}
|
|
1016
1039
|
function handleRichText(slice, queueCardsFromChangedTr) {
|
|
1017
1040
|
return function (state, dispatch) {
|
|
1018
|
-
var _slice$content, _slice$content2, _firstChildOfSlice$ty, _lastChildOfSlice$typ, _panelParentOverCurre;
|
|
1041
|
+
var _slice$content, _slice$content2, _findParentNodeOfType3, _firstChildOfSlice$ty, _lastChildOfSlice$typ, _panelParentOverCurre;
|
|
1019
1042
|
var _state$schema$nodes4 = state.schema.nodes,
|
|
1020
1043
|
codeBlock = _state$schema$nodes4.codeBlock,
|
|
1021
1044
|
heading = _state$schema$nodes4.heading,
|
|
@@ -1025,6 +1048,7 @@ function handleRichText(slice, queueCardsFromChangedTr) {
|
|
|
1025
1048
|
schema = state.schema;
|
|
1026
1049
|
var firstChildOfSlice = (_slice$content = slice.content) === null || _slice$content === void 0 ? void 0 : _slice$content.firstChild;
|
|
1027
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;
|
|
1028
1052
|
|
|
1029
1053
|
// In case user is pasting inline code,
|
|
1030
1054
|
// any backtick ` immediately preceding it should be removed.
|
|
@@ -1109,6 +1133,12 @@ function handleRichText(slice, queueCardsFromChangedTr) {
|
|
|
1109
1133
|
}
|
|
1110
1134
|
}
|
|
1111
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
|
+
}
|
|
1112
1142
|
tr.setStoredMarks([]);
|
|
1113
1143
|
if (tr.selection.empty && tr.selection.$from.parent.type === codeBlock) {
|
|
1114
1144
|
tr.setSelection(_state.TextSelection.near(tr.selection.$from, 1));
|
|
@@ -3,6 +3,7 @@ import uuid from 'uuid/v4';
|
|
|
3
3
|
import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
4
4
|
import { addLinkMetadata } from '@atlaskit/editor-common/card';
|
|
5
5
|
import { insideTable } from '@atlaskit/editor-common/core-utils';
|
|
6
|
+
import { getBlockMarkAttrs, getFirstParagraphBlockMarkAttrs, reconcileBlockMarkForContainerAtPos } from '@atlaskit/editor-common/lists';
|
|
6
7
|
import { anyMarkActive } from '@atlaskit/editor-common/mark';
|
|
7
8
|
import { getParentOfTypeCount, getPositionAfterTopParentNodeOfType } from '@atlaskit/editor-common/nesting';
|
|
8
9
|
import { GapCursorSelection, Side } from '@atlaskit/editor-common/selection';
|
|
@@ -898,25 +899,36 @@ function getTopLevelMarkTypesInSlice(slice) {
|
|
|
898
899
|
return markTypes;
|
|
899
900
|
}
|
|
900
901
|
export function handleParagraphBlockMarks(state, slice) {
|
|
902
|
+
var _findParentNodeOfType2;
|
|
901
903
|
if (slice.content.size === 0) {
|
|
902
904
|
return slice;
|
|
903
905
|
}
|
|
904
906
|
const {
|
|
905
907
|
schema,
|
|
908
|
+
selection,
|
|
906
909
|
selection: {
|
|
907
910
|
$from
|
|
908
911
|
}
|
|
909
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;
|
|
910
918
|
|
|
911
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.
|
|
912
921
|
// Note: this doesn't check for marks applied to lower level nodes such as text
|
|
913
|
-
if (!sliceHasTopLevelMarks(slice)) {
|
|
922
|
+
if (!sliceHasTopLevelMarks(slice) && !destinationBlockMarkAttrs) {
|
|
914
923
|
return slice;
|
|
915
924
|
}
|
|
925
|
+
const shouldNormalizeFontSizeForTarget = expValEquals('platform_editor_small_font_size', 'isEnabled', true) && !!schema.marks.fontSize && (!!destinationListNode || isInNormalTaskContext || !!isInSmallTaskContext);
|
|
916
926
|
|
|
917
|
-
// 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.
|
|
918
930
|
const destinationHasContent = $from.parent.textContent.length > 0;
|
|
919
|
-
if (slice.content.childCount === 1 && destinationHasContent) {
|
|
931
|
+
if (slice.content.childCount === 1 && destinationHasContent && !shouldNormalizeFontSizeForTarget) {
|
|
920
932
|
return slice;
|
|
921
933
|
}
|
|
922
934
|
|
|
@@ -930,7 +942,19 @@ export function handleParagraphBlockMarks(state, slice) {
|
|
|
930
942
|
forbiddenMarkTypes.push(markType);
|
|
931
943
|
}
|
|
932
944
|
}
|
|
933
|
-
|
|
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) {
|
|
934
958
|
// In a slice containing one or more paragraphs at the document level (not wrapped in
|
|
935
959
|
// another node), the first paragraph will only have its text content captured and pasted
|
|
936
960
|
// since openStart is 1. We decrement the open depth of the slice so it retains any block
|
|
@@ -939,18 +963,15 @@ export function handleParagraphBlockMarks(state, slice) {
|
|
|
939
963
|
const openStart = Math.max(0, slice.openStart - 1);
|
|
940
964
|
return new Slice(slice.content, openStart, slice.openEnd);
|
|
941
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
|
+
}
|
|
942
970
|
|
|
943
971
|
// If the paragraph or heading contains marks forbidden by the parent node
|
|
944
|
-
// (e.g. alignment/indentation), drop those marks from the slice
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
return schema.nodes.paragraph.createChecked(undefined, node.content, node.marks.filter(mark => !forbiddenMarkTypes.includes(mark.type)));
|
|
948
|
-
} else if (node.type === schema.nodes.heading) {
|
|
949
|
-
// Preserve heading attributes to keep formatting
|
|
950
|
-
return schema.nodes.heading.createChecked(node.attrs, node.content, node.marks.filter(mark => !forbiddenMarkTypes.includes(mark.type)));
|
|
951
|
-
}
|
|
952
|
-
return node;
|
|
953
|
-
});
|
|
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);
|
|
954
975
|
}
|
|
955
976
|
|
|
956
977
|
/**
|
|
@@ -992,7 +1013,7 @@ export function flattenNestedListInSlice(slice) {
|
|
|
992
1013
|
}
|
|
993
1014
|
export function handleRichText(slice, queueCardsFromChangedTr) {
|
|
994
1015
|
return (state, dispatch) => {
|
|
995
|
-
var _slice$content, _slice$content2, _firstChildOfSlice$ty, _lastChildOfSlice$typ, _panelParentOverCurre;
|
|
1016
|
+
var _slice$content, _slice$content2, _findParentNodeOfType3, _firstChildOfSlice$ty, _lastChildOfSlice$typ, _panelParentOverCurre;
|
|
996
1017
|
const {
|
|
997
1018
|
codeBlock,
|
|
998
1019
|
heading,
|
|
@@ -1005,6 +1026,7 @@ export function handleRichText(slice, queueCardsFromChangedTr) {
|
|
|
1005
1026
|
} = state;
|
|
1006
1027
|
const firstChildOfSlice = (_slice$content = slice.content) === null || _slice$content === void 0 ? void 0 : _slice$content.firstChild;
|
|
1007
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;
|
|
1008
1030
|
|
|
1009
1031
|
// In case user is pasting inline code,
|
|
1010
1032
|
// any backtick ` immediately preceding it should be removed.
|
|
@@ -1089,6 +1111,12 @@ export function handleRichText(slice, queueCardsFromChangedTr) {
|
|
|
1089
1111
|
}
|
|
1090
1112
|
}
|
|
1091
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
|
+
}
|
|
1092
1120
|
tr.setStoredMarks([]);
|
|
1093
1121
|
if (tr.selection.empty && tr.selection.$from.parent.type === codeBlock) {
|
|
1094
1122
|
tr.setSelection(TextSelection.near(tr.selection.$from, 1));
|
|
@@ -11,6 +11,7 @@ import uuid from 'uuid/v4';
|
|
|
11
11
|
import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
12
12
|
import { addLinkMetadata } from '@atlaskit/editor-common/card';
|
|
13
13
|
import { insideTable } from '@atlaskit/editor-common/core-utils';
|
|
14
|
+
import { getBlockMarkAttrs, getFirstParagraphBlockMarkAttrs, reconcileBlockMarkForContainerAtPos } from '@atlaskit/editor-common/lists';
|
|
14
15
|
import { anyMarkActive } from '@atlaskit/editor-common/mark';
|
|
15
16
|
import { getParentOfTypeCount, getPositionAfterTopParentNodeOfType } from '@atlaskit/editor-common/nesting';
|
|
16
17
|
import { GapCursorSelection, Side } from '@atlaskit/editor-common/selection';
|
|
@@ -885,21 +886,32 @@ function getTopLevelMarkTypesInSlice(slice) {
|
|
|
885
886
|
return markTypes;
|
|
886
887
|
}
|
|
887
888
|
export function handleParagraphBlockMarks(state, slice) {
|
|
889
|
+
var _findParentNodeOfType2;
|
|
888
890
|
if (slice.content.size === 0) {
|
|
889
891
|
return slice;
|
|
890
892
|
}
|
|
891
893
|
var schema = state.schema,
|
|
894
|
+
selection = state.selection,
|
|
892
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;
|
|
893
901
|
|
|
894
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.
|
|
895
904
|
// Note: this doesn't check for marks applied to lower level nodes such as text
|
|
896
|
-
if (!sliceHasTopLevelMarks(slice)) {
|
|
905
|
+
if (!sliceHasTopLevelMarks(slice) && !destinationBlockMarkAttrs) {
|
|
897
906
|
return slice;
|
|
898
907
|
}
|
|
908
|
+
var shouldNormalizeFontSizeForTarget = expValEquals('platform_editor_small_font_size', 'isEnabled', true) && !!schema.marks.fontSize && (!!destinationListNode || isInNormalTaskContext || !!isInSmallTaskContext);
|
|
899
909
|
|
|
900
|
-
// 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.
|
|
901
913
|
var destinationHasContent = $from.parent.textContent.length > 0;
|
|
902
|
-
if (slice.content.childCount === 1 && destinationHasContent) {
|
|
914
|
+
if (slice.content.childCount === 1 && destinationHasContent && !shouldNormalizeFontSizeForTarget) {
|
|
903
915
|
return slice;
|
|
904
916
|
}
|
|
905
917
|
|
|
@@ -922,23 +934,16 @@ export function handleParagraphBlockMarks(state, slice) {
|
|
|
922
934
|
} finally {
|
|
923
935
|
_iterator.f();
|
|
924
936
|
}
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
// another node), the first paragraph will only have its text content captured and pasted
|
|
928
|
-
// since openStart is 1. We decrement the open depth of the slice so it retains any block
|
|
929
|
-
// marks applied to it. We only care about the depth at the start of the selection so
|
|
930
|
-
// there's no need to change openEnd - the rest of the slice gets pasted correctly.
|
|
931
|
-
var openStart = Math.max(0, slice.openStart - 1);
|
|
932
|
-
return new Slice(slice.content, openStart, slice.openEnd);
|
|
933
|
-
}
|
|
934
|
-
|
|
935
|
-
// If the paragraph or heading contains marks forbidden by the parent node
|
|
936
|
-
// (e.g. alignment/indentation), drop those marks from the slice
|
|
937
|
-
return mapSlice(slice, function (node) {
|
|
937
|
+
var fontSizeMarkType = shouldNormalizeFontSizeForTarget ? schema.marks.fontSize : undefined;
|
|
938
|
+
var normalizedContent = mapSlice(slice, function (node) {
|
|
938
939
|
if (node.type === schema.nodes.paragraph) {
|
|
939
|
-
|
|
940
|
+
var paragraphMarks = node.marks.filter(function (mark) {
|
|
940
941
|
return !forbiddenMarkTypes.includes(mark.type);
|
|
941
|
-
})
|
|
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);
|
|
942
947
|
} else if (node.type === schema.nodes.heading) {
|
|
943
948
|
// Preserve heading attributes to keep formatting
|
|
944
949
|
return schema.nodes.heading.createChecked(node.attrs, node.content, node.marks.filter(function (mark) {
|
|
@@ -947,6 +952,24 @@ export function handleParagraphBlockMarks(state, slice) {
|
|
|
947
952
|
}
|
|
948
953
|
return node;
|
|
949
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);
|
|
950
973
|
}
|
|
951
974
|
|
|
952
975
|
/**
|
|
@@ -988,7 +1011,7 @@ export function flattenNestedListInSlice(slice) {
|
|
|
988
1011
|
}
|
|
989
1012
|
export function handleRichText(slice, queueCardsFromChangedTr) {
|
|
990
1013
|
return function (state, dispatch) {
|
|
991
|
-
var _slice$content, _slice$content2, _firstChildOfSlice$ty, _lastChildOfSlice$typ, _panelParentOverCurre;
|
|
1014
|
+
var _slice$content, _slice$content2, _findParentNodeOfType3, _firstChildOfSlice$ty, _lastChildOfSlice$typ, _panelParentOverCurre;
|
|
992
1015
|
var _state$schema$nodes4 = state.schema.nodes,
|
|
993
1016
|
codeBlock = _state$schema$nodes4.codeBlock,
|
|
994
1017
|
heading = _state$schema$nodes4.heading,
|
|
@@ -998,6 +1021,7 @@ export function handleRichText(slice, queueCardsFromChangedTr) {
|
|
|
998
1021
|
schema = state.schema;
|
|
999
1022
|
var firstChildOfSlice = (_slice$content = slice.content) === null || _slice$content === void 0 ? void 0 : _slice$content.firstChild;
|
|
1000
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;
|
|
1001
1025
|
|
|
1002
1026
|
// In case user is pasting inline code,
|
|
1003
1027
|
// any backtick ` immediately preceding it should be removed.
|
|
@@ -1082,6 +1106,12 @@ export function handleRichText(slice, queueCardsFromChangedTr) {
|
|
|
1082
1106
|
}
|
|
1083
1107
|
}
|
|
1084
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
|
+
}
|
|
1085
1115
|
tr.setStoredMarks([]);
|
|
1086
1116
|
if (tr.selection.empty && tr.selection.$from.parent.type === codeBlock) {
|
|
1087
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,7 +36,7 @@
|
|
|
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",
|
|
@@ -48,15 +48,15 @@
|
|
|
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
|
},
|