@atlaskit/editor-plugin-show-diff 20.0.10 → 21.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/dist/cjs/pm-plugins/NodeViewSerializer.js +71 -7
- package/dist/cjs/pm-plugins/calculateDiff/attrAwareTokenEncoder.js +9 -7
- package/dist/cjs/pm-plugins/createEditorProxy.js +84 -0
- package/dist/cjs/pm-plugins/decorations/createContributorTagWidget.js +25 -6
- package/dist/cjs/pm-plugins/decorations/createNodeChangedDecorationWidget.js +35 -11
- package/dist/cjs/pm-plugins/decorations/utils/excerptIncludeAttrs.js +27 -0
- package/dist/cjs/pm-plugins/decorations/utils/getAttrChangeRanges.js +7 -0
- package/dist/cjs/pm-plugins/decorations/utils/wrapBlockNodeView.js +38 -2
- package/dist/cjs/pm-plugins/markViews.js +65 -0
- package/dist/es2019/pm-plugins/NodeViewSerializer.js +64 -8
- package/dist/es2019/pm-plugins/calculateDiff/attrAwareTokenEncoder.js +9 -7
- package/dist/es2019/pm-plugins/createEditorProxy.js +76 -0
- package/dist/es2019/pm-plugins/decorations/createContributorTagWidget.js +26 -8
- package/dist/es2019/pm-plugins/decorations/createNodeChangedDecorationWidget.js +35 -12
- package/dist/es2019/pm-plugins/decorations/utils/excerptIncludeAttrs.js +13 -0
- package/dist/es2019/pm-plugins/decorations/utils/getAttrChangeRanges.js +10 -1
- package/dist/es2019/pm-plugins/decorations/utils/wrapBlockNodeView.js +36 -2
- package/dist/es2019/pm-plugins/markViews.js +61 -0
- package/dist/esm/pm-plugins/NodeViewSerializer.js +71 -7
- package/dist/esm/pm-plugins/calculateDiff/attrAwareTokenEncoder.js +9 -7
- package/dist/esm/pm-plugins/createEditorProxy.js +78 -0
- package/dist/esm/pm-plugins/decorations/createContributorTagWidget.js +27 -8
- package/dist/esm/pm-plugins/decorations/createNodeChangedDecorationWidget.js +37 -12
- package/dist/esm/pm-plugins/decorations/utils/excerptIncludeAttrs.js +20 -0
- package/dist/esm/pm-plugins/decorations/utils/getAttrChangeRanges.js +7 -0
- package/dist/esm/pm-plugins/decorations/utils/wrapBlockNodeView.js +38 -2
- package/dist/esm/pm-plugins/markViews.js +60 -0
- package/dist/types/pm-plugins/NodeViewSerializer.d.ts +7 -2
- package/dist/types/pm-plugins/createEditorProxy.d.ts +18 -0
- package/dist/types/pm-plugins/decorations/createContributorTagWidget.d.ts +2 -1
- package/dist/types/pm-plugins/decorations/utils/excerptIncludeAttrs.d.ts +6 -0
- package/dist/types/pm-plugins/markViews.d.ts +14 -0
- package/package.json +13 -10
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
|
2
2
|
import _createClass from "@babel/runtime/helpers/createClass";
|
|
3
|
+
import { expandedState } from '@atlaskit/editor-common/expand';
|
|
3
4
|
import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
|
|
5
|
+
import { contains } from '@atlaskit/editor-prosemirror/utils';
|
|
4
6
|
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
|
|
7
|
+
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
8
|
+
import { createEditorProxy } from './createEditorProxy';
|
|
9
|
+
import { wrapInMarkViews } from './markViews';
|
|
5
10
|
|
|
6
11
|
/**
|
|
7
12
|
* Utilities for working with ProseMirror node views and DOM serialization within the
|
|
@@ -30,6 +35,16 @@ export function isEditorViewWithNodeViews(view) {
|
|
|
30
35
|
return view.nodeViews !== undefined;
|
|
31
36
|
}
|
|
32
37
|
|
|
38
|
+
/** Expand-family nodes whose expanded state lives in a node-keyed WeakMap. */
|
|
39
|
+
var EXPAND_TYPES = new Set(['expand', 'nestedExpand']);
|
|
40
|
+
|
|
41
|
+
/** Tables are the only node views that read and write positions, so only they need a preview. */
|
|
42
|
+
var containsTable = function containsTable(node) {
|
|
43
|
+
var table = node.type.schema.nodes.table;
|
|
44
|
+
// `contains` only checks descendants, so the node itself is checked separately.
|
|
45
|
+
return !!table && (node.type === table || contains(node, table));
|
|
46
|
+
};
|
|
47
|
+
|
|
33
48
|
/**
|
|
34
49
|
* Encapsulates DOM serialization and node view access/creation.
|
|
35
50
|
*
|
|
@@ -75,11 +90,18 @@ export var NodeViewSerializer = /*#__PURE__*/function () {
|
|
|
75
90
|
key: "appendChildNodes",
|
|
76
91
|
value: function appendChildNodes(children, contentDOM) {
|
|
77
92
|
var _this = this;
|
|
93
|
+
var basePos = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
|
|
94
|
+
var editorProxy = arguments.length > 3 ? arguments[3] : undefined;
|
|
95
|
+
// A node's first child sits one position inside it, and each subsequent
|
|
96
|
+
// child is offset by the previous child's `nodeSize`. Tracking this lets nested node
|
|
97
|
+
// views resolve to their real depth instead of every one of them seeing depth 0.
|
|
98
|
+
var childPos = basePos + 1;
|
|
78
99
|
children.forEach(function (child) {
|
|
79
|
-
var childNode = _this.
|
|
100
|
+
var childNode = _this.tryCreateNodeViewInner(child, childPos, editorProxy) || _this.serializeNode(child);
|
|
80
101
|
if (childNode) {
|
|
81
102
|
contentDOM === null || contentDOM === void 0 || contentDOM.append(childNode);
|
|
82
103
|
}
|
|
104
|
+
childPos += child.nodeSize;
|
|
83
105
|
});
|
|
84
106
|
}
|
|
85
107
|
|
|
@@ -88,11 +110,29 @@ export var NodeViewSerializer = /*#__PURE__*/function () {
|
|
|
88
110
|
*
|
|
89
111
|
* Returns `null` when there is no `EditorView`, no constructor for the node type,
|
|
90
112
|
* or the node type is blocklisted. Otherwise returns the constructed node view instance.
|
|
113
|
+
*
|
|
114
|
+
* `$sourcePos` is where the node sits in the doc it came from, so nested tables keep their depth.
|
|
91
115
|
*/
|
|
92
116
|
}, {
|
|
93
117
|
key: "tryCreateNodeView",
|
|
94
118
|
value: function tryCreateNodeView(targetNode) {
|
|
119
|
+
var _preview$rootPos;
|
|
120
|
+
var basePos = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
121
|
+
var $sourcePos = arguments.length > 2 ? arguments[2] : undefined;
|
|
122
|
+
if (!this.editorView) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
// The preview becomes the document every nested node view resolves its position against,
|
|
126
|
+
// so positions stay internally consistent.
|
|
127
|
+
var preview = fg('platform_editor_ai_show_diff_patch_2') && containsTable(targetNode) ? createEditorProxy(this.editorView, targetNode, $sourcePos) : null;
|
|
128
|
+
return this.tryCreateNodeViewInner(targetNode, (_preview$rootPos = preview === null || preview === void 0 ? void 0 : preview.rootPos) !== null && _preview$rootPos !== void 0 ? _preview$rootPos : basePos, preview === null || preview === void 0 ? void 0 : preview.editorProxy);
|
|
129
|
+
}
|
|
130
|
+
}, {
|
|
131
|
+
key: "tryCreateNodeViewInner",
|
|
132
|
+
value: function tryCreateNodeViewInner(targetNode) {
|
|
95
133
|
var _this$nodeViews;
|
|
134
|
+
var basePos = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
135
|
+
var editorProxy = arguments.length > 2 ? arguments[2] : undefined;
|
|
96
136
|
if (!this.editorView) {
|
|
97
137
|
return null;
|
|
98
138
|
}
|
|
@@ -138,23 +178,47 @@ export var NodeViewSerializer = /*#__PURE__*/function () {
|
|
|
138
178
|
if (!isExperimentEnabled('platform_editor_show_diff_deleted_nodeview_content') && targetNode.type.name === 'paragraph' && targetNode.children.length === 1) {
|
|
139
179
|
return this.serializeFragment(targetNode.content);
|
|
140
180
|
}
|
|
141
|
-
this.appendChildNodes(targetNode.children, _contentDOM);
|
|
181
|
+
this.appendChildNodes(targetNode.children, _contentDOM, basePos, editorProxy);
|
|
142
182
|
}
|
|
143
|
-
return _dom;
|
|
183
|
+
return this.withMarkViews(targetNode, _dom, editorProxy);
|
|
144
184
|
}
|
|
145
|
-
|
|
146
|
-
|
|
185
|
+
|
|
186
|
+
// The expand node view reads `expandedState.get(node) ?? false`, never `attrs.__expanded`.
|
|
187
|
+
// Open the preview so its tables get real layout; an existing entry is the live expand's
|
|
188
|
+
// own state, so leave it alone.
|
|
189
|
+
if (EXPAND_TYPES.has(targetNode.type.name) && !expandedState.has(targetNode) && fg('platform_editor_ai_show_diff_patch_2')) {
|
|
190
|
+
expandedState.set(targetNode, true);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// `isTableNested` is `doc.resolve(pos).depth > 0`, so the old hardcoded `0` made nested
|
|
194
|
+
// tables size as top-level. Positions are resolved against the preview document, so
|
|
195
|
+
// they are only meaningful with an editor proxy.
|
|
196
|
+
var view = editorProxy !== null && editorProxy !== void 0 ? editorProxy : this.editorView;
|
|
197
|
+
var docSize = view.state.doc.content.size;
|
|
198
|
+
var resolvedPos = editorProxy ? Math.max(0, Math.min(basePos, docSize)) : 0;
|
|
199
|
+
var _constructor = constructor(targetNode, view, function () {
|
|
200
|
+
return resolvedPos;
|
|
147
201
|
}, [], {}),
|
|
148
202
|
dom = _constructor.dom,
|
|
149
203
|
contentDOM = _constructor.contentDOM;
|
|
150
204
|
// Iteratively populate children
|
|
151
|
-
this.appendChildNodes(targetNode.children, contentDOM);
|
|
152
|
-
return dom;
|
|
205
|
+
this.appendChildNodes(targetNode.children, contentDOM, basePos, editorProxy);
|
|
206
|
+
return this.withMarkViews(targetNode, dom, editorProxy);
|
|
153
207
|
} catch (_unused) {
|
|
154
208
|
return null;
|
|
155
209
|
}
|
|
156
210
|
}
|
|
157
211
|
|
|
212
|
+
/** Wraps rendered DOM in its marks, rendered against the editor proxy when there is one. */
|
|
213
|
+
}, {
|
|
214
|
+
key: "withMarkViews",
|
|
215
|
+
value: function withMarkViews(targetNode, nodeDom, editorProxy) {
|
|
216
|
+
return wrapInMarkViews(targetNode, nodeDom, {
|
|
217
|
+
nodeViews: this.nodeViews,
|
|
218
|
+
view: editorProxy !== null && editorProxy !== void 0 ? editorProxy : this.editorView
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
158
222
|
/**
|
|
159
223
|
* Serializes a node to a DOM `Node` using the schema's `DOMSerializer`.
|
|
160
224
|
*/
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
|
|
2
|
+
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
2
3
|
import { getDiffableAttrNames } from '../decorations/utils/diffableAttrs';
|
|
4
|
+
import { getComparableExcerptIncludeAttrs, isExcerptInclude } from '../decorations/utils/excerptIncludeAttrs';
|
|
3
5
|
import { encodeCharacterWithMarks } from './encodeCharacterWithMarks';
|
|
4
6
|
|
|
5
7
|
/**
|
|
@@ -11,14 +13,12 @@ import { encodeCharacterWithMarks } from './encodeCharacterWithMarks';
|
|
|
11
13
|
*/
|
|
12
14
|
|
|
13
15
|
// Stable composite token; attr names are pre-ordered by the caller.
|
|
14
|
-
var encodeNodeWithAttrs = function encodeNodeWithAttrs(
|
|
15
|
-
var _node$attrs;
|
|
16
|
-
var attrs = (_node$attrs = node.attrs) !== null && _node$attrs !== void 0 ? _node$attrs : {};
|
|
16
|
+
var encodeNodeWithAttrs = function encodeNodeWithAttrs(nodeTypeName, attrs, attrNames) {
|
|
17
17
|
var parts = attrNames.map(function (name) {
|
|
18
18
|
var _attrs$name;
|
|
19
19
|
return "".concat(name, "=").concat(JSON.stringify((_attrs$name = attrs[name]) !== null && _attrs$name !== void 0 ? _attrs$name : null));
|
|
20
20
|
});
|
|
21
|
-
return "".concat(
|
|
21
|
+
return "".concat(nodeTypeName, "|").concat(parts.join('|'));
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
// Like the library default, but node types with a `diffableAttrs` rule fold their
|
|
@@ -29,11 +29,13 @@ export var attrAwareTokenEncoder = {
|
|
|
29
29
|
return encodeCharacterWithMarks(char, marks);
|
|
30
30
|
},
|
|
31
31
|
encodeNodeStart: function encodeNodeStart(node) {
|
|
32
|
-
|
|
32
|
+
// A one-sided reference is not comparable from an isolated token. Attribute-step comparison
|
|
33
|
+
// checks the reference when both versions have one.
|
|
34
|
+
var attrs = fg('platform_editor_normalize_excerpt_diff') && node.type.name === 'extension' && isExcerptInclude(node.attrs) ? getComparableExcerptIncludeAttrs(node.attrs) : node.attrs;
|
|
33
35
|
// Normalise variants (e.g. `panel_c1` → `panel`) so `diffableAttrs` needs one entry.
|
|
34
|
-
var attrNames = getDiffableAttrNames(getBaseNodeTypeName(node.type),
|
|
36
|
+
var attrNames = getDiffableAttrNames(getBaseNodeTypeName(node.type), attrs !== null && attrs !== void 0 ? attrs : {});
|
|
35
37
|
if (attrNames && attrNames.length > 0) {
|
|
36
|
-
return encodeNodeWithAttrs(node, attrNames);
|
|
38
|
+
return encodeNodeWithAttrs(node.type.name, attrs, attrNames);
|
|
37
39
|
}
|
|
38
40
|
return node.type.name;
|
|
39
41
|
},
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { GapCursorSelection, Side } from '@atlaskit/editor-common/selection/gap-cursor/selection';
|
|
2
|
+
/**
|
|
3
|
+
* A preview is rendered by the live view's own node views, which read `getPos()` against
|
|
4
|
+
* `view.state.doc` for both layout (`isTableNested`) and writes (`scaleTable` builds attribute
|
|
5
|
+
* steps at `getPos() + 1`). Handing them live positions makes the layout correct but points the
|
|
6
|
+
* writes at unrelated live nodes, so give them a view whose document *is* the preview instead.
|
|
7
|
+
*
|
|
8
|
+
* With `$sourcePos` (the node's position in the doc it came from) the node is swapped into a copy
|
|
9
|
+
* of its real top-level ancestor, so a table inside an expand still resolves as nested.
|
|
10
|
+
*
|
|
11
|
+
* Returns `null` when the node cannot be a top-level child (e.g. a bare `tableCell`), in which
|
|
12
|
+
* case the caller falls back to the live view and the previous stubbed positions.
|
|
13
|
+
*/
|
|
14
|
+
export function createEditorProxy(liveView, rootNode, $sourcePos) {
|
|
15
|
+
var liveState = liveView.state;
|
|
16
|
+
var createDoc = function createDoc(topLevel) {
|
|
17
|
+
return liveState.schema.topNodeType.createChecked(null, topLevel);
|
|
18
|
+
};
|
|
19
|
+
var previewDoc;
|
|
20
|
+
var rootPos = 0;
|
|
21
|
+
try {
|
|
22
|
+
var _$sourcePos$nodeAfter;
|
|
23
|
+
if ($sourcePos && $sourcePos.depth > 0 && ((_$sourcePos$nodeAfter = $sourcePos.nodeAfter) === null || _$sourcePos$nodeAfter === void 0 ? void 0 : _$sourcePos$nodeAfter.type) === rootNode.type) {
|
|
24
|
+
var topLevel = rootNode;
|
|
25
|
+
for (var depth = $sourcePos.depth; depth > 0; depth--) {
|
|
26
|
+
var ancestor = $sourcePos.node(depth);
|
|
27
|
+
topLevel = ancestor.copy(ancestor.content.replaceChild($sourcePos.index(depth), topLevel));
|
|
28
|
+
}
|
|
29
|
+
previewDoc = createDoc(topLevel);
|
|
30
|
+
rootPos = $sourcePos.pos - $sourcePos.before(1);
|
|
31
|
+
} else {
|
|
32
|
+
previewDoc = createDoc(rootNode);
|
|
33
|
+
}
|
|
34
|
+
} catch (_unused) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// A gap cursor just before the node selects nothing, so the table's node view doesn't render
|
|
39
|
+
// as selected or show its controls.
|
|
40
|
+
var previewSelection = new GapCursorSelection(previewDoc.resolve(rootPos), Side.LEFT);
|
|
41
|
+
// Proxy rather than `EditorState.create` so plugin state is shared as-is: re-initialising
|
|
42
|
+
// every plugin per preview would be costly and re-runs their side effects.
|
|
43
|
+
var stateProxy = new Proxy(liveState, {
|
|
44
|
+
get: function get(target, prop, receiver) {
|
|
45
|
+
if (prop === 'doc') {
|
|
46
|
+
return previewDoc;
|
|
47
|
+
}
|
|
48
|
+
if (prop === 'selection') {
|
|
49
|
+
return previewSelection;
|
|
50
|
+
}
|
|
51
|
+
return Reflect.get(target, prop, receiver);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
var editorProxy = new Proxy(liveView, {
|
|
55
|
+
get: function get(target, prop, receiver) {
|
|
56
|
+
if (prop === 'state') {
|
|
57
|
+
return stateProxy;
|
|
58
|
+
}
|
|
59
|
+
if (prop === 'dispatch') {
|
|
60
|
+
// Keep the transaction inside the preview. It was built against `previewDoc`, so
|
|
61
|
+
// applying it to the live state would corrupt the real document.
|
|
62
|
+
return function (tr) {
|
|
63
|
+
try {
|
|
64
|
+
stateProxy = stateProxy.apply(tr);
|
|
65
|
+
} catch (_unused2) {
|
|
66
|
+
// A preview is throwaway; a failed self-update is not worth surfacing.
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
var value = Reflect.get(target, prop, receiver);
|
|
71
|
+
return typeof value === 'function' ? value.bind(target) : value;
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
return {
|
|
75
|
+
editorProxy: editorProxy,
|
|
76
|
+
rootPos: rootPos
|
|
77
|
+
};
|
|
78
|
+
}
|
|
@@ -5,8 +5,8 @@ import { Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
|
5
5
|
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
6
6
|
import { ContributorTagController } from '../../ui/ContributorTag/contributorTagController';
|
|
7
7
|
import { buildCharsByOffset, isWhitespaceChar } from '../utils/charsByOffset';
|
|
8
|
-
import { clampAnchorPosIntoCell } from './createAnchorDecorationWidgets';
|
|
9
|
-
import { AnchorTypeKey, buildAnchorDecorationKey, buildContributorTagDecorationSpec } from './decorationKeys';
|
|
8
|
+
import { clampAnchorPosIntoCell, createAnchorNameSpan } from './createAnchorDecorationWidgets';
|
|
9
|
+
import { AnchorTypeKey, buildAnchorDecorationKey, buildAnchorDecorationSpec, buildContributorTagDecorationSpec } from './decorationKeys';
|
|
10
10
|
|
|
11
11
|
/** Marks the host element of one tag, so a tag can be found in the document by its own diff. */
|
|
12
12
|
export var CONTRIBUTOR_TAG_HOST_ATTRIBUTE = 'data-contributor-tag-host';
|
|
@@ -218,13 +218,14 @@ export var resolveHoistedCodeBlockAnchor = function resolveHoistedCodeBlockAncho
|
|
|
218
218
|
* highlights — or, with `anchorAtRangeStart`, at `from` itself. A host inside a code block is
|
|
219
219
|
* hoisted in front of it instead, anchored via `resolveHoistedCodeBlockAnchor` (EDITOR-9045).
|
|
220
220
|
*
|
|
221
|
-
* Returns one decoration
|
|
221
|
+
* Returns one decoration when a caller-supplied `anchorName` is used, two (marker + tag)
|
|
222
|
+
* otherwise — hoisted out of a code block, or anchored to its own point marker.
|
|
222
223
|
*
|
|
223
224
|
* The tag is mounted in `toDOM` and taken down in `destroy`, so it lives exactly as long as the host
|
|
224
225
|
* element ProseMirror drew it into — see `mountContributorTag`.
|
|
225
226
|
*/
|
|
226
227
|
export var createContributorTagWidget = function createContributorTagWidget(_ref4) {
|
|
227
|
-
var _hoisted$
|
|
228
|
+
var _hoisted$codeBlockSta, _ref5, _hoisted$anchorName;
|
|
228
229
|
var _ref4$anchorAtRangeSt = _ref4.anchorAtRangeStart,
|
|
229
230
|
anchorAtRangeStart = _ref4$anchorAtRangeSt === void 0 ? false : _ref4$anchorAtRangeSt,
|
|
230
231
|
anchorName = _ref4.anchorName,
|
|
@@ -244,15 +245,33 @@ export var createContributorTagWidget = function createContributorTagWidget(_ref
|
|
|
244
245
|
// A change inside a code block is hoisted out of it, anchored to its own marker; anything else
|
|
245
246
|
// keeps its own anchor.
|
|
246
247
|
var hoisted = resolveHoistedCodeBlockAnchor(doc, anchorPos, diffId);
|
|
247
|
-
|
|
248
|
+
// Keep the host out of the table row's grid (EDITOR-8442).
|
|
249
|
+
var hostPos = clampAnchorPosIntoCell(doc, (_hoisted$codeBlockSta = hoisted === null || hoisted === void 0 ? void 0 : hoisted.codeBlockStart) !== null && _hoisted$codeBlockSta !== void 0 ? _hoisted$codeBlockSta : anchorPos, 1);
|
|
250
|
+
|
|
251
|
+
// Inline diffs pass no anchorName. Give them their own point anchor instead of the
|
|
252
|
+
// `position: relative` fallback, which drifts left once the range wraps a line (EDITOR-9286).
|
|
253
|
+
var ownAnchorName = buildAnchorDecorationKey({
|
|
254
|
+
diffId: diffId,
|
|
255
|
+
anchorType: AnchorTypeKey.tag
|
|
256
|
+
});
|
|
257
|
+
var effectiveAnchorName = (_ref5 = (_hoisted$anchorName = hoisted === null || hoisted === void 0 ? void 0 : hoisted.anchorName) !== null && _hoisted$anchorName !== void 0 ? _hoisted$anchorName : anchorName) !== null && _ref5 !== void 0 ? _ref5 : ownAnchorName;
|
|
248
258
|
var tagAnchorName = effectiveAnchorName && supportsAnchorPositioning() ? effectiveAnchorName : undefined;
|
|
249
259
|
var decorations = [];
|
|
250
260
|
if (hoisted) {
|
|
251
261
|
decorations.push(hoisted.marker);
|
|
262
|
+
} else if (!anchorName && tagAnchorName) {
|
|
263
|
+
decorations.push(Decoration.widget(hostPos, function () {
|
|
264
|
+
return createAnchorNameSpan(ownAnchorName);
|
|
265
|
+
}, _objectSpread(_objectSpread({}, buildAnchorDecorationSpec({
|
|
266
|
+
diffId: diffId,
|
|
267
|
+
anchorType: AnchorTypeKey.tag,
|
|
268
|
+
side: -1
|
|
269
|
+
})), {}, {
|
|
270
|
+
marks: [],
|
|
271
|
+
ignoreSelection: true
|
|
272
|
+
})));
|
|
252
273
|
}
|
|
253
|
-
decorations.push(Decoration.widget(
|
|
254
|
-
// Keep the host out of the table row's grid (EDITOR-8442).
|
|
255
|
-
clampAnchorPosIntoCell(doc, (_hoisted$codeBlockSta = hoisted === null || hoisted === void 0 ? void 0 : hoisted.codeBlockStart) !== null && _hoisted$codeBlockSta !== void 0 ? _hoisted$codeBlockSta : anchorPos, 1), function () {
|
|
274
|
+
decorations.push(Decoration.widget(hostPos, function () {
|
|
256
275
|
var host = buildContributorTagHost(diffId, tagAnchorName);
|
|
257
276
|
mount = mountContributorTag({
|
|
258
277
|
anchorName: tagAnchorName,
|
|
@@ -5,7 +5,7 @@ import { Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
|
5
5
|
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
6
6
|
import { countEmptyTextBlockOnlySlice } from '../utils/emptyTextBlocks';
|
|
7
7
|
import { isEmptyParagraphSlice } from '../utils/isEmptyParagraphSlice';
|
|
8
|
-
import { clampAnchorPosIntoCell, createLeftAnchorWidget } from './createAnchorDecorationWidgets';
|
|
8
|
+
import { clampAnchorPosIntoCell, createAnchorNameSpan, createLeftAnchorWidget } from './createAnchorDecorationWidgets';
|
|
9
9
|
import { createChangedRowDecorationWidgets } from './createChangedRowDecorationWidgets';
|
|
10
10
|
import { createContributorTagHost, resolveHoistedCodeBlockAnchor, unmountContributorTag } from './createContributorTagWidget';
|
|
11
11
|
import { AnchorTypeKey, buildContributorTagDecorationSpec, buildDiffDecorationSpec, buildAnchorDecorationKey, scrollMarginTopValue } from './decorationKeys';
|
|
@@ -17,6 +17,22 @@ import { findSafeInsertPos } from './utils/findSafeInsertPos';
|
|
|
17
17
|
import { safeResolve } from './utils/safeResolve';
|
|
18
18
|
import { getTableDiffMode } from './utils/tableDiffMode';
|
|
19
19
|
import { wrapBlockNodeView, createRemovedLozenge, injectInnerWrapper, createContentWrapper } from './utils/wrapBlockNodeView';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Where a slice's `index`th child sits in `doc`: the children belong to the ancestor `openStart`
|
|
23
|
+
* levels above the change. `null` if out of range — `posAtIndex` throws past the last child.
|
|
24
|
+
*/
|
|
25
|
+
var getSourcePos = function getSourcePos(doc, $changeFrom, openStart, index) {
|
|
26
|
+
var depth = $changeFrom ? $changeFrom.depth - openStart : -1;
|
|
27
|
+
if (!$changeFrom || depth < 0) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
var childIndex = $changeFrom.index(depth) + index;
|
|
31
|
+
if (childIndex >= $changeFrom.node(depth).childCount) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
return safeResolve(doc, $changeFrom.posAtIndex(childIndex, depth));
|
|
35
|
+
};
|
|
20
36
|
var isHeadingLevel = function isHeadingLevel(level) {
|
|
21
37
|
return typeof level === 'number' && level >= 1 && level <= 6;
|
|
22
38
|
};
|
|
@@ -284,7 +300,7 @@ export var createNodeChangedDecorationWidget = function createNodeChangedDecorat
|
|
|
284
300
|
* and if it's the first or last content, we go in however many the sliced Open
|
|
285
301
|
* or sliced End depth is and match only the entire node.
|
|
286
302
|
*/
|
|
287
|
-
slice.content.forEach(function (node) {
|
|
303
|
+
slice.content.forEach(function (node, _offset, index) {
|
|
288
304
|
var isFirst = firstReplacedNode === node;
|
|
289
305
|
var isLast = lastReplacedNode === node;
|
|
290
306
|
var isOpenAtSliceBoundary = isFirst && slice.openStart > 0 || isLast && slice.openEnd > 0;
|
|
@@ -355,7 +371,8 @@ export var createNodeChangedDecorationWidget = function createNodeChangedDecorat
|
|
|
355
371
|
}
|
|
356
372
|
|
|
357
373
|
// Try to create node view, fallback to serialization
|
|
358
|
-
var
|
|
374
|
+
var $sourcePos = fg('platform_editor_ai_show_diff_patch_2') ? getSourcePos(doc, $changeFromA, slice.openStart, index) : null;
|
|
375
|
+
var nodeView = serializer.tryCreateNodeView(node, 0, $sourcePos !== null && $sourcePos !== void 0 ? $sourcePos : undefined);
|
|
359
376
|
if (nodeView) {
|
|
360
377
|
if (node.isInline) {
|
|
361
378
|
var wrapper = createContentWrapper(colorScheme, isActive, isInserted, reveal);
|
|
@@ -458,18 +475,27 @@ export var createNodeChangedDecorationWidget = function createNodeChangedDecorat
|
|
|
458
475
|
});
|
|
459
476
|
}
|
|
460
477
|
|
|
461
|
-
// Needed even
|
|
462
|
-
// widget.
|
|
478
|
+
// Needed even with the indicator bar off, since it anchors its top/bottom to the widget.
|
|
463
479
|
if (showIndicators || showContributorTags) {
|
|
464
480
|
dom.style.setProperty('anchor-name', "--".concat(buildAnchorDecorationKey({
|
|
465
481
|
diffId: diffId
|
|
466
482
|
})));
|
|
467
|
-
//
|
|
468
|
-
//
|
|
469
|
-
if (fg('confluence_ncs_step_diffing_version_history')) {
|
|
470
|
-
|
|
471
|
-
diffId: diffId
|
|
483
|
+
// `dom` is inline, so its box fragments across a line wrap and `anchor()` resolves to the
|
|
484
|
+
// wrong edge. The tag anchors to its own point marker instead (EDITOR-9286).
|
|
485
|
+
if (fg('confluence_ncs_step_diffing_version_history') && !contributorTagAnchorName) {
|
|
486
|
+
var tagPointAnchorName = buildAnchorDecorationKey({
|
|
487
|
+
diffId: diffId,
|
|
488
|
+
anchorType: AnchorTypeKey.tag
|
|
472
489
|
});
|
|
490
|
+
contributorTagAnchorName = tagPointAnchorName;
|
|
491
|
+
decorations.push(Decoration.widget(safeInsertPos, function () {
|
|
492
|
+
return createAnchorNameSpan(tagPointAnchorName);
|
|
493
|
+
}, {
|
|
494
|
+
key: "contributor-tag-anchor-".concat(diffId),
|
|
495
|
+
side: -1,
|
|
496
|
+
marks: [],
|
|
497
|
+
ignoreSelection: true
|
|
498
|
+
}));
|
|
473
499
|
}
|
|
474
500
|
}
|
|
475
501
|
|
|
@@ -504,8 +530,7 @@ export var createNodeChangedDecorationWidget = function createNodeChangedDecorat
|
|
|
504
530
|
}
|
|
505
531
|
})));
|
|
506
532
|
} else {
|
|
507
|
-
//
|
|
508
|
-
// the deleted content wraps its box is the union of its line fragments.
|
|
533
|
+
// Anchored to the point marker pushed above, not to `dom` (EDITOR-9286).
|
|
509
534
|
var tagHost = createContributorTagHost({
|
|
510
535
|
anchorName: contributorTagAnchorName,
|
|
511
536
|
diffId: diffId,
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import _typeof from "@babel/runtime/helpers/typeof";
|
|
2
|
+
import pick from 'lodash/pick';
|
|
3
|
+
var asRecord = function asRecord(value) {
|
|
4
|
+
return value !== null && _typeof(value) === 'object' && !Array.isArray(value) ? value : undefined;
|
|
5
|
+
};
|
|
6
|
+
export var isExcerptInclude = function isExcerptInclude(attrs) {
|
|
7
|
+
return attrs.extensionKey === 'excerpt-include';
|
|
8
|
+
};
|
|
9
|
+
export var getReferencedContentId = function getReferencedContentId(attrs) {
|
|
10
|
+
var _asRecord;
|
|
11
|
+
var parameters = asRecord(attrs.parameters);
|
|
12
|
+
var macroParams = asRecord(parameters === null || parameters === void 0 ? void 0 : parameters.macroParams);
|
|
13
|
+
var value = (_asRecord = asRecord(macroParams === null || macroParams === void 0 ? void 0 : macroParams._referencedContentId)) === null || _asRecord === void 0 ? void 0 : _asRecord.value;
|
|
14
|
+
return typeof value === 'string' ? value : undefined;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/** Compare macro identity and authored options, excluding publish-time rendering metadata. */
|
|
18
|
+
export var getComparableExcerptIncludeAttrs = function getComparableExcerptIncludeAttrs(attrs) {
|
|
19
|
+
return pick(attrs, ['extensionType', 'layout', 'parameters.macroMetadata.macroId.value', 'parameters.macroParams[""].value', 'parameters.macroParams.name.value', 'parameters.macroParams.nopanel.value', 'parameters.macroParams.inline.value']);
|
|
20
|
+
};
|
|
@@ -6,7 +6,9 @@ import omit from 'lodash/omit';
|
|
|
6
6
|
import { SetAttrsStep } from '@atlaskit/adf-schema/steps/set-attrs';
|
|
7
7
|
import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
|
|
8
8
|
import { AttrStep } from '@atlaskit/editor-prosemirror/transform';
|
|
9
|
+
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
9
10
|
import { getRequiredIncludedDiffableAttrs, isDiffableAttr } from './diffableAttrs';
|
|
11
|
+
import { getComparableExcerptIncludeAttrs, getReferencedContentId, isExcerptInclude } from './excerptIncludeAttrs';
|
|
10
12
|
var filterUndefined = function filterUndefined(x) {
|
|
11
13
|
return !!x;
|
|
12
14
|
};
|
|
@@ -44,6 +46,11 @@ var getComparableExtensionAttrs = function getComparableExtensionAttrs(node) {
|
|
|
44
46
|
return omit(node.attrs, transientExtensionAttrPaths);
|
|
45
47
|
};
|
|
46
48
|
var haveSameRelevantExtensionAttrs = function haveSameRelevantExtensionAttrs(beforeNode, afterNode) {
|
|
49
|
+
if (fg('platform_editor_normalize_excerpt_diff') && isExcerptInclude(beforeNode.attrs) && isExcerptInclude(afterNode.attrs)) {
|
|
50
|
+
var beforeReference = getReferencedContentId(beforeNode.attrs);
|
|
51
|
+
var afterReference = getReferencedContentId(afterNode.attrs);
|
|
52
|
+
return isEqual(getComparableExcerptIncludeAttrs(beforeNode.attrs), getComparableExcerptIncludeAttrs(afterNode.attrs)) && (beforeReference === undefined || afterReference === undefined || beforeReference === afterReference);
|
|
53
|
+
}
|
|
47
54
|
return isEqual(getComparableExtensionAttrs(beforeNode), getComparableExtensionAttrs(afterNode));
|
|
48
55
|
};
|
|
49
56
|
var getStepAttrs = function getStepAttrs(step) {
|
|
@@ -314,6 +314,21 @@ var applyTextLikeBlockNodeStyles = function applyTextLikeBlockNodeStyles(_ref8)
|
|
|
314
314
|
/**
|
|
315
315
|
* Creates a content wrapper with deleted styles for a block node
|
|
316
316
|
*/
|
|
317
|
+
/**
|
|
318
|
+
* The element that spans breakout width, for nodes carrying a `breakout` mark. The wrapper divs
|
|
319
|
+
* stay at editor-column width, so anything that should align to the node's visible edges —
|
|
320
|
+
* outlines, absolutely positioned lozenges — has to attach here instead.
|
|
321
|
+
*/
|
|
322
|
+
var findBreakoutElement = function findBreakoutElement(targetNode, nodeView) {
|
|
323
|
+
var _targetNode$marks;
|
|
324
|
+
var hasBreakoutMark = (_targetNode$marks = targetNode.marks) === null || _targetNode$marks === void 0 ? void 0 : _targetNode$marks.some(function (mark) {
|
|
325
|
+
return mark.type.name === 'breakout';
|
|
326
|
+
});
|
|
327
|
+
if (!hasBreakoutMark || !(nodeView instanceof HTMLElement)) {
|
|
328
|
+
return null;
|
|
329
|
+
}
|
|
330
|
+
return nodeView.matches('[data-node-type]') ? nodeView : nodeView.querySelector('[data-node-type]');
|
|
331
|
+
};
|
|
317
332
|
var createBlockNodeContentWrapper = function createBlockNodeContentWrapper(_ref9) {
|
|
318
333
|
var nodeView = _ref9.nodeView,
|
|
319
334
|
targetNode = _ref9.targetNode,
|
|
@@ -331,7 +346,16 @@ var createBlockNodeContentWrapper = function createBlockNodeContentWrapper(_ref9
|
|
|
331
346
|
// should not also get the inline content style (borderBottom underline) on their container.
|
|
332
347
|
var shouldSkipContentStyle = isInserted && nodeStyle !== undefined;
|
|
333
348
|
var contentStyle = shouldSkipContentStyle ? '' : getChangedContentStyle(colorScheme, isActive, isInserted, hideAddedDiffsUnderline);
|
|
334
|
-
|
|
349
|
+
|
|
350
|
+
// A `breakout` node renders wider than the editor column while the wrapper divs
|
|
351
|
+
// stay at column width, so paint the outline on the node element that spans that width.
|
|
352
|
+
var breakoutTarget = nodeStyle ? findBreakoutElement(targetNode, nodeView) : null;
|
|
353
|
+
if (fg('platform_editor_ai_show_diff_patch_2') && breakoutTarget) {
|
|
354
|
+
appendStyleToElement(breakoutTarget, nodeStyle !== null && nodeStyle !== void 0 ? nodeStyle : '');
|
|
355
|
+
contentWrapper.setAttribute('style', contentStyle || '');
|
|
356
|
+
} else {
|
|
357
|
+
contentWrapper.setAttribute('style', "".concat(contentStyle).concat(nodeStyle || ''));
|
|
358
|
+
}
|
|
335
359
|
contentWrapper.append(nodeView);
|
|
336
360
|
return contentWrapper;
|
|
337
361
|
};
|
|
@@ -461,7 +485,19 @@ var wrapBlockNode = function wrapBlockNode(_ref10) {
|
|
|
461
485
|
})) {
|
|
462
486
|
return;
|
|
463
487
|
}
|
|
464
|
-
|
|
488
|
+
|
|
489
|
+
// `lozenge` is absolutely positioned, so it lands on the nearest positioned ancestor. For a
|
|
490
|
+
// breakout node that is the column-width wrapper, leaving the pill short of the node's
|
|
491
|
+
// right edge — host it on the breakout element, which must establish a containing block.
|
|
492
|
+
var breakoutHost = fg('platform_editor_ai_show_diff_patch_2') ? findBreakoutElement(targetNode, nodeView) : null;
|
|
493
|
+
if (breakoutHost) {
|
|
494
|
+
appendStyleToElement(breakoutHost, convertToInlineCss({
|
|
495
|
+
position: 'relative'
|
|
496
|
+
}));
|
|
497
|
+
breakoutHost.append(lozenge);
|
|
498
|
+
} else {
|
|
499
|
+
blockWrapper.append(lozenge);
|
|
500
|
+
}
|
|
465
501
|
}
|
|
466
502
|
var contentWrapper = createBlockNodeContentWrapper({
|
|
467
503
|
nodeView: nodeView,
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
+
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* `@atlaskit/editor-prosemirror/view` doesn't re-export prosemirror-view's `MarkViewConstructor`,
|
|
6
|
+
* so it's typed locally, as `EditorSSRRenderer` does.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** Where to look up a mark's renderer, and the view to render it against. */
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Renders a mark as ProseMirror does: `view.nodeViews` also holds mark views, keyed by mark name,
|
|
13
|
+
* so `breakout` resolves whether it's registered under `markViews` or `nodeViews`. Falls back to
|
|
14
|
+
* `toDOM` — they can differ: `breakout` renders `.fabric-editor-breakout-mark-dom`, which the width
|
|
15
|
+
* CSS targets.
|
|
16
|
+
*/
|
|
17
|
+
var renderMarkView = function renderMarkView(mark, inline, _ref) {
|
|
18
|
+
var nodeViews = _ref.nodeViews,
|
|
19
|
+
view = _ref.view;
|
|
20
|
+
try {
|
|
21
|
+
var markView = nodeViews === null || nodeViews === void 0 ? void 0 : nodeViews[mark.type.name];
|
|
22
|
+
if (markView && view) {
|
|
23
|
+
var rendered = markView(mark, view, inline);
|
|
24
|
+
return {
|
|
25
|
+
dom: rendered.dom,
|
|
26
|
+
contentDOM: rendered.contentDOM
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
var toDOM = mark.type.spec.toDOM;
|
|
30
|
+
if (!toDOM) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
return DOMSerializer.renderSpec(document, toDOM(mark, inline));
|
|
34
|
+
} catch (_unused) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Wraps rendered DOM in its marks, as ProseMirror does for the live document. Without this a
|
|
41
|
+
* block node loses `breakout`, whose wrapper supplies the width. Marks nest
|
|
42
|
+
* outside-in, so `marks[0]` is outermost.
|
|
43
|
+
*/
|
|
44
|
+
export var wrapInMarkViews = function wrapInMarkViews(targetNode, nodeDom, sources) {
|
|
45
|
+
if (targetNode.marks.length === 0 || !fg('platform_editor_ai_show_diff_patch_2')) {
|
|
46
|
+
return nodeDom;
|
|
47
|
+
}
|
|
48
|
+
var wrapped = nodeDom;
|
|
49
|
+
for (var index = targetNode.marks.length - 1; index >= 0; index--) {
|
|
50
|
+
var _mark = targetNode.marks[index];
|
|
51
|
+
var rendered = renderMarkView(_mark, targetNode.isInline, sources);
|
|
52
|
+
// No content hole means nowhere to nest the node, so skip the mark, not the node.
|
|
53
|
+
if (!(rendered !== null && rendered !== void 0 && rendered.contentDOM)) {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
rendered.contentDOM.appendChild(wrapped);
|
|
57
|
+
wrapped = rendered.dom;
|
|
58
|
+
}
|
|
59
|
+
return wrapped;
|
|
60
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { NodeViewConstructor } from '@atlaskit/editor-common/lazy-node-view';
|
|
2
|
-
import type { Node as PMNode, Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
+
import type { Node as PMNode, Fragment, ResolvedPos } from '@atlaskit/editor-prosemirror/model';
|
|
3
3
|
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
4
4
|
/**
|
|
5
5
|
* Utilities for working with ProseMirror node views and DOM serialization within the
|
|
@@ -58,8 +58,13 @@ export declare class NodeViewSerializer {
|
|
|
58
58
|
*
|
|
59
59
|
* Returns `null` when there is no `EditorView`, no constructor for the node type,
|
|
60
60
|
* or the node type is blocklisted. Otherwise returns the constructed node view instance.
|
|
61
|
+
*
|
|
62
|
+
* `$sourcePos` is where the node sits in the doc it came from, so nested tables keep their depth.
|
|
61
63
|
*/
|
|
62
|
-
tryCreateNodeView(targetNode: PMNode): Node | null;
|
|
64
|
+
tryCreateNodeView(targetNode: PMNode, basePos?: number, $sourcePos?: ResolvedPos): Node | null;
|
|
65
|
+
private tryCreateNodeViewInner;
|
|
66
|
+
/** Wraps rendered DOM in its marks, rendered against the editor proxy when there is one. */
|
|
67
|
+
private withMarkViews;
|
|
63
68
|
/**
|
|
64
69
|
* Serializes a node to a DOM `Node` using the schema's `DOMSerializer`.
|
|
65
70
|
*/
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Node as PMNode, ResolvedPos } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
+
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
3
|
+
/**
|
|
4
|
+
* A preview is rendered by the live view's own node views, which read `getPos()` against
|
|
5
|
+
* `view.state.doc` for both layout (`isTableNested`) and writes (`scaleTable` builds attribute
|
|
6
|
+
* steps at `getPos() + 1`). Handing them live positions makes the layout correct but points the
|
|
7
|
+
* writes at unrelated live nodes, so give them a view whose document *is* the preview instead.
|
|
8
|
+
*
|
|
9
|
+
* With `$sourcePos` (the node's position in the doc it came from) the node is swapped into a copy
|
|
10
|
+
* of its real top-level ancestor, so a table inside an expand still resolves as nested.
|
|
11
|
+
*
|
|
12
|
+
* Returns `null` when the node cannot be a top-level child (e.g. a bare `tableCell`), in which
|
|
13
|
+
* case the caller falls back to the live view and the previous stubbed positions.
|
|
14
|
+
*/
|
|
15
|
+
export declare function createEditorProxy(liveView: EditorView, rootNode: PMNode, $sourcePos?: ResolvedPos): {
|
|
16
|
+
editorProxy: EditorView;
|
|
17
|
+
rootPos: number;
|
|
18
|
+
} | null;
|
|
@@ -68,7 +68,8 @@ export declare const resolveHoistedCodeBlockAnchor: (doc: PMNode, pos: number, d
|
|
|
68
68
|
* highlights — or, with `anchorAtRangeStart`, at `from` itself. A host inside a code block is
|
|
69
69
|
* hoisted in front of it instead, anchored via `resolveHoistedCodeBlockAnchor` (EDITOR-9045).
|
|
70
70
|
*
|
|
71
|
-
* Returns one decoration
|
|
71
|
+
* Returns one decoration when a caller-supplied `anchorName` is used, two (marker + tag)
|
|
72
|
+
* otherwise — hoisted out of a code block, or anchored to its own point marker.
|
|
72
73
|
*
|
|
73
74
|
* The tag is mounted in `toDOM` and taken down in `destroy`, so it lives exactly as long as the host
|
|
74
75
|
* element ProseMirror drew it into — see `mountContributorTag`.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
type ExtensionAttrs = Record<string, unknown>;
|
|
2
|
+
export declare const isExcerptInclude: (attrs: ExtensionAttrs) => boolean;
|
|
3
|
+
export declare const getReferencedContentId: (attrs: ExtensionAttrs) => string | undefined;
|
|
4
|
+
/** Compare macro identity and authored options, excluding publish-time rendering metadata. */
|
|
5
|
+
export declare const getComparableExcerptIncludeAttrs: (attrs: ExtensionAttrs) => ExtensionAttrs;
|
|
6
|
+
export {};
|