@atlaskit/editor-common 110.34.3 → 110.34.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.
Files changed (38) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/cjs/card/utils.js +1 -0
  3. package/dist/cjs/experiences/Experience.js +6 -4
  4. package/dist/cjs/hooks/usePluginStateEffect.js +2 -0
  5. package/dist/cjs/keymaps/keymap.js +1 -0
  6. package/dist/cjs/link/LinkSearch/index.js +3 -1
  7. package/dist/cjs/monitoring/error.js +23 -7
  8. package/dist/cjs/monitoring/normalise-sentry-breadcrumbs.js +38 -0
  9. package/dist/cjs/ui/DropList/index.js +1 -1
  10. package/dist/cjs/utils/document.js +3 -0
  11. package/dist/cjs/utils/plugin-state-factory.js +4 -0
  12. package/dist/es2019/card/utils.js +1 -0
  13. package/dist/es2019/experiences/Experience.js +6 -4
  14. package/dist/es2019/hooks/usePluginStateEffect.js +2 -0
  15. package/dist/es2019/keymaps/keymap.js +1 -0
  16. package/dist/es2019/link/LinkSearch/index.js +3 -1
  17. package/dist/es2019/monitoring/error.js +18 -2
  18. package/dist/es2019/monitoring/normalise-sentry-breadcrumbs.js +33 -0
  19. package/dist/es2019/ui/DropList/index.js +1 -1
  20. package/dist/es2019/utils/document.js +3 -0
  21. package/dist/es2019/utils/plugin-state-factory.js +4 -0
  22. package/dist/esm/card/utils.js +1 -0
  23. package/dist/esm/experiences/Experience.js +6 -4
  24. package/dist/esm/hooks/usePluginStateEffect.js +2 -0
  25. package/dist/esm/keymaps/keymap.js +1 -0
  26. package/dist/esm/link/LinkSearch/index.js +3 -1
  27. package/dist/esm/monitoring/error.js +23 -7
  28. package/dist/esm/monitoring/normalise-sentry-breadcrumbs.js +32 -0
  29. package/dist/esm/ui/DropList/index.js +1 -1
  30. package/dist/esm/utils/document.js +3 -0
  31. package/dist/esm/utils/plugin-state-factory.js +4 -0
  32. package/dist/types/analytics/types/experience-events.d.ts +23 -23
  33. package/dist/types/experiences/Experience.d.ts +24 -16
  34. package/dist/types/monitoring/normalise-sentry-breadcrumbs.d.ts +8 -0
  35. package/dist/types-ts4.5/analytics/types/experience-events.d.ts +23 -23
  36. package/dist/types-ts4.5/experiences/Experience.d.ts +24 -16
  37. package/dist/types-ts4.5/monitoring/normalise-sentry-breadcrumbs.d.ts +8 -0
  38. package/package.json +4 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @atlaskit/editor-common
2
2
 
3
+ ## 110.34.5
4
+
5
+ ### Patch Changes
6
+
7
+ - [`cfa9f26687992`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/cfa9f26687992) -
8
+ Enable breadcrumbs in Sentry for Editor
9
+ - [`34ebbcd3440c2`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/34ebbcd3440c2) -
10
+ NO-ISSUE Split by action subject id for experience tracking
11
+
12
+ ## 110.34.4
13
+
14
+ ### Patch Changes
15
+
16
+ - [`4d676bbdb3ce6`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/4d676bbdb3ce6) -
17
+ ts-ignore added temporarily to unblock local consumption for help-center, will be removed once
18
+ project refs are setup
19
+ - Updated dependencies
20
+
3
21
  ## 110.34.3
4
22
 
5
23
  ### Patch Changes
@@ -28,6 +28,7 @@ function addLinkMetadata(initialSelection, tr, metadata) {
28
28
  return tr;
29
29
  }
