@atlaskit/editor-common 112.9.0 → 112.10.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,31 @@
1
1
  # @atlaskit/editor-common
2
2
 
3
+ ## 112.10.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`6da6979e0583c`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/6da6979e0583c) -
8
+ fix a11y issue for InlineImageWrapper for media inline
9
+
10
+ ### Patch Changes
11
+
12
+ - [`673732f902814`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/673732f902814) -
13
+ Add error handling with plugin context to EditorPresetBuilder to improve debugging of plugin
14
+ initialization failures. When a plugin fails to initialize, the name of the plugin is added to the
15
+ error message before it's thrown.
16
+ - Updated dependencies
17
+
18
+ ## 112.9.1
19
+
20
+ ### Patch Changes
21
+
22
+ - [`9b33b26d69865`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/9b33b26d69865) -
23
+ Narrow list replacement range during indent/outdent for collab-friendly cursor preservation
24
+ - [`3f6f3c13a6033`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/3f6f3c13a6033) -
25
+ Fix fontSize mark preservation during list type conversions (bullet/ordered ↔ task list) and
26
+ blockTaskItem handling when toggling task list off
27
+ - Updated dependencies
28
+
3
29
  ## 112.9.0
4
30
 
5
31
  ### Minor Changes
@@ -99,6 +99,12 @@ Object.defineProperty(exports, "moveTargetIntoList", {
99
99
  return _replaceContent.moveTargetIntoList;
100
100
  }
101
101
  });
