@atlaskit/renderer 93.0.4 → 95.0.1

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 (42) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/cjs/react/marks/link.js +3 -1
  3. package/dist/cjs/react/nodes/codeBlock.js +5 -0
  4. package/dist/cjs/react/nodes/codeBlockCopyButton.js +3 -1
  5. package/dist/cjs/react/nodes/heading-anchor.js +4 -2
  6. package/dist/cjs/react/nodes/table/sticky.js +19 -17
  7. package/dist/cjs/render-document.js +141 -54
  8. package/dist/cjs/ui/Renderer/index.js +19 -23
  9. package/dist/cjs/ui/Renderer/style.js +30 -28
  10. package/dist/cjs/ui/Renderer/truncated-wrapper.js +6 -3
  11. package/dist/cjs/ui/SortingIcon.js +6 -2
  12. package/dist/cjs/ui/annotations/draft/component.js +1 -1
  13. package/dist/cjs/ui/annotations/element/mark.js +1 -1
  14. package/dist/cjs/version.json +1 -1
  15. package/dist/es2019/react/marks/link.js +8 -3
  16. package/dist/es2019/react/nodes/codeBlock.js +5 -0
  17. package/dist/es2019/react/nodes/codeBlockCopyButton.js +7 -6
  18. package/dist/es2019/react/nodes/heading-anchor.js +3 -2
  19. package/dist/es2019/react/nodes/table/sticky.js +28 -24
  20. package/dist/es2019/render-document.js +116 -55
  21. package/dist/es2019/ui/Renderer/index.js +3 -8
  22. package/dist/es2019/ui/Renderer/style.js +34 -29
  23. package/dist/es2019/ui/Renderer/truncated-wrapper.js +5 -3
  24. package/dist/es2019/ui/SortingIcon.js +7 -5
  25. package/dist/es2019/ui/annotations/draft/component.js +1 -1
  26. package/dist/es2019/ui/annotations/element/mark.js +1 -1
  27. package/dist/es2019/version.json +1 -1
  28. package/dist/esm/react/marks/link.js +3 -2
  29. package/dist/esm/react/nodes/codeBlock.js +5 -0
  30. package/dist/esm/react/nodes/codeBlockCopyButton.js +2 -1
  31. package/dist/esm/react/nodes/heading-anchor.js +3 -2
  32. package/dist/esm/react/nodes/table/sticky.js +18 -18
  33. package/dist/esm/render-document.js +136 -54
  34. package/dist/esm/ui/Renderer/index.js +19 -23
  35. package/dist/esm/ui/Renderer/style.js +29 -28
  36. package/dist/esm/ui/Renderer/truncated-wrapper.js +5 -3
  37. package/dist/esm/ui/SortingIcon.js +5 -3
  38. package/dist/esm/ui/annotations/draft/component.js +1 -1
  39. package/dist/esm/ui/annotations/element/mark.js +1 -1
  40. package/dist/esm/version.json +1 -1
  41. package/dist/types/render-document.d.ts +1 -1
  42. package/package.json +22 -16
@@ -23,6 +23,8 @@ var _react = require("@emotion/react");
23
23
 
24
24
  var _react2 = require("react");
25
25
 
26
+ var _tokens = require("@atlaskit/tokens");
27
+
26
28
  var _templateObject;
27
29
 
28
30
  function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2.default)(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2.default)(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2.default)(this, result); }; }
@@ -30,7 +32,7 @@ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflec
30
32
  function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
31
33
 
