@atlaskit/editor-plugin-paste 7.4.3 → 7.4.5

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
+ ## 7.4.5
4
+
5
+ ### Patch Changes
6
+
7
+ - [`4cab7924c4af0`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/4cab7924c4af0) -
8
+ [ux] Clean up editor_inline_comments_paste_insert_nodes
9
+ - Updated dependencies
10
+
11
+ ## 7.4.4
12
+
13
+ ### Patch Changes
14
+
15
+ - [`c094becfaeeaa`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/c094becfaeeaa) -
16
+ EDITOR-2476 Introduce new utility method to check if nested tables is supported in the schema to
17
+ facilitate removal of gate `platform_editor_use_nested_table_pm_nodes`
18
+ - Updated dependencies
19
+
3
20
  ## 7.4.3
4
21
 
5
22
  ### Patch Changes
@@ -14,6 +14,7 @@ var _analytics = require("@atlaskit/editor-common/analytics");
14
14
  var _card = require("@atlaskit/editor-common/card");
15
15
  var _coreUtils = require("@atlaskit/editor-common/core-utils");
16
16
  var _extensions = require("@atlaskit/editor-common/extensions");
17
+ var _nesting = require("@atlaskit/editor-common/nesting");
17
18
  var _paste = require("@atlaskit/editor-common/paste");
18
19
  var _measureRender = require("@atlaskit/editor-common/performance/measure-render");
19
20
  var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
@@ -39,7 +40,7 @@ var _handlers = require("./util/handlers");
39
40
  var _tinyMCE = require("./util/tinyMCE");
40
41
  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; } } }; }
41
42
  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; } }
42
- 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; }
43
+ 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; } // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
43
44
  var isInsideBlockQuote = exports.isInsideBlockQuote = function isInsideBlockQuote(state) {
44
45
  var blockquote = state.schema.nodes.blockquote;
45
46
  return (0, _utils2.hasParentNodeOfType)(blockquote)(state.selection);
@@ -207,6 +208,7 @@ function createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFlags, pl
207
208
  }
208
209
  var state = view.state;
209
210
  var content = (0, _analytics2.getContentNodeTypes)(slice.content);
211
+ // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
210
212
  var pasteId = (0, _uuid.default)();
211
213
  var measureName = "".concat(PASTE, "_").concat(pasteId);
212
214
  (0, _measureRender.measureRender)(measureName, function (_ref) {
@@ -437,7 +439,7 @@ function createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFlags, pl
437
439
  }
438
440
 
439
441
  // handle paste of nested tables to ensure nesting limits are respected
440
- if ((0, _analytics2.handleNestedTablePasteWithAnalytics)(editorAnalyticsAPI, (0, _platformFeatureFlags.fg)('platform_editor_use_nested_table_pm_nodes'))(view, event, slice)(state, dispatch)) {
442
+ if ((0, _analytics2.handleNestedTablePasteWithAnalytics)(editorAnalyticsAPI, (0, _nesting.isNestedTablesSupported)(state.schema) && (0, _platformFeatureFlags.fg)('platform_editor_use_nested_table_pm_nodes'))(view, event, slice)(state, dispatch)) {
441
443
  return true;
442
444
  }
443
445
  if ((0, _analytics2.handlePasteIntoTaskAndDecisionWithAnalytics)(view, event, slice, isPlainText ? _analytics.PasteTypes.plain : _analytics.PasteTypes.richText, pluginInjectionApi)(state, dispatch)) {
@@ -52,7 +52,8 @@ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol
52
52
  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; } }
53
53
  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; }
54
54
  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; }
55
- 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; } // TODO: ED-20519 - Needs Macro extraction
55
+ 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; } // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
56
+ // TODO: ED-20519 - Needs Macro extraction
56
57
  var insideExpand = function insideExpand(state) {
57
58
  var _state$schema$nodes = state.schema.nodes,
58
59
  expand = _state$schema$nodes.expand,
@@ -653,6 +654,8 @@ function handleMacroAutoConvert(text, slice, queueCardsFromChangedTr, runMacroAu
653
654
  if (!view) {
654
655
  throw new Error('View is missing');
655
656
  }
657
+
658
+ // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
656
659
  var trackingId = (0, _v.default)();
657
660
  var trackingFrom = "handleMacroAutoConvert-from-".concat(trackingId);
658
661
  var trackingTo = "handleMacroAutoConvert-to-".concat(trackingId);
@@ -218,13 +218,11 @@ function applyTextMarksToSlice(schema, marks) {
218
218
  }))).sort((0, _legacyRankPlugins.sortByOrderWithTypeName)('marks'));