30
30
  function getLinkMetadataFromTransaction(tr) {
31
+ // @ts-ignore - Workaround for help-center local consumption
31
32
  return tr.steps.reduce(function (metadata, step) {
32
33
  if (!(step instanceof _steps.LinkMetaStep)) {
33
34
  return metadata;
@@ -38,13 +38,14 @@ var Experience = exports.Experience = /*#__PURE__*/function () {
38
38
  /**
39
39
  * Creates a new Experience instance for tracking user experiences.
40
40
  *
41
- * @param id - Unique identifier for the experience
41
+ * @param id - Unique identifier for the experience e.g. 'toolbar-open' 'menu-action'
42
42
  * @param options - Configuration options for the experience
43
43
  * @param options.checks - Experience checks to monitor for completion
44
44
  * @param options.dispatchAnalyticsEvent - Function to dispatch analytics events
45
45
  * @param options.sampleRate - Sample rate for experienceSampled events
46
46
  * @param options.metadata - Global metadata to attach to all events
47
- * @param options.action - Optional sub identifier for the specific experience action
47
+ * @param options.action - Optional sub identifier for the specific experience action e.g. 'bold' 'insert-table'
48
+ * @param options.actionSubjectId - Optional sub identifier for the experience action subject e.g. 'selection-toolbar' 'quick-insert'
48
49
  */
49
50
  function Experience(id, options) {
50
51
  var _options$sampleRate;
@@ -57,6 +58,7 @@ var Experience = exports.Experience = /*#__PURE__*/function () {
57
58
  */
58
59
  (0, _defineProperty2.default)(this, "statesSeen", new Set());
59
60
  this.id = id;
61
+ this.actionSubjectId = options.actionSubjectId;
60
62
  this.dispatchAnalyticsEvent = options.dispatchAnalyticsEvent;
61
63
  this.sampleRate = (_options$sampleRate = options.sampleRate) !== null && _options$sampleRate !== void 0 ? _options$sampleRate : _consts.DEFAULT_EXPERIENCE_SAMPLE_RATE;
62
64
  this.globalMetadata = _objectSpread(_objectSpread({}, options.metadata), {}, {
@@ -161,7 +163,7 @@ var Experience = exports.Experience = /*#__PURE__*/function () {
161
163
  var experienceMeasuredEvent = {
162
164
  action: _analytics.ACTION.EXPERIENCE_MEASURED,
163
165
  actionSubject: _analytics.ACTION_SUBJECT.EDITOR,
164
- actionSubjectId: undefined,
166
+ actionSubjectId: this.actionSubjectId,
165
167
  eventType: _analytics.EVENT_TYPE.OPERATIONAL,
166
168
  attributes: attributes
167
169
  };
@@ -170,7 +172,7 @@ var Experience = exports.Experience = /*#__PURE__*/function () {
170
172
  var experienceSampledEvent = {
171
173
  action: _analytics.ACTION.EXPERIENCE_SAMPLED,
172
174
  actionSubject: _analytics.ACTION_SUBJECT.EDITOR,
173
- actionSubjectId: undefined,
175
+ actionSubjectId: this.actionSubjectId,
174
176
  eventType: _analytics.EVENT_TYPE.OPERATIONAL,
175
177
  attributes: attributes
176
178
  };
@@ -95,6 +95,8 @@ function usePluginStateEffect(injectionApi, plugins, effect) {
95
95
  return _objectSpread(_objectSpread({}, acc), {}, (0, _defineProperty2.default)({}, "".concat(String(pluginName), "State"), injectionApi === null || injectionApi === void 0 ? void 0 : injectionApi[pluginName]));
96
96
  }, {});
97
97
  }, [injectionApi, pluginNames]);
98
+
99
+ // @ts-ignore - Workaround for help-center local consumption
98
100
  usePluginStateEffectInternal(namedExternalPlugins, effect, options);
99
101
  }
100
102
  function usePluginStateEffectInternal(externalPlugins, effect) {
@@ -19,6 +19,7 @@ var _safePlugin = require("../safe-plugin");
19
19
  function keymap(bindings) {
20
20
  return new _safePlugin.SafePlugin({
21
21
  props: {
22
+ // @ts-ignore - Workaround for help-center local consumption
22
23
  handleKeyDown: function handleKeyDown(view, event) {
23
24
  var name = (0, _w3cKeyname.keyName)(event);
24
25
  var keyboardEvent = event;
@@ -327,4 +327,6 @@ var RecentLink = /*#__PURE__*/function (_React$Component) {
327
327
  (0, _defineProperty2.default)(RecentLink, "defaultProps", {
328
328
  limit: DEFAULT_ITEMS_LIMIT
329
329
  });
330
- var _default = exports.default = (0, _withActivityProvider.default)((0, _reactIntlNext.injectIntl)(RecentLink));
330
+ var _default = exports.default = (0, _withActivityProvider.default)(
331
+ // @ts-ignore - Workaround for help-center local consumption (prop type incompatibility)
332
+ (0, _reactIntlNext.injectIntl)(RecentLink));
@@ -10,13 +10,16 @@ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"))
10
10
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
11
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
12
12
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
13
+ var _browser = require("@sentry/browser");
14
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
13
15
  var _environment = require("./environment");
16
+ var _normaliseSentryBreadcrumbs = require("./normalise-sentry-breadcrumbs");
14
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; }
15
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; }
16
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); }
17
20
  var SENTRY_DSN = 'https://0b10c8e02fb44d8796c047b102c9bee8@o55978.ingest.sentry.io/4505129224110080';
18
21
  var packageName = 'editor-common'; // Sentry doesn't accept '/' in its releases https://docs.sentry.io/platforms/javascript/configuration/releases/
19
- var packageVersion = "110.34.2";
22
+ var packageVersion = "110.34.4";
20
23
  var sanitiseSentryEvents = function sanitiseSentryEvents(data, _hint) {
21
24
  // Remove URL as it has UGC
22
25
  // Ignored via go/ees007
@@ -29,7 +32,7 @@ var sanitiseSentryEvents = function sanitiseSentryEvents(data, _hint) {
29
32
  };
30
33
  var logException = exports.logException = /*#__PURE__*/function () {
31
34
  var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(error, tags) {
32
- var _process$env$CLOUD_EN, _yield$import, BrowserClient, defaultIntegrations, getCurrentHub, _yield$import2, ExtraErrorData, sentryOptions, client, hub;
35
+ var _process$env$CLOUD_EN, _yield$import, BrowserClient, defaultIntegrations, getCurrentHub, _yield$import2, ExtraErrorData, breadcrumbsIntegration, sentryOptions, client, hub;
33
36
  return _regenerator.default.wrap(function _callee$(_context) {
34
37
  while (1) switch (_context.prev = _context.next) {
35
38
  case 0:
@@ -56,10 +59,23 @@ var logException = exports.logException = /*#__PURE__*/function () {
56
59
  case 11:
57
60
  _yield$import2 = _context.sent;
58
61
  ExtraErrorData = _yield$import2.ExtraErrorData;
62
+ breadcrumbsIntegration = (0, _platformFeatureFlags.fg)('platform_editor_sentry_breadcrumbs') ? new _browser.Integrations.Breadcrumbs({
63
+ // only enable breadcrumbs for dom (UI clicks and inputs)
64
+ // include 'data-test-id', 'data-testid' in the breadcrumbs if they are found
65
+ dom: {
66
+ serializeAttribute: _normaliseSentryBreadcrumbs.SERIALIZABLE_ATTRIBUTES
67
+ },
68
+ fetch: false,
69
+ xhr: false,
70
+ console: false,
71
+ history: false,
72
+ sentry: false
73
+ }) : undefined;
59
74
  sentryOptions = {
60
75
  dsn: (0, _environment.isFedRamp)() ? undefined : SENTRY_DSN,
61
76
  release: "".concat(packageName, "@").concat(packageVersion),
62
77
  environment: (_process$env$CLOUD_EN = process.env.CLOUD_ENV) !== null && _process$env$CLOUD_EN !== void 0 ? _process$env$CLOUD_EN : 'unknown',
78
+ beforeBreadcrumb: (0, _platformFeatureFlags.fg)('platform_editor_sentry_breadcrumbs') ? _normaliseSentryBreadcrumbs.normaliseSentryBreadcrumbs : undefined,
63
79
  ignoreErrors: [
64
80
  // Network issues
65
81
  // Ignored via go/ees005
@@ -78,7 +94,7 @@ var logException = exports.logException = /*#__PURE__*/function () {
78
94
  return [].concat((0, _toConsumableArray2.default)(defaultIntegrations.filter(function (_ref2) {
79
95
  var name = _ref2.name;
80
96
  return name !== 'Breadcrumbs';
81
- })), [
97
+ })), (0, _toConsumableArray2.default)(breadcrumbsIntegration ? [breadcrumbsIntegration] : []), [
82
98
  // Extracts all non-native attributes from the error object and attaches them to the event as the extra data
83
99
  // https://docs.sentry.io/platforms/javascript/configuration/integrations/plugin/?original_referrer=https%3A%2F%2Fduckduckgo.com%2F#extraerrordata
84
100
  new ExtraErrorData()]);
@@ -113,14 +129,14 @@ var logException = exports.logException = /*#__PURE__*/function () {
113
129
 
114
130
  // @ts-ignore - TypeScript 5.9.2 upgrade
115
131
  return _context.abrupt("return", client.close());
116
- case 21:
117
- _context.prev = 21;
132
+ case 22:
133
+ _context.prev = 22;
118
134
  _context.t0 = _context["catch"](0);
119
- case 23:
135
+ case 24:
120
136
  case "end":
121
137
  return _context.stop();
122
138
  }
123
- }, _callee, null, [[0, 21]]);
139
+ }, _callee, null, [[0, 22]]);
124
140
  }));
125
141
  return function logException(_x, _x2) {
126
142
  return _ref.apply(this, arguments);
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.normaliseSentryBreadcrumbs = exports.SERIALIZABLE_ATTRIBUTES = void 0;
7
+ var SERIALIZABLE_ATTRIBUTES = exports.SERIALIZABLE_ATTRIBUTES = ['data-test-id', 'data-testid'];
8
+ var WHITELISTED_ATTRIBNUTES = ['type', 'name'].concat(SERIALIZABLE_ATTRIBUTES);
9
+ var REG_MATCH_NOTALLOWED_ATTRIBUTES = new RegExp("\\[(?!".concat(WHITELISTED_ATTRIBNUTES.join('|'), ").*?\\]"), 'gmu');
10
+
11
+ // attributes may contain UGC that we need to strip out
12
+ // only allow type and name attributes
13
+ var sanitiseUiBreadcrumbMessage = function sanitiseUiBreadcrumbMessage(message) {
14
+ return message.replace(REG_MATCH_NOTALLOWED_ATTRIBUTES, '');
15
+ };
16
+ /**
17
+ * Sanitizes messages within UI category breadcrumbs to ensure user-generated content is
18
+ * appropriately cleaned before being logged by Sentry. This helps in maintaining
19
+ * privacy and security by preventing sensitive data exposure.
20
+ */
21
+ var normaliseSentryBreadcrumbs = exports.normaliseSentryBreadcrumbs = function normaliseSentryBreadcrumbs(breadcrumb) {
22
+ var _ref = breadcrumb || {},
23
+ category = _ref.category;
24
+
25
+ // allow "ui*"" category breadcrumbs, that include clicks and inputs on DOM elements
26
+ // they may contain UGC that needs to be stripped out
27
+ if (category !== null && category !== void 0 && category.startsWith('ui')) {
28
+ // sentry can include the element attributes in the data
29
+ // which may contain UGC that we need to strip out
30
+ var sanitisedBreadCrumb = breadcrumb;
31
+ var message = sanitisedBreadCrumb.message;
32
+ if (message !== null && message !== undefined) {
33
+ sanitisedBreadCrumb.message = sanitiseUiBreadcrumbMessage(message);
34
+ }
35
+ return breadcrumb;
36
+ }
37
+ return breadcrumb;
38
+ };
@@ -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 = "110.34.2";
27
+ var packageVersion = "110.34.4";
28
28
  var halfFocusRing = 1;
29
29
  var dropOffset = '0, 8';
30
30
  var fadeIn = (0, _react2.keyframes)({
@@ -20,7 +20,10 @@ var _editorCoreUtils = require("./editor-core-utils");
20
20
  var getStepRange = exports.getStepRange = function getStepRange(transaction) {
21
21
  var from = -1;
22
22
  var to = -1;
23
+
24
+ // @ts-ignore - Workaround for help-center local consumption
23
25
  transaction.mapping.maps.forEach(function (stepMap, index) {
26
+ // @ts-ignore - Workaround for help-center local consumption
24
27
  stepMap.forEach(function (oldStart, oldEnd) {
25
28
  var newStart = transaction.mapping.slice(index).map(oldStart, -1);
26
29
  var newEnd = transaction.mapping.slice(index).map(oldEnd);
@@ -64,9 +64,13 @@ function pluginFactory(pluginKey, reducer) {
64
64
  return {
65
65
  createPluginState: function createPluginState(dispatch, initialState) {
66
66
  return {
67
+ // @ts-ignore - Workaround for help-center local consumption
68
+
67
69
  init: function init(_, state) {
68
70
  return isFunction(initialState) ? initialState(state) : initialState;
69
71
  },
72
+ // @ts-ignore - Workaround for help-center local consumption
73
+
70
74
  apply: function apply(tr, _pluginState, _oldEditorState, newEditorState) {
71
75
  var oldPluginState = mapping ? mapping(tr, _pluginState, newEditorState) : _pluginState;
72
76
  var newPluginState = oldPluginState;
@@ -18,6 +18,7 @@ export function addLinkMetadata(initialSelection, tr, metadata) {
18
18
  return tr;
19
19
  }
20
20
  export function getLinkMetadataFromTransaction(tr) {
21
+ // @ts-ignore - Workaround for help-center local consumption
21
22
  return tr.steps.reduce((metadata, step) => {
22
23
  if (!(step instanceof LinkMetaStep)) {
23
24
  return metadata;
@@ -27,13 +27,14 @@ export class Experience {
27
27
  /**
28
28
  * Creates a new Experience instance for tracking user experiences.
29
29
  *
30
- * @param id - Unique identifier for the experience
30
+ * @param id - Unique identifier for the experience e.g. 'toolbar-open' 'menu-action'
31
31
  * @param options - Configuration options for the experience
32
32
  * @param options.checks - Experience checks to monitor for completion
33
33
  * @param options.dispatchAnalyticsEvent - Function to dispatch analytics events
34
34
  * @param options.sampleRate - Sample rate for experienceSampled events
35
35
  * @param options.metadata - Global metadata to attach to all events
36
- * @param options.action - Optional sub identifier for the specific experience action
36
+ * @param options.action - Optional sub identifier for the specific experience action e.g. 'bold' 'insert-table'
37
+ * @param options.actionSubjectId - Optional sub identifier for the experience action subject e.g. 'selection-toolbar' 'quick-insert'
37
38
  */
38
39
  constructor(id, options) {
39
40
  var _options$sampleRate;
@@ -45,6 +46,7 @@ export class Experience {
45
46
  */
46
47
  _defineProperty(this, "statesSeen", new Set());
47
48
  this.id = id;
49
+ this.actionSubjectId = options.actionSubjectId;
48
50
  this.dispatchAnalyticsEvent = options.dispatchAnalyticsEvent;
49
51
  this.sampleRate = (_options$sampleRate = options.sampleRate) !== null && _options$sampleRate !== void 0 ? _options$sampleRate : DEFAULT_EXPERIENCE_SAMPLE_RATE;
50
52
  this.globalMetadata = {
@@ -145,7 +147,7 @@ export class Experience {
145
147
  const experienceMeasuredEvent = {
146
148
  action: ACTION.EXPERIENCE_MEASURED,
147
149
  actionSubject: ACTION_SUBJECT.EDITOR,
148
- actionSubjectId: undefined,
150
+ actionSubjectId: this.actionSubjectId,
149
151
  eventType: EVENT_TYPE.OPERATIONAL,
150
152
  attributes
151
153
  };
@@ -154,7 +156,7 @@ export class Experience {
154
156
  const experienceSampledEvent = {
155
157
  action: ACTION.EXPERIENCE_SAMPLED,
156
158
  actionSubject: ACTION_SUBJECT.EDITOR,
157
- actionSubjectId: undefined,
159
+ actionSubjectId: this.actionSubjectId,
158
160
  eventType: EVENT_TYPE.OPERATIONAL,
159
161
  attributes
160
162
  };
@@ -79,6 +79,8 @@ export function usePluginStateEffect(injectionApi, plugins, effect, options = {}
79
79
  ...acc,
80
80
  [`${String(pluginName)}State`]: injectionApi === null || injectionApi === void 0 ? void 0 : injectionApi[pluginName]
81
81
  }), {}), [injectionApi, pluginNames]);
82
+
83
+ // @ts-ignore - Workaround for help-center local consumption
82
84
  usePluginStateEffectInternal(namedExternalPlugins, effect, options);
83
85
  }
84
86
  function usePluginStateEffectInternal(externalPlugins, effect, options = {}) {
@@ -14,6 +14,7 @@ import { SafePlugin } from '../safe-plugin';
14
14
  export function keymap(bindings) {
15
15
  return new SafePlugin({
16
16
  props: {
17
+ // @ts-ignore - Workaround for help-center local consumption
17
18
  handleKeyDown(view, event) {
18
19
  const name = keyName(event);
19
20
  let keyboardEvent = event;
@@ -220,4 +220,6 @@ class RecentLink extends React.Component {
220
220
  _defineProperty(RecentLink, "defaultProps", {
221
221
  limit: DEFAULT_ITEMS_LIMIT
222
222
  });
223
- export default withActivityProvider(injectIntl(RecentLink));
223
+ export default withActivityProvider(
224
+ // @ts-ignore - Workaround for help-center local consumption (prop type incompatibility)
225
+ injectIntl(RecentLink));
@@ -1,7 +1,10 @@
1
+ import { Integrations } from '@sentry/browser';
2
+ import { fg } from '@atlaskit/platform-feature-flags';
1
3
  import { isFedRamp } from './environment';
4
+ import { normaliseSentryBreadcrumbs, SERIALIZABLE_ATTRIBUTES } from './normalise-sentry-breadcrumbs';
2
5
  const SENTRY_DSN = 'https://0b10c8e02fb44d8796c047b102c9bee8@o55978.ingest.sentry.io/4505129224110080';
3
6
  const packageName = 'editor-common'; // Sentry doesn't accept '/' in its releases https://docs.sentry.io/platforms/javascript/configuration/releases/
4
- const packageVersion = "110.34.2";
7
+ const packageVersion = "110.34.4";
5
8
  const sanitiseSentryEvents = (data, _hint) => {
6
9
  // Remove URL as it has UGC
7
10
  // Ignored via go/ees007
@@ -27,10 +30,23 @@ export const logException = async (error, tags) => {
27
30
  const {
28
31
  ExtraErrorData
29
32
  } = await import( /* webpackChunkName: "@atlaskit-internal_editor-sentryintegrations" */'@sentry/integrations');
33
+ const breadcrumbsIntegration = fg('platform_editor_sentry_breadcrumbs') ? new Integrations.Breadcrumbs({
34
+ // only enable breadcrumbs for dom (UI clicks and inputs)
35
+ // include 'data-test-id', 'data-testid' in the breadcrumbs if they are found
36
+ dom: {
37
+ serializeAttribute: SERIALIZABLE_ATTRIBUTES
38
+ },
39
+ fetch: false,
40
+ xhr: false,
41
+ console: false,
42
+ history: false,
43
+ sentry: false
44
+ }) : undefined;
30
45
  const sentryOptions = {
31
46
  dsn: isFedRamp() ? undefined : SENTRY_DSN,
32
47
  release: `${packageName}@${packageVersion}`,
33
48
  environment: (_process$env$CLOUD_EN = process.env.CLOUD_ENV) !== null && _process$env$CLOUD_EN !== void 0 ? _process$env$CLOUD_EN : 'unknown',
49
+ beforeBreadcrumb: fg('platform_editor_sentry_breadcrumbs') ? normaliseSentryBreadcrumbs : undefined,
34
50
  ignoreErrors: [
35
51
  // Network issues
36
52
  // Ignored via go/ees005
@@ -50,7 +66,7 @@ export const logException = async (error, tags) => {
50
66
  // https://docs.sentry.io/platforms/javascript/configuration/integrations/default/
51
67
  ...defaultIntegrations.filter(({
52
68
  name
53
- }) => name !== 'Breadcrumbs'),
69
+ }) => name !== 'Breadcrumbs'), ...(breadcrumbsIntegration ? [breadcrumbsIntegration] : []),
54
70
  // Extracts all non-native attributes from the error object and attaches them to the event as the extra data
55
71
  // https://docs.sentry.io/platforms/javascript/configuration/integrations/plugin/?original_referrer=https%3A%2F%2Fduckduckgo.com%2F#extraerrordata
56
72
  new ExtraErrorData()],
@@ -0,0 +1,33 @@
1
+ export const SERIALIZABLE_ATTRIBUTES = ['data-test-id', 'data-testid'];
2
+ const WHITELISTED_ATTRIBNUTES = ['type', 'name', ...SERIALIZABLE_ATTRIBUTES];
3
+ const REG_MATCH_NOTALLOWED_ATTRIBUTES = new RegExp(`\\[(?!${WHITELISTED_ATTRIBNUTES.join('|')}).*?\\]`, 'gmu');
4
+
5
+ // attributes may contain UGC that we need to strip out
6
+ // only allow type and name attributes
7
+ const sanitiseUiBreadcrumbMessage = message => message.replace(REG_MATCH_NOTALLOWED_ATTRIBUTES, '');
8
+ /**
9
+ * Sanitizes messages within UI category breadcrumbs to ensure user-generated content is
10
+ * appropriately cleaned before being logged by Sentry. This helps in maintaining
11
+ * privacy and security by preventing sensitive data exposure.
12
+ */
13
+ export const normaliseSentryBreadcrumbs = breadcrumb => {
14
+ const {
15
+ category
16
+ } = breadcrumb || {};
17
+
18
+ // allow "ui*"" category breadcrumbs, that include clicks and inputs on DOM elements
19
+ // they may contain UGC that needs to be stripped out
20
+ if (category !== null && category !== void 0 && category.startsWith('ui')) {
21
+ // sentry can include the element attributes in the data
22
+ // which may contain UGC that we need to strip out
23
+ const sanitisedBreadCrumb = breadcrumb;
24
+ const {
25
+ message
26
+ } = sanitisedBreadCrumb;
27
+ if (message !== null && message !== undefined) {
28
+ sanitisedBreadCrumb.message = sanitiseUiBreadcrumbMessage(message);
29
+ }
30
+ return breadcrumb;
31
+ }
32
+ return breadcrumb;
33
+ };
@@ -14,7 +14,7 @@ import withAnalyticsEvents from '@atlaskit/analytics-next/withAnalyticsEvents';
14
14
  import { fg } from '@atlaskit/platform-feature-flags';
15
15
  import Layer from '../Layer';
16
16
  const packageName = "@atlaskit/editor-common";
17
- const packageVersion = "110.34.2";
17
+ const packageVersion = "110.34.4";
18
18
  const halfFocusRing = 1;
19
19
  const dropOffset = '0, 8';
20
20
  const fadeIn = keyframes({
@@ -5,7 +5,10 @@ import { isEmptyParagraph } from './editor-core-utils';
5
5
  export const getStepRange = transaction => {
6
6
  let from = -1;
7
7
  let to = -1;
8
+
9
+ // @ts-ignore - Workaround for help-center local consumption
8
10
  transaction.mapping.maps.forEach((stepMap, index) => {
11
+ // @ts-ignore - Workaround for help-center local consumption
9
12
  stepMap.forEach((oldStart, oldEnd) => {
10
13
  const newStart = transaction.mapping.slice(index).map(oldStart, -1);
11
14
  const newEnd = transaction.mapping.slice(index).map(oldEnd);
@@ -59,7 +59,11 @@ export function pluginFactory(pluginKey, reducer, options = {}) {
59
59
  return {
60
60
  createPluginState(dispatch, initialState) {
61
61
  return {
62
+ // @ts-ignore - Workaround for help-center local consumption
63
+
62
64
  init: (_, state) => isFunction(initialState) ? initialState(state) : initialState,
65
+ // @ts-ignore - Workaround for help-center local consumption
66
+
63
67
  apply: (tr, _pluginState, _oldEditorState, newEditorState) => {
64
68
  const oldPluginState = mapping ? mapping(tr, _pluginState, newEditorState) : _pluginState;
65
69
  let newPluginState = oldPluginState;
@@ -19,6 +19,7 @@ export function addLinkMetadata(initialSelection, tr, metadata) {
19
19
  return tr;
20
20
  }
21
21
  export function getLinkMetadataFromTransaction(tr) {
22
+ // @ts-ignore - Workaround for help-center local consumption
22
23
  return tr.steps.reduce(function (metadata, step) {
23
24
  if (!(step instanceof LinkMetaStep)) {
24
25
  return metadata;
@@ -31,13 +31,14 @@ export var Experience = /*#__PURE__*/function () {
31
31
  /**
32
32
  * Creates a new Experience instance for tracking user experiences.
33
33
  *
34
- * @param id - Unique identifier for the experience
34
+ * @param id - Unique identifier for the experience e.g. 'toolbar-open' 'menu-action'
35
35
  * @param options - Configuration options for the experience
36
36
  * @param options.checks - Experience checks to monitor for completion
37
37
  * @param options.dispatchAnalyticsEvent - Function to dispatch analytics events
38
38
  * @param options.sampleRate - Sample rate for experienceSampled events
39
39
  * @param options.metadata - Global metadata to attach to all events
40
- * @param options.action - Optional sub identifier for the specific experience action
40
+ * @param options.action - Optional sub identifier for the specific experience action e.g. 'bold' 'insert-table'
41
+ * @param options.actionSubjectId - Optional sub identifier for the experience action subject e.g. 'selection-toolbar' 'quick-insert'
41
42
  */
42
43
  function Experience(id, options) {
43
44
  var _options$sampleRate;
@@ -50,6 +51,7 @@ export var Experience = /*#__PURE__*/function () {
50
51
  */
51
52
  _defineProperty(this, "statesSeen", new Set());
52
53
  this.id = id;
54
+ this.actionSubjectId = options.actionSubjectId;
53
55
  this.dispatchAnalyticsEvent = options.dispatchAnalyticsEvent;
54
56
  this.sampleRate = (_options$sampleRate = options.sampleRate) !== null && _options$sampleRate !== void 0 ? _options$sampleRate : DEFAULT_EXPERIENCE_SAMPLE_RATE;
55
57
  this.globalMetadata = _objectSpread(_objectSpread({}, options.metadata), {}, {
@@ -154,7 +156,7 @@ export var Experience = /*#__PURE__*/function () {
154
156
  var experienceMeasuredEvent = {
155
157
  action: ACTION.EXPERIENCE_MEASURED,
156
158
  actionSubject: ACTION_SUBJECT.EDITOR,
157
- actionSubjectId: undefined,
159
+ actionSubjectId: this.actionSubjectId,
158
160
  eventType: EVENT_TYPE.OPERATIONAL,
159
161
  attributes: attributes
160
162
  };
@@ -163,7 +165,7 @@ export var Experience = /*#__PURE__*/function () {
163
165
  var experienceSampledEvent = {
164
166
  action: ACTION.EXPERIENCE_SAMPLED,
165
167
  actionSubject: ACTION_SUBJECT.EDITOR,
166
- actionSubjectId: undefined,
168
+ actionSubjectId: this.actionSubjectId,
167
169
  eventType: EVENT_TYPE.OPERATIONAL,
168
170
  attributes: attributes
169
171
  };
@@ -89,6 +89,8 @@ export function usePluginStateEffect(injectionApi, plugins, effect) {
89
89
  return _objectSpread(_objectSpread({}, acc), {}, _defineProperty({}, "".concat(String(pluginName), "State"), injectionApi === null || injectionApi === void 0 ? void 0 : injectionApi[pluginName]));
90
90
  }, {});
91
91
  }, [injectionApi, pluginNames]);
92
+
93
+ // @ts-ignore - Workaround for help-center local consumption
92
94
  usePluginStateEffectInternal(namedExternalPlugins, effect, options);
93
95
  }
94
96
  function usePluginStateEffectInternal(externalPlugins, effect) {
@@ -14,6 +14,7 @@ import { SafePlugin } from '../safe-plugin';
14
14
  export function keymap(bindings) {
15
15
  return new SafePlugin({
16
16
  props: {
17
+ // @ts-ignore - Workaround for help-center local consumption
17
18
  handleKeyDown: function handleKeyDown(view, event) {
18
19
  var name = keyName(event);
19
20
  var keyboardEvent = event;
@@ -320,4 +320,6 @@ var RecentLink = /*#__PURE__*/function (_React$Component) {
320
320
  _defineProperty(RecentLink, "defaultProps", {
321
321
  limit: DEFAULT_ITEMS_LIMIT
322
322
  });
323
- export default withActivityProvider(injectIntl(RecentLink));
323
+ export default withActivityProvider(
324
+ // @ts-ignore - Workaround for help-center local consumption (prop type incompatibility)
325
+ injectIntl(RecentLink));
@@ -4,10 +4,13 @@ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
4
4
  import _regeneratorRuntime from "@babel/runtime/regenerator";
5
5
  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; }
6
6
  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; }
7
+ import { Integrations } from '@sentry/browser';
8
+ import { fg } from '@atlaskit/platform-feature-flags';
7
9
  import { isFedRamp } from './environment';
10
+ import { normaliseSentryBreadcrumbs, SERIALIZABLE_ATTRIBUTES } from './normalise-sentry-breadcrumbs';
8
11
  var SENTRY_DSN = 'https://0b10c8e02fb44d8796c047b102c9bee8@o55978.ingest.sentry.io/4505129224110080';
9
12
  var packageName = 'editor-common'; // Sentry doesn't accept '/' in its releases https://docs.sentry.io/platforms/javascript/configuration/releases/
10
- var packageVersion = "110.34.2";
13
+ var packageVersion = "110.34.4";
11
14
  var sanitiseSentryEvents = function sanitiseSentryEvents(data, _hint) {
12
15
  // Remove URL as it has UGC
13
16
  // Ignored via go/ees007
@@ -20,7 +23,7 @@ var sanitiseSentryEvents = function sanitiseSentryEvents(data, _hint) {
20
23
  };
21
24
  export var logException = /*#__PURE__*/function () {
22
25
  var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(error, tags) {
23
- var _process$env$CLOUD_EN, _yield$import, BrowserClient, defaultIntegrations, getCurrentHub, _yield$import2, ExtraErrorData, sentryOptions, client, hub;
26
+ var _process$env$CLOUD_EN, _yield$import, BrowserClient, defaultIntegrations, getCurrentHub, _yield$import2, ExtraErrorData, breadcrumbsIntegration, sentryOptions, client, hub;
24
27
  return _regeneratorRuntime.wrap(function _callee$(_context) {
25
28
  while (1) switch (_context.prev = _context.next) {
26
29
  case 0:
@@ -43,10 +46,23 @@ export var logException = /*#__PURE__*/function () {
43
46
  case 11:
44
47
  _yield$import2 = _context.sent;
45
48
  ExtraErrorData = _yield$import2.ExtraErrorData;
49
+ breadcrumbsIntegration = fg('platform_editor_sentry_breadcrumbs') ? new Integrations.Breadcrumbs({
50
+ // only enable breadcrumbs for dom (UI clicks and inputs)
51
+ // include 'data-test-id', 'data-testid' in the breadcrumbs if they are found
52
+ dom: {
53
+ serializeAttribute: SERIALIZABLE_ATTRIBUTES
54
+ },
55
+ fetch: false,
56
+ xhr: false,
57
+ console: false,
58
+ history: false,
59
+ sentry: false
60
+ }) : undefined;
46
61
  sentryOptions = {
47
62
  dsn: isFedRamp() ? undefined : SENTRY_DSN,
48
63
  release: "".concat(packageName, "@").concat(packageVersion),
49
64
  environment: (_process$env$CLOUD_EN = process.env.CLOUD_ENV) !== null && _process$env$CLOUD_EN !== void 0 ? _process$env$CLOUD_EN : 'unknown',
65
+ beforeBreadcrumb: fg('platform_editor_sentry_breadcrumbs') ? normaliseSentryBreadcrumbs : undefined,
50
66
  ignoreErrors: [
51
67
  // Network issues
52
68
  // Ignored via go/ees005
@@ -65,7 +81,7 @@ export var logException = /*#__PURE__*/function () {
65
81
  return [].concat(_toConsumableArray(defaultIntegrations.filter(function (_ref2) {
66
82
  var name = _ref2.name;
67
83
  return name !== 'Breadcrumbs';
68
- })), [
84
+ })), _toConsumableArray(breadcrumbsIntegration ? [breadcrumbsIntegration] : []), [
69
85
  // Extracts all non-native attributes from the error object and attaches them to the event as the extra data
70
86
  // https://docs.sentry.io/platforms/javascript/configuration/integrations/plugin/?original_referrer=https%3A%2F%2Fduckduckgo.com%2F#extraerrordata
71
87
  new ExtraErrorData()]);
@@ -100,14 +116,14 @@ export var logException = /*#__PURE__*/function () {
100
116
 
101
117
  // @ts-ignore - TypeScript 5.9.2 upgrade
102
118
  return _context.abrupt("return", client.close());
103
- case 21:
104
- _context.prev = 21;
119
+ case 22:
120
+ _context.prev = 22;
105
121
  _context.t0 = _context["catch"](0);
106
- case 23:
122
+ case 24:
107
123
  case "end":
108
124
  return _context.stop();
109
125
  }
110
- }, _callee, null, [[0, 21]]);
126
+ }, _callee, null, [[0, 22]]);
111
127
  }));
112
128
  return function logException(_x, _x2) {
113
129
  return _ref.apply(this, arguments);
@@ -0,0 +1,32 @@
1
+ export var SERIALIZABLE_ATTRIBUTES = ['data-test-id', 'data-testid'];
2
+ var WHITELISTED_ATTRIBNUTES = ['type', 'name'].concat(SERIALIZABLE_ATTRIBUTES);
3
+ var REG_MATCH_NOTALLOWED_ATTRIBUTES = new RegExp("\\[(?!".concat(WHITELISTED_ATTRIBNUTES.join('|'), ").*?\\]"), 'gmu');
4
+
5
+ // attributes may contain UGC that we need to strip out
6
+ // only allow type and name attributes
7
+ var sanitiseUiBreadcrumbMessage = function sanitiseUiBreadcrumbMessage(message) {
8
+ return message.replace(REG_MATCH_NOTALLOWED_ATTRIBUTES, '');
9
+ };
10
+ /**
11
+ * Sanitizes messages within UI category breadcrumbs to ensure user-generated content is
12
+ * appropriately cleaned before being logged by Sentry. This helps in maintaining
13
+ * privacy and security by preventing sensitive data exposure.
14
+ */
15
+ export var normaliseSentryBreadcrumbs = function normaliseSentryBreadcrumbs(breadcrumb) {
16
+ var _ref = breadcrumb || {},
17
+ category = _ref.category;
18
+
19
+ // allow "ui*"" category breadcrumbs, that include clicks and inputs on DOM elements
20
+ // they may contain UGC that needs to be stripped out
21
+ if (category !== null && category !== void 0 && category.startsWith('ui')) {
22
+ // sentry can include the element attributes in the data
23
+ // which may contain UGC that we need to strip out
24
+ var sanitisedBreadCrumb = breadcrumb;
25
+ var message = sanitisedBreadCrumb.message;
26
+ if (message !== null && message !== undefined) {
27
+ sanitisedBreadCrumb.message = sanitiseUiBreadcrumbMessage(message);
28
+ }
29
+ return breadcrumb;
30
+ }
31
+ return breadcrumb;
32
+ };
@@ -21,7 +21,7 @@ import withAnalyticsEvents from '@atlaskit/analytics-next/withAnalyticsEvents';
21
21
  import { fg } from '@atlaskit/platform-feature-flags';
22
22
  import Layer from '../Layer';
23
23
  var packageName = "@atlaskit/editor-common";
24
- var packageVersion = "110.34.2";
24
+ var packageVersion = "110.34.4";
25
25
  var halfFocusRing = 1;
26
26
  var dropOffset = '0, 8';
27
27
  var fadeIn = keyframes({
@@ -5,7 +5,10 @@ import { isEmptyParagraph } from './editor-core-utils';
5
5
  export var getStepRange = function getStepRange(transaction) {
6
6
  var from = -1;
7
7
  var to = -1;
8
+
9
+ // @ts-ignore - Workaround for help-center local consumption
8
10
  transaction.mapping.maps.forEach(function (stepMap, index) {
11
+ // @ts-ignore - Workaround for help-center local consumption
9
12
  stepMap.forEach(function (oldStart, oldEnd) {
10
13
  var newStart = transaction.mapping.slice(index).map(oldStart, -1);
11
14
  var newEnd = transaction.mapping.slice(index).map(oldEnd);
@@ -58,9 +58,13 @@ export function pluginFactory(pluginKey, reducer) {
58
58
  return {
59
59
  createPluginState: function createPluginState(dispatch, initialState) {
60
60
  return {
61
+ // @ts-ignore - Workaround for help-center local consumption
62
+
61
63
  init: function init(_, state) {
62
64
  return isFunction(initialState) ? initialState(state) : initialState;
63
65
  },
66
+ // @ts-ignore - Workaround for help-center local consumption
67
+
64
68
  apply: function apply(tr, _pluginState, _oldEditorState, newEditorState) {
65
69
  var oldPluginState = mapping ? mapping(tr, _pluginState, newEditorState) : _pluginState;
66
70
  var newPluginState = oldPluginState;
@@ -6,52 +6,52 @@ import type { OperationalAEP } from './utils';
6
6
  */
7
7
  export type ExperienceEventAttributes = CustomExperienceMetadata & {
8
8
  /**
9
- * The unique key identifying the experience being tracked.
10
- */
11
- experienceKey: string;
12
- /**
13
- * The state the experience transitioned to.
14
- */
15
- experienceStatus: ExperienceState;
16
- /**
17
- * Whether this is the first transition to this status for this experience
18
- * in the current editor session.
19
- */
20
- experienceStatusFirstSeen: boolean;
21
- /**
22
- * Timestamp when the experience started.
23
- *
24
- * Milliseconds since epoch.
9
+ * Optional action that triggered the experience, if applicable.
25
10
  */
26
- experienceStartTime: number;
11
+ experienceAction?: string;
27
12
  /**
28
13
  * Duration from experience start to current status transition.
29
14
  *
30
15
  * Measured in milliseconds.
31
16
  */
32
17
  experienceDuration: number;
18
+ /**
19
+ * Optional reason for experience end, e.g., abort or failure reason.
20
+ */
21
+ experienceEndReason?: string;
22
+ /**
23
+ * The unique key identifying the experience being tracked.
24
+ */
25
+ experienceKey: string;
33
26
  /**
34
27
  * Optional method for experience start, e.g., how the experience was initiated.
35
28
  */
36
29
  experienceStartMethod?: string;
37
30
  /**
38
- * Optional reason for experience end, e.g., abort or failure reason.
31
+ * Timestamp when the experience started.
32
+ *
33
+ * Milliseconds since epoch.
39
34
  */
40
- experienceEndReason?: string;
35
+ experienceStartTime: number;
41
36
  /**
42
- * Optional action that triggered the experience, if applicable.
37
+ * The state the experience transitioned to.
43
38
  */
44
- experienceAction?: string;
39
+ experienceStatus: ExperienceState;
40
+ /**
41
+ * Whether this is the first transition to this status for this experience
42
+ * in the current editor session.
43
+ */
44
+ experienceStatusFirstSeen: boolean;
45
45
  };
46
46
  /**
47
47
  * Event fired on every successful experience state transition.
48
48
  * Used for data analysis in Databricks.
49
49
  */
50
- type ExperienceMeasuredAEP = OperationalAEP<ACTION.EXPERIENCE_MEASURED, ACTION_SUBJECT.EDITOR, undefined, ExperienceEventAttributes>;
50
+ type ExperienceMeasuredAEP = OperationalAEP<ACTION.EXPERIENCE_MEASURED, ACTION_SUBJECT.EDITOR, string, ExperienceEventAttributes>;
51
51
  /**
52
52
  * Event fired on sampled experience state transitions (e.g., 1 in 1000).
53
53
  * Can be forwarded to Signal FX, Statsig, etc. for use in SLOs and defining experiment metrics.
54
54
  */
55
- type ExperienceSampledAEP = OperationalAEP<ACTION.EXPERIENCE_SAMPLED, ACTION_SUBJECT.EDITOR, undefined, ExperienceEventAttributes>;
55
+ type ExperienceSampledAEP = OperationalAEP<ACTION.EXPERIENCE_SAMPLED, ACTION_SUBJECT.EDITOR, string, ExperienceEventAttributes>;
56
56
  export type ExperienceEventPayload = ExperienceMeasuredAEP | ExperienceSampledAEP;
57
57
  export {};
@@ -2,6 +2,18 @@ import type { DispatchAnalyticsEvent } from '../analytics';
2
2
  import type { ExperienceCheck } from './ExperienceCheck';
3
3
  import type { CustomExperienceMetadata } from './types';
4
4
  type ExperienceOptions = {
5
+ /**
6
+ * An optional sub identifier to further classify the specific experience action taken
7
+ *
8
+ * e.g. 'bold' 'bullet' 'insert-table'
9
+ */
10
+ action?: string;
11
+ /**
12
+ * An optional sub identifier to further classify the specific experience action subject
13
+ *
14
+ * e.g. 'selection-toolbar' 'quick-insert'
15
+ */
16
+ actionSubjectId?: string;
5
17
  /**
6
18
  * Checks used to control experience transition to various states.
7
19
  * Once the experience is in progress, these checks can automatically trigger
@@ -13,6 +25,12 @@ type ExperienceOptions = {
13
25
  * Required for tracking experienceMeasured and experienceSampled events.
14
26
  */
15
27
  dispatchAnalyticsEvent: DispatchAnalyticsEvent;
28
+ /**
29
+ * Optional global metadata to attach to all analytics events for this experience.
30
+ *
31
+ * Can be overridden by metadata provided in individual start/abort/fail/success calls.
32
+ */
33
+ metadata?: CustomExperienceMetadata;
16
34
  /**
17
35
  * Sample rate for experienceSampled events.
18
36
  * Determines how frequently we should track events for the experience based on
@@ -25,30 +43,19 @@ type ExperienceOptions = {
25
43
  * instrumentation, then the sample rate can be tuned up to a safe threshold.
26
44
  */
27
45
  sampleRate?: number;
28
- /**
29
- * Optional global metadata to attach to all analytics events for this experience.
30
- *
31
- * Can be overridden by metadata provided in individual start/abort/fail/success calls.
32
- */
33
- metadata?: CustomExperienceMetadata;
34
- /**
35
- * An optional sub identifier to further classify the specific experience action taken
36
- *
37
- * e.g. 'bold' 'bullet' 'insert-table'
38
- */
39
- action?: string;
40
46
  };
41
47
  type ExperienceStartOptions = {
48
+ forceRestart?: boolean;
42
49
  metadata?: CustomExperienceMetadata;
43
50
  method?: string;
44
- forceRestart?: boolean;
45
51
  };
46
52
  type ExperienceEndOptions = {
47
- reason?: string;
48
53
  metadata?: CustomExperienceMetadata;
54
+ reason?: string;
49
55
  };
50
56
  export declare class Experience {
51
57
  private readonly id;
58
+ private readonly actionSubjectId;
52
59
  private readonly dispatchAnalyticsEvent;
53
60
  private readonly sampleRate;
54
61
  private readonly globalMetadata;
@@ -83,13 +90,14 @@ export declare class Experience {
83
90
  /**
84
91
  * Creates a new Experience instance for tracking user experiences.
85
92
  *
86
- * @param id - Unique identifier for the experience
93
+ * @param id - Unique identifier for the experience e.g. 'toolbar-open' 'menu-action'
87
94
  * @param options - Configuration options for the experience
88
95
  * @param options.checks - Experience checks to monitor for completion
89
96
  * @param options.dispatchAnalyticsEvent - Function to dispatch analytics events
90
97
  * @param options.sampleRate - Sample rate for experienceSampled events
91
98
  * @param options.metadata - Global metadata to attach to all events
92
- * @param options.action - Optional sub identifier for the specific experience action
99
+ * @param options.action - Optional sub identifier for the specific experience action e.g. 'bold' 'insert-table'
100
+ * @param options.actionSubjectId - Optional sub identifier for the experience action subject e.g. 'selection-toolbar' 'quick-insert'
93
101
  */
94
102
  constructor(id: string, options: ExperienceOptions);
95
103
  private startCheck;
@@ -0,0 +1,8 @@
1
+ import type { Breadcrumb } from '@sentry/types';
2
+ export declare const SERIALIZABLE_ATTRIBUTES: string[];
3
+ /**
4
+ * Sanitizes messages within UI category breadcrumbs to ensure user-generated content is
5
+ * appropriately cleaned before being logged by Sentry. This helps in maintaining
6
+ * privacy and security by preventing sensitive data exposure.
7
+ */
8
+ export declare const normaliseSentryBreadcrumbs: (breadcrumb: Breadcrumb) => Breadcrumb;
@@ -6,52 +6,52 @@ import type { OperationalAEP } from './utils';
6
6
  */
7
7
  export type ExperienceEventAttributes = CustomExperienceMetadata & {
8
8
  /**
9
- * The unique key identifying the experience being tracked.
10
- */
11
- experienceKey: string;
12
- /**
13
- * The state the experience transitioned to.
14
- */
15
- experienceStatus: ExperienceState;
16
- /**
17
- * Whether this is the first transition to this status for this experience
18
- * in the current editor session.
19
- */
20
- experienceStatusFirstSeen: boolean;
21
- /**
22
- * Timestamp when the experience started.
23
- *
24
- * Milliseconds since epoch.
9
+ * Optional action that triggered the experience, if applicable.
25
10
  */
26
- experienceStartTime: number;
11
+ experienceAction?: string;
27
12
  /**
28
13
  * Duration from experience start to current status transition.
29
14
  *
30
15
  * Measured in milliseconds.
31
16
  */
32
17
  experienceDuration: number;
18
+ /**
19
+ * Optional reason for experience end, e.g., abort or failure reason.
20
+ */
21
+ experienceEndReason?: string;
22
+ /**
23
+ * The unique key identifying the experience being tracked.
24
+ */
25
+ experienceKey: string;
33
26
  /**
34
27
  * Optional method for experience start, e.g., how the experience was initiated.
35
28
  */
36
29
  experienceStartMethod?: string;
37
30
  /**
38
- * Optional reason for experience end, e.g., abort or failure reason.
31
+ * Timestamp when the experience started.
32
+ *
33
+ * Milliseconds since epoch.
39
34
  */
40
- experienceEndReason?: string;
35
+ experienceStartTime: number;
41
36
  /**
42
- * Optional action that triggered the experience, if applicable.
37
+ * The state the experience transitioned to.
43
38
  */
44
- experienceAction?: string;
39
+ experienceStatus: ExperienceState;
40
+ /**
41
+ * Whether this is the first transition to this status for this experience
42
+ * in the current editor session.
43
+ */
44
+ experienceStatusFirstSeen: boolean;
45
45
  };
46
46
  /**
47
47
  * Event fired on every successful experience state transition.
48
48
  * Used for data analysis in Databricks.
49
49
  */
50
- type ExperienceMeasuredAEP = OperationalAEP<ACTION.EXPERIENCE_MEASURED, ACTION_SUBJECT.EDITOR, undefined, ExperienceEventAttributes>;
50
+ type ExperienceMeasuredAEP = OperationalAEP<ACTION.EXPERIENCE_MEASURED, ACTION_SUBJECT.EDITOR, string, ExperienceEventAttributes>;
51
51
  /**
52
52
  * Event fired on sampled experience state transitions (e.g., 1 in 1000).
53
53
  * Can be forwarded to Signal FX, Statsig, etc. for use in SLOs and defining experiment metrics.
54
54
  */
55
- type ExperienceSampledAEP = OperationalAEP<ACTION.EXPERIENCE_SAMPLED, ACTION_SUBJECT.EDITOR, undefined, ExperienceEventAttributes>;
55
+ type ExperienceSampledAEP = OperationalAEP<ACTION.EXPERIENCE_SAMPLED, ACTION_SUBJECT.EDITOR, string, ExperienceEventAttributes>;
56
56
  export type ExperienceEventPayload = ExperienceMeasuredAEP | ExperienceSampledAEP;
57
57
  export {};
@@ -2,6 +2,18 @@ import type { DispatchAnalyticsEvent } from '../analytics';
2
2
  import type { ExperienceCheck } from './ExperienceCheck';
3
3
  import type { CustomExperienceMetadata } from './types';
4
4
  type ExperienceOptions = {
5
+ /**
6
+ * An optional sub identifier to further classify the specific experience action taken
7
+ *
8
+ * e.g. 'bold' 'bullet' 'insert-table'
9
+ */
10
+ action?: string;
11
+ /**
12
+ * An optional sub identifier to further classify the specific experience action subject
13
+ *
14
+ * e.g. 'selection-toolbar' 'quick-insert'
15
+ */
16
+ actionSubjectId?: string;
5
17
  /**
6
18
  * Checks used to control experience transition to various states.
7
19
  * Once the experience is in progress, these checks can automatically trigger
@@ -13,6 +25,12 @@ type ExperienceOptions = {
13
25
  * Required for tracking experienceMeasured and experienceSampled events.
14
26
  */
15
27
  dispatchAnalyticsEvent: DispatchAnalyticsEvent;
28
+ /**
29
+ * Optional global metadata to attach to all analytics events for this experience.
30
+ *
31
+ * Can be overridden by metadata provided in individual start/abort/fail/success calls.
32
+ */
33
+ metadata?: CustomExperienceMetadata;
16
34
  /**
17
35
  * Sample rate for experienceSampled events.
18
36
  * Determines how frequently we should track events for the experience based on
@@ -25,30 +43,19 @@ type ExperienceOptions = {
25
43
  * instrumentation, then the sample rate can be tuned up to a safe threshold.
26
44
  */
27
45
  sampleRate?: number;
28
- /**
29
- * Optional global metadata to attach to all analytics events for this experience.
30
- *
31
- * Can be overridden by metadata provided in individual start/abort/fail/success calls.
32
- */
33
- metadata?: CustomExperienceMetadata;
34
- /**
35
- * An optional sub identifier to further classify the specific experience action taken
36
- *
37
- * e.g. 'bold' 'bullet' 'insert-table'
38
- */
39
- action?: string;
40
46
  };
41
47
  type ExperienceStartOptions = {
48
+ forceRestart?: boolean;
42
49
  metadata?: CustomExperienceMetadata;
43
50
  method?: string;
44
- forceRestart?: boolean;
45
51
  };
46
52
  type ExperienceEndOptions = {
47
- reason?: string;
48
53
  metadata?: CustomExperienceMetadata;
54
+ reason?: string;
49
55
  };
50
56
  export declare class Experience {
51
57
  private readonly id;
58
+ private readonly actionSubjectId;
52
59
  private readonly dispatchAnalyticsEvent;
53
60
  private readonly sampleRate;
54
61
  private readonly globalMetadata;
@@ -83,13 +90,14 @@ export declare class Experience {
83
90
  /**
84
91
  * Creates a new Experience instance for tracking user experiences.
85
92
  *
86
- * @param id - Unique identifier for the experience
93
+ * @param id - Unique identifier for the experience e.g. 'toolbar-open' 'menu-action'
87
94
  * @param options - Configuration options for the experience
88
95
  * @param options.checks - Experience checks to monitor for completion
89
96
  * @param options.dispatchAnalyticsEvent - Function to dispatch analytics events
90
97
  * @param options.sampleRate - Sample rate for experienceSampled events
91
98
  * @param options.metadata - Global metadata to attach to all events
92
- * @param options.action - Optional sub identifier for the specific experience action
99
+ * @param options.action - Optional sub identifier for the specific experience action e.g. 'bold' 'insert-table'
100
+ * @param options.actionSubjectId - Optional sub identifier for the experience action subject e.g. 'selection-toolbar' 'quick-insert'
93
101
  */
94
102
  constructor(id: string, options: ExperienceOptions);
95
103
  private startCheck;
@@ -0,0 +1,8 @@
1
+ import type { Breadcrumb } from '@sentry/types';
2
+ export declare const SERIALIZABLE_ATTRIBUTES: string[];
3
+ /**
4
+ * Sanitizes messages within UI category breadcrumbs to ensure user-generated content is
5
+ * appropriately cleaned before being logged by Sentry. This helps in maintaining
6
+ * privacy and security by preventing sensitive data exposure.
7
+ */
8
+ export declare const normaliseSentryBreadcrumbs: (breadcrumb: Breadcrumb) => Breadcrumb;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-common",
3
- "version": "110.34.3",
3
+ "version": "110.34.5",
4
4
  "description": "A package that contains common classes and components for editor and renderer",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -263,6 +263,9 @@
263
263
  },
264
264
  "platform_editor_transform_invalid_media_width": {
265
265
  "type": "boolean"
266
+ },
267
+ "platform_editor_sentry_breadcrumbs": {
268
+ "type": "boolean"
266
269
  }
267
270
  }
268
271
  }