@atlaskit/renderer 144.0.3 → 144.1.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.
- package/CHANGELOG.md +19 -0
- package/dist/cjs/react/index.js +9 -11
- package/dist/cjs/react/nodes/inline.js +46 -3
- package/dist/cjs/react/nodes/paragraph.js +5 -2
- package/dist/cjs/react/nodes/text-wrapper.js +2 -1
- package/dist/cjs/react/utils/render-text-segments.js +13 -3
- package/dist/cjs/react/utils/render-text.js +23 -0
- package/dist/cjs/ui/Expand.js +1 -3
- package/dist/cjs/ui/Renderer/index.js +1 -1
- package/dist/cjs/ui/annotations/draft/component.js +15 -14
- package/dist/cjs/ui/utils/expand-body.js +0 -4
- package/dist/es2019/react/index.js +9 -11
- package/dist/es2019/react/nodes/inline.js +33 -3
- package/dist/es2019/react/nodes/paragraph.js +5 -2
- package/dist/es2019/react/nodes/text-wrapper.js +2 -1
- package/dist/es2019/react/utils/render-text-segments.js +9 -2
- package/dist/es2019/react/utils/render-text.js +18 -0
- package/dist/es2019/ui/Expand.js +1 -3
- package/dist/es2019/ui/Renderer/index.js +1 -1
- package/dist/es2019/ui/annotations/draft/component.js +13 -14
- package/dist/es2019/ui/utils/expand-body.js +0 -4
- package/dist/esm/react/index.js +9 -11
- package/dist/esm/react/nodes/inline.js +45 -3
- package/dist/esm/react/nodes/paragraph.js +5 -2
- package/dist/esm/react/nodes/text-wrapper.js +2 -1
- package/dist/esm/react/utils/render-text-segments.js +13 -3
- package/dist/esm/react/utils/render-text.js +18 -0
- package/dist/esm/ui/Expand.js +1 -3
- package/dist/esm/ui/Renderer/index.js +1 -1
- package/dist/esm/ui/annotations/draft/component.js +15 -14
- package/dist/esm/ui/utils/expand-body.js +0 -4
- package/dist/types/react/index.d.ts +1 -0
- package/dist/types/react/nodes/inline.d.ts +16 -0
- package/dist/types/react/nodes/paragraph.d.ts +1 -1
- package/dist/types/react/nodes/text-wrapper.d.ts +1 -0
- package/dist/types/react/types.d.ts +5 -0
- package/dist/types/react/utils/render-text-segments.d.ts +1 -1
- package/dist/types/react/utils/render-text.d.ts +12 -0
- package/dist/types/ui/annotations/draft/component.d.ts +4 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @atlaskit/renderer
|
|
2
2
|
|
|
3
|
+
## 144.1.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`68ede3b9de2a6`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/68ede3b9de2a6) -
|
|
8
|
+
Clean up experiment `platform_editor_defer_collapsed_expand_body`. A collapsed expand defers its
|
|
9
|
+
body and shows the body's text via `hidden="until-found"` for all readers now, and `nestedExpand`
|
|
10
|
+
always serializes through the expand props builder.
|
|
11
|
+
- Updated dependencies
|
|
12
|
+
|
|
13
|
+
## 144.1.0
|
|
14
|
+
|
|
15
|
+
### Minor Changes
|
|
16
|
+
|
|
17
|
+
- [`778fd05c90b9a`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/778fd05c90b9a) -
|
|
18
|
+
Reduce per-text-node and per-paragraph allocations in the React serializer (plain-text fast path,
|
|
19
|
+
non-allocating empty-paragraph check) behind the new `platform_renderer_text_paragraph_fast_path`
|
|
20
|
+
experiment. No visual or DOM change.
|
|
21
|
+
|
|
3
22
|
## 144.0.3
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
package/dist/cjs/react/index.js
CHANGED
|
@@ -16,7 +16,7 @@ var _utils = require("@atlaskit/editor-common/utils");
|
|
|
16
16
|
var _validator = require("@atlaskit/editor-common/validator");
|
|
17
17
|
var _model = require("@atlaskit/editor-prosemirror/model");
|
|
18
18
|
var _utils2 = require("@atlaskit/editor-prosemirror/utils");
|
|
19
|
-
var
|
|
19
|
+
var _expVal = require("@atlaskit/platform-feature-experiments/exp-val");
|
|
20
20
|
var _fg = require("@atlaskit/platform-feature-flags/fg");
|
|
21
21
|
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
|
|
22
22
|
var _expandBody = require("../ui/utils/expand-body");
|
|
@@ -30,8 +30,7 @@ var _contentGetter = require("./utils/content-getter");
|
|
|
30
30
|
var _getStandaloneBackgroundColorMarks = require("./utils/getStandaloneBackgroundColorMarks");
|
|
31
31
|
var _links = require("./utils/links");
|
|
32
32
|
var _markBlockAsInline = require("./utils/markBlockAsInline");
|
|
33
|
-
var
|
|
34
|
-
var _segmentText = require("./utils/segment-text");
|
|
33
|
+
var _renderText = require("./utils/render-text");
|
|
35
34
|
var _excluded = ["key"];
|
|
36
35
|
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; }
|
|
37
36
|
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; }
|
|
@@ -66,6 +65,7 @@ var ReactSerializer = exports.default = /*#__PURE__*/function () {
|
|
|
66
65
|
(0, _defineProperty2.default)(this, "allowPlaceholderText", true);
|
|
67
66
|
(0, _defineProperty2.default)(this, "allowCustomPanels", false);
|
|
68
67
|
(0, _defineProperty2.default)(this, "surroundTextNodesWithTextWrapper", false);
|
|
68
|
+
(0, _defineProperty2.default)(this, "textFastPath", false);
|
|
69
69
|
(0, _defineProperty2.default)(this, "allowAnnotations", false);
|
|
70
70
|
(0, _defineProperty2.default)(this, "standaloneBackgroundColorMarks", []);
|
|
71
71
|
(0, _defineProperty2.default)(this, "inlinePositions", new Set());
|
|
@@ -209,6 +209,7 @@ var ReactSerializer = exports.default = /*#__PURE__*/function () {
|
|
|
209
209
|
this.allowMediaLinking = init.allowMediaLinking;
|
|
210
210
|
this.allowAnnotations = Boolean(init.allowAnnotations);
|
|
211
211
|
this.surroundTextNodesWithTextWrapper = Boolean(init.surroundTextNodesWithTextWrapper);
|
|
212
|
+
this.textFastPath = (0, _expVal.expVal)('platform_renderer_text_paragraph_fast_path', 'isEnabled', false);
|
|
212
213
|
this.media = init.media;
|
|
213
214
|
this.mentionNodeDataProvider = init.mentionNodeDataProvider;
|
|
214
215
|
this.emojiProviderLookupOrder = init.emojiProviderLookupOrder;
|
|
@@ -277,12 +278,8 @@ var ReactSerializer = exports.default = /*#__PURE__*/function () {
|
|
|
277
278
|
case 'inlineCard':
|
|
278
279
|
return this.getInlineCardProps(node, path);
|
|
279
280
|
case 'expand':
|
|
280
|
-
return this.getExpandProps(node, path);
|
|
281
281
|
case 'nestedExpand':
|
|
282
|
-
|
|
283
|
-
return this.getExpandProps(node, path);
|
|
284
|
-
}
|
|
285
|
-
return this.getProps(node, path);
|
|
282
|
+
return this.getExpandProps(node, path);
|
|
286
283
|
case 'unsupportedBlock':
|
|
287
284
|
case 'unsupportedInline':
|
|
288
285
|
return this.getUnsupportedContentProps(node);
|
|
@@ -386,11 +383,11 @@ var ReactSerializer = exports.default = /*#__PURE__*/function () {
|
|
|
386
383
|
startPos: startPos + parentDepth,
|
|
387
384
|
endPos: endPos + parentDepth,
|
|
388
385
|
textHighlighter: this.textHighlighter,
|
|
389
|
-
marks: mark.marks
|
|
386
|
+
marks: mark.marks,
|
|
387
|
+
plainTextFastPath: this.textFastPath
|
|
390
388
|
}, mark.text);
|
|
391
389
|
}
|
|
392
|
-
|
|
393
|
-
return (0, _renderTextSegments.renderTextSegments)(segments, this.textHighlighter, mark.marks, startPos);
|
|
390
|
+
return (0, _renderText.renderText)(mark.text, this.textHighlighter, mark.marks, startPos, this.textFastPath);
|
|
394
391
|
}
|
|
395
392
|
}, {
|
|
396
393
|
key: "renderNode",
|
|
@@ -671,6 +668,7 @@ var ReactSerializer = exports.default = /*#__PURE__*/function () {
|
|
|
671
668
|
var startPos = this.startPos + path.length;
|
|
672
669
|
return _objectSpread({
|
|
673
670
|
asInline: this.inlinePositions.has(startPos) ? 'on' : undefined,
|
|
671
|
+
plainTextFastPath: this.textFastPath,
|
|
674
672
|
text: node.text,
|
|
675
673
|
providers: this.providers,
|
|
676
674
|
eventHandlers: this.eventHandlers,
|
|
@@ -5,13 +5,56 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
7
|
exports.default = Inline;
|
|
8
|
+
exports.hasRenderableChild = hasRenderableChild;
|
|
8
9
|
var _react = _interopRequireDefault(require("react"));
|
|
10
|
+
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; } } }; }
|
|
11
|
+
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; } }
|
|
12
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
13
|
+
/**
|
|
14
|
+
* Allocation-free equivalent of `React.Children.toArray(children).length > 0`.
|
|
15
|
+
*
|
|
16
|
+
* Mirrors `toArray` semantics: `null`, `undefined` and booleans are dropped; arrays are flattened;
|
|
17
|
+
* everything else (strings including `''`, numbers, elements, fragments, portals) counts as a child.
|
|
18
|
+
*/
|
|
19
|
+
function hasRenderableChild(children) {
|
|
20
|
+
if (children == null || typeof children === 'boolean') {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
if (Array.isArray(children)) {
|
|
24
|
+
var _iterator = _createForOfIteratorHelper(children),
|
|
25
|
+
_step;
|
|
26
|
+
try {
|
|
27
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
28
|
+
var child = _step.value;
|
|
29
|
+
if (hasRenderableChild(child)) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
} catch (err) {
|
|
34
|
+
_iterator.e(err);
|
|
35
|
+
} finally {
|
|
36
|
+
_iterator.f();
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Renders inline content, substituting a non-breaking space when there is nothing to render so
|
|
45
|
+
* an empty paragraph keeps its height.
|
|
46
|
+
*
|
|
47
|
+
* `plainTextFastPath` is threaded down from `ReactSerializer`, which evaluates the experiment
|
|
48
|
+
* once per instance. This component renders once per paragraph, so it must not evaluate the
|
|
49
|
+
* experiment itself. When the prop is absent the original behaviour is used.
|
|
50
|
+
*/
|
|
9
51
|
// Ignored via go/ees005
|
|
10
52
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
11
53
|
function Inline(props) {
|
|
12
|
-
var children = props.children
|
|
13
|
-
|
|
14
|
-
|
|
54
|
+
var children = props.children,
|
|
55
|
+
plainTextFastPath = props.plainTextFastPath;
|
|
56
|
+
var isEmpty = plainTextFastPath ? !hasRenderableChild(children) : _react.default.Children.toArray(children).length === 0;
|
|
57
|
+
if (isEmpty) {
|
|
15
58
|
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, "\xA0");
|
|
16
59
|
}
|
|
17
60
|
return children;
|
|
@@ -12,7 +12,8 @@ function Paragraph(_ref) {
|
|
|
12
12
|
var children = _ref.children,
|
|
13
13
|
dataAttributes = _ref.dataAttributes,
|
|
14
14
|
localId = _ref.localId,
|
|
15
|
-
asInline = _ref.asInline
|
|
15
|
+
asInline = _ref.asInline,
|
|
16
|
+
plainTextFastPath = _ref.plainTextFastPath;
|
|
16
17
|
return (
|
|
17
18
|
/*#__PURE__*/
|
|
18
19
|
// ignore the eslint warning Text primitive does not support dataAttributes
|
|
@@ -22,6 +23,8 @@ function Paragraph(_ref) {
|
|
|
22
23
|
_react.default.createElement("p", (0, _extends2.default)({}, dataAttributes, {
|
|
23
24
|
"data-local-id": localId,
|
|
24
25
|
"data-as-inline": asInline
|
|
25
|
-
}), /*#__PURE__*/_react.default.createElement(_inline.default,
|
|
26
|
+
}), /*#__PURE__*/_react.default.createElement(_inline.default, {
|
|
27
|
+
plainTextFastPath: plainTextFastPath
|
|
28
|
+
}, children))
|
|
26
29
|
);
|
|
27
30
|
}
|
|
@@ -18,7 +18,8 @@ var TextWrapper = function TextWrapper(props) {
|
|
|
18
18
|
startPos: startPos,
|
|
19
19
|
endPos: endPos,
|
|
20
20
|
textHighlighter: props.textHighlighter,
|
|
21
|
-
marks: props.marks
|
|
21
|
+
marks: props.marks,
|
|
22
|
+
plainTextFastPath: props.plainTextFastPath
|
|
22
23
|
}, children);
|
|
23
24
|
};
|
|
24
25
|
var _default = exports.default = TextWrapper;
|
|
@@ -6,16 +6,26 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
});
|
|
7
7
|
exports.renderTextSegments = renderTextSegments;
|
|
8
8
|
var _react = _interopRequireDefault(require("react"));
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
/** Collects the mark type names a highlighter component receives for a text node. */
|
|
10
|
+
var toMarkNames = function toMarkNames(marksList) {
|
|
11
|
+
return new Set(marksList.map(function (m) {
|
|
12
12
|
return m.type.name;
|
|
13
13
|
}));
|
|
14
|
+
};
|
|
15
|
+
function renderTextSegments(segments, textHighlighter, marksList, startPos) {
|
|
16
|
+
var lazyMarks = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
|
17
|
+
var Component = textHighlighter === null || textHighlighter === void 0 ? void 0 : textHighlighter.component;
|
|
18
|
+
// With `lazyMarks`, the Set is only built once a highlighted segment is actually rendered, so
|
|
19
|
+
// a highlighter with no matches on this text allocates nothing extra.
|
|
20
|
+
var marks = lazyMarks ? undefined : toMarkNames(marksList);
|
|
14
21
|
function renderSegment(segment) {
|
|
15
22
|
var idx = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
16
23
|
if (segment.type === 'plain' || !Component) {
|
|
17
24
|
return segment.text;
|
|
18
25
|
}
|
|
26
|
+
if (!marks) {
|
|
27
|
+
marks = toMarkNames(marksList);
|
|
28
|
+
}
|
|
19
29
|
return /*#__PURE__*/_react.default.createElement("span", {
|
|
20
30
|
"data-highlighted": true,
|
|
21
31
|
"data-vc": "highlighted-text",
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.renderText = renderText;
|
|
7
|
+
var _renderTextSegments = require("./render-text-segments");
|
|
8
|
+
var _segmentText = require("./segment-text");
|
|
9
|
+
/**
|
|
10
|
+
* Renders a text node's string, applying the text highlighter when one is configured.
|
|
11
|
+
*
|
|
12
|
+
* When `fastPath` is enabled and there is no highlighter (or no text), the input string is
|
|
13
|
+
* returned directly. This is output-identical to the segmented path, which for a single plain
|
|
14
|
+
* segment also returns the bare string, but skips the per-text-node segment array/object and
|
|
15
|
+
* marks Set allocations.
|
|
16
|
+
*/
|
|
17
|
+
function renderText(text, textHighlighter, marks, startPos, fastPath) {
|
|
18
|
+
if (fastPath && (!textHighlighter || !text)) {
|
|
19
|
+
return text !== null && text !== void 0 ? text : '';
|
|
20
|
+
}
|
|
21
|
+
var segments = (0, _segmentText.segmentText)(text, textHighlighter);
|
|
22
|
+
return (0, _renderTextSegments.renderTextSegments)(segments, textHighlighter, marks, startPos, fastPath);
|
|
23
|
+
}
|
package/dist/cjs/ui/Expand.js
CHANGED
|
@@ -17,7 +17,6 @@ var _analytics = require("@atlaskit/editor-common/analytics");
|
|
|
17
17
|
var _ui = require("@atlaskit/editor-common/ui");
|
|
18
18
|
var _editorSharedStyles = require("@atlaskit/editor-shared-styles");
|
|
19
19
|
var _chevronRight = _interopRequireDefault(require("@atlaskit/icon/core/chevron-right"));
|
|
20
|
-
var _isExperimentEnabled = require("@atlaskit/platform-feature-experiments/is-experiment-enabled");
|
|
21
20
|
var _Tooltip = _interopRequireDefault(require("@atlaskit/tooltip/Tooltip"));
|
|
22
21
|
var _events = require("../analytics/events");
|
|
23
22
|
var _activeHeaderIdProvider = require("./active-header-id-provider");
|
|
@@ -372,11 +371,10 @@ function Expand(_ref) {
|
|
|
372
371
|
// when:
|
|
373
372
|
// - the expand is open, or has been opened before, so the reader wants to see the content;
|
|
374
373
|
// - no node was given, so this expand never opted into lazy loading;
|
|
375
|
-
// - the experiment is off;
|
|
376
374
|
// - the browser has no hidden="until-found", so the text would not be findable and standing it in
|
|
377
375
|
// would gain nothing. While we still do not know, we assume the browser has it — assuming the
|
|
378
376
|
// opposite would render the whole body on the first paint and lose the saving entirely.
|
|
379
|
-
var revealed = expanded || hasBeenExpanded || !node || supportsHiddenUntilFound === false
|
|
377
|
+
var revealed = expanded || hasBeenExpanded || !node || supportsHiddenUntilFound === false;
|
|
380
378
|
var expandBody = (0, _react.useMemo)(function () {
|
|
381
379
|
return {
|
|
382
380
|
revealed: revealed,
|
|
@@ -71,7 +71,7 @@ var DEGRADED_SEVERITY_THRESHOLD = exports.DEGRADED_SEVERITY_THRESHOLD = 3000;
|
|
|
71
71
|
var TABLE_INFO_TIMEOUT = 10000;
|
|
72
72
|
var RENDER_EVENT_SAMPLE_RATE = 0.1;
|
|
73
73
|
var packageName = "@atlaskit/renderer";
|
|
74
|
-
var packageVersion = "144.0
|
|
74
|
+
var packageVersion = "144.1.0";
|
|
75
75
|
var setAsQueryContainerStyles = (0, _react2.css)({
|
|
76
76
|
containerName: 'ak-renderer-wrapper',
|
|
77
77
|
containerType: 'inline-size'
|
|
@@ -9,8 +9,7 @@ exports.getAnnotationIndex = exports.applyAnnotationOnText = exports.TextWithAnn
|
|
|
9
9
|
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
|
10
10
|
var _react = _interopRequireWildcard(require("react"));
|
|
11
11
|
var _react2 = require("@emotion/react");
|
|
12
|
-
var
|
|
13
|
-
var _segmentText = require("../../../react/utils/segment-text");
|
|
12
|
+
var _renderText = require("../../../react/utils/render-text");
|
|
14
13
|
var _AnnotationManagerContext = require("../contexts/AnnotationManagerContext");
|
|
15
14
|
var _AnnotationRangeContext = require("../contexts/AnnotationRangeContext");
|
|
16
15
|
var _types = require("../types");
|
|
@@ -85,10 +84,12 @@ var applyAnnotationOnText = exports.applyAnnotationOnText = function applyAnnota
|
|
|
85
84
|
shouldApplyAnnotationAt = _ref2.shouldApplyAnnotationAt,
|
|
86
85
|
draftPosition = _ref2.draftPosition,
|
|
87
86
|
textHighlighter = _ref2.textHighlighter,
|
|
88
|
-
marks = _ref2.marks
|
|
87
|
+
marks = _ref2.marks,
|
|
88
|
+
_ref2$plainTextFastPa = _ref2.plainTextFastPath,
|
|
89
|
+
plainTextFastPath = _ref2$plainTextFastPa === void 0 ? false : _ref2$plainTextFastPa;
|
|
89
90
|
var annotateIndex = getAnnotationIndex(shouldApplyAnnotationAt, texts.length);
|
|
90
91
|
return texts.map(function (value, index) {
|
|
91
|
-
var
|
|
92
|
+
var rendered = (0, _renderText.renderText)(value, textHighlighter, marks || [], draftPosition.from, plainTextFastPath);
|
|
92
93
|
if (annotateIndex === index) {
|
|
93
94
|
return (
|
|
94
95
|
// Ignored via go/ees005
|
|
@@ -96,7 +97,7 @@ var applyAnnotationOnText = exports.applyAnnotationOnText = function applyAnnota
|
|
|
96
97
|
(0, _react2.jsx)(AnnotationDraft, {
|
|
97
98
|
key: index,
|
|
98
99
|
draftPosition: draftPosition
|
|
99
|
-
},
|
|
100
|
+
}, rendered)
|
|
100
101
|
);
|
|
101
102
|
}
|
|
102
103
|
return (
|
|
@@ -104,7 +105,7 @@ var applyAnnotationOnText = exports.applyAnnotationOnText = function applyAnnota
|
|
|
104
105
|
// eslint-disable-next-line react/no-array-index-key
|
|
105
106
|
(0, _react2.jsx)(_react.default.Fragment, {
|
|
106
107
|
key: index
|
|
107
|
-
},
|
|
108
|
+
}, rendered)
|
|
108
109
|
);
|
|
109
110
|
});
|
|
110
111
|
};
|
|
@@ -113,7 +114,9 @@ var TextWithAnnotationDraft = exports.TextWithAnnotationDraft = function TextWit
|
|
|
113
114
|
endPos = _ref3.endPos,
|
|
114
115
|
children = _ref3.children,
|
|
115
116
|
textHighlighter = _ref3.textHighlighter,
|
|
116
|
-
marks = _ref3.marks
|
|
117
|
+
marks = _ref3.marks,
|
|
118
|
+
_ref3$plainTextFastPa = _ref3.plainTextFastPath,
|
|
119
|
+
plainTextFastPath = _ref3$plainTextFastPa === void 0 ? false : _ref3$plainTextFastPa;
|
|
117
120
|
var textPosition = _react.default.useMemo(function () {
|
|
118
121
|
return {
|
|
119
122
|
start: startPos,
|
|
@@ -133,28 +136,26 @@ var TextWithAnnotationDraft = exports.TextWithAnnotationDraft = function TextWit
|
|
|
133
136
|
return (0, _react2.jsx)(_react.Fragment, null, children);
|
|
134
137
|
}
|
|
135
138
|
if (shouldApplyAnnotationAt === false || !nextDraftPosition) {
|
|
136
|
-
|
|
137
|
-
return (0, _react2.jsx)(_react.Fragment, null, (0, _renderTextSegments.renderTextSegments)(segments, textHighlighter, marks || [], startPos));
|
|
139
|
+
return (0, _react2.jsx)(_react.Fragment, null, (0, _renderText.renderText)(textString, textHighlighter, marks || [], startPos, plainTextFastPath));
|
|
138
140
|
}
|
|
139
141
|
if (shouldApplyAnnotationAt === _types.InsertDraftPosition.AROUND_TEXT) {
|
|
140
|
-
var _segments = (0, _segmentText.segmentText)(textString, textHighlighter);
|
|
141
142
|
return (0, _react2.jsx)(AnnotationDraft, {
|
|
142
143
|
key: 0,
|
|
143
144
|
draftPosition: nextDraftPosition
|
|
144
|
-
}, (0,
|
|
145
|
+
}, (0, _renderText.renderText)(textString, textHighlighter, marks || [], startPos, plainTextFastPath));
|
|
145
146
|
}
|
|
146
147
|
var offsets = (0, _text.calcTextSplitOffset)(nextDraftPosition, textPosition, textString);
|
|
147
148
|
var texts = (0, _text.splitText)(textString, offsets);
|
|
148
149
|
if (!texts) {
|
|
149
|
-
|
|
150
|
-
return (0, _react2.jsx)(_react.Fragment, null, (0, _renderTextSegments.renderTextSegments)(_segments2, textHighlighter, marks || [], startPos));
|
|
150
|
+
return (0, _react2.jsx)(_react.Fragment, null, (0, _renderText.renderText)(textString, textHighlighter, marks || [], startPos, plainTextFastPath));
|
|
151
151
|
}
|
|
152
152
|
var components = applyAnnotationOnText({
|
|
153
153
|
texts: texts,
|
|
154
154
|
shouldApplyAnnotationAt: shouldApplyAnnotationAt,
|
|
155
155
|
draftPosition: nextDraftPosition,
|
|
156
156
|
textHighlighter: textHighlighter,
|
|
157
|
-
marks: marks
|
|
157
|
+
marks: marks,
|
|
158
|
+
plainTextFastPath: plainTextFastPath
|
|
158
159
|
});
|
|
159
160
|
return (0, _react2.jsx)(_react.Fragment, null, components);
|
|
160
161
|
};
|
|
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
});
|
|
7
7
|
exports.withExpandBodyBlock = exports.useExpandBody = exports.mergeExpandBodyText = exports.ExpandBodyTable = exports.ExpandBodyProvider = exports.ExpandBodyBlock = void 0;
|
|
8
8
|
var _react = _interopRequireWildcard(require("react"));
|
|
9
|
-
var _isExperimentEnabled = require("@atlaskit/platform-feature-experiments/is-experiment-enabled");
|
|
10
9
|
var _expandSearchText = require("./expand-search-text");
|
|
11
10
|
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); }
|
|
12
11
|
var ExpandBodyContext = /*#__PURE__*/(0, _react.createContext)(null);
|
|
@@ -51,9 +50,6 @@ var withExpandBodyBlock = exports.withExpandBodyBlock = function withExpandBodyB
|
|
|
51
50
|
if (!parent || !(0, _expandSearchText.isExpandNode)(parent)) {
|
|
52
51
|
return serialized;
|
|
53
52
|
}
|
|
54
|
-
if (!(0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_defer_collapsed_expand_body')) {
|
|
55
|
-
return serialized;
|
|
56
|
-
}
|
|
57
53
|
|
|
58
54
|
// `serialized` is only null for a node the renderer has no component for, which a table is not.
|
|
59
55
|
// Such a table falls through to the paths below, which do not reach into it.
|
|
@@ -5,7 +5,7 @@ import { getColumnWidths } from '@atlaskit/editor-common/utils';
|
|
|
5
5
|
import { getMarksByOrder, isSameMark } from '@atlaskit/editor-common/validator';
|
|
6
6
|
import { MarkType } from '@atlaskit/editor-prosemirror/model';
|
|
7
7
|
import { findChildrenByType } from '@atlaskit/editor-prosemirror/utils';
|
|
8
|
-
import {
|
|
8
|
+
import { expVal } from '@atlaskit/platform-feature-experiments/exp-val';
|
|
9
9
|
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
10
10
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
11
11
|
import { mergeExpandBodyText, withExpandBodyBlock } from '../ui/utils/expand-body';
|
|
@@ -19,8 +19,7 @@ import { createContentGetter } from './utils/content-getter';
|
|
|
19
19
|
import { getStandaloneBackgroundColorMarks } from './utils/getStandaloneBackgroundColorMarks';
|
|
20
20
|
import { isNestedHeaderLinksEnabled } from './utils/links';
|
|
21
21
|
import { markBlockAsInline } from './utils/markBlockAsInline';
|
|
22
|
-
import {
|
|
23
|
-
import { segmentText } from './utils/segment-text';
|
|
22
|
+
import { renderText } from './utils/render-text';
|
|
24
23
|
function mergeMarks(marksAndNodes) {
|
|
25
24
|
return marksAndNodes.reduce((acc, markOrNode) => {
|
|
26
25
|
const prev = acc.length && acc[acc.length - 1] || null;
|
|
@@ -50,6 +49,7 @@ export default class ReactSerializer {
|
|
|
50
49
|
_defineProperty(this, "allowPlaceholderText", true);
|
|
51
50
|
_defineProperty(this, "allowCustomPanels", false);
|
|
52
51
|
_defineProperty(this, "surroundTextNodesWithTextWrapper", false);
|
|
52
|
+
_defineProperty(this, "textFastPath", false);
|
|
53
53
|
_defineProperty(this, "allowAnnotations", false);
|
|
54
54
|
_defineProperty(this, "standaloneBackgroundColorMarks", []);
|
|
55
55
|
_defineProperty(this, "inlinePositions", new Set());
|
|
@@ -196,6 +196,7 @@ export default class ReactSerializer {
|
|
|
196
196
|
this.allowMediaLinking = init.allowMediaLinking;
|
|
197
197
|
this.allowAnnotations = Boolean(init.allowAnnotations);
|
|
198
198
|
this.surroundTextNodesWithTextWrapper = Boolean(init.surroundTextNodesWithTextWrapper);
|
|
199
|
+
this.textFastPath = expVal('platform_renderer_text_paragraph_fast_path', 'isEnabled', false);
|
|
199
200
|
this.media = init.media;
|
|
200
201
|
this.mentionNodeDataProvider = init.mentionNodeDataProvider;
|
|
201
202
|
this.emojiProviderLookupOrder = init.emojiProviderLookupOrder;
|
|
@@ -260,12 +261,8 @@ export default class ReactSerializer {
|
|
|
260
261
|
case 'inlineCard':
|
|
261
262
|
return this.getInlineCardProps(node, path);
|
|
262
263
|
case 'expand':
|
|
263
|
-
return this.getExpandProps(node, path);
|
|
264
264
|
case 'nestedExpand':
|
|
265
|
-
|
|
266
|
-
return this.getExpandProps(node, path);
|
|
267
|
-
}
|
|
268
|
-
return this.getProps(node, path);
|
|
265
|
+
return this.getExpandProps(node, path);
|
|
269
266
|
case 'unsupportedBlock':
|
|
270
267
|
case 'unsupportedInline':
|
|
271
268
|
return this.getUnsupportedContentProps(node);
|
|
@@ -360,11 +357,11 @@ export default class ReactSerializer {
|
|
|
360
357
|
startPos: startPos + parentDepth,
|
|
361
358
|
endPos: endPos + parentDepth,
|
|
362
359
|
textHighlighter: this.textHighlighter,
|
|
363
|
-
marks: mark.marks
|
|
360
|
+
marks: mark.marks,
|
|
361
|
+
plainTextFastPath: this.textFastPath
|
|
364
362
|
}, mark.text);
|
|
365
363
|
}
|
|
366
|
-
|
|
367
|
-
return renderTextSegments(segments, this.textHighlighter, mark.marks, startPos);
|
|
364
|
+
return renderText(mark.text, this.textHighlighter, mark.marks, startPos, this.textFastPath);
|
|
368
365
|
}
|
|
369
366
|
renderNode(
|
|
370
367
|
// Ignored via go/ees005
|
|
@@ -597,6 +594,7 @@ export default class ReactSerializer {
|
|
|
597
594
|
const startPos = this.startPos + path.length;
|
|
598
595
|
return {
|
|
599
596
|
asInline: this.inlinePositions.has(startPos) ? 'on' : undefined,
|
|
597
|
+
plainTextFastPath: this.textFastPath,
|
|
600
598
|
text: node.text,
|
|
601
599
|
providers: this.providers,
|
|
602
600
|
eventHandlers: this.eventHandlers,
|
|
@@ -1,13 +1,43 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Allocation-free equivalent of `React.Children.toArray(children).length > 0`.
|
|
5
|
+
*
|
|
6
|
+
* Mirrors `toArray` semantics: `null`, `undefined` and booleans are dropped; arrays are flattened;
|
|
7
|
+
* everything else (strings including `''`, numbers, elements, fragments, portals) counts as a child.
|
|
8
|
+
*/
|
|
9
|
+
export function hasRenderableChild(children) {
|
|
10
|
+
if (children == null || typeof children === 'boolean') {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
if (Array.isArray(children)) {
|
|
14
|
+
for (const child of children) {
|
|
15
|
+
if (hasRenderableChild(child)) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Renders inline content, substituting a non-breaking space when there is nothing to render so
|
|
26
|
+
* an empty paragraph keeps its height.
|
|
27
|
+
*
|
|
28
|
+
* `plainTextFastPath` is threaded down from `ReactSerializer`, which evaluates the experiment
|
|
29
|
+
* once per instance. This component renders once per paragraph, so it must not evaluate the
|
|
30
|
+
* experiment itself. When the prop is absent the original behaviour is used.
|
|
31
|
+
*/
|
|
3
32
|
// Ignored via go/ees005
|
|
4
33
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5
34
|
export default function Inline(props) {
|
|
6
35
|
const {
|
|
7
|
-
children
|
|
36
|
+
children,
|
|
37
|
+
plainTextFastPath
|
|
8
38
|
} = props;
|
|
9
|
-
const
|
|
10
|
-
if (
|
|
39
|
+
const isEmpty = plainTextFastPath ? !hasRenderableChild(children) : React.Children.toArray(children).length === 0;
|
|
40
|
+
if (isEmpty) {
|
|
11
41
|
return /*#__PURE__*/React.createElement(React.Fragment, null, "\xA0");
|
|
12
42
|
}
|
|
13
43
|
return children;
|
|
@@ -5,7 +5,8 @@ export default function Paragraph({
|
|
|
5
5
|
children,
|
|
6
6
|
dataAttributes,
|
|
7
7
|
localId,
|
|
8
|
-
asInline
|
|
8
|
+
asInline,
|
|
9
|
+
plainTextFastPath
|
|
9
10
|
}) {
|
|
10
11
|
return (
|
|
11
12
|
/*#__PURE__*/
|
|
@@ -16,6 +17,8 @@ export default function Paragraph({
|
|
|
16
17
|
React.createElement("p", _extends({}, dataAttributes, {
|
|
17
18
|
"data-local-id": localId,
|
|
18
19
|
"data-as-inline": asInline
|
|
19
|
-
}), /*#__PURE__*/React.createElement(Inline,
|
|
20
|
+
}), /*#__PURE__*/React.createElement(Inline, {
|
|
21
|
+
plainTextFastPath: plainTextFastPath
|
|
22
|
+
}, children))
|
|
20
23
|
);
|
|
21
24
|
}
|
|
@@ -15,7 +15,8 @@ const TextWrapper = props => {
|
|
|
15
15
|
startPos: startPos,
|
|
16
16
|
endPos: endPos,
|
|
17
17
|
textHighlighter: props.textHighlighter,
|
|
18
|
-
marks: props.marks
|
|
18
|
+
marks: props.marks,
|
|
19
|
+
plainTextFastPath: props.plainTextFastPath
|
|
19
20
|
}, children);
|
|
20
21
|
};
|
|
21
22
|
export default TextWrapper;
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
2
|
+
/** Collects the mark type names a highlighter component receives for a text node. */
|
|
3
|
+
const toMarkNames = marksList => new Set(marksList.map(m => m.type.name));
|
|
4
|
+
export function renderTextSegments(segments, textHighlighter, marksList, startPos, lazyMarks = false) {
|
|
3
5
|
const Component = textHighlighter === null || textHighlighter === void 0 ? void 0 : textHighlighter.component;
|
|
4
|
-
|
|
6
|
+
// With `lazyMarks`, the Set is only built once a highlighted segment is actually rendered, so
|
|
7
|
+
// a highlighter with no matches on this text allocates nothing extra.
|
|
8
|
+
let marks = lazyMarks ? undefined : toMarkNames(marksList);
|
|
5
9
|
function renderSegment(segment, idx = 0) {
|
|
6
10
|
if (segment.type === 'plain' || !Component) {
|
|
7
11
|
return segment.text;
|
|
8
12
|
}
|
|
13
|
+
if (!marks) {
|
|
14
|
+
marks = toMarkNames(marksList);
|
|
15
|
+
}
|
|
9
16
|
return /*#__PURE__*/React.createElement("span", {
|
|
10
17
|
"data-highlighted": true,
|
|
11
18
|
"data-vc": "highlighted-text",
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { renderTextSegments } from './render-text-segments';
|
|
2
|
+
import { segmentText } from './segment-text';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Renders a text node's string, applying the text highlighter when one is configured.
|
|
6
|
+
*
|
|
7
|
+
* When `fastPath` is enabled and there is no highlighter (or no text), the input string is
|
|
8
|
+
* returned directly. This is output-identical to the segmented path, which for a single plain
|
|
9
|
+
* segment also returns the bare string, but skips the per-text-node segment array/object and
|
|
10
|
+
* marks Set allocations.
|
|
11
|
+
*/
|
|
12
|
+
export function renderText(text, textHighlighter, marks, startPos, fastPath) {
|
|
13
|
+
if (fastPath && (!textHighlighter || !text)) {
|
|
14
|
+
return text !== null && text !== void 0 ? text : '';
|
|
15
|
+
}
|
|
16
|
+
const segments = segmentText(text, textHighlighter);
|
|
17
|
+
return renderTextSegments(segments, textHighlighter, marks, startPos, fastPath);
|
|
18
|
+
}
|
package/dist/es2019/ui/Expand.js
CHANGED
|
@@ -15,7 +15,6 @@ import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '@atlaskit/editor-common/anal
|
|
|
15
15
|
import { ExpandIconWrapper, ExpandLayoutWrapperWithRef, expandMessages, WidthProvider } from '@atlaskit/editor-common/ui';
|
|
16
16
|
import { akEditorLineHeight, akEditorSwoopCubicBezier, akLayoutGutterOffset } from '@atlaskit/editor-shared-styles';
|
|
17
17
|
import ChevronRightIcon from '@atlaskit/icon/core/chevron-right';
|
|
18
|
-
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
|
|
19
18
|
import Tooltip from '@atlaskit/tooltip/Tooltip';
|
|
20
19
|
import { MODE, PLATFORM } from '../analytics/events';
|
|
21
20
|
import { ActiveHeaderIdConsumer } from './active-header-id-provider';
|
|
@@ -350,11 +349,10 @@ function Expand({
|
|
|
350
349
|
// when:
|
|
351
350
|
// - the expand is open, or has been opened before, so the reader wants to see the content;
|
|
352
351
|
// - no node was given, so this expand never opted into lazy loading;
|
|
353
|
-
// - the experiment is off;
|
|
354
352
|
// - the browser has no hidden="until-found", so the text would not be findable and standing it in
|
|
355
353
|
// would gain nothing. While we still do not know, we assume the browser has it — assuming the
|
|
356
354
|
// opposite would render the whole body on the first paint and lose the saving entirely.
|
|
357
|
-
const revealed = expanded || hasBeenExpanded || !node || supportsHiddenUntilFound === false
|
|
355
|
+
const revealed = expanded || hasBeenExpanded || !node || supportsHiddenUntilFound === false;
|
|
358
356
|
const expandBody = useMemo(() => ({
|
|
359
357
|
revealed,
|
|
360
358
|
openWithAncestors,
|
|
@@ -56,7 +56,7 @@ export const DEGRADED_SEVERITY_THRESHOLD = 3000;
|
|
|
56
56
|
const TABLE_INFO_TIMEOUT = 10000;
|
|
57
57
|
const RENDER_EVENT_SAMPLE_RATE = 0.1;
|
|
58
58
|
const packageName = "@atlaskit/renderer";
|
|
59
|
-
const packageVersion = "144.0
|
|
59
|
+
const packageVersion = "144.1.0";
|
|
60
60
|
const setAsQueryContainerStyles = css({
|
|
61
61
|
containerName: 'ak-renderer-wrapper',
|
|
62
62
|
containerType: 'inline-size'
|
|
@@ -8,8 +8,7 @@ import React, { Fragment, useCallback } from 'react';
|
|
|
8
8
|
// eslint-disable-next-line @typescript-eslint/consistent-type-imports, @atlaskit/ui-styling-standard/use-compiled -- emotion jsx pragma; go/DSP-18766
|
|
9
9
|
import { css, jsx } from '@emotion/react'; // oxlint-ignore @typescript-eslint/consistent-type-imports -- classic @jsx jsx factory + jsx.JSX.Element types
|
|
10
10
|
|
|
11
|
-
import {
|
|
12
|
-
import { segmentText } from '../../../react/utils/segment-text';
|
|
11
|
+
import { renderText } from '../../../react/utils/render-text';
|
|
13
12
|
import { useAnnotationManagerDispatch } from '../contexts/AnnotationManagerContext';
|
|
14
13
|
import { useAnnotationRangeState } from '../contexts/AnnotationRangeContext';
|
|
15
14
|
import { InsertDraftPosition } from '../types';
|
|
@@ -78,11 +77,12 @@ export const applyAnnotationOnText = ({
|
|
|
78
77
|
shouldApplyAnnotationAt,
|
|
79
78
|
draftPosition,
|
|
80
79
|
textHighlighter,
|
|
81
|
-
marks
|
|
80
|
+
marks,
|
|
81
|
+
plainTextFastPath = false
|
|
82
82
|
}) => {
|
|
83
83
|
const annotateIndex = getAnnotationIndex(shouldApplyAnnotationAt, texts.length);
|
|
84
84
|
return texts.map((value, index) => {
|
|
85
|
-
const
|
|
85
|
+
const rendered = renderText(value, textHighlighter, marks || [], draftPosition.from, plainTextFastPath);
|
|
86
86
|
if (annotateIndex === index) {
|
|
87
87
|
return (
|
|
88
88
|
// Ignored via go/ees005
|
|
@@ -90,7 +90,7 @@ export const applyAnnotationOnText = ({
|
|
|
90
90
|
jsx(AnnotationDraft, {
|
|
91
91
|
key: index,
|
|
92
92
|
draftPosition: draftPosition
|
|
93
|
-
},
|
|
93
|
+
}, rendered)
|
|
94
94
|
);
|
|
95
95
|
}
|
|
96
96
|
return (
|
|
@@ -98,7 +98,7 @@ export const applyAnnotationOnText = ({
|
|
|
98
98
|
// eslint-disable-next-line react/no-array-index-key
|
|
99
99
|
jsx(React.Fragment, {
|
|
100
100
|
key: index
|
|
101
|
-
},
|
|
101
|
+
}, rendered)
|
|
102
102
|
);
|
|
103
103
|
});
|
|
104
104
|
};
|
|
@@ -107,7 +107,8 @@ export const TextWithAnnotationDraft = ({
|
|
|
107
107
|
endPos,
|
|
108
108
|
children,
|
|
109
109
|
textHighlighter,
|
|
110
|
-
marks
|
|
110
|
+
marks,
|
|
111
|
+
plainTextFastPath = false
|
|
111
112
|
}) => {
|
|
112
113
|
const textPosition = React.useMemo(() => ({
|
|
113
114
|
start: startPos,
|
|
@@ -127,28 +128,26 @@ export const TextWithAnnotationDraft = ({
|
|
|
127
128
|
return jsx(Fragment, null, children);
|
|
128
129
|
}
|
|
129
130
|
if (shouldApplyAnnotationAt === false || !nextDraftPosition) {
|
|
130
|
-
|
|
131
|
-
return jsx(Fragment, null, renderTextSegments(segments, textHighlighter, marks || [], startPos));
|
|
131
|
+
return jsx(Fragment, null, renderText(textString, textHighlighter, marks || [], startPos, plainTextFastPath));
|
|
132
132
|
}
|
|
133
133
|
if (shouldApplyAnnotationAt === InsertDraftPosition.AROUND_TEXT) {
|
|
134
|
-
const segments = segmentText(textString, textHighlighter);
|
|
135
134
|
return jsx(AnnotationDraft, {
|
|
136
135
|
key: 0,
|
|
137
136
|
draftPosition: nextDraftPosition
|
|
138
|
-
},
|
|
137
|
+
}, renderText(textString, textHighlighter, marks || [], startPos, plainTextFastPath));
|
|
139
138
|
}
|
|
140
139
|
const offsets = calcTextSplitOffset(nextDraftPosition, textPosition, textString);
|
|
141
140
|
const texts = splitText(textString, offsets);
|
|
142
141
|
if (!texts) {
|
|
143
|
-
|
|
144
|
-
return jsx(Fragment, null, renderTextSegments(segments, textHighlighter, marks || [], startPos));
|
|
142
|
+
return jsx(Fragment, null, renderText(textString, textHighlighter, marks || [], startPos, plainTextFastPath));
|
|
145
143
|
}
|
|
146
144
|
const components = applyAnnotationOnText({
|
|
147
145
|
texts,
|
|
148
146
|
shouldApplyAnnotationAt,
|
|
149
147
|
draftPosition: nextDraftPosition,
|
|
150
148
|
textHighlighter,
|
|
151
|
-
marks
|
|
149
|
+
marks,
|
|
150
|
+
plainTextFastPath
|
|
152
151
|
});
|
|
153
152
|
return jsx(Fragment, null, components);
|
|
154
153
|
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React, { createContext, isValidElement, useContext } from 'react';
|
|
2
|
-
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
|
|
3
2
|
import { BLOCK_SEPARATOR, getBlockSearchText, getTableStandInParts, holdsRevealableContent, isExpandNode } from './expand-search-text';
|
|
4
3
|
const ExpandBodyContext = /*#__PURE__*/createContext(null);
|
|
5
4
|
export const ExpandBodyProvider = ExpandBodyContext.Provider;
|
|
@@ -42,9 +41,6 @@ export const withExpandBodyBlock = (node, ancestors, index, serialized) => {
|
|
|
42
41
|
if (!parent || !isExpandNode(parent)) {
|
|
43
42
|
return serialized;
|
|
44
43
|
}
|
|
45
|
-
if (!isExperimentEnabled('platform_editor_defer_collapsed_expand_body')) {
|
|
46
|
-
return serialized;
|
|
47
|
-
}
|
|
48
44
|
|
|
49
45
|
// `serialized` is only null for a node the renderer has no component for, which a table is not.
|
|
50
46
|
// Such a table falls through to the paths below, which do not reach into it.
|
package/dist/esm/react/index.js
CHANGED
|
@@ -12,7 +12,7 @@ import { getColumnWidths } from '@atlaskit/editor-common/utils';
|
|
|
12
12
|
import { getMarksByOrder, isSameMark } from '@atlaskit/editor-common/validator';
|
|
13
13
|
import { MarkType } from '@atlaskit/editor-prosemirror/model';
|
|
14
14
|
import { findChildrenByType } from '@atlaskit/editor-prosemirror/utils';
|
|
15
|
-
import {
|
|
15
|
+
import { expVal } from '@atlaskit/platform-feature-experiments/exp-val';
|
|
16
16
|
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
17
17
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
18
18
|
import { mergeExpandBodyText, withExpandBodyBlock } from '../ui/utils/expand-body';
|
|
@@ -26,8 +26,7 @@ import { createContentGetter } from './utils/content-getter';
|
|
|
26
26
|
import { getStandaloneBackgroundColorMarks } from './utils/getStandaloneBackgroundColorMarks';
|
|
27
27
|
import { isNestedHeaderLinksEnabled } from './utils/links';
|
|
28
28
|
import { markBlockAsInline } from './utils/markBlockAsInline';
|
|
29
|
-
import {
|
|
30
|
-
import { segmentText } from './utils/segment-text';
|
|
29
|
+
import { renderText } from './utils/render-text';
|
|
31
30
|
function mergeMarks(marksAndNodes) {
|
|
32
31
|
return marksAndNodes.reduce(function (acc, markOrNode) {
|
|
33
32
|
var prev = acc.length && acc[acc.length - 1] || null;
|
|
@@ -59,6 +58,7 @@ var ReactSerializer = /*#__PURE__*/function () {
|
|
|
59
58
|
_defineProperty(this, "allowPlaceholderText", true);
|
|
60
59
|
_defineProperty(this, "allowCustomPanels", false);
|
|
61
60
|
_defineProperty(this, "surroundTextNodesWithTextWrapper", false);
|
|
61
|
+
_defineProperty(this, "textFastPath", false);
|
|
62
62
|
_defineProperty(this, "allowAnnotations", false);
|
|
63
63
|
_defineProperty(this, "standaloneBackgroundColorMarks", []);
|
|
64
64
|
_defineProperty(this, "inlinePositions", new Set());
|
|
@@ -202,6 +202,7 @@ var ReactSerializer = /*#__PURE__*/function () {
|
|
|
202
202
|
this.allowMediaLinking = init.allowMediaLinking;
|
|
203
203
|
this.allowAnnotations = Boolean(init.allowAnnotations);
|
|
204
204
|
this.surroundTextNodesWithTextWrapper = Boolean(init.surroundTextNodesWithTextWrapper);
|
|
205
|
+
this.textFastPath = expVal('platform_renderer_text_paragraph_fast_path', 'isEnabled', false);
|
|
205
206
|
this.media = init.media;
|
|
206
207
|
this.mentionNodeDataProvider = init.mentionNodeDataProvider;
|
|
207
208
|
this.emojiProviderLookupOrder = init.emojiProviderLookupOrder;
|
|
@@ -270,12 +271,8 @@ var ReactSerializer = /*#__PURE__*/function () {
|
|
|
270
271
|
case 'inlineCard':
|
|
271
272
|
return this.getInlineCardProps(node, path);
|
|
272
273
|
case 'expand':
|
|
273
|
-
return this.getExpandProps(node, path);
|
|
274
274
|
case 'nestedExpand':
|
|
275
|
-
|
|
276
|
-
return this.getExpandProps(node, path);
|
|
277
|
-
}
|
|
278
|
-
return this.getProps(node, path);
|
|
275
|
+
return this.getExpandProps(node, path);
|
|
279
276
|
case 'unsupportedBlock':
|
|
280
277
|
case 'unsupportedInline':
|
|
281
278
|
return this.getUnsupportedContentProps(node);
|
|
@@ -379,11 +376,11 @@ var ReactSerializer = /*#__PURE__*/function () {
|
|
|
379
376
|
startPos: startPos + parentDepth,
|
|
380
377
|
endPos: endPos + parentDepth,
|
|
381
378
|
textHighlighter: this.textHighlighter,
|
|
382
|
-
marks: mark.marks
|
|
379
|
+
marks: mark.marks,
|
|
380
|
+
plainTextFastPath: this.textFastPath
|
|
383
381
|
}, mark.text);
|
|
384
382
|
}
|
|
385
|
-
|
|
386
|
-
return renderTextSegments(segments, this.textHighlighter, mark.marks, startPos);
|
|
383
|
+
return renderText(mark.text, this.textHighlighter, mark.marks, startPos, this.textFastPath);
|
|
387
384
|
}
|
|
388
385
|
}, {
|
|
389
386
|
key: "renderNode",
|
|
@@ -664,6 +661,7 @@ var ReactSerializer = /*#__PURE__*/function () {
|
|
|
664
661
|
var startPos = this.startPos + path.length;
|
|
665
662
|
return _objectSpread({
|
|
666
663
|
asInline: this.inlinePositions.has(startPos) ? 'on' : undefined,
|
|
664
|
+
plainTextFastPath: this.textFastPath,
|
|
667
665
|
text: node.text,
|
|
668
666
|
providers: this.providers,
|
|
669
667
|
eventHandlers: this.eventHandlers,
|
|
@@ -1,11 +1,53 @@
|
|
|
1
|
+
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; } } }; }
|
|
2
|
+
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; } }
|
|
3
|
+
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; }
|
|
1
4
|
import React from 'react';
|
|
2
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Allocation-free equivalent of `React.Children.toArray(children).length > 0`.
|
|
8
|
+
*
|
|
9
|
+
* Mirrors `toArray` semantics: `null`, `undefined` and booleans are dropped; arrays are flattened;
|
|
10
|
+
* everything else (strings including `''`, numbers, elements, fragments, portals) counts as a child.
|
|
11
|
+
*/
|
|
12
|
+
export function hasRenderableChild(children) {
|
|
13
|
+
if (children == null || typeof children === 'boolean') {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
if (Array.isArray(children)) {
|
|
17
|
+
var _iterator = _createForOfIteratorHelper(children),
|
|
18
|
+
_step;
|
|
19
|
+
try {
|
|
20
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
21
|
+
var child = _step.value;
|
|
22
|
+
if (hasRenderableChild(child)) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
} catch (err) {
|
|
27
|
+
_iterator.e(err);
|
|
28
|
+
} finally {
|
|
29
|
+
_iterator.f();
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Renders inline content, substituting a non-breaking space when there is nothing to render so
|
|
38
|
+
* an empty paragraph keeps its height.
|
|
39
|
+
*
|
|
40
|
+
* `plainTextFastPath` is threaded down from `ReactSerializer`, which evaluates the experiment
|
|
41
|
+
* once per instance. This component renders once per paragraph, so it must not evaluate the
|
|
42
|
+
* experiment itself. When the prop is absent the original behaviour is used.
|
|
43
|
+
*/
|
|
3
44
|
// Ignored via go/ees005
|
|
4
45
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5
46
|
export default function Inline(props) {
|
|
6
|
-
var children = props.children
|
|
7
|
-
|
|
8
|
-
|
|
47
|
+
var children = props.children,
|
|
48
|
+
plainTextFastPath = props.plainTextFastPath;
|
|
49
|
+
var isEmpty = plainTextFastPath ? !hasRenderableChild(children) : React.Children.toArray(children).length === 0;
|
|
50
|
+
if (isEmpty) {
|
|
9
51
|
return /*#__PURE__*/React.createElement(React.Fragment, null, "\xA0");
|
|
10
52
|
}
|
|
11
53
|
return children;
|
|
@@ -5,7 +5,8 @@ export default function Paragraph(_ref) {
|
|
|
5
5
|
var children = _ref.children,
|
|
6
6
|
dataAttributes = _ref.dataAttributes,
|
|
7
7
|
localId = _ref.localId,
|
|
8
|
-
asInline = _ref.asInline
|
|
8
|
+
asInline = _ref.asInline,
|
|
9
|
+
plainTextFastPath = _ref.plainTextFastPath;
|
|
9
10
|
return (
|
|
10
11
|
/*#__PURE__*/
|
|
11
12
|
// ignore the eslint warning Text primitive does not support dataAttributes
|
|
@@ -15,6 +16,8 @@ export default function Paragraph(_ref) {
|
|
|
15
16
|
React.createElement("p", _extends({}, dataAttributes, {
|
|
16
17
|
"data-local-id": localId,
|
|
17
18
|
"data-as-inline": asInline
|
|
18
|
-
}), /*#__PURE__*/React.createElement(Inline,
|
|
19
|
+
}), /*#__PURE__*/React.createElement(Inline, {
|
|
20
|
+
plainTextFastPath: plainTextFastPath
|
|
21
|
+
}, children))
|
|
19
22
|
);
|
|
20
23
|
}
|
|
@@ -11,7 +11,8 @@ var TextWrapper = function TextWrapper(props) {
|
|
|
11
11
|
startPos: startPos,
|
|
12
12
|
endPos: endPos,
|
|
13
13
|
textHighlighter: props.textHighlighter,
|
|
14
|
-
marks: props.marks
|
|
14
|
+
marks: props.marks,
|
|
15
|
+
plainTextFastPath: props.plainTextFastPath
|
|
15
16
|
}, children);
|
|
16
17
|
};
|
|
17
18
|
export default TextWrapper;
|
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
/** Collects the mark type names a highlighter component receives for a text node. */
|
|
3
|
+
var toMarkNames = function toMarkNames(marksList) {
|
|
4
|
+
return new Set(marksList.map(function (m) {
|
|
5
5
|
return m.type.name;
|
|
6
6
|
}));
|
|
7
|
+
};
|
|
8
|
+
export function renderTextSegments(segments, textHighlighter, marksList, startPos) {
|
|
9
|
+
var lazyMarks = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
|
10
|
+
var Component = textHighlighter === null || textHighlighter === void 0 ? void 0 : textHighlighter.component;
|
|
11
|
+
// With `lazyMarks`, the Set is only built once a highlighted segment is actually rendered, so
|
|
12
|
+
// a highlighter with no matches on this text allocates nothing extra.
|
|
13
|
+
var marks = lazyMarks ? undefined : toMarkNames(marksList);
|
|
7
14
|
function renderSegment(segment) {
|
|
8
15
|
var idx = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
9
16
|
if (segment.type === 'plain' || !Component) {
|
|
10
17
|
return segment.text;
|
|
11
18
|
}
|
|
19
|
+
if (!marks) {
|
|
20
|
+
marks = toMarkNames(marksList);
|
|
21
|
+
}
|
|
12
22
|
return /*#__PURE__*/React.createElement("span", {
|
|
13
23
|
"data-highlighted": true,
|
|
14
24
|
"data-vc": "highlighted-text",
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { renderTextSegments } from './render-text-segments';
|
|
2
|
+
import { segmentText } from './segment-text';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Renders a text node's string, applying the text highlighter when one is configured.
|
|
6
|
+
*
|
|
7
|
+
* When `fastPath` is enabled and there is no highlighter (or no text), the input string is
|
|
8
|
+
* returned directly. This is output-identical to the segmented path, which for a single plain
|
|
9
|
+
* segment also returns the bare string, but skips the per-text-node segment array/object and
|
|
10
|
+
* marks Set allocations.
|
|
11
|
+
*/
|
|
12
|
+
export function renderText(text, textHighlighter, marks, startPos, fastPath) {
|
|
13
|
+
if (fastPath && (!textHighlighter || !text)) {
|
|
14
|
+
return text !== null && text !== void 0 ? text : '';
|
|
15
|
+
}
|
|
16
|
+
var segments = segmentText(text, textHighlighter);
|
|
17
|
+
return renderTextSegments(segments, textHighlighter, marks, startPos, fastPath);
|
|
18
|
+
}
|
package/dist/esm/ui/Expand.js
CHANGED
|
@@ -16,7 +16,6 @@ import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '@atlaskit/editor-common/anal
|
|
|
16
16
|
import { ExpandIconWrapper, ExpandLayoutWrapperWithRef, expandMessages, WidthProvider } from '@atlaskit/editor-common/ui';
|
|
17
17
|
import { akEditorLineHeight, akEditorSwoopCubicBezier, akLayoutGutterOffset } from '@atlaskit/editor-shared-styles';
|
|
18
18
|
import ChevronRightIcon from '@atlaskit/icon/core/chevron-right';
|
|
19
|
-
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
|
|
20
19
|
import Tooltip from '@atlaskit/tooltip/Tooltip';
|
|
21
20
|
import { MODE, PLATFORM } from '../analytics/events';
|
|
22
21
|
import { ActiveHeaderIdConsumer } from './active-header-id-provider';
|
|
@@ -363,11 +362,10 @@ function Expand(_ref) {
|
|
|
363
362
|
// when:
|
|
364
363
|
// - the expand is open, or has been opened before, so the reader wants to see the content;
|
|
365
364
|
// - no node was given, so this expand never opted into lazy loading;
|
|
366
|
-
// - the experiment is off;
|
|
367
365
|
// - the browser has no hidden="until-found", so the text would not be findable and standing it in
|
|
368
366
|
// would gain nothing. While we still do not know, we assume the browser has it — assuming the
|
|
369
367
|
// opposite would render the whole body on the first paint and lose the saving entirely.
|
|
370
|
-
var revealed = expanded || hasBeenExpanded || !node || supportsHiddenUntilFound === false
|
|
368
|
+
var revealed = expanded || hasBeenExpanded || !node || supportsHiddenUntilFound === false;
|
|
371
369
|
var expandBody = useMemo(function () {
|
|
372
370
|
return {
|
|
373
371
|
revealed: revealed,
|
|
@@ -61,7 +61,7 @@ export var DEGRADED_SEVERITY_THRESHOLD = 3000;
|
|
|
61
61
|
var TABLE_INFO_TIMEOUT = 10000;
|
|
62
62
|
var RENDER_EVENT_SAMPLE_RATE = 0.1;
|
|
63
63
|
var packageName = "@atlaskit/renderer";
|
|
64
|
-
var packageVersion = "144.0
|
|
64
|
+
var packageVersion = "144.1.0";
|
|
65
65
|
var setAsQueryContainerStyles = css({
|
|
66
66
|
containerName: 'ak-renderer-wrapper',
|
|
67
67
|
containerType: 'inline-size'
|
|
@@ -8,8 +8,7 @@ import React, { Fragment, useCallback } from 'react';
|
|
|
8
8
|
// eslint-disable-next-line @typescript-eslint/consistent-type-imports, @atlaskit/ui-styling-standard/use-compiled -- emotion jsx pragma; go/DSP-18766
|
|
9
9
|
import { css, jsx } from '@emotion/react'; // oxlint-ignore @typescript-eslint/consistent-type-imports -- classic @jsx jsx factory + jsx.JSX.Element types
|
|
10
10
|
|
|
11
|
-
import {
|
|
12
|
-
import { segmentText } from '../../../react/utils/segment-text';
|
|
11
|
+
import { renderText } from '../../../react/utils/render-text';
|
|
13
12
|
import { useAnnotationManagerDispatch } from '../contexts/AnnotationManagerContext';
|
|
14
13
|
import { useAnnotationRangeState } from '../contexts/AnnotationRangeContext';
|
|
15
14
|
import { InsertDraftPosition } from '../types';
|
|
@@ -76,10 +75,12 @@ export var applyAnnotationOnText = function applyAnnotationOnText(_ref2) {
|
|
|
76
75
|
shouldApplyAnnotationAt = _ref2.shouldApplyAnnotationAt,
|
|
77
76
|
draftPosition = _ref2.draftPosition,
|
|
78
77
|
textHighlighter = _ref2.textHighlighter,
|
|
79
|
-
marks = _ref2.marks
|
|
78
|
+
marks = _ref2.marks,
|
|
79
|
+
_ref2$plainTextFastPa = _ref2.plainTextFastPath,
|
|
80
|
+
plainTextFastPath = _ref2$plainTextFastPa === void 0 ? false : _ref2$plainTextFastPa;
|
|
80
81
|
var annotateIndex = getAnnotationIndex(shouldApplyAnnotationAt, texts.length);
|
|
81
82
|
return texts.map(function (value, index) {
|
|
82
|
-
var
|
|
83
|
+
var rendered = renderText(value, textHighlighter, marks || [], draftPosition.from, plainTextFastPath);
|
|
83
84
|
if (annotateIndex === index) {
|
|
84
85
|
return (
|
|
85
86
|
// Ignored via go/ees005
|
|
@@ -87,7 +88,7 @@ export var applyAnnotationOnText = function applyAnnotationOnText(_ref2) {
|
|
|
87
88
|
jsx(AnnotationDraft, {
|
|
88
89
|
key: index,
|
|
89
90
|
draftPosition: draftPosition
|
|
90
|
-
},
|
|
91
|
+
}, rendered)
|
|
91
92
|
);
|
|
92
93
|
}
|
|
93
94
|
return (
|
|
@@ -95,7 +96,7 @@ export var applyAnnotationOnText = function applyAnnotationOnText(_ref2) {
|
|
|
95
96
|
// eslint-disable-next-line react/no-array-index-key
|
|
96
97
|
jsx(React.Fragment, {
|
|
97
98
|
key: index
|
|
98
|
-
},
|
|
99
|
+
}, rendered)
|
|
99
100
|
);
|
|
100
101
|
});
|
|
101
102
|
};
|
|
@@ -104,7 +105,9 @@ export var TextWithAnnotationDraft = function TextWithAnnotationDraft(_ref3) {
|
|
|
104
105
|
endPos = _ref3.endPos,
|
|
105
106
|
children = _ref3.children,
|
|
106
107
|
textHighlighter = _ref3.textHighlighter,
|
|
107
|
-
marks = _ref3.marks
|
|
108
|
+
marks = _ref3.marks,
|
|
109
|
+
_ref3$plainTextFastPa = _ref3.plainTextFastPath,
|
|
110
|
+
plainTextFastPath = _ref3$plainTextFastPa === void 0 ? false : _ref3$plainTextFastPa;
|
|
108
111
|
var textPosition = React.useMemo(function () {
|
|
109
112
|
return {
|
|
110
113
|
start: startPos,
|
|
@@ -124,28 +127,26 @@ export var TextWithAnnotationDraft = function TextWithAnnotationDraft(_ref3) {
|
|
|
124
127
|
return jsx(Fragment, null, children);
|
|
125
128
|
}
|
|
126
129
|
if (shouldApplyAnnotationAt === false || !nextDraftPosition) {
|
|
127
|
-
|
|
128
|
-
return jsx(Fragment, null, renderTextSegments(segments, textHighlighter, marks || [], startPos));
|
|
130
|
+
return jsx(Fragment, null, renderText(textString, textHighlighter, marks || [], startPos, plainTextFastPath));
|
|
129
131
|
}
|
|
130
132
|
if (shouldApplyAnnotationAt === InsertDraftPosition.AROUND_TEXT) {
|
|
131
|
-
var _segments = segmentText(textString, textHighlighter);
|
|
132
133
|
return jsx(AnnotationDraft, {
|
|
133
134
|
key: 0,
|
|
134
135
|
draftPosition: nextDraftPosition
|
|
135
|
-
},
|
|
136
|
+
}, renderText(textString, textHighlighter, marks || [], startPos, plainTextFastPath));
|
|
136
137
|
}
|
|
137
138
|
var offsets = calcTextSplitOffset(nextDraftPosition, textPosition, textString);
|
|
138
139
|
var texts = splitText(textString, offsets);
|
|
139
140
|
if (!texts) {
|
|
140
|
-
|
|
141
|
-
return jsx(Fragment, null, renderTextSegments(_segments2, textHighlighter, marks || [], startPos));
|
|
141
|
+
return jsx(Fragment, null, renderText(textString, textHighlighter, marks || [], startPos, plainTextFastPath));
|
|
142
142
|
}
|
|
143
143
|
var components = applyAnnotationOnText({
|
|
144
144
|
texts: texts,
|
|
145
145
|
shouldApplyAnnotationAt: shouldApplyAnnotationAt,
|
|
146
146
|
draftPosition: nextDraftPosition,
|
|
147
147
|
textHighlighter: textHighlighter,
|
|
148
|
-
marks: marks
|
|
148
|
+
marks: marks,
|
|
149
|
+
plainTextFastPath: plainTextFastPath
|
|
149
150
|
});
|
|
150
151
|
return jsx(Fragment, null, components);
|
|
151
152
|
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React, { createContext, isValidElement, useContext } from 'react';
|
|
2
|
-
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
|
|
3
2
|
import { BLOCK_SEPARATOR, getBlockSearchText, getTableStandInParts, holdsRevealableContent, isExpandNode } from './expand-search-text';
|
|
4
3
|
var ExpandBodyContext = /*#__PURE__*/createContext(null);
|
|
5
4
|
export var ExpandBodyProvider = ExpandBodyContext.Provider;
|
|
@@ -43,9 +42,6 @@ export var withExpandBodyBlock = function withExpandBodyBlock(node, ancestors, i
|
|
|
43
42
|
if (!parent || !isExpandNode(parent)) {
|
|
44
43
|
return serialized;
|
|
45
44
|
}
|
|
46
|
-
if (!isExperimentEnabled('platform_editor_defer_collapsed_expand_body')) {
|
|
47
|
-
return serialized;
|
|
48
|
-
}
|
|
49
45
|
|
|
50
46
|
// `serialized` is only null for a node the renderer has no component for, which a table is not.
|
|
51
47
|
// Such a table falls through to the paths below, which do not reach into it.
|
|
@@ -104,6 +104,7 @@ export default class ReactSerializer implements Serializer<JSX.Element> {
|
|
|
104
104
|
private initStartPos;
|
|
105
105
|
private startPos;
|
|
106
106
|
private surroundTextNodesWithTextWrapper;
|
|
107
|
+
private textFastPath;
|
|
107
108
|
private media?;
|
|
108
109
|
private mentionNodeDataProvider?;
|
|
109
110
|
private emojiProviderLookupOrder?;
|
|
@@ -1 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Allocation-free equivalent of `React.Children.toArray(children).length > 0`.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors `toArray` semantics: `null`, `undefined` and booleans are dropped; arrays are flattened;
|
|
6
|
+
* everything else (strings including `''`, numbers, elements, fragments, portals) counts as a child.
|
|
7
|
+
*/
|
|
8
|
+
export declare function hasRenderableChild(children: React.ReactNode): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Renders inline content, substituting a non-breaking space when there is nothing to render so
|
|
11
|
+
* an empty paragraph keeps its height.
|
|
12
|
+
*
|
|
13
|
+
* `plainTextFastPath` is threaded down from `ReactSerializer`, which evaluates the experiment
|
|
14
|
+
* once per instance. This component renders once per paragraph, so it must not evaluate the
|
|
15
|
+
* experiment itself. When the prop is absent the original behaviour is used.
|
|
16
|
+
*/
|
|
1
17
|
export default function Inline(props: any): any;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { NodeProps } from '../types';
|
|
3
|
-
export default function Paragraph({ children, dataAttributes, localId, asInline, }: NodeProps): React.JSX.Element;
|
|
3
|
+
export default function Paragraph({ children, dataAttributes, localId, asInline, plainTextFastPath, }: NodeProps): React.JSX.Element;
|
|
@@ -45,6 +45,11 @@ export interface NodeMeta {
|
|
|
45
45
|
hideExtensionKeysWhilePending?: string[];
|
|
46
46
|
marks: PMNode['marks'];
|
|
47
47
|
nodeType: NodeType['name'];
|
|
48
|
+
/**
|
|
49
|
+
* Whether the text and paragraph fast path experiment is enabled for this render.
|
|
50
|
+
* Evaluated once per `ReactSerializer` instance rather than per node.
|
|
51
|
+
*/
|
|
52
|
+
plainTextFastPath?: boolean;
|
|
48
53
|
portal?: HTMLElement | undefined;
|
|
49
54
|
providers?: ProviderFactory | undefined;
|
|
50
55
|
rendererAppearance?: RendererAppearance;
|
|
@@ -2,4 +2,4 @@ import React from 'react';
|
|
|
2
2
|
import type { Mark } from '@atlaskit/editor-prosemirror/model';
|
|
3
3
|
import type { TextHighlighter } from '../types';
|
|
4
4
|
import type { TextSegment } from './segment-text';
|
|
5
|
-
export declare function renderTextSegments(segments: Array<TextSegment>, textHighlighter: TextHighlighter | undefined, marksList: readonly Mark[], startPos: number): string | React.JSX.Element;
|
|
5
|
+
export declare function renderTextSegments(segments: Array<TextSegment>, textHighlighter: TextHighlighter | undefined, marksList: readonly Mark[], startPos: number, lazyMarks?: boolean): string | React.JSX.Element;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import type { Mark } from '@atlaskit/editor-prosemirror/model';
|
|
3
|
+
import type { TextHighlighter } from '../types';
|
|
4
|
+
/**
|
|
5
|
+
* Renders a text node's string, applying the text highlighter when one is configured.
|
|
6
|
+
*
|
|
7
|
+
* When `fastPath` is enabled and there is no highlighter (or no text), the input string is
|
|
8
|
+
* returned directly. This is output-identical to the segmented path, which for a single plain
|
|
9
|
+
* segment also returns the bare string, but skips the per-text-node segment array/object and
|
|
10
|
+
* marks Set allocations.
|
|
11
|
+
*/
|
|
12
|
+
export declare function renderText(text: string | undefined, textHighlighter: TextHighlighter | undefined, marks: readonly Mark[], startPos: number, fastPath: boolean): string | React.JSX.Element;
|
|
@@ -14,17 +14,19 @@ export declare const AnnotationDraft: ({ draftPosition, children, }: React.Props
|
|
|
14
14
|
type ApplyAnnotationsProps = {
|
|
15
15
|
draftPosition: Position;
|
|
16
16
|
marks?: readonly Mark[];
|
|
17
|
+
plainTextFastPath?: boolean;
|
|
17
18
|
shouldApplyAnnotationAt: InsertDraftPosition.INSIDE | InsertDraftPosition.START | InsertDraftPosition.END;
|
|
18
19
|
textHighlighter?: TextHighlighter;
|
|
19
20
|
texts: string[];
|
|
20
21
|
};
|
|
21
22
|
export declare const getAnnotationIndex: (annotationPosition: InsertDraftPosition, fragmentCount: number) => number;
|
|
22
|
-
export declare const applyAnnotationOnText: ({ texts, shouldApplyAnnotationAt, draftPosition, textHighlighter, marks, }: ApplyAnnotationsProps) => JSX.Element[];
|
|
23
|
+
export declare const applyAnnotationOnText: ({ texts, shouldApplyAnnotationAt, draftPosition, textHighlighter, marks, plainTextFastPath, }: ApplyAnnotationsProps) => JSX.Element[];
|
|
23
24
|
type Props = React.PropsWithChildren<{
|
|
24
25
|
endPos: number;
|
|
25
26
|
marks?: readonly Mark[];
|
|
27
|
+
plainTextFastPath?: boolean;
|
|
26
28
|
startPos: number;
|
|
27
29
|
textHighlighter?: TextHighlighter;
|
|
28
30
|
}>;
|
|
29
|
-
export declare const TextWithAnnotationDraft: ({ startPos, endPos, children, textHighlighter, marks, }: Props) => jsx.JSX.Element;
|
|
31
|
+
export declare const TextWithAnnotationDraft: ({ startPos, endPos, children, textHighlighter, marks, plainTextFastPath, }: Props) => jsx.JSX.Element;
|
|
30
32
|
export {};
|