219
219
  return false;
220
220
  }
221
- if ((0, _platformFeatureFlags.fg)('editor_inline_comments_paste_insert_nodes')) {
222
- if (node.isInline && ['inlineCard', 'emoji', 'status', 'date', 'mention'].includes(node.type.name) && parent && parent.isBlock) {
223
- // @ts-ignore - [unblock prosemirror bump] assigning to readonly prop
224
- node.marks = [].concat((0, _toConsumableArray2.default)(node.marks), (0, _toConsumableArray2.default)(parent.type.allowedMarks(marks).filter(function (mark) {
225
- return mark.type === schema.marks.annotation;
226
- })));
227
- }
221
+ if (node.isInline && ['inlineCard', 'emoji', 'status', 'date', 'mention'].includes(node.type.name) && parent && parent.isBlock) {
222
+ // @ts-ignore - [unblock prosemirror bump] assigning to readonly prop
223
+ node.marks = [].concat((0, _toConsumableArray2.default)(node.marks), (0, _toConsumableArray2.default)(parent.type.allowedMarks(marks).filter(function (mark) {
224
+ return mark.type === schema.marks.annotation;
225
+ })));
228
226
  }
229
227
  return true;
230
228
  });
@@ -1,8 +1,10 @@
1
+ // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
1
2
  import uuid from 'uuid';
2
3
  import { ACTION, INPUT_METHOD, PasteTypes } from '@atlaskit/editor-common/analytics';
3
4
  import { addLinkMetadata } from '@atlaskit/editor-common/card';
4
5
  import { insideTable } from '@atlaskit/editor-common/core-utils';
5
6
  import { getExtensionAutoConvertersFromProvider } from '@atlaskit/editor-common/extensions';
7
+ import { isNestedTablesSupported } from '@atlaskit/editor-common/nesting';
6
8
  import { isPastedFile as isPastedFileFromEvent, md } from '@atlaskit/editor-common/paste';
7
9
  import { measureRender } from '@atlaskit/editor-common/performance/measure-render';
8
10
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
@@ -174,6 +176,7 @@ export function createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFl
174
176
  state
175
177
  } = view;
176
178
  const content = getContentNodeTypes(slice.content);
179
+ // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
177
180
  const pasteId = uuid();
178
181
  const measureName = `${PASTE}_${pasteId}`;