102
+ Object.defineProperty(exports, "narrowReplacementRange", {
103
+ enumerable: true,
104
+ get: function get() {
105
+ return _narrowReplacementRange.narrowReplacementRange;
106
+ }
107
+ });
102
108
  Object.defineProperty(exports, "normalizeListItemsSelection", {
103
109
  enumerable: true,
104
110
  get: function get() {
@@ -124,6 +130,7 @@ var _analytics = require("./analytics");
124
130
  var _indentation = require("./indentation");
125
131
  var _restoreSelection = require("./restore-selection");
126
132
  var _buildReplacementFragment = require("./build-replacement-fragment");
133
+ var _narrowReplacementRange = require("./narrow-replacement-range");
127
134
  var _flattenList = require("./flatten-list");
128
135
  var _utils = require("../utils");
129
136
  var _messages = require("./messages");
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.narrowReplacementRange = narrowReplacementRange;
7
+ var _model = require("@atlaskit/editor-prosemirror/model");
8
+ /**
9
+ * Narrows a full-list replacement to the minimal changed range.
10
+ *
11
+ * Compares the old root list node with the new replacement fragment
12
+ * from both ends to find the first and last positions where they differ,
13
+ * then returns only the changed subrange.
14
+ *
15
+ * This reduces the scope of `tr.replaceWith()` so that remote cursors
16
+ * on unchanged items are preserved during collaborative editing.
17
+ */
18
+ function narrowReplacementRange(doc, rootListStart, rootListEnd, fragment, contentStartOffsets) {
19
+ var oldNode = doc.nodeAt(rootListStart);
20
+ var newNode = fragment.childCount === 1 ? fragment.firstChild : null;
21
+ if (!oldNode || !newNode || newNode.type !== oldNode.type) {
22
+ return {
23
+ start: rootListStart,
24
+ end: rootListEnd,
25
+ fragment: fragment,
26
+ adjustedContentStartOffsets: contentStartOffsets
27
+ };
28
+ }
29
+ var minChildCount = Math.min(oldNode.childCount, newNode.childCount);
30
+ var commonPrefixChildren = 0;
31
+ var prefixSize = 0;
32
+ for (var i = 0; i < minChildCount; i++) {
33
+ var oldChild = oldNode.child(i);
34
+ var newChild = newNode.child(i);
35
+ if (oldChild.eq(newChild)) {
36
+ commonPrefixChildren++;
37
+ prefixSize += oldChild.nodeSize;
38
+ } else {
39
+ break;
40
+ }
41
+ }
42
+ var commonSuffixChildren = 0;
43
+ var suffixSize = 0;
44
+ for (var _i = 0; _i < minChildCount - commonPrefixChildren; _i++) {
45
+ var _oldChild = oldNode.child(oldNode.childCount - 1 - _i);
46
+ var _newChild = newNode.child(newNode.childCount - 1 - _i);
47
+ if (_oldChild.eq(_newChild)) {
48
+ commonSuffixChildren++;
49
+ suffixSize += _oldChild.nodeSize;
50
+ } else {
51
+ break;
52
+ }
53
+ }
54
+ var totalCommon = commonPrefixChildren + commonSuffixChildren;
55
+ if (totalCommon >= oldNode.childCount && totalCommon >= newNode.childCount) {
56
+ return {
57
+ start: rootListStart,
58
+ end: rootListStart,
59
+ fragment: _model.Fragment.empty,
60
+ adjustedContentStartOffsets: contentStartOffsets
61
+ };
62
+ }
63
+ var narrowedStart = rootListStart + 1 + prefixSize;
64
+ var narrowedEnd = rootListEnd - 1 - suffixSize;
65
+ var changedChildStart = commonPrefixChildren;
66
+ var changedChildEnd = newNode.childCount - commonSuffixChildren;
67
+ var changedNodes = [];
68
+ for (var _i2 = changedChildStart; _i2 < changedChildEnd; _i2++) {
69
+ changedNodes.push(newNode.child(_i2));
70
+ }
71
+ var narrowedFragment = _model.Fragment.from(changedNodes);
72
+ var prefixOffset = 1 + prefixSize;
73
+ var adjustedContentStartOffsets = contentStartOffsets.map(function (offset) {
74
+ return offset - prefixOffset;
75
+ });
76
+ return {
77
+ start: narrowedStart,
78
+ end: narrowedEnd,
79
+ fragment: narrowedFragment,
80
+ adjustedContentStartOffsets: adjustedContentStartOffsets
81
+ };
82
+ }
@@ -9,6 +9,7 @@ var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")
9
9
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
10
10
  var _react = require("@emotion/react");
11
11
  var _editorPalette = require("@atlaskit/editor-palette");
12
+ var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
12
13
  var _styles = require("./styles");
13
14
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
14
15
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } /**
@@ -35,8 +36,17 @@ var InlineImageWrapper = exports.InlineImageWrapper = function InlineImageWrappe
35
36
  onClick = _ref.onClick;
36
37
  var borderStyleVars = borderSize && borderColor ? (0, _defineProperty2.default)((0, _defineProperty2.default)({}, _styles.INLINE_IMAGE_BORDER_SIZE_CSS_VAR_KEY, borderSize), _styles.INLINE_IMAGE_BORDER_COLOR_CSS_VAR_KEY, (0, _editorPalette.hexToEditorBorderPaletteColor)(borderColor) || borderColor) : {};
37
38
  var aspectStyleVars = aspectRatio ? (0, _defineProperty2.default)({}, _styles.INLINE_IMAGE_ASPECT_RATIO_CSS_VAR_KEY, aspectRatio) : {};
39
+ var onKeyDown = function onKeyDown(e) {
40
+ if ((0, _expValEquals.expValEquals)('editor_a11y__enghealth-46814_fy26', 'isEnabled', true)) {
41
+ if (e.key === 'Enter' || e.key === ' ') {
42
+ e.preventDefault();
43
+ onClick(e);
44
+ }
45
+ }
46
+ return undefined;
47
+ };
38
48
  return (
39
- // eslint-disable-next-line @atlaskit/design-system/prefer-primitives, @atlassian/a11y/click-events-have-key-events, @atlassian/a11y/interactive-element-not-keyboard-focusable, @atlassian/a11y/no-static-element-interactions
49
+ // eslint-disable-next-line @atlaskit/design-system/prefer-primitives
40
50
  (0, _react.jsx)("span", (0, _extends2.default)({
41
51
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
42
52
  style: _objectSpread(_objectSpread({}, borderStyleVars), aspectStyleVars)
@@ -51,7 +61,10 @@ var InlineImageWrapper = exports.InlineImageWrapper = function InlineImageWrappe
51
61
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766
52
62
  isSelected && _styles.selectedStyle],
53
63
  "data-testid": "inline-image-wrapper",
54
- onClick: onClick
64
+ role: (0, _expValEquals.expValEquals)('editor_a11y__enghealth-46814_fy26', 'isEnabled', true) ? 'button' : undefined,
65
+ tabIndex: (0, _expValEquals.expValEquals)('editor_a11y__enghealth-46814_fy26', 'isEnabled', true) ? 0 : undefined,
66
+ onClick: onClick,
67
+ onKeyDown: onKeyDown
55
68
  // Ignored via go/ees005
56
69
  // eslint-disable-next-line react/jsx-props-no-spreading
57
70
  }, htmlAttrs), (0, _react.jsx)("span", {
@@ -19,7 +19,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
19
19
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
20
20
  var SENTRY_DSN = 'https://0b10c8e02fb44d8796c047b102c9bee8@o55978.ingest.sentry.io/4505129224110080';
21
21
  var packageName = 'editor-common'; // Sentry doesn't accept '/' in its releases https://docs.sentry.io/platforms/javascript/configuration/releases/
22
- var packageVersion = "112.8.4";
22
+ var packageVersion = "112.9.1";
23
23
  var sanitiseSentryEvents = function sanitiseSentryEvents(data, _hint) {
24
24
  // Remove URL as it has UGC
25
25
  // Ignored via go/ees007
@@ -11,6 +11,7 @@ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers
11
11
  var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
12
12
  var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
13
13
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
14
+ var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
14
15
  var _eventDispatcher = require("../event-dispatcher");
15
16
  /*********************
16
17
  * *
@@ -635,12 +636,28 @@ var EditorPresetBuilder = exports.EditorPresetBuilder = /*#__PURE__*/function ()
635
636
  if (typeof fn !== 'function') {
636
637
  return null;
637
638
  }
638
- var plugin = pluginInjectionAPI ? fn({
639
- config: config,
640
- api: pluginInjectionAPI.api()
641
- }) : fn({
642
- config: config
643
- });
639
+ var plugin;
640
+ if ((0, _expValEquals.expValEquals)('platform_editor_improve_preset_builder_logging', 'isEnabled', true)) {
641
+ try {
642
+ plugin = pluginInjectionAPI ? fn({
643
+ config: config,
644
+ api: pluginInjectionAPI.api()
645
+ }) : fn({
646
+ config: config
647
+ });
648
+ } catch (error) {
649
+ var pluginName = fn.name || 'unknown';
650
+ var enhancedError = error instanceof Error ? new Error("Failed to initialize plugin '".concat(pluginName, "': ").concat(error.message)) : new Error("Failed to initialize plugin '".concat(pluginName, "'"));
651
+ throw enhancedError;
652
+ }
653
+ } else {
654
+ plugin = pluginInjectionAPI ? fn({
655
+ config: config,
656
+ api: pluginInjectionAPI.api()
657
+ }) : fn({
658
+ config: config
659
+ });
660
+ }
644
661
  if (plugin && excludePlugins !== null && excludePlugins !== void 0 && excludePlugins.has(plugin.name)) {
645
662
  return null;
646
663
  }
@@ -9,7 +9,11 @@ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers
9
9
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
10
10
  var _model = require("@atlaskit/editor-prosemirror/model");
11
11
  var _utils = require("@atlaskit/editor-prosemirror/utils");
12
+ var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
12
13
  var _listUtils = require("./list-utils");
14
+ 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; } } }; }
15
+ 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; } }
16
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
13
17
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
14
18
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
15
19
  var getContentSupportChecker = function getContentSupportChecker(targetNodeType) {
@@ -21,6 +25,16 @@ var getContentSupportChecker = function getContentSupportChecker(targetNodeType)
21
25
  }