32
34
  var fadeOutStyles = function fadeOutStyles(maxHeight, top, backgroundColor) {
33
- return (0, _react.css)(_templateObject || (_templateObject = (0, _taggedTemplateLiteral2.default)(["\n position: relative;\n overflow-y: hidden;\n max-height: ", "px;\n &::after {\n content: '';\n position: absolute;\n top: ", "px;\n bottom: 0;\n left: 0;\n right: 0;\n background-image: linear-gradient(\n rgba(255, 255, 255, 0),\n ", "\n );\n }\n"])), maxHeight, top, backgroundColor);
35
+ return (0, _react.css)(_templateObject || (_templateObject = (0, _taggedTemplateLiteral2.default)(["\n position: relative;\n overflow-y: hidden;\n max-height: ", "px;\n &::after {\n content: '';\n position: absolute;\n top: ", "px;\n bottom: 0;\n left: 0;\n right: 0;\n background-image: linear-gradient(\n ", ",\n ", "\n );\n }\n"])), maxHeight, top, (0, _tokens.token)('color.background.neutral.subtle', 'rgba(255, 255, 255, 0)'), backgroundColor);
34
36
  };
35
37
 
36
38
  var FadeOut = function FadeOut(props) {
@@ -53,7 +55,8 @@ var TruncatedWrapper = /*#__PURE__*/function (_Component) {
53
55
  function TruncatedWrapper(props) {
54
56
  (0, _classCallCheck2.default)(this, TruncatedWrapper);
55
57
  return _super.call(this, props);
56
- }
58
+ } // TODO: Quality ticket as elevation.surface will be issue when sits top of modal. https://product-fabric.atlassian.net/browse/DSP-4123
59
+
57
60
 
58
61
  (0, _createClass2.default)(TruncatedWrapper, [{
59
62
  key: "render",
@@ -64,7 +67,7 @@ var TruncatedWrapper = /*#__PURE__*/function (_Component) {
64
67
  _this$props$fadeHeigh = _this$props.fadeHeight,
65
68
  fadeHeight = _this$props$fadeHeigh === void 0 ? 24 : _this$props$fadeHeigh,
66
69
  _this$props$backgroun = _this$props.backgroundColor,
67
- backgroundColor = _this$props$backgroun === void 0 ? 'white' : _this$props$backgroun,
70
+ backgroundColor = _this$props$backgroun === void 0 ? (0, _tokens.token)('elevation.surface', 'white') : _this$props$backgroun,
68
71
  children = _this$props.children;
69
72
  return (0, _react.jsx)(FadeOut, {
70
73
  height: height,
@@ -23,15 +23,19 @@ var _messages = require("../messages");
23
23
 
24
24
  var _reactIntlNext = require("react-intl-next");
25
25
 
26
+ var _tokens = require("@atlaskit/tokens");
27
+
26
28
  var _templateObject, _templateObject2;
27
29
 
28
30
  // We use data url here because of this issue:
29
31
  // https://product-fabric.atlassian.net/browse/ED-8001
30
32
  // Remove this workaround if Firefox has fixed: https://bugzilla.mozilla.org/show_bug.cgi?id=1664350
33
+ // TODO: Quality ticket: https://product-fabric.atlassian.net/browse/DSP-4136
31
34
  var TableSortIconDataUrl = "data:image/svg+xml;utf8,".concat(encodeURIComponent("<svg xmlns=\"http://www.w3.org/2000/svg\"><g fill=\"none\" fill-rule=\"evenodd\"><path d=\"M-8-6h24v24H-8z\"></path><path d=\"M3 8.509V1c0-.552.449-1 1-1 .552 0 1 .448 1 1V8.51l1.217-1.206a1.05 1.05 0 011.477 0 1.03 1.03 0 01.004 1.463l-.003.002-2.956 2.93a1.053 1.053 0 01-1.478 0L.305 8.767a1.03 1.03 0 01.001-1.464 1.05 1.05 0 011.477 0L3 8.508z\" fill=\"#42526E\"></path></g></svg>"));
32
35
  exports.TableSortIconDataUrl = TableSortIconDataUrl;
33
36
  var TABLE_SORTING_ICON_CLASS = 'table-sorting-icon';
34
- var StatusClassNames;
37
+ var StatusClassNames; // TODO: get design to check border
38
+
35
39
  exports.StatusClassNames = StatusClassNames;
36
40
 
37
41
  (function (StatusClassNames) {
@@ -41,7 +45,7 @@ exports.StatusClassNames = StatusClassNames;
41
45
  StatusClassNames["SORTING_NOT_ALLOWED"] = "sorting-icon-svg__not-allowed";
42
46
  })(StatusClassNames || (exports.StatusClassNames = StatusClassNames = {}));
43
47
 
44
- var wrapperStyles = (0, _react.css)(_templateObject || (_templateObject = (0, _taggedTemplateLiteral2.default)(["\n position: absolute;\n display: flex;\n height: 28px;\n width: 28px;\n margin: 6px;\n right: 0;\n top: 0;\n border: 2px solid #fff;\n border-radius: ", "px;\n background-color: ", ";\n justify-content: center;\n align-items: center;\n\n &:hover {\n background-color: ", ";\n }\n\n &.", " {\n cursor: not-allowed;\n }\n"])), (0, _constants.gridSize)() / 2, _colors.N20, _colors.N30, StatusClassNames.SORTING_NOT_ALLOWED);
48
+ var wrapperStyles = (0, _react.css)(_templateObject || (_templateObject = (0, _taggedTemplateLiteral2.default)(["\n position: absolute;\n display: flex;\n height: 28px;\n width: 28px;\n margin: 6px;\n right: 0;\n top: 0;\n border: 2px solid ", ";\n border-radius: ", "px;\n background-color: ", ";\n justify-content: center;\n align-items: center;\n\n &:hover {\n background-color: ", ";\n }\n\n &.", " {\n cursor: not-allowed;\n }\n"])), (0, _tokens.token)('color.border.inverse', '#fff'), (0, _constants.gridSize)() / 2, (0, _tokens.token)('color.background.neutral.subtle', _colors.N20), (0, _tokens.token)('color.background.neutral.subtle.hovered', _colors.N30), StatusClassNames.SORTING_NOT_ALLOWED);
45
49
  var tableSortingIconStyles = (0, _react.css)(_templateObject2 || (_templateObject2 = (0, _taggedTemplateLiteral2.default)(["\n width: 8px;\n height: 12px;\n transition: transform 0.3s cubic-bezier(0.15, 1, 0.3, 1);\n transform-origin: 50% 50%;\n background-image: url(", ");\n\n &.", " {\n transform: rotate(-180deg);\n }\n\n &.", "-inactive {\n opacity: 0.7;\n }\n"])), TableSortIconDataUrl, StatusClassNames.DESC, TABLE_SORTING_ICON_CLASS);
46
50
 
47
51
  var getClassName = function getClassName(status) {
@@ -36,7 +36,7 @@ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "functio
36
36
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
37
37
 
38
38
  var markStyles = function markStyles(props) {
39
- return (0, _react2.css)(_templateObject || (_templateObject = (0, _taggedTemplateLiteral2.default)(["\n color: inherit;\n background-color: unset;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n\n ", ";\n"])), (0, _styles.AnnotationSharedCSSByState)(props).focus);
39
+ return (0, _react2.css)(_templateObject || (_templateObject = (0, _taggedTemplateLiteral2.default)(["\n color: inherit;\n background-color: unset;\n -webkit-tap-highlight-color: transparent;\n\n ", ";\n"])), (0, _styles.AnnotationSharedCSSByState)(props).focus);
40
40
  };
41
41
 
42
42
  var AnnotationDraft = function AnnotationDraft(_ref) {
@@ -36,7 +36,7 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
36
36
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
37
37
 
38
38
  var markStyles = function markStyles(props) {
39
- return (0, _react2.css)(_templateObject || (_templateObject = (0, _taggedTemplateLiteral2.default)(["\n color: inherit;\n background-color: unset;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n\n &[data-mark-annotation-state='", "'] {\n ", ";\n\n &:focus,\n &[data-has-focus='true'] {\n ", ";\n }\n }\n"])), _adfSchema.AnnotationMarkStates.ACTIVE, (0, _styles.AnnotationSharedCSSByState)({
39
+ return (0, _react2.css)(_templateObject || (_templateObject = (0, _taggedTemplateLiteral2.default)(["\n color: inherit;\n background-color: unset;\n -webkit-tap-highlight-color: transparent;\n\n &[data-mark-annotation-state='", "'] {\n ", ";\n\n &:focus,\n &[data-has-focus='true'] {\n ", ";\n }\n }\n"])), _adfSchema.AnnotationMarkStates.ACTIVE, (0, _styles.AnnotationSharedCSSByState)({
40
40
  theme: props
41
41
  }).blur, (0, _styles.AnnotationSharedCSSByState)({
42
42
  theme: props
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/renderer",
3
- "version": "93.0.4",
3
+ "version": "95.0.1",
4
4
  "sideEffects": false
5
5
  }
@@ -3,17 +3,22 @@ import _extends from "@babel/runtime/helpers/extends";
3
3
  /** @jsx jsx */
4
4
  import React, { Fragment } from 'react';
5
5
  import { css, jsx } from '@emotion/react';
6
- import { B400, B300 } from '@atlaskit/theme/colors';
6
+ import { B400, B300, B500 } from '@atlaskit/theme/colors';
7
7
  import { getEventHandler } from '../../utils';
8
8
  import { PLATFORM, MODE } from '../../analytics/events';
9
9
  import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '../../analytics/enums';
10
+ import { token } from '@atlaskit/tokens';
10
11
  const anchorStyles = css`
11
- color: ${B400};
12
+ color: ${token('color.link', B400)};
12
13
 
13
14
  &:hover {
14
- color: ${B300};
15
+ color: ${token('color.link', B300)};
15
16
  text-decoration: underline;
16
17
  }
18
+
19
+ &:active {
20
+ color: ${token('color.link.pressed', B500)};
21
+ }
17
22
  `;
18
23
  export default function Link(props) {
19
24
  const {
@@ -10,6 +10,9 @@ import { codeBidiWarningMessages } from '@atlaskit/editor-common/messages';
10
10
  import { useFeatureFlags } from '../../use-feature-flags';
11
11
  import CopyButton from './codeBlockCopyButton';
12
12
 
13
+ // TODO: Quality ticket https://product-fabric.atlassian.net/browse/DSP-4118
14
+
15
+ /* eslint-disable @atlaskit/design-system/ensure-design-token-usage */
13
16
  const codeBlockStyle = props => css`
14
17
  tab-size: 4;
15
18
  [data-ds--code--code-block] {
@@ -26,6 +29,8 @@ const codeBlockStyle = props => css`
26
29
  background-position: 100% 0, 100% 0, 0 0;
27
30
  }
28
31
  `;
32
+ /* eslint-enable */
33
+
29
34
 
30
35
  function CodeBlock(props) {
31
36
  const {
@@ -8,6 +8,7 @@ import CopyIcon from '@atlaskit/icon/glyph/copy';
8
8
  import { N20, N30, N700 } from '@atlaskit/theme/colors';
9
9
  import { CopyTextConsumer } from './copy-text-provider';
10
10
  import { codeBlockCopyButtonMessages } from '../../messages';
11
+ import { token } from '@atlaskit/tokens';
11
12
  const copyButtonWrapperStyles = css`
12
13
  display: flex;
13
14
  position: sticky;
@@ -25,19 +26,19 @@ const copyButtonWrapperStyles = css`
25
26
  padding: 2px;
26
27
  opacity: 0;
27
28
  transition: opacity 0.2s ease 0s;
28
- border: 2px solid #fff;
29
+ border: 2px solid ${token('color.border.inverse', '#fff')};
29
30
  border-radius: 4px;
30
- background-color: ${N20};
31
- color: rgb(66, 82, 110);
31
+ background-color: ${token('color.background.neutral.subtle', N20)};
32
+ color: ${token('color.icon', 'rgb(66, 82, 110)')};
32
33
  }
33
34
 
34
35
  button:hover {
35
- background-color: ${N30};
36
+ background-color: ${token('color.background.neutral.hovered', N30)};
36
37
  }
37
38
 
38
39
  button.clicked {
39
- background-color: ${N700};
40
- color: #fff !important;
40
+ background-color: ${token('color.background.neutral.bold.pressed', N700)};
41
+ color: ${token('color.icon.inverse', '#fff')} !important;
41
42
  }
42
43
  `;
43
44
 
@@ -9,6 +9,7 @@ import LinkIcon from '@atlaskit/icon/glyph/link';
9
9
  import Tooltip from '@atlaskit/tooltip';
10
10
  import { injectIntl } from 'react-intl-next';
11
11
  import { headingAnchorLinkMessages } from '../../messages';
12
+ import { token } from '@atlaskit/tokens';
12
13
  export const HeadingAnchorWrapperClassName = 'heading-anchor-wrapper';
13
14
  const CopyAnchorWrapperWithRef = /*#__PURE__*/React.forwardRef((props, ref) => {
14
15
  const {
@@ -25,7 +26,7 @@ const copyAnchorButtonStyles = css`
25
26
  outline: none;
26
27
  background-color: transparent;
27
28
  border: none;
28
- color: ${N500};
29
+ color: ${token('color.icon', N500)};
29
30
  cursor: pointer;
30
31
  right: 0;
31
32
  `;
@@ -82,7 +83,7 @@ class HeadingAnchor extends React.PureComponent {
82
83
  }, jsx(LinkIcon, {
83
84
  label: this.getCopyAriaLabel(),
84
85
  size: this.props.level > 3 ? 'small' : 'medium',
85
- primaryColor: this.state.isClicked ? B400 : N200
86
+ primaryColor: this.state.isClicked ? token('color.icon.selected', B400) : token('color.icon.subtle', N200)
86
87
  }));
87
88
  });
88
89
  }
@@ -1,35 +1,34 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+
1
3
  /** @jsx jsx */
2
4
  import React from 'react';
3
5
  import { css, jsx } from '@emotion/react';
4
6
  import { TableSharedCssClassName } from '@atlaskit/editor-common/styles';
5
7
  import { akEditorStickyHeaderZIndex } from '@atlaskit/editor-shared-styles';
6
- import * as colors from '@atlaskit/theme/colors';
8
+ import * as colors from '@atlaskit/theme/colors'; // eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage
9
+
7
10
  const {
8
11
  N40A
9
12
  } = colors;
13
+ import { token } from '@atlaskit/tokens';
10
14
  import { findHorizontalOverflowScrollParent } from '../../../utils';
11
15
  import { Table } from './table';
12
16
  import { recursivelyInjectProps } from '../../utils/inject-props';
13
17
  export const tableStickyPadding = 8;
14
- const fixedTableDivModeToPosition = {
15
- stick: 'fixed',
16
- 'pin-bottom': 'absolute'
17
- };
18
-
19
- const getModeSpecificStyles = mode => {
20
- if (mode === 'none') {
21
- return css`
22
- display: none;
23
- `;
24
- } else {
25
- return css`
26
- position: ${fixedTableDivModeToPosition[mode]};
27
- `;
28
- }
29
- };
18
+ const modeSpecficStyles = {
19
+ none: css`
20
+ display: none;
21
+ `,
22
+ stick: css`
23
+ position: fixed;
24
+ `,
25
+ 'pin-bottom': css`
26
+ position: absolute;
27
+ `
28
+ }; // TODO: Quality ticket: https://product-fabric.atlassian.net/browse/DSP-4123
30
29
 
31
30
  const fixedTableDivStaticStyles = (top, width) => css`
32
- top: ${top}px;
31
+ ${typeof top === 'number' && `top: ${top}px;`}
33
32
  width: ${width}px;
34
33
  z-index: ${akEditorStickyHeaderZIndex};
35
34
  &
@@ -41,9 +40,10 @@ const fixedTableDivStaticStyles = (top, width) => css`
41
40
  margin-bottom: 0;
42
41
  }
43
42
 
44
- border-top: ${tableStickyPadding}px solid white;
45
- background: white;
46
- box-shadow: 0 6px 4px -4px ${N40A};
43
+ border-top: ${tableStickyPadding}px solid
44
+ ${token('elevation.surface', 'white')};
45
+ background: ${token('elevation.surface.overlay', 'white')};
46
+ box-shadow: ${token('elevation.shadow.overflow', `0 6px 4px -4px ${N40A}`)};
47
47
 
48
48
  div[data-expanded='false'] & {
49
49
  display: none;
@@ -64,10 +64,14 @@ export const FixedTableDiv = props => {
64
64
  wrapperWidth,
65
65
  mode
66
66
  } = props;
67
- const fixedTableCss = [fixedTableDivStaticStyles(top, wrapperWidth), getModeSpecificStyles(mode)];
68
- return jsx("div", {
67
+ const fixedTableCss = [fixedTableDivStaticStyles(top, wrapperWidth), modeSpecficStyles === null || modeSpecficStyles === void 0 ? void 0 : modeSpecficStyles[mode]];
68
+ const attrs = {
69
+ mode
70
+ };
71
+ return jsx("div", _extends({}, attrs, {
72
+ "data-testid": "sticky-table-fixed",
69
73
  css: fixedTableCss
70
- }, props.children);
74
+ }), props.children);
71
75
  };
72
76
  export const StickyTable = ({
73
77
  top,
@@ -1,3 +1,4 @@
1
+ import memoizeOne from 'memoize-one';
1
2
  import { defaultSchema } from '@atlaskit/adf-schema/schema-default';
2
3
  import { getValidDocument } from '@atlaskit/editor-common/validator';
3
4
  import { validateADFEntity, findAndTrackUnsupportedContentNodes } from '@atlaskit/editor-common/utils';
@@ -18,6 +19,116 @@ const withStopwatch = cb => {
18
19
  };
19
20
  };
20
21
 
22
+ const _validation = (doc, schema, adfStage, useSpecBasedValidator, dispatchAnalyticsEvent) => {
23
+ let result;
24
+
25
+ if (useSpecBasedValidator) {
26
+ // link mark on mediaSingle is deprecated, need to move link mark to child media node
27
+ // https://product-fabric.atlassian.net/browse/ED-14043
28
+ const {
29
+ transformedAdf,
30
+ isTransformed
31
+ } = transformMediaLinkMarks(doc);
32
+
33
+ if (isTransformed && dispatchAnalyticsEvent) {
34
+ dispatchAnalyticsEvent({
35
+ action: ACTION.MEDIA_LINK_TRANSFORMED,
36
+ actionSubject: ACTION_SUBJECT.RENDERER,
37
+ eventType: EVENT_TYPE.OPERATIONAL
38
+ });
39
+ }
40
+
41
+ result = validateADFEntity(schema, transformedAdf || doc, dispatchAnalyticsEvent);
42
+ } else {
43
+ result = getValidDocument(doc, schema, adfStage);
44
+ }
45
+
46
+ if (!result) {
47
+ return result;
48
+ } // ProseMirror always require a child under doc
49
+
50
+
51
+ if (result.type === 'doc' && useSpecBasedValidator) {
52
+ if (Array.isArray(result.content) && result.content.length === 0) {
53
+ result.content.push({
54
+ type: 'paragraph',
55
+ content: []
56
+ });
57
+ } // Just making sure doc is always valid
58
+
59
+
60
+ if (!result.version) {
61
+ result.version = 1;
62
+ }
63
+ }
64
+
65
+ return result;
66
+ };
67
+
68
+ const memoValidation = memoizeOne(_validation, (newArgs, lastArgs) => {
69
+ const [newDoc, newSchema, newADFStage, newUseSpecValidator] = newArgs;
70
+ const [oldDoc, oldSchema, oldADFStage, oldUseSpecValidator] = lastArgs; // we're ignoring changes to dispatchAnalyticsEvent in this check
71
+
72
+ const result = areDocsEqual(newDoc, oldDoc) && newSchema === oldSchema && newADFStage === oldADFStage && newUseSpecValidator === oldUseSpecValidator;
73
+ return result;
74
+ });
75
+
76
+ const areDocsEqual = (docA, docB) => {
77
+ if (docA === docB) {
78
+ return true;
79
+ }
80
+
81
+ if (typeof docA === 'string' && typeof docB === 'string') {
82
+ return docA === docB;
83
+ } // PMNode
84
+
85
+
86
+ if (docA.type && docA.toJSON && docB.type && docB.toJSON) {
87
+ return JSON.stringify(docA.toJSON()) === JSON.stringify(docB.toJSON());
88
+ } // Object
89
+
90
+
91
+ return JSON.stringify(docA) === JSON.stringify(docB);
92
+ };
93
+
94
+ const _serializeFragment = (serializer, doc) => {
95
+ return serializer.serializeFragment(doc.content);
96
+ };
97
+
98
+ const memoSerializeFragment = memoizeOne(_serializeFragment, (newArgs, lastArgs) => {
99
+ const [newSerializer, newDoc] = newArgs;
100
+ const [oldSerializer, oldDoc] = lastArgs;
101
+ return newSerializer === oldSerializer && areDocsEqual(newDoc, oldDoc);
102
+ });
103
+
104
+ const _createNodeAndCheck = (schema, doc, dispatchAnalyticsEvent) => {
105
+ const pmNode = schema.nodeFromJSON(doc);
106
+
107
+ try {
108
+ pmNode.check();
109
+ } catch (err) {
110
+ if (dispatchAnalyticsEvent) {
111
+ dispatchAnalyticsEvent({
112
+ action: ACTION.INVALID_PROSEMIRROR_DOCUMENT,
113
+ actionSubject: ACTION_SUBJECT.RENDERER,
114
+ attributes: {
115
+ platform: PLATFORM.WEB,
116
+ error: err === null || err === void 0 ? void 0 : err.toString()
117
+ },
118
+ eventType: EVENT_TYPE.OPERATIONAL
119
+ });
120
+ }
121
+ }
122
+
123
+ return pmNode;
124
+ };
125
+
126
+ const memoCreateNodeAndCheck = memoizeOne(_createNodeAndCheck, (newArgs, lastArgs) => {
127
+ // ignore dispatchAnalyticsEvent
128
+ const [newSchema, newDoc] = newArgs;
129
+ const [oldSchema, oldDoc] = lastArgs;
130
+ return newSchema === oldSchema && areDocsEqual(newDoc, oldDoc);
131
+ });
21
132
  export const renderDocument = (doc, serializer, schema = defaultSchema, adfStage = 'final', useSpecBasedValidator = false, rendererId = 'noid', dispatchAnalyticsEvent, unsupportedContentLevelsTracking, appearance) => {
22
133
  const stat = {
23
134
  sanitizeTime: 0
@@ -26,26 +137,7 @@ export const renderDocument = (doc, serializer, schema = defaultSchema, adfStage
26
137
  output: validDoc,
27
138
  time: sanitizeTime
28
139
  } = withStopwatch(() => {
29
- if (useSpecBasedValidator) {
30
- // link mark on mediaSingle is deprecated, need to move link mark to child media node
31
- // https://product-fabric.atlassian.net/browse/ED-14043
32
- const {
33
- transformedAdf,
34
- isTransformed
35
- } = transformMediaLinkMarks(doc);
36
-
37
- if (isTransformed && dispatchAnalyticsEvent) {
38
- dispatchAnalyticsEvent({
39
- action: ACTION.MEDIA_LINK_TRANSFORMED,
40
- actionSubject: ACTION_SUBJECT.RENDERER,
41
- eventType: EVENT_TYPE.OPERATIONAL
42
- });
43
- }
44
-
45
- return validateADFEntity(schema, transformedAdf || doc, dispatchAnalyticsEvent);
46
- }
47
-
48
- return getValidDocument(doc, schema, adfStage);
140
+ return memoValidation(doc, schema, adfStage, useSpecBasedValidator, dispatchAnalyticsEvent);
49
141
  }); // save sanitize time to stats
50
142
 
51
143
  stat.sanitizeTime = sanitizeTime;
@@ -55,53 +147,22 @@ export const renderDocument = (doc, serializer, schema = defaultSchema, adfStage
55
147
  stat,
56
148
  result: null
57
149
  };
58
- } // ProseMirror always require a child under doc
59
-
60
-
61
- if (validDoc.type === 'doc' && useSpecBasedValidator) {
62
- if (Array.isArray(validDoc.content) && validDoc.content.length === 0) {
63
- validDoc.content.push({
64
- type: 'paragraph',
65
- content: []
66
- });
67
- } // Just making sure doc is always valid
68
-
69
-
70
- if (!validDoc.version) {
71
- validDoc.version = 1;
72
- }
73
150
  }
74
151
 
75
152
  const {
76
153
  output: node,
77
154
  time: buildTreeTime
78
155
  } = withStopwatch(() => {
79
- const pmNode = schema.nodeFromJSON(validDoc);
80
-
81
- try {
82
- pmNode.check();
83
- } catch (err) {
84
- if (dispatchAnalyticsEvent) {
85
- dispatchAnalyticsEvent({
86
- action: ACTION.INVALID_PROSEMIRROR_DOCUMENT,
87
- actionSubject: ACTION_SUBJECT.RENDERER,
88
- attributes: {
89
- platform: PLATFORM.WEB,
90
- error: err === null || err === void 0 ? void 0 : err.toString()
91
- },
92
- eventType: EVENT_TYPE.OPERATIONAL
93
- });
94
- }
95
- }
96
-
97
- return pmNode;
156
+ return memoCreateNodeAndCheck(schema, validDoc, dispatchAnalyticsEvent);
98
157
  }); // save build tree time to stats
99
158
 
100
159
  stat.buildTreeTime = buildTreeTime;
101
160
  const {
102
161
  output: result,
103
162
  time: serializeTime
104
- } = withStopwatch(() => serializer.serializeFragment(node.content)); // save serialize tree time to stats
163
+ } = withStopwatch(() => {
164
+ return memoSerializeFragment(serializer, node);
165
+ }); // save serialize tree time to stats
105
166
 
106
167
  stat.serializeTime = serializeTime;
107
168
 
@@ -61,18 +61,13 @@ export class Renderer extends PureComponent {
61
61
  }
62
62
  });
63
63
 
64
- _defineProperty(this, "getSchema", () => {
65
- const {
66
- schema,
67
- adfStage
68
- } = this.props;
69
-
64
+ _defineProperty(this, "getSchema", memoizeOne((schema, adfStage) => {
70
65
  if (schema) {
71
66
  return schema;
72
67
  }
73
68
 
74
69
  return getSchemaBasedOnStage(adfStage);
75
- });
70
+ }));
76
71
 
77
72
  _defineProperty(this, "onMouseDownEditView", () => {
78
73
  // When the user is deselecting text on the screen by clicking, if they are clicking outside
@@ -283,7 +278,7 @@ export class Renderer extends PureComponent {
283
278
  try {
284
279
  var _this$featureFlags, _this$featureFlags$fe, _this$featureFlags$fe2;
285
280
 
286
- const schema = this.getSchema();
281
+ const schema = this.getSchema(this.props.schema, this.props.adfStage);
287
282
  const {
288
283
  result,
289
284
  stat,