179
182
  measureRender(measureName, ({
@@ -398,7 +401,7 @@ export function createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFl
398
401
  }
399
402
 
400
403
  // handle paste of nested tables to ensure nesting limits are respected
401
- if (handleNestedTablePasteWithAnalytics(editorAnalyticsAPI, fg('platform_editor_use_nested_table_pm_nodes'))(view, event, slice)(state, dispatch)) {
404
+ if (handleNestedTablePasteWithAnalytics(editorAnalyticsAPI, isNestedTablesSupported(state.schema) && fg('platform_editor_use_nested_table_pm_nodes'))(view, event, slice)(state, dispatch)) {
402
405
  return true;
403
406
  }
404
407
  if (handlePasteIntoTaskAndDecisionWithAnalytics(view, event, slice, isPlainText ? PasteTypes.plain : PasteTypes.richText, pluginInjectionApi)(state, dispatch)) {
@@ -1,3 +1,4 @@
1
+ // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
1
2
  import uuid from 'uuid/v4';
2
3
  import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
3
4
  import { insideTable } from '@atlaskit/editor-common/core-utils';
@@ -623,6 +624,8 @@ export function handleMacroAutoConvert(text, slice, queueCardsFromChangedTr, run
623
624
  if (!view) {
624
625
  throw new Error('View is missing');
625
626
  }
627
+
628
+ // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
626
629
  const trackingId = uuid();
627
630
  const trackingFrom = `handleMacroAutoConvert-from-${trackingId}`;
628
631
  const trackingTo = `handleMacroAutoConvert-to-${trackingId}`;
@@ -198,11 +198,9 @@ export function applyTextMarksToSlice(schema, marks) {
198
198
  ...parent.type.allowedMarks(marks).filter(mark => mark.type !== linkMark)].sort(sortByOrderWithTypeName('marks'));
199
199
  return false;
200
200
  }
201
- if (fg('editor_inline_comments_paste_insert_nodes')) {
202
- if (node.isInline && ['inlineCard', 'emoji', 'status', 'date', 'mention'].includes(node.type.name) && parent && parent.isBlock) {
203
- // @ts-ignore - [unblock prosemirror bump] assigning to readonly prop
204
- node.marks = [...node.marks, ...parent.type.allowedMarks(marks).filter(mark => mark.type === schema.marks.annotation)];
205
- }
201
+ if (node.isInline && ['inlineCard', 'emoji', 'status', 'date', 'mention'].includes(node.type.name) && parent && parent.isBlock) {
202
+ // @ts-ignore - [unblock prosemirror bump] assigning to readonly prop
203
+ node.marks = [...node.marks, ...parent.type.allowedMarks(marks).filter(mark => mark.type === schema.marks.annotation)];
206
204
  }
207
205
  return true;
208
206
  });
@@ -3,11 +3,13 @@ import _regeneratorRuntime from "@babel/runtime/regenerator";
3
3
  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; } } }; }
4
4
  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; } }
5
5
  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; }
6
+ // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
6
7
  import uuid from 'uuid';
7
8
  import { ACTION, INPUT_METHOD, PasteTypes } from '@atlaskit/editor-common/analytics';
8
9
  import { addLinkMetadata } from '@atlaskit/editor-common/card';
9
10
  import { insideTable } from '@atlaskit/editor-common/core-utils';
10
11
  import { getExtensionAutoConvertersFromProvider } from '@atlaskit/editor-common/extensions';
12
+ import { isNestedTablesSupported } from '@atlaskit/editor-common/nesting';
11
13
  import { isPastedFile as isPastedFileFromEvent, md } from '@atlaskit/editor-common/paste';
12
14
  import { measureRender } from '@atlaskit/editor-common/performance/measure-render';
13
15
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
@@ -198,6 +200,7 @@ export function createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFl
198
200
  }
199
201
  var state = view.state;
200
202
  var content = getContentNodeTypes(slice.content);
203
+ // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
201
204
  var pasteId = uuid();
202
205
  var measureName = "".concat(PASTE, "_").concat(pasteId);
203
206
  measureRender(measureName, function (_ref) {
@@ -428,7 +431,7 @@ export function createPlugin(schema, dispatchAnalyticsEvent, dispatch, featureFl
428
431
  }
429
432
 
430
433
  // handle paste of nested tables to ensure nesting limits are respected
431
- if (handleNestedTablePasteWithAnalytics(editorAnalyticsAPI, fg('platform_editor_use_nested_table_pm_nodes'))(view, event, slice)(state, dispatch)) {
434
+ if (handleNestedTablePasteWithAnalytics(editorAnalyticsAPI, isNestedTablesSupported(state.schema) && fg('platform_editor_use_nested_table_pm_nodes'))(view, event, slice)(state, dispatch)) {
432
435
  return true;
433
436
  }
434
437
  if (handlePasteIntoTaskAndDecisionWithAnalytics(view, event, slice, isPlainText ? PasteTypes.plain : PasteTypes.richText, pluginInjectionApi)(state, dispatch)) {
@@ -6,6 +6,7 @@ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r)
6
6
  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; }
7
7
  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; }
8
8
  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) { _defineProperty(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; }
9
+ // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
9
10
  import uuid from 'uuid/v4';
10
11
  import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
11
12
  import { insideTable } from '@atlaskit/editor-common/core-utils';
@@ -627,6 +628,8 @@ export function handleMacroAutoConvert(text, slice, queueCardsFromChangedTr, run
627
628
  if (!view) {
628
629
  throw new Error('View is missing');
629
630
  }
631
+
632
+ // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
630
633
  var trackingId = uuid();
631
634
  var trackingFrom = "handleMacroAutoConvert-from-".concat(trackingId);
632
635
  var trackingTo = "handleMacroAutoConvert-to-".concat(trackingId);
@@ -197,13 +197,11 @@ export function applyTextMarksToSlice(schema, marks) {
197
197
  }))).sort(sortByOrderWithTypeName('marks'));