22
26
  };
23
27
  };
28
+ var createBlockTaskItemWithMarks = function createBlockTaskItemWithMarks(content, marks, schema) {
29
+ var _schema$nodes = schema.nodes,
30
+ blockTaskItem = _schema$nodes.blockTaskItem,
31
+ paragraph = _schema$nodes.paragraph;
32
+ var allowedMarks = marks.filter(function (mark) {
33
+ return blockTaskItem.allowsMarkType(mark.type);
34
+ });
35
+ var newParagraph = paragraph.create(null, content.length > 0 ? content : null, allowedMarks);
36
+ return blockTaskItem.create(null, newParagraph);
37
+ };
24
38
  var _transformListRecursively = exports.transformListRecursively = function transformListRecursively(props, onhandleUnsupportedContent) {
25
39
  var transformedItems = [];
26
40
  var listNode = props.listNode,
@@ -31,17 +45,36 @@ var _transformListRecursively = exports.transformListRecursively = function tran
31
45
  supportedListTypes = props.supportedListTypes,
32
46
  schema = props.schema,
33
47
  targetNodeType = props.targetNodeType;
34
- var _schema$nodes = schema.nodes,
35
- taskList = _schema$nodes.taskList,
36
- listItem = _schema$nodes.listItem,
37
- taskItem = _schema$nodes.taskItem,
38
- paragraph = _schema$nodes.paragraph;
48
+ var _schema$nodes2 = schema.nodes,
49
+ taskList = _schema$nodes2.taskList,
50
+ listItem = _schema$nodes2.listItem,
51
+ taskItem = _schema$nodes2.taskItem,
52
+ paragraph = _schema$nodes2.paragraph,
53
+ blockTaskItem = _schema$nodes2.blockTaskItem;
54
+
55
+ // gating behind platform_editor_small_font_size to support task lists with font size applied,
56
+ // but keep this solution general
57
+ var isBlockTaskEnabled = !!blockTaskItem && (0, _expValEquals.expValEquals)('platform_editor_small_font_size', 'isEnabled', true);
58
+
59
+ /**
60
+ * Extracts paragraph children from a blockTaskItem, preserving their marks.
61
+ */
62
+ var extractParagraphsFromBlockTaskItem = function extractParagraphsFromBlockTaskItem(node) {
63
+ var paragraphs = [];
64
+ node.forEach(function (child) {
65
+ if (child.type === paragraph) {
66
+ paragraphs.push(child);
67
+ }
68
+ });
69
+ return paragraphs;
70
+ };
39
71
  listNode.forEach(function (child) {
40
72
  if (isSourceBulletOrOrdered && isTargetTask) {
41
73
  // Convert bullet/ordered => task
42
74
  if (child.type === listItem) {
43
75
  var inlineContent = [];
44
76
  var nestedTaskLists = [];
77
+ var blockMarks = [];
45
78
  child.forEach(function (grandChild) {
46
79
  if (supportedListTypes.has(grandChild.type) && grandChild.type !== taskList) {
47
80
  nestedTaskLists.push(_transformListRecursively(_objectSpread(_objectSpread({}, props), {}, {
@@ -50,18 +83,39 @@ var _transformListRecursively = exports.transformListRecursively = function tran
50
83
  } else if (!getContentSupportChecker(taskItem)(grandChild) && !grandChild.isTextblock) {
51
84
  onhandleUnsupportedContent === null || onhandleUnsupportedContent === void 0 || onhandleUnsupportedContent(grandChild);
52
85
  } else {
86
+ if (isBlockTaskEnabled && grandChild.type === paragraph && grandChild.marks.length > 0) {
87
+ blockMarks = grandChild.marks;
88
+ }
53
89
  inlineContent.push.apply(inlineContent, (0, _toConsumableArray2.default)((0, _listUtils.convertBlockToInlineContent)(grandChild, schema)));
54
90
  }
55
91
  });
56
- transformedItems.push(taskItem.create(null, inlineContent.length > 0 ? inlineContent : null));
92
+ if (isBlockTaskEnabled && blockMarks.length > 0) {
93
+ transformedItems.push(createBlockTaskItemWithMarks(inlineContent, blockMarks, schema));
94
+ } else {
95
+ transformedItems.push(taskItem.create(null, inlineContent.length > 0 ? inlineContent : null));
96
+ }
57
97
  transformedItems.push.apply(transformedItems, nestedTaskLists);
58
98
  }
59
99
  } else if (isSourceTask && isTargetBulletOrOrdered) {
60
100
  // Convert task => bullet/ordered
61
101
  if (child.type === taskItem) {
62
102
  var _inlineContent = (0, _toConsumableArray2.default)(child.content.content);
63
- var paragraphNode = paragraph.create(null, _inlineContent.length > 0 ? _inlineContent : null);
103
+
104
+ // Transfer taskItem's block marks to the paragraph.
105
+ // Use listItem.allowsMarkType since the paragraph will be inside a listItem
106
+ // (which uses ParagraphWithFontSizeStage0 that allows fontSize).
107
+ var paragraphMarks = isBlockTaskEnabled && child.marks.length > 0 ? child.marks.filter(function (mark) {
108
+ return listItem.allowsMarkType(mark.type);
109
+ }) : undefined;
110
+ var paragraphNode = paragraph.create(null, _inlineContent.length > 0 ? _inlineContent : null, paragraphMarks);
64
111
  transformedItems.push(listItem.create(null, [paragraphNode]));
112
+ } else if (isBlockTaskEnabled && child.type === blockTaskItem) {
113
+ // blockTaskItem wraps content in paragraphs — extract them directly,
114
+ // preserving their fontSize marks
115
+ var paragraphs = extractParagraphsFromBlockTaskItem(child);
116
+ if (paragraphs.length > 0) {
117
+ transformedItems.push(listItem.create(null, paragraphs));
118
+ }
65
119
  } else if (child.type === taskList) {
66
120
  var transformedNestedList = _transformListRecursively(_objectSpread(_objectSpread({}, props), {}, {
67
121
  listNode: child
@@ -195,21 +249,27 @@ var transformBetweenListTypes = exports.transformBetweenListTypes = function tra
195
249
  */
196
250
  var transformToTaskList = exports.transformToTaskList = function transformToTaskList(tr, range, targetNodeType, targetAttrs, nodes) {
197
251
  try {
198
- var taskItem = nodes.taskItem;
252
+ var taskItem = nodes.taskItem,
253
+ paragraph = nodes.paragraph,
254
+ blockTaskItem = nodes.blockTaskItem;
255
+ // gating behind platform_editor_small_font_size to support task lists with font size applied,
256
+ // but keep this solution general
257
+ var isBlockTaskItemEnabled = !!blockTaskItem && (0, _expValEquals.expValEquals)('platform_editor_small_font_size', 'isEnabled', true);
199
258
  var listItems = [];
200
259
 
201
260
  // Process each block in the range
202
261
  tr.doc.nodesBetween(range.start, range.end, function (node) {
203
262
  if (node.isBlock) {
204
- // For block nodes like paragraphs, directly use their inline content
205
263
  var inlineContent = (0, _toConsumableArray2.default)(node.content.content);
206
264
  if (inlineContent.length > 0) {
207
- // Create task item with inline content directly
208
- var listItem = taskItem.create(targetAttrs, inlineContent);
209
- listItems.push(listItem);
265
+ if (isBlockTaskItemEnabled && node.type === paragraph && node.marks.length > 0) {
266
+ listItems.push(createBlockTaskItemWithMarks(inlineContent, node.marks, tr.doc.type.schema));
267
+ } else {
268
+ listItems.push(taskItem.create(targetAttrs, inlineContent));
269
+ }
210
270
  }
211
271
  }
212
- return false; // Don't traverse into children
272
+ return false;
213
273
  });
214
274
  if (listItems.length === 0) {
215
275
  return null;
@@ -233,6 +293,44 @@ var transformTaskListToBlockNodes = exports.transformTaskListToBlockNodes = func
233
293
  sourcePos = context.sourcePos;
234
294
  var selection = tr.selection;
235
295
  var schema = selection.$from.doc.type.schema;
296
+ var blockTaskItem = schema.nodes.blockTaskItem;
297
+
298
+ // gating behind platform_editor_small_font_size to support task lists with font size applied,
299
+ // but keep this solution general
300
+ var isBlockTaskItemEnabled = !!blockTaskItem && (0, _expValEquals.expValEquals)('platform_editor_small_font_size', 'isEnabled', true);
301
+ if (isBlockTaskItemEnabled) {
302
+ var blockTaskItemsResult = (0, _utils.findChildrenByType)(sourceNode, blockTaskItem);
303
+ if (blockTaskItemsResult.length > 0 && targetNodeType === schema.nodes.paragraph) {
304
+ // blockTaskItem content is (paragraph | extension)+
305
+ // Extract paragraph children directly — they may carry block marks (e.g. fontSize)
306
+ var _targetNodes = [];
307
+ var _iterator = _createForOfIteratorHelper(blockTaskItemsResult),
308
+ _step;
309
+ try {
310
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
311
+ var blockItem = _step.value.node;
312
+ blockItem.forEach(function (child) {
313
+ if (child.type === schema.nodes.paragraph) {
314
+ _targetNodes.push(child);
315
+ }
316
+ });
317
+ }
318
+ } catch (err) {
319
+ _iterator.e(err);
320
+ } finally {
321
+ _iterator.f();
322
+ }
323
+ if (_targetNodes.length === 0) {
324
+ return null;
325
+ }
326
+ var _slice = new _model.Slice(_model.Fragment.fromArray(_targetNodes), 0, 0);
327
+ var _rangeStart = sourcePos !== null ? sourcePos : selection.from;
328
+ tr.replaceRange(_rangeStart, _rangeStart + sourceNode.nodeSize, _slice);
329
+ return tr;
330
+ }
331
+ }
332
+
333
+ // Original logic for regular taskItem children
236
334
  var taskItemsResult = (0, _utils.findChildrenByType)(sourceNode, schema.nodes.taskItem);
237
335
  var taskItems = taskItemsResult.map(function (item) {
238
336
  return item.node;
@@ -280,6 +378,10 @@ var getFormattedNode = exports.getFormattedNode = function getFormattedNode(tr)
280
378
  var selection = tr.selection;
281
379
  var nodes = tr.doc.type.schema.nodes;
282
380
 
381
+ // gating behind platform_editor_small_font_size to support task lists with font size applied,
382
+ // but keep this solution general
383
+ var isBlockTaskItemEnabled = !!nodes.blockTaskItem && (0, _expValEquals.expValEquals)('platform_editor_small_font_size', 'isEnabled', true);
384
+
283
385
  // Find the node to format from the current selection
284
386
  var nodeToFormat;
285
387
  var nodePos = selection.from;
@@ -291,13 +393,17 @@ var getFormattedNode = exports.getFormattedNode = function getFormattedNode(tr)
291
393
  nodePos = selectedNode.pos;
292
394
  } else {
293
395
  // Try to find parent node (including list parents)
294
- var parentNode = (0, _utils.findParentNodeOfType)([nodes.blockquote, nodes.panel, nodes.expand, nodes.codeBlock, nodes.listItem, nodes.taskItem, nodes.layoutSection])(selection);
396
+ var parentNodeTypes = [nodes.blockquote, nodes.panel, nodes.expand, nodes.codeBlock, nodes.listItem, nodes.taskItem, nodes.layoutSection];
397
+ if (isBlockTaskItemEnabled) {
398
+ parentNodeTypes.push(nodes.blockTaskItem);
399
+ }
400
+ var parentNode = (0, _utils.findParentNodeOfType)(parentNodeTypes)(selection);
295
401
  if (parentNode) {
296
402
  nodeToFormat = parentNode.node;
297
403
  nodePos = parentNode.pos;
298
404
  var paragraphOrHeadingNode = (0, _utils.findParentNodeOfType)([nodes.paragraph, nodes.heading])(selection);
299
- // Special case: if we found a listItem, check if we need the parent list instead
300
- if (parentNode.node.type === nodes.listItem || parentNode.node.type === nodes.taskItem) {
405
+ // Special case: if we found a listItem/taskItem/blockTaskItem, check if we need the parent list instead
406
+ if (parentNode.node.type === nodes.listItem || parentNode.node.type === nodes.taskItem || isBlockTaskItemEnabled && parentNode.node.type === nodes.blockTaskItem) {
301
407
  var listParent = (0, _utils.findParentNodeOfType)([nodes.bulletList, nodes.orderedList, nodes.taskList])(selection);
302
408
  if (listParent) {
303
409
  // For list transformations, we want the list parent, not the listItem
@@ -24,7 +24,7 @@ function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.
24
24
  * @jsx jsx
25
25
  */ // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
26
26
  var packageName = "@atlaskit/editor-common";
27
- var packageVersion = "112.8.4";
27
+ var packageVersion = "112.9.1";
28
28
  var halfFocusRing = 1;
29
29
  var dropOffset = '0, 8';
30
30
  var fadeIn = (0, _react2.keyframes)({
@@ -8,6 +8,7 @@ export { getCommonListAnalyticsAttributes, countListItemsInSelection } from './a
8
8
  export { hasValidListIndentationLevel } from './indentation';
9
9
  export { restoreSelection, computeSelectionOffsets } from './restore-selection';
10
10
  export { buildReplacementFragment } from './build-replacement-fragment';
11
+ export { narrowReplacementRange } from './narrow-replacement-range';
11
12
  export { flattenList } from './flatten-list';
12
13
  export { isListNode, isListItemNode, isBulletList, isParagraphNode } from '../utils';
13
14
  export { messages } from './messages';
@@ -0,0 +1,74 @@
1
+ import { Fragment } from '@atlaskit/editor-prosemirror/model';
2
+ /**
3
+ * Narrows a full-list replacement to the minimal changed range.
4
+ *
5
+ * Compares the old root list node with the new replacement fragment
6
+ * from both ends to find the first and last positions where they differ,
7
+ * then returns only the changed subrange.
8
+ *
9
+ * This reduces the scope of `tr.replaceWith()` so that remote cursors
10
+ * on unchanged items are preserved during collaborative editing.
11
+ */
12
+ export function narrowReplacementRange(doc, rootListStart, rootListEnd, fragment, contentStartOffsets) {
13
+ const oldNode = doc.nodeAt(rootListStart);
14
+ const newNode = fragment.childCount === 1 ? fragment.firstChild : null;
15
+ if (!oldNode || !newNode || newNode.type !== oldNode.type) {
16
+ return {
17
+ start: rootListStart,
18
+ end: rootListEnd,
19
+ fragment,
20
+ adjustedContentStartOffsets: contentStartOffsets
21
+ };
22
+ }
23
+ const minChildCount = Math.min(oldNode.childCount, newNode.childCount);
24
+ let commonPrefixChildren = 0;
25
+ let prefixSize = 0;
26
+ for (let i = 0; i < minChildCount; i++) {
27
+ const oldChild = oldNode.child(i);
28
+ const newChild = newNode.child(i);
29
+ if (oldChild.eq(newChild)) {
30
+ commonPrefixChildren++;
31
+ prefixSize += oldChild.nodeSize;
32
+ } else {
33
+ break;
34
+ }
35
+ }
36
+ let commonSuffixChildren = 0;
37
+ let suffixSize = 0;
38
+ for (let i = 0; i < minChildCount - commonPrefixChildren; i++) {
39
+ const oldChild = oldNode.child(oldNode.childCount - 1 - i);
40
+ const newChild = newNode.child(newNode.childCount - 1 - i);
41
+ if (oldChild.eq(newChild)) {
42
+ commonSuffixChildren++;
43
+ suffixSize += oldChild.nodeSize;
44
+ } else {
45
+ break;
46
+ }
47
+ }
48
+ const totalCommon = commonPrefixChildren + commonSuffixChildren;
49
+ if (totalCommon >= oldNode.childCount && totalCommon >= newNode.childCount) {
50
+ return {
51
+ start: rootListStart,
52
+ end: rootListStart,
53
+ fragment: Fragment.empty,
54
+ adjustedContentStartOffsets: contentStartOffsets
55
+ };
56
+ }
57
+ const narrowedStart = rootListStart + 1 + prefixSize;
58
+ const narrowedEnd = rootListEnd - 1 - suffixSize;
59
+ const changedChildStart = commonPrefixChildren;
60
+ const changedChildEnd = newNode.childCount - commonSuffixChildren;
61
+ const changedNodes = [];
62
+ for (let i = changedChildStart; i < changedChildEnd; i++) {
63
+ changedNodes.push(newNode.child(i));
64
+ }
65
+ const narrowedFragment = Fragment.from(changedNodes);
66
+ const prefixOffset = 1 + prefixSize;
67
+ const adjustedContentStartOffsets = contentStartOffsets.map(offset => offset - prefixOffset);
68
+ return {
69
+ start: narrowedStart,
70
+ end: narrowedEnd,
71
+ fragment: narrowedFragment,
72
+ adjustedContentStartOffsets
73
+ };
74
+ }
@@ -7,6 +7,7 @@ import _extends from "@babel/runtime/helpers/extends";
7
7
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled, @typescript-eslint/consistent-type-imports -- Ignored via go/DSP-18766; jsx required at runtime for @jsxRuntime classic
8
8
  import { css, jsx } from '@emotion/react';
9
9
  import { hexToEditorBorderPaletteColor } from '@atlaskit/editor-palette';
10
+ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
10
11
  import { borderStyle, INLINE_IMAGE_ASPECT_RATIO_CSS_VAR_KEY, INLINE_IMAGE_BORDER_COLOR_CSS_VAR_KEY, INLINE_IMAGE_BORDER_SIZE_CSS_VAR_KEY, INLINE_IMAGE_WRAPPER_CLASS_NAME, selectedStyle, wrapperStyle } from './styles';
11
12
 
12
13
  // The MediaImage component needs to obtain its parent's dimensions.
@@ -34,8 +35,17 @@ export const InlineImageWrapper = ({
34
35
  const aspectStyleVars = aspectRatio ? {
35
36
  [INLINE_IMAGE_ASPECT_RATIO_CSS_VAR_KEY]: aspectRatio
36
37
  } : {};
38
+ const onKeyDown = e => {
39
+ if (expValEquals('editor_a11y__enghealth-46814_fy26', 'isEnabled', true)) {
40
+ if (e.key === 'Enter' || e.key === ' ') {
41
+ e.preventDefault();
42
+ onClick(e);
43
+ }
44
+ }
45
+ return undefined;
46
+ };
37
47
  return (
38
- // eslint-disable-next-line @atlaskit/design-system/prefer-primitives, @atlassian/a11y/click-events-have-key-events, @atlassian/a11y/interactive-element-not-keyboard-focusable, @atlassian/a11y/no-static-element-interactions
48
+ // eslint-disable-next-line @atlaskit/design-system/prefer-primitives
39
49
  jsx("span", _extends({
40
50
  // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
41
51
  style: {
@@ -53,7 +63,10 @@ export const InlineImageWrapper = ({
53
63
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/design-system/consistent-css-prop-usage -- Ignored via go/DSP-18766
54
64
  isSelected && selectedStyle],
55
65
  "data-testid": "inline-image-wrapper",
56
- onClick: onClick
66
+ role: expValEquals('editor_a11y__enghealth-46814_fy26', 'isEnabled', true) ? 'button' : undefined,
67
+ tabIndex: expValEquals('editor_a11y__enghealth-46814_fy26', 'isEnabled', true) ? 0 : undefined,
68
+ onClick: onClick,
69
+ onKeyDown: onKeyDown
57
70
  // Ignored via go/ees005
58
71
  // eslint-disable-next-line react/jsx-props-no-spreading
59
72
  }, htmlAttrs), jsx("span", {
@@ -4,7 +4,7 @@ import { isFedRamp } from './environment';
4
4
  import { normaliseSentryBreadcrumbs, SERIALIZABLE_ATTRIBUTES } from './normalise-sentry-breadcrumbs';
5
5
  const SENTRY_DSN = 'https://0b10c8e02fb44d8796c047b102c9bee8@o55978.ingest.sentry.io/4505129224110080';
6
6
  const packageName = 'editor-common'; // Sentry doesn't accept '/' in its releases https://docs.sentry.io/platforms/javascript/configuration/releases/
7
- const packageVersion = "112.8.4";
7
+ const packageVersion = "112.9.1";
8
8
  const sanitiseSentryEvents = (data, _hint) => {
9
9
  // Remove URL as it has UGC
10
10
  // Ignored via go/ees007
@@ -1,4 +1,5 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
2
3
  import { EventDispatcher } from '../event-dispatcher';
3
4
 
4
5
  /*********************
@@ -632,12 +633,28 @@ export class EditorPresetBuilder {
632
633
  if (typeof fn !== 'function') {
633
634
  return null;
634
635
  }
635
- const plugin = pluginInjectionAPI ? fn({
636
- config,
637
- api: pluginInjectionAPI.api()
638
- }) : fn({
639
- config
640
- });
636
+ let plugin;
637
+ if (expValEquals('platform_editor_improve_preset_builder_logging', 'isEnabled', true)) {
638
+ try {
639
+ plugin = pluginInjectionAPI ? fn({
640
+ config,
641
+ api: pluginInjectionAPI.api()
642
+ }) : fn({
643
+ config
644
+ });
645
+ } catch (error) {
646
+ const pluginName = fn.name || 'unknown';
647
+ const enhancedError = error instanceof Error ? new Error(`Failed to initialize plugin '${pluginName}': ${error.message}`) : new Error(`Failed to initialize plugin '${pluginName}'`);
648
+ throw enhancedError;
649
+ }
650
+ } else {
651
+ plugin = pluginInjectionAPI ? fn({
652
+ config,
653
+ api: pluginInjectionAPI.api()
654
+ }) : fn({
655
+ config
656
+ });
657
+ }
641
658
  if (plugin && excludePlugins !== null && excludePlugins !== void 0 && excludePlugins.has(plugin.name)) {
642
659
  return null;
643
660
  }