198
198
  return false;
199
199
  }
200
- if (fg('editor_inline_comments_paste_insert_nodes')) {
201
- if (node.isInline && ['inlineCard', 'emoji', 'status', 'date', 'mention'].includes(node.type.name) && parent && parent.isBlock) {
202
- // @ts-ignore - [unblock prosemirror bump] assigning to readonly prop
203
- node.marks = [].concat(_toConsumableArray(node.marks), _toConsumableArray(parent.type.allowedMarks(marks).filter(function (mark) {
204
- return mark.type === schema.marks.annotation;
205
- })));
206
- }
200
+ if (node.isInline && ['inlineCard', 'emoji', 'status', 'date', 'mention'].includes(node.type.name) && parent && parent.isBlock) {
201
+ // @ts-ignore - [unblock prosemirror bump] assigning to readonly prop
202
+ node.marks = [].concat(_toConsumableArray(node.marks), _toConsumableArray(parent.type.allowedMarks(marks).filter(function (mark) {
203
+ return mark.type === schema.marks.annotation;
204
+ })));
207
205
  }
208
206
  return true;
209
207
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-paste",
3
- "version": "7.4.3",
3
+ "version": "7.4.5",
4
4
  "description": "Paste plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -33,7 +33,7 @@
33
33
  "@atlaskit/editor-plugin-analytics": "^6.2.0",
34
34
  "@atlaskit/editor-plugin-annotation": "^6.2.0",
35
35
  "@atlaskit/editor-plugin-better-type-history": "^6.1.0",
36
- "@atlaskit/editor-plugin-card": "^11.4.0",
36
+ "@atlaskit/editor-plugin-card": "^11.5.0",
37
37
  "@atlaskit/editor-plugin-feature-flags": "^5.0.0",
38
38
  "@atlaskit/editor-plugin-list": "^8.2.0",
39
39
  "@atlaskit/editor-plugin-media": "^8.4.0",
@@ -41,17 +41,17 @@
41
41
  "@atlaskit/editor-prosemirror": "7.0.0",
42
42
  "@atlaskit/editor-tables": "^2.9.0",
43
43
  "@atlaskit/insm": "^0.2.0",
44
- "@atlaskit/media-client": "^35.5.0",
44
+ "@atlaskit/media-client": "^35.6.0",
45
45
  "@atlaskit/media-common": "^12.3.0",
46
46
  "@atlaskit/platform-feature-flags": "^1.1.0",
47
- "@atlaskit/tmp-editor-statsig": "^13.23.0",
47
+ "@atlaskit/tmp-editor-statsig": "^13.38.0",
48
48
  "@babel/runtime": "^7.0.0",
49
49
  "lodash": "^4.17.21",
50
50
  "react-intl-next": "npm:react-intl@^5.18.1",
51
51
  "uuid": "^3.1.0"
52
52
  },
53
53
  "peerDependencies": {
54
- "@atlaskit/editor-common": "^110.20.0",
54
+ "@atlaskit/editor-common": "^110.29.0",
55
55
  "react": "^18.2.0",
56
56
  "react-dom": "^18.2.0"
57
57
  },
@@ -102,9 +102,6 @@
102
102
  }
103
103
  },
104
104
  "platform-feature-flags": {
105
- "editor_inline_comments_paste_insert_nodes": {
106
- "type": "boolean"
107
- },
108
105
  "platform_editor_use_nested_table_pm_nodes": {
109
106
  "type": "boolean"
110
107
  },