@atlaskit/editor-plugin-show-diff 21.0.0 → 21.0.2
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 +17 -0
- package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +51 -13
- package/dist/cjs/pm-plugins/calculateDiff/markAwareTokenEncoder.js +2 -1
- package/dist/cjs/pm-plugins/calculateDiff/selectTokenEncoder.js +1 -1
- package/dist/cjs/pm-plugins/decorations/utils/diffableAttrs.js +5 -1
- package/dist/cjs/pm-plugins/decorations/utils/getAttrChangeRanges.js +10 -7
- package/dist/cjs/pm-plugins/resolveDiffContributors.js +3 -3
- package/dist/cjs/ui/ContributorTag/contributorAvatarRenderer.js +8 -9
- package/dist/cjs/ui/ContributorTag/contributorTagIcons.js +1 -8
- package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +38 -11
- package/dist/es2019/pm-plugins/calculateDiff/markAwareTokenEncoder.js +2 -1
- package/dist/es2019/pm-plugins/calculateDiff/selectTokenEncoder.js +1 -1
- package/dist/es2019/pm-plugins/decorations/utils/diffableAttrs.js +6 -1
- package/dist/es2019/pm-plugins/decorations/utils/getAttrChangeRanges.js +4 -3
- package/dist/es2019/pm-plugins/resolveDiffContributors.js +3 -3
- package/dist/es2019/ui/ContributorTag/contributorAvatarRenderer.js +8 -9
- package/dist/es2019/ui/ContributorTag/contributorTagIcons.js +1 -8
- package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +51 -13
- package/dist/esm/pm-plugins/calculateDiff/markAwareTokenEncoder.js +2 -1
- package/dist/esm/pm-plugins/calculateDiff/selectTokenEncoder.js +1 -1
- package/dist/esm/pm-plugins/decorations/utils/diffableAttrs.js +6 -1
- package/dist/esm/pm-plugins/decorations/utils/getAttrChangeRanges.js +10 -7
- package/dist/esm/pm-plugins/resolveDiffContributors.js +3 -3
- package/dist/esm/ui/ContributorTag/contributorAvatarRenderer.js +8 -9
- package/dist/esm/ui/ContributorTag/contributorTagIcons.js +1 -8
- package/dist/types/pm-plugins/calculateDiff/markAwareTokenEncoder.d.ts +2 -1
- package/dist/types/pm-plugins/calculateDiff/selectTokenEncoder.d.ts +1 -1
- package/dist/types/ui/ContributorTag/contributorTagIcons.d.ts +1 -4
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-show-diff
|
|
2
2
|
|
|
3
|
+
## 21.0.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`1647c1098fca5`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/1647c1098fca5) -
|
|
8
|
+
Highlight changed inline nodes and the edited portion of link display text
|
|
9
|
+
|
|
10
|
+
## 21.0.1
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- [`df1aa098e75d3`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/df1aa098e75d3) -
|
|
15
|
+
Contributor tags now always render Rovo's real avatar URL when available, instead of the hardcoded
|
|
16
|
+
Rovo glyph. The glyph was removed; the generic agent fallback is used when no URL is supplied or
|
|
17
|
+
it fails to load, matching Figma/Lovable/Replit.
|
|
18
|
+
- Updated dependencies
|
|
19
|
+
|
|
3
20
|
## 21.0.0
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
|
@@ -464,11 +464,14 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
|
|
|
464
464
|
};
|
|
465
465
|
}
|
|
466
466
|
}
|
|
467
|
-
// The attribute-aware encoder is
|
|
468
|
-
|
|
467
|
+
// The attribute-aware encoder is needed by the smart classifier and is gated with it.
|
|
468
|
+
// The NCS version-history path also uses it so the main diff calculation detects attribute-only
|
|
469
|
+
// node replacements, e.g. changing an emoji or mention without changing the node type.
|
|
470
|
+
var _selectTokenEncoder = (0, _selectTokenEncoder2.selectTokenEncoder)(diffType === 'smart' && (0, _fg.fg)('platform_editor_ai_smart_diff') || (0, _fg.fg)('confluence_ncs_step_diffing_version_history')),
|
|
469
471
|
tokenEncoder = _selectTokenEncoder.tokenEncoder,
|
|
470
472
|
shouldHideMarkOnlyDeletions = _selectTokenEncoder.shouldHideMarkOnlyDeletions;
|
|
471
473
|
var changes;
|
|
474
|
+
var contentChanges;
|
|
472
475
|
var attributedChanges = [];
|
|
473
476
|
var attributionColors;
|
|
474
477
|
if (attributedChangesetEnabled) {
|
|
@@ -482,6 +485,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
|
|
|
482
485
|
stepIndex: stepIndex
|
|
483
486
|
});
|
|
484
487
|
}));
|
|
488
|
+
contentChanges = changeset.changes;
|
|
485
489
|
attributedChanges = diffType === 'step' ? (0, _diffBySteps.diffBySteps)(originalDoc, simplifiedSteps, simplifiedStepAttributions) : (0, _toConsumableArray2.default)(changeset.changes);
|
|
486
490
|
// The attributed pipeline gives no guarantee that its output ranges are disjoint — see
|
|
487
491
|
// `collapseOverlappingChanges`.
|
|
@@ -501,6 +505,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
|
|
|
501
505
|
}
|
|
502
506
|
} else {
|
|
503
507
|
var _changeset = _prosemirrorChangeset.ChangeSet.create(originalDoc, undefined, tokenEncoder).addSteps(steppedDoc, stepMaps, tr.doc);
|
|
508
|
+
contentChanges = _changeset.changes;
|
|
504
509
|
changes = getChanges({
|
|
505
510
|
changeset: _changeset,
|
|
506
511
|
originalDoc: originalDoc,
|
|
@@ -760,20 +765,52 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
|
|
|
760
765
|
changes.forEach(function (change) {
|
|
761
766
|
createDecorationsForChange(change);
|
|
762
767
|
});
|
|
763
|
-
//
|
|
764
|
-
//
|
|
765
|
-
//
|
|
766
|
-
|
|
767
|
-
(0, _getMarkChangeRanges.getMarkChangeRanges)(simplifiedSteps, simplifiedStepAttributions, (0, _fg.fg)('confluence_ncs_step_diffing_version_history') ? stepMaps : undefined).filter(function (_ref10) {
|
|
768
|
+
// Compare the content outside replacement ranges at matching positions in both documents.
|
|
769
|
+
// This preserves real formatting edits without highlighting an unchanged link mark reapplied
|
|
770
|
+
// while editing its display text.
|
|
771
|
+
var hasUnhighlightedMarkChanges = function hasUnhighlightedMarkChanges(_ref10) {
|
|
768
772
|
var fromB = _ref10.fromB,
|
|
769
773
|
toB = _ref10.toB;
|
|
770
|
-
|
|
771
|
-
|
|
774
|
+
var from = fromB;
|
|
775
|
+
var offset = 0;
|
|
776
|
+
var differs = function differs(to) {
|
|
777
|
+
return from < to && !originalDoc.slice(from + offset, to + offset).content.eq(tr.doc.slice(from, to).content);
|
|
778
|
+
};
|
|
779
|
+
var _iterator5 = _createForOfIteratorHelper(contentChanges),
|
|
780
|
+
_step5;
|
|
781
|
+
try {
|
|
782
|
+
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
|
|
783
|
+
var change = _step5.value;
|
|
784
|
+
if (change.fromB >= toB) {
|
|
785
|
+
break;
|
|
786
|
+
}
|
|
787
|
+
if (change.toB > from) {
|
|
788
|
+
if (differs(change.fromB)) {
|
|
789
|
+
return true;
|
|
790
|
+
}
|
|
791
|
+
from = change.toB;
|
|
792
|
+
}
|
|
793
|
+
offset = change.toA - change.toB;
|
|
794
|
+
}
|
|
795
|
+
} catch (err) {
|
|
796
|
+
_iterator5.e(err);
|
|
797
|
+
} finally {
|
|
798
|
+
_iterator5.f();
|
|
799
|
+
}
|
|
800
|
+
return differs(toB);
|
|
801
|
+
};
|
|
802
|
+
|
|
803
|
+
// The attribute-aware token encoder already reports mark-only changes as regular changes in the
|
|
804
|
+
// smart path and the NCS version-history path. For NCS version history, only skip the step-range
|
|
805
|
+
// highlight if the main diff covers it or the remaining content has unchanged formatting.
|
|
806
|
+
(0, _getMarkChangeRanges.getMarkChangeRanges)(simplifiedSteps, simplifiedStepAttributions, (0, _fg.fg)('confluence_ncs_step_diffing_version_history') ? stepMaps : undefined).filter(function (_ref11) {
|
|
772
807
|
var fromB = _ref11.fromB,
|
|
773
808
|
toB = _ref11.toB;
|
|
809
|
+
return !isHandledByTable(fromB, toB);
|
|
810
|
+
}).filter(function (range) {
|
|
774
811
|
return !(0, _fg.fg)('confluence_ncs_step_diffing_version_history') || !changes.some(function (change) {
|
|
775
|
-
return change.fromB
|
|
776
|
-
});
|
|
812
|
+
return change.fromB <= range.fromB && change.toB >= range.toB;
|
|
813
|
+
}) && hasUnhighlightedMarkChanges(range);
|
|
777
814
|
}).forEach(function (change) {
|
|
778
815
|
var _attributionColors$ge, _attributionColors;
|
|
779
816
|
var changeColorScheme = change.attributionKey ? (_attributionColors$ge = (_attributionColors = attributionColors) === null || _attributionColors === void 0 ? void 0 : _attributionColors.get(change.attributionKey)) !== null && _attributionColors$ge !== void 0 ? _attributionColors$ge : colorScheme : colorScheme;
|
|
@@ -797,8 +834,9 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
|
|
|
797
834
|
return !isHandledByTable(fromB, toB);
|
|
798
835
|
}).filter(function (_ref13) {
|
|
799
836
|
var fromB = _ref13.fromB,
|
|
800
|
-
toB = _ref13.toB
|
|
801
|
-
|
|
837
|
+
toB = _ref13.toB,
|
|
838
|
+
isInline = _ref13.isInline;
|
|
839
|
+
return !(0, _fg.fg)('confluence_ncs_step_diffing_version_history') || !isInline || !changes.some(function (change) {
|
|
802
840
|
return change.fromB === fromB && change.toB === toB;
|
|
803
841
|
});
|
|
804
842
|
}).forEach(function (change) {
|
|
@@ -20,7 +20,8 @@ var typeID = function typeID(type) {
|
|
|
20
20
|
*
|
|
21
21
|
* Deliberately narrower than `attrAwareTokenEncoder`: node-start tokens keep the library default
|
|
22
22
|
* and do not fold in diffable attributes, which `getAttrChangeRanges` already reports for every
|
|
23
|
-
* diff type.
|
|
23
|
+
* diff type. The NCS version-history path also uses `attrAwareTokenEncoder` so main diff calculation
|
|
24
|
+
* detects attribute-only node replacements.
|
|
24
25
|
*/
|
|
25
26
|
var markAwareTokenEncoder = exports.markAwareTokenEncoder = {
|
|
26
27
|
encodeCharacter: function encodeCharacter(char, marks) {
|
|
@@ -11,7 +11,7 @@ var _markAwareTokenEncoder = require("./markAwareTokenEncoder");
|
|
|
11
11
|
* `computeDiffChanges` so the two cannot drift.
|
|
12
12
|
*
|
|
13
13
|
* @param useAttrAwareEncoder Caller is running the smart classifier, which needs node attrs folded
|
|
14
|
-
* into the token.
|
|
14
|
+
* into the token. Also used by the NCS version-history path to detect attribute-only node changes.
|
|
15
15
|
*/
|
|
16
16
|
var selectTokenEncoder = exports.selectTokenEncoder = function selectTokenEncoder(useAttrAwareEncoder) {
|
|
17
17
|
if (useAttrAwareEncoder) {
|
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.isDiffableAttr = exports.getRequiredIncludedDiffableAttrs = exports.getIncludedDiffableAttrs = exports.getDiffableAttrNames = exports.DIFFABLE_ATTRS_BY_NODE_TYPE = void 0;
|
|
7
|
+
var _fg = require("@atlaskit/platform-feature-flags/fg");
|
|
7
8
|
/**
|
|
8
9
|
* Single source of truth for which attributes of a node type represent a
|
|
9
10
|
* meaningful change. Shared by `attrAwareTokenEncoder` (changeset detection)
|
|
@@ -94,10 +95,13 @@ var getRequiredIncludedDiffableAttrs = exports.getRequiredIncludedDiffableAttrs
|
|
|
94
95
|
* order is not stable across the two diffed documents.
|
|
95
96
|
*/
|
|
96
97
|
var getDiffableAttrNames = exports.getDiffableAttrNames = function getDiffableAttrNames(nodeTypeName, attrs) {
|
|
98
|
+
// Adding a column updates existing widths, ignore this attribute change. Move this into
|
|
99
|
+
// DIFFABLE_ATTRS_BY_NODE_TYPE when cleaning up confluence_ncs_step_diffing_version_history
|
|
100
|
+
var ignoreColumnWidth = nodeTypeName === 'layoutColumn' && (0, _fg.fg)('confluence_ncs_step_diffing_version_history');
|
|
97
101
|
var rule = DIFFABLE_ATTRS_BY_NODE_TYPE[nodeTypeName];
|
|
98
102
|
if (!rule) {
|
|
99
103
|
return Object.keys(attrs).filter(function (name) {
|
|
100
|
-
return !DEFAULT_EXCLUDED_ATTRS.includes(name);
|
|
104
|
+
return !DEFAULT_EXCLUDED_ATTRS.includes(name) && !(ignoreColumnWidth && name === 'width');
|
|
101
105
|
}).sort();
|
|
102
106
|
}
|
|
103
107
|
if ('include' in rule) {
|
|
@@ -90,6 +90,11 @@ var getAttrChangeRanges = exports.getAttrChangeRanges = function getAttrChangeRa
|
|
|
90
90
|
var $pos = doc.resolve(finalPos);
|
|
91
91
|
var nodeAtPos = doc.nodeAt(finalPos);
|
|
92
92
|
var originalNodeAtPos = originalPos === undefined ? null : originalDoc.nodeAt(originalPos);
|
|
93
|
+
var hasChangedAttr = function hasChangedAttr(watchedAttrs) {
|
|
94
|
+
return attrsToCheck.some(function (attr) {
|
|
95
|
+
return watchedAttrs.includes(attr) && (!(0, _fg.fg)('confluence_ncs_step_diffing_version_history') || !originalNodeAtPos || originalNodeAtPos.type !== (nodeAtPos === null || nodeAtPos === void 0 ? void 0 : nodeAtPos.type) || !(0, _isEqual.default)(originalNodeAtPos.attrs[attr], nodeAtPos === null || nodeAtPos === void 0 ? void 0 : nodeAtPos.attrs[attr]));
|
|
96
|
+
});
|
|
97
|
+
};
|
|
93
98
|
|
|
94
99
|
// The changeset path (createDecorationsForChange) handles the deletion widget via
|
|
95
100
|
// prosemirror-changeset; we only need to add the inline insertion highlight here.
|
|
@@ -97,9 +102,7 @@ var getAttrChangeRanges = exports.getAttrChangeRanges = function getAttrChangeRa
|
|
|
97
102
|
var nodeName = nodeAtPos.type.name;
|
|
98
103
|
if (isInlineAttrChangeNodeName(nodeName)) {
|
|
99
104
|
var watchedAttrs = inlineNodeAttrMap[nodeName];
|
|
100
|
-
if (
|
|
101
|
-
return watchedAttrs.includes(v);
|
|
102
|
-
})) {
|
|
105
|
+
if (hasChangedAttr(watchedAttrs)) {
|
|
103
106
|
return _objectSpread(_objectSpread({}, attributionKey ? {
|
|
104
107
|
attributionKey: attributionKey
|
|
105
108
|
} : {}), {}, {
|
|
@@ -131,9 +134,7 @@ var getAttrChangeRanges = exports.getAttrChangeRanges = function getAttrChangeRa
|
|
|
131
134
|
// (e.g. note -> warning) — highlight the new panel and, when the original node
|
|
132
135
|
// is resolvable, expose its range (fromA/toA) so the caller can render the old
|
|
133
136
|
// panel as a "deleted" widget for a before/after comparison.
|
|
134
|
-
if (
|
|
135
|
-
return panelAttrs.includes(v);
|
|
136
|
-
}) && nodeAtPos && (0, _nodeTypeUtils.getBaseNodeTypeName)(nodeAtPos.type) === 'panel') {
|
|
137
|
+
if (hasChangedAttr(panelAttrs) && nodeAtPos && (0, _nodeTypeUtils.getBaseNodeTypeName)(nodeAtPos.type) === 'panel') {
|
|
137
138
|
return _objectSpread(_objectSpread({}, attributionKey ? {
|
|
138
139
|
attributionKey: attributionKey
|
|
139
140
|
} : {}), {}, {
|
|
@@ -181,7 +182,9 @@ var getAttrChangeRanges = exports.getAttrChangeRanges = function getAttrChangeRa
|
|
|
181
182
|
// (e.g. setNodeAttribute(pos, 'text', ...) + setNodeAttribute(pos, 'color', ...))
|
|
182
183
|
// should produce only one decoration, not one per step.
|
|
183
184
|
.filter(function (range, i, arr) {
|
|
184
|
-
return arr.
|
|
185
|
+
return (0, _fg.fg)('confluence_ncs_step_diffing_version_history') ? !arr.some(function (r, nextIndex) {
|
|
186
|
+
return nextIndex > i && r.fromB === range.fromB;
|
|
187
|
+
}) : arr.findIndex(function (r) {
|
|
185
188
|
return r.fromB === range.fromB;
|
|
186
189
|
}) === i;
|
|
187
190
|
});
|
|
@@ -30,10 +30,10 @@ var SHOW_DIFF_AGENT_BRANDS = {
|
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* Brands that prefer the account's real avatar over their fixed glyph when the invoking profile
|
|
33
|
-
* has one. Claude/ChatGPT
|
|
34
|
-
*
|
|
33
|
+
* has one. Claude/ChatGPT intentionally keep their fixed glyph always (see `AGENT_KIND_ICONS` in
|
|
34
|
+
* `contributorAvatarRenderer.ts`).
|
|
35
35
|
*/
|
|
36
|
-
var AVATAR_ELIGIBLE_BRANDS = new Set(['figma', 'lovable', 'replit']);
|
|
36
|
+
var AVATAR_ELIGIBLE_BRANDS = new Set(['figma', 'lovable', 'replit', 'rovo']);
|
|
37
37
|
|
|
38
38
|
/** Known external agent types emitted by Confluence's agent identification service that carry
|
|
39
39
|
* no `@atlaskit/agent-color` brand — a generic labelled fallback. */
|
|
@@ -10,25 +10,24 @@ var _default = require("@atlaskit/avatar/constants/default");
|
|
|
10
10
|
var _lazyNodeView = require("@atlaskit/editor-common/lazy-node-view");
|
|
11
11
|
var _contributorTagIcons = require("./contributorTagIcons");
|
|
12
12
|
/**
|
|
13
|
-
* Agent kinds with a custom contributor-tag icon
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* Agent kinds with a custom contributor-tag icon, used as a fallback glyph when no `avatarUrl` is
|
|
14
|
+
* available or its image fails to load (see `showContributorIcon`). Rovo/Figma/Lovable/Replit have
|
|
15
|
+
* no entry here — they fall back to the generic `aiAgent` glyph. The declared type stays the wider
|
|
16
16
|
* `TagContributor['agentKind']` so indexing below (with `'identified' | 'external'` in play too)
|
|
17
17
|
* stays safely partial.
|
|
18
18
|
*/
|
|
19
19
|
var AGENT_KIND_ICONS = {
|
|
20
20
|
claude: 'claude',
|
|
21
|
-
chatgpt: 'chatgpt'
|
|
22
|
-
rovo: 'rovoHex'
|
|
21
|
+
chatgpt: 'chatgpt'
|
|
23
22
|
};
|
|
24
23
|
|
|
25
24
|
/**
|
|
26
25
|
* Brands that always render their fixed glyph, even when the contributor also carries an
|
|
27
|
-
* `avatarUrl`. Figma/Lovable/Replit are excluded here and use the real avatar when
|
|
26
|
+
* `avatarUrl`. Rovo/Figma/Lovable/Replit are excluded here and use the real avatar when
|
|
28
27
|
* `resolveDiffContributors` supplies one, falling back to the generic `aiAgent` glyph on load
|
|
29
28
|
* failure.
|
|
30
29
|
*/
|
|
31
|
-
var FIXED_GLYPH_AGENT_KINDS = new Set(['claude', 'chatgpt'
|
|
30
|
+
var FIXED_GLYPH_AGENT_KINDS = new Set(['claude', 'chatgpt']);
|
|
32
31
|
|
|
33
32
|
/** The size `@atlaskit/avatar`'s `xxsmall` rendered at. */
|
|
34
33
|
var AVATAR_SIZE = _avatarSizes.AVATAR_SIZES.xxsmall;
|
|
@@ -125,8 +124,8 @@ var contributorAvatarRenderer = exports.contributorAvatarRenderer = function con
|
|
|
125
124
|
};
|
|
126
125
|
if (contributor.avatarUrl) {
|
|
127
126
|
var _contributor$agentKin2;
|
|
128
|
-
// Claude/ChatGPT
|
|
129
|
-
//
|
|
127
|
+
// Claude/ChatGPT always use their fixed glyph, even when the profile also has an avatar
|
|
128
|
+
// URL. Other agents (e.g. Rovo/Figma/Lovable/Replit) and users prefer the real avatar.
|
|
130
129
|
var usesFixedGlyph = isAgent && FIXED_GLYPH_AGENT_KINDS.has((_contributor$agentKin2 = contributor.agentKind) !== null && _contributor$agentKin2 !== void 0 ? _contributor$agentKin2 : 'external');
|
|
131
130
|
if (usesFixedGlyph) {
|
|
132
131
|
showContributorIcon();
|
|
@@ -10,9 +10,6 @@ exports.getContributorTagIcon = void 0;
|
|
|
10
10
|
* Neither `@atlaskit/icon`, `@atlaskit/icon-lab` nor `@atlaskit/logo` exposes a raw-SVG entry
|
|
11
11
|
* point, so the markup is copied here rather than kept as a React island for these glyphs. Keep in
|
|
12
12
|
* sync with the sources named on each constant.
|
|
13
|
-
*
|
|
14
|
-
* The Rovo hex is the `brand` appearance, whose `--rovo-*-color` variables resolve to `initial` in
|
|
15
|
-
* both themes — the fallbacks below are the rendered colours, so no theme observer is needed.
|
|
16
13
|
*/
|
|
17
14
|
|
|
18
15
|
/** `@atlaskit/icon/core/person`, at the 16px the avatar renders it. */
|
|
@@ -28,9 +25,6 @@ var AI_BOT_ICON_SVG = "<svg width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0
|
|
|
28
25
|
*/
|
|
29
26
|
var AI_AGENT_ICON_SVG = "<svg width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 16 16\" role=\"presentation\" style=\"display:block\"><path fill=\"currentcolor\" fill-rule=\"evenodd\" d=\"M6.971.493a2 2 0 0 1 2.058 0l5 3A2 2 0 0 1 15 5.208v5.584a2 2 0 0 1-.971 1.715l-5 3a2 2 0 0 1-2.058 0l-5-3A2 2 0 0 1 1 10.792V5.208a2 2 0 0 1 .971-1.715zm1.286 1.286a.5.5 0 0 0-.514 0l-5 3a.5.5 0 0 0-.243.429v5.584a.5.5 0 0 0 .243.429l1.098.66a4.25 4.25 0 1 1 8.318 0l1.098-.66a.5.5 0 0 0 .243-.429V5.208a.5.5 0 0 0-.243-.429zM8 8.25a2.75 2.75 0 1 0 0 5.5 2.75 2.75 0 0 0 0-5.5\" clip-rule=\"evenodd\"/></svg>";
|
|
30
27
|
|
|
31
|
-
/** `RovoHexIcon` from `@atlaskit/logo/rovo-hex/icon`, at the 16px `xxsmall` renders. */
|
|
32
|
-
var ROVO_HEX_ICON_SVG = "<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" role=\"presentation\" style=\"display:block\"><path fill=\"#1868db\" fill-rule=\"evenodd\" d=\"m13.227 16.789-7.154 4.169-3.403-1.96a2.72 2.72 0 0 1-1.362-2.355V7.366c0-.973.518-1.87 1.361-2.354l6.044-3.487-.038.114a3.6 3.6 0 0 0-.172 1.088v9.278c0 1.274.68 2.45 1.786 3.085z\" clip-rule=\"evenodd\"/><path fill=\"#6a9a23\" fill-rule=\"evenodd\" d=\"m11.296 15.671-7.193 4.153 6.607 3.812a2.73 2.73 0 0 0 2.676.026l.048-.033a2.73 2.73 0 0 0 1.232-1.525 2.7 2.7 0 0 0 .127-.822v-3.594z\" clip-rule=\"evenodd\"/><path fill=\"#af59e1\" fill-rule=\"evenodd\" d=\"m21.477 5.003-4.404-2.539-5.904 4.89 2.69 1.556a3.56 3.56 0 0 1 1.785 3.086v9.277a3.6 3.6 0 0 1-.21 1.202l6.044-3.486a2.71 2.71 0 0 0 1.362-2.355V7.357c0-.97-.521-1.87-1.363-2.354\" clip-rule=\"evenodd\"/><path fill=\"#fca700\" fill-rule=\"evenodd\" d=\"M12.74 8.266 9.353 6.312V2.718c0-.283.044-.56.127-.821A2.73 2.73 0 0 1 10.71.372V.37a.4.4 0 0 0 .048-.033 2.73 2.73 0 0 1 2.676.026l6.499 3.75z\" clip-rule=\"evenodd\"/></svg>";
|
|
33
|
-
|
|
34
28
|
/** Claude hexagon lockup from the brand asset: the hexagon and knot glyph both baked in. */
|
|
35
29
|
var CLAUDE_ICON_SVG = "<svg width=\"16\" height=\"18\" viewBox=\"0 0 16 18\" fill=\"none\" role=\"presentation\" style=\"display:block\"><path fill=\"#D97757\" d=\"M14.5007 3.28903L9.50384 0.402344C8.5736 -0.13506 7.42701 -0.134016 6.49774 0.405082L1.49458 3.30759C0.569434 3.8443 0 4.83297 0 5.90253V11.1804C0 12.2519 0.571497 13.2421 1.49931 13.7781L6.49931 16.6666C7.42787 17.203 8.57213 17.203 9.50069 16.6666L14.5007 13.7781C15.4285 13.2421 16 12.2519 16 11.1804V5.88671C16 4.8152 15.4285 3.82504 14.5007 3.28903Z\"/><path fill=\"#FAF9F6\" d=\"M5.19791 10.055L7.0123 9.03681L7.04267 8.94806L7.0123 8.89907H6.92357L6.62 8.88034L5.58321 8.85232L4.68418 8.815L3.81317 8.76826L3.59367 8.72158L3.38818 8.4507L3.4092 8.31526L3.59367 8.1915L3.85754 8.21485L4.44133 8.25455L5.317 8.31526L5.95216 8.35262L6.89321 8.4507H7.04267L7.06368 8.38999L7.0123 8.35262L6.97261 8.31526L6.06658 7.70112L5.08582 7.05196L4.5721 6.67834L4.29422 6.48919L4.15411 6.31172L4.09339 5.92409L4.34559 5.64621L4.68418 5.66956L4.77058 5.69291L5.11384 5.95678L5.84708 6.52422L6.80448 7.22943L6.94459 7.34618L7.00063 7.30649L7.00763 7.27846L6.94459 7.17338L6.42385 6.23233L5.86809 5.27492L5.62057 4.87795L5.55519 4.63977C5.53183 4.54169 5.51549 4.45996 5.51549 4.35956L5.80271 3.96959L5.9615 3.91821L6.34446 3.96959L6.50558 4.10969L6.74377 4.65378L7.12907 5.51077L7.72686 6.676L7.90199 7.0216L7.99539 7.34152L8.0304 7.43959H8.09113V7.38354L8.14018 6.72737L8.23124 5.92175L8.31999 4.88496L8.35032 4.59307L8.49511 4.24279L8.78232 4.05365L9.00649 4.16107L9.19098 4.42494L9.16533 4.5954L9.05555 5.30762L8.84073 6.42381L8.70062 7.17105H8.78232L8.87574 7.07764L9.25401 6.57559L9.88922 5.78165L10.1694 5.4664L10.4963 5.11847L10.7065 4.95267H11.1035L11.3953 5.38701L11.2646 5.83535L10.8559 6.35375L10.5173 6.79276L10.0316 7.4466L9.72807 7.96966L9.7561 8.0117L9.82849 8.00469L10.926 7.77118L11.5191 7.66376L12.2266 7.54233L12.5466 7.69178L12.5816 7.84356L12.4555 8.15414L11.6989 8.34095L10.8116 8.51842L9.48985 8.83136L9.4735 8.84303L9.49223 8.86637L10.0877 8.92241L10.3422 8.93639H10.9657L12.1262 9.02283L12.4298 9.2236L12.612 9.46881L12.5816 9.6556L12.1146 9.89382L11.4841 9.74434L10.013 9.3941L9.50858 9.26797H9.43849V9.31004L9.85882 9.721L10.6294 10.4169L11.5938 11.3136L11.6429 11.5354L11.5191 11.7106L11.3884 11.6918L10.5407 11.0544L10.2137 10.7672L9.4735 10.1436H9.42451V10.209L9.59495 10.4589L10.4963 11.8133L10.543 12.2289L10.4776 12.3644L10.2441 12.4461L9.98726 12.3994L9.45952 11.6592L8.91544 10.8255L8.47645 10.0783L8.42271 10.1086L8.16352 12.8991L8.04207 13.0416L7.76188 13.149L7.52837 12.9715L7.40461 12.6843L7.52837 12.1168L7.67781 11.3766L7.79925 10.7881L7.90899 10.0573L7.97438 9.81443L7.96971 9.79808L7.916 9.80507L7.36491 10.5617L6.5266 11.6942L5.86342 12.4041L5.70463 12.4671L5.42909 12.3247L5.45477 12.0702L5.60889 11.8436L6.5266 10.6761L7.08002 9.95217L7.4373 9.53421L7.43497 9.47349H7.41395L4.97607 11.0567L4.54174 11.1127L4.35493 10.9376L4.37828 10.6504L4.46702 10.557L5.20024 10.0526L5.19791 10.055Z\"/></svg>";
|
|
36
30
|
|
|
@@ -41,8 +35,7 @@ var markup = {
|
|
|
41
35
|
aiBot: AI_BOT_ICON_SVG,
|
|
42
36
|
chatgpt: CHATGPT_ICON_SVG,
|
|
43
37
|
claude: CLAUDE_ICON_SVG,
|
|
44
|
-
person: PERSON_ICON_SVG
|
|
45
|
-
rovoHex: ROVO_HEX_ICON_SVG
|
|
38
|
+
person: PERSON_ICON_SVG
|
|
46
39
|
};
|
|
47
40
|
|
|
48
41
|
/**
|
|
@@ -418,12 +418,15 @@ const calculateDiffDecorationsInner = ({
|
|
|
418
418
|
};
|
|
419
419
|
}
|
|
420
420
|
}
|
|
421
|
-
// The attribute-aware encoder is
|
|
421
|
+
// The attribute-aware encoder is needed by the smart classifier and is gated with it.
|
|
422
|
+
// The NCS version-history path also uses it so the main diff calculation detects attribute-only
|
|
423
|
+
// node replacements, e.g. changing an emoji or mention without changing the node type.
|
|
422
424
|
const {
|
|
423
425
|
tokenEncoder,
|
|
424
426
|
shouldHideMarkOnlyDeletions
|
|
425
|
-
} = selectTokenEncoder(diffType === 'smart' && fg('platform_editor_ai_smart_diff'));
|
|
427
|
+
} = selectTokenEncoder(diffType === 'smart' && fg('platform_editor_ai_smart_diff') || fg('confluence_ncs_step_diffing_version_history'));
|
|
426
428
|
let changes;
|
|
429
|
+
let contentChanges;
|
|
427
430
|
let attributedChanges = [];
|
|
428
431
|
let attributionColors;
|
|
429
432
|
if (attributedChangesetEnabled) {
|
|
@@ -434,6 +437,7 @@ const calculateDiffDecorationsInner = ({
|
|
|
434
437
|
...attribution,
|
|
435
438
|
stepIndex
|
|
436
439
|
})));
|
|
440
|
+
contentChanges = changeset.changes;
|
|
437
441
|
attributedChanges = diffType === 'step' ? diffBySteps(originalDoc, simplifiedSteps, simplifiedStepAttributions) : [...changeset.changes];
|
|
438
442
|
// The attributed pipeline gives no guarantee that its output ranges are disjoint — see
|
|
439
443
|
// `collapseOverlappingChanges`.
|
|
@@ -453,6 +457,7 @@ const calculateDiffDecorationsInner = ({
|
|
|
453
457
|
}
|
|
454
458
|
} else {
|
|
455
459
|
const changeset = ChangeSet.create(originalDoc, undefined, tokenEncoder).addSteps(steppedDoc, stepMaps, tr.doc);
|
|
460
|
+
contentChanges = changeset.changes;
|
|
456
461
|
changes = getChanges({
|
|
457
462
|
changeset,
|
|
458
463
|
originalDoc,
|
|
@@ -686,17 +691,38 @@ const calculateDiffDecorationsInner = ({
|
|
|
686
691
|
changes.forEach(change => {
|
|
687
692
|
createDecorationsForChange(change);
|
|
688
693
|
});
|
|
689
|
-
//
|
|
690
|
-
//
|
|
691
|
-
//
|
|
692
|
-
|
|
693
|
-
getMarkChangeRanges(simplifiedSteps, simplifiedStepAttributions, fg('confluence_ncs_step_diffing_version_history') ? stepMaps : undefined).filter(({
|
|
694
|
+
// Compare the content outside replacement ranges at matching positions in both documents.
|
|
695
|
+
// This preserves real formatting edits without highlighting an unchanged link mark reapplied
|
|
696
|
+
// while editing its display text.
|
|
697
|
+
const hasUnhighlightedMarkChanges = ({
|
|
694
698
|
fromB,
|
|
695
699
|
toB
|
|
696
|
-
}) =>
|
|
700
|
+
}) => {
|
|
701
|
+
let from = fromB;
|
|
702
|
+
let offset = 0;
|
|
703
|
+
const differs = to => from < to && !originalDoc.slice(from + offset, to + offset).content.eq(tr.doc.slice(from, to).content);
|
|
704
|
+
for (const change of contentChanges) {
|
|
705
|
+
if (change.fromB >= toB) {
|
|
706
|
+
break;
|
|
707
|
+
}
|
|
708
|
+
if (change.toB > from) {
|
|
709
|
+
if (differs(change.fromB)) {
|
|
710
|
+
return true;
|
|
711
|
+
}
|
|
712
|
+
from = change.toB;
|
|
713
|
+
}
|
|
714
|
+
offset = change.toA - change.toB;
|
|
715
|
+
}
|
|
716
|
+
return differs(toB);
|
|
717
|
+
};
|
|
718
|
+
|
|
719
|
+
// The attribute-aware token encoder already reports mark-only changes as regular changes in the
|
|
720
|
+
// smart path and the NCS version-history path. For NCS version history, only skip the step-range
|
|
721
|
+
// highlight if the main diff covers it or the remaining content has unchanged formatting.
|
|
722
|
+
getMarkChangeRanges(simplifiedSteps, simplifiedStepAttributions, fg('confluence_ncs_step_diffing_version_history') ? stepMaps : undefined).filter(({
|
|
697
723
|
fromB,
|
|
698
724
|
toB
|
|
699
|
-
}) => !fg('confluence_ncs_step_diffing_version_history') || !changes.some(change => change.fromB
|
|
725
|
+
}) => !isHandledByTable(fromB, toB)).filter(range => !fg('confluence_ncs_step_diffing_version_history') || !changes.some(change => change.fromB <= range.fromB && change.toB >= range.toB) && hasUnhighlightedMarkChanges(range)).forEach(change => {
|
|
700
726
|
var _attributionColors$ge, _attributionColors;
|
|
701
727
|
const changeColorScheme = change.attributionKey ? (_attributionColors$ge = (_attributionColors = attributionColors) === null || _attributionColors === void 0 ? void 0 : _attributionColors.get(change.attributionKey)) !== null && _attributionColors$ge !== void 0 ? _attributionColors$ge : colorScheme : colorScheme;
|
|
702
728
|
const attributionKey = showContributorTags ? change.attributionKey : undefined;
|
|
@@ -718,8 +744,9 @@ const calculateDiffDecorationsInner = ({
|
|
|
718
744
|
toB
|
|
719
745
|
}) => !isHandledByTable(fromB, toB)).filter(({
|
|
720
746
|
fromB,
|
|
721
|
-
toB
|
|
722
|
-
|
|
747
|
+
toB,
|
|
748
|
+
isInline
|
|
749
|
+
}) => !fg('confluence_ncs_step_diffing_version_history') || !isInline || !changes.some(change => change.fromB === fromB && change.toB === toB)).forEach(change => {
|
|
723
750
|
var _attributionColors$ge2, _attributionColors2;
|
|
724
751
|
const changeColorScheme = change.attributionKey ? (_attributionColors$ge2 = (_attributionColors2 = attributionColors) === null || _attributionColors2 === void 0 ? void 0 : _attributionColors2.get(change.attributionKey)) !== null && _attributionColors$ge2 !== void 0 ? _attributionColors$ge2 : colorScheme : colorScheme;
|
|
725
752
|
const attributionKey = showContributorTags ? change.attributionKey : undefined;
|
|
@@ -15,7 +15,8 @@ const typeID = type => {
|
|
|
15
15
|
*
|
|
16
16
|
* Deliberately narrower than `attrAwareTokenEncoder`: node-start tokens keep the library default
|
|
17
17
|
* and do not fold in diffable attributes, which `getAttrChangeRanges` already reports for every
|
|
18
|
-
* diff type.
|
|
18
|
+
* diff type. The NCS version-history path also uses `attrAwareTokenEncoder` so main diff calculation
|
|
19
|
+
* detects attribute-only node replacements.
|
|
19
20
|
*/
|
|
20
21
|
export const markAwareTokenEncoder = {
|
|
21
22
|
encodeCharacter: (char, marks) => encodeCharacterWithMarks(char, marks),
|
|
@@ -5,7 +5,7 @@ import { markAwareTokenEncoder } from './markAwareTokenEncoder';
|
|
|
5
5
|
* `computeDiffChanges` so the two cannot drift.
|
|
6
6
|
*
|
|
7
7
|
* @param useAttrAwareEncoder Caller is running the smart classifier, which needs node attrs folded
|
|
8
|
-
* into the token.
|
|
8
|
+
* into the token. Also used by the NCS version-history path to detect attribute-only node changes.
|
|
9
9
|
*/
|
|
10
10
|
export const selectTokenEncoder = useAttrAwareEncoder => {
|
|
11
11
|
if (useAttrAwareEncoder) {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Single source of truth for which attributes of a node type represent a
|
|
3
5
|
* meaningful change. Shared by `attrAwareTokenEncoder` (changeset detection)
|
|
@@ -88,9 +90,12 @@ export const getRequiredIncludedDiffableAttrs = nodeTypeName => {
|
|
|
88
90
|
* order is not stable across the two diffed documents.
|
|
89
91
|
*/
|
|
90
92
|
export const getDiffableAttrNames = (nodeTypeName, attrs) => {
|
|
93
|
+
// Adding a column updates existing widths, ignore this attribute change. Move this into
|
|
94
|
+
// DIFFABLE_ATTRS_BY_NODE_TYPE when cleaning up confluence_ncs_step_diffing_version_history
|
|
95
|
+
const ignoreColumnWidth = nodeTypeName === 'layoutColumn' && fg('confluence_ncs_step_diffing_version_history');
|
|
91
96
|
const rule = DIFFABLE_ATTRS_BY_NODE_TYPE[nodeTypeName];
|
|
92
97
|
if (!rule) {
|
|
93
|
-
return Object.keys(attrs).filter(name => !DEFAULT_EXCLUDED_ATTRS.includes(name)).sort();
|
|
98
|
+
return Object.keys(attrs).filter(name => !DEFAULT_EXCLUDED_ATTRS.includes(name) && !(ignoreColumnWidth && name === 'width')).sort();
|
|
94
99
|
}
|
|
95
100
|
if ('include' in rule) {
|
|
96
101
|
return rule.include;
|
|
@@ -74,6 +74,7 @@ export const getAttrChangeRanges = (doc, attrStepContexts, originalDoc) => {
|
|
|
74
74
|
const $pos = doc.resolve(finalPos);
|
|
75
75
|
const nodeAtPos = doc.nodeAt(finalPos);
|
|
76
76
|
const originalNodeAtPos = originalPos === undefined ? null : originalDoc.nodeAt(originalPos);
|
|
77
|
+
const hasChangedAttr = watchedAttrs => attrsToCheck.some(attr => watchedAttrs.includes(attr) && (!fg('confluence_ncs_step_diffing_version_history') || !originalNodeAtPos || originalNodeAtPos.type !== (nodeAtPos === null || nodeAtPos === void 0 ? void 0 : nodeAtPos.type) || !isEqual(originalNodeAtPos.attrs[attr], nodeAtPos === null || nodeAtPos === void 0 ? void 0 : nodeAtPos.attrs[attr])));
|
|
77
78
|
|
|
78
79
|
// The changeset path (createDecorationsForChange) handles the deletion widget via
|
|
79
80
|
// prosemirror-changeset; we only need to add the inline insertion highlight here.
|
|
@@ -81,7 +82,7 @@ export const getAttrChangeRanges = (doc, attrStepContexts, originalDoc) => {
|
|
|
81
82
|
const nodeName = nodeAtPos.type.name;
|
|
82
83
|
if (isInlineAttrChangeNodeName(nodeName)) {
|
|
83
84
|
const watchedAttrs = inlineNodeAttrMap[nodeName];
|
|
84
|
-
if (
|
|
85
|
+
if (hasChangedAttr(watchedAttrs)) {
|
|
85
86
|
return {
|
|
86
87
|
...(attributionKey ? {
|
|
87
88
|
attributionKey
|
|
@@ -114,7 +115,7 @@ export const getAttrChangeRanges = (doc, attrStepContexts, originalDoc) => {
|
|
|
114
115
|
// (e.g. note -> warning) — highlight the new panel and, when the original node
|
|
115
116
|
// is resolvable, expose its range (fromA/toA) so the caller can render the old
|
|
116
117
|
// panel as a "deleted" widget for a before/after comparison.
|
|
117
|
-
if (
|
|
118
|
+
if (hasChangedAttr(panelAttrs) && nodeAtPos && getBaseNodeTypeName(nodeAtPos.type) === 'panel') {
|
|
118
119
|
return {
|
|
119
120
|
...(attributionKey ? {
|
|
120
121
|
attributionKey
|
|
@@ -161,7 +162,7 @@ export const getAttrChangeRanges = (doc, attrStepContexts, originalDoc) => {
|
|
|
161
162
|
// Deduplicate by node position: multiple AttrSteps on the same node
|
|
162
163
|
// (e.g. setNodeAttribute(pos, 'text', ...) + setNodeAttribute(pos, 'color', ...))
|
|
163
164
|
// should produce only one decoration, not one per step.
|
|
164
|
-
.filter((range, i, arr) => arr.findIndex(r => r.fromB === range.fromB) === i);
|
|
165
|
+
.filter((range, i, arr) => fg('confluence_ncs_step_diffing_version_history') ? !arr.some((r, nextIndex) => nextIndex > i && r.fromB === range.fromB) : arr.findIndex(r => r.fromB === range.fromB) === i);
|
|
165
166
|
};
|
|
166
167
|
|
|
167
168
|
/**
|
|
@@ -18,10 +18,10 @@ const SHOW_DIFF_AGENT_BRANDS = {
|
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Brands that prefer the account's real avatar over their fixed glyph when the invoking profile
|
|
21
|
-
* has one. Claude/ChatGPT
|
|
22
|
-
*
|
|
21
|
+
* has one. Claude/ChatGPT intentionally keep their fixed glyph always (see `AGENT_KIND_ICONS` in
|
|
22
|
+
* `contributorAvatarRenderer.ts`).
|
|
23
23
|
*/
|
|
24
|
-
const AVATAR_ELIGIBLE_BRANDS = new Set(['figma', 'lovable', 'replit']);
|
|
24
|
+
const AVATAR_ELIGIBLE_BRANDS = new Set(['figma', 'lovable', 'replit', 'rovo']);
|
|
25
25
|
|
|
26
26
|
/** Known external agent types emitted by Confluence's agent identification service that carry
|
|
27
27
|
* no `@atlaskit/agent-color` brand — a generic labelled fallback. */
|
|
@@ -5,25 +5,24 @@ import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
|
|
|
5
5
|
import { getContributorTagIcon } from './contributorTagIcons';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Agent kinds with a custom contributor-tag icon
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* Agent kinds with a custom contributor-tag icon, used as a fallback glyph when no `avatarUrl` is
|
|
9
|
+
* available or its image fails to load (see `showContributorIcon`). Rovo/Figma/Lovable/Replit have
|
|
10
|
+
* no entry here — they fall back to the generic `aiAgent` glyph. The declared type stays the wider
|
|
11
11
|
* `TagContributor['agentKind']` so indexing below (with `'identified' | 'external'` in play too)
|
|
12
12
|
* stays safely partial.
|
|
13
13
|
*/
|
|
14
14
|
const AGENT_KIND_ICONS = {
|
|
15
15
|
claude: 'claude',
|
|
16
|
-
chatgpt: 'chatgpt'
|
|
17
|
-
rovo: 'rovoHex'
|
|
16
|
+
chatgpt: 'chatgpt'
|
|
18
17
|
};
|
|
19
18
|
|
|
20
19
|
/**
|
|
21
20
|
* Brands that always render their fixed glyph, even when the contributor also carries an
|
|
22
|
-
* `avatarUrl`. Figma/Lovable/Replit are excluded here and use the real avatar when
|
|
21
|
+
* `avatarUrl`. Rovo/Figma/Lovable/Replit are excluded here and use the real avatar when
|
|
23
22
|
* `resolveDiffContributors` supplies one, falling back to the generic `aiAgent` glyph on load
|
|
24
23
|
* failure.
|
|
25
24
|
*/
|
|
26
|
-
const FIXED_GLYPH_AGENT_KINDS = new Set(['claude', 'chatgpt'
|
|
25
|
+
const FIXED_GLYPH_AGENT_KINDS = new Set(['claude', 'chatgpt']);
|
|
27
26
|
|
|
28
27
|
/** The size `@atlaskit/avatar`'s `xxsmall` rendered at. */
|
|
29
28
|
const AVATAR_SIZE = AVATAR_SIZES.xxsmall;
|
|
@@ -121,8 +120,8 @@ export const contributorAvatarRenderer = ({
|
|
|
121
120
|
};
|
|
122
121
|
if (contributor.avatarUrl) {
|
|
123
122
|
var _contributor$agentKin2;
|
|
124
|
-
// Claude/ChatGPT
|
|
125
|
-
//
|
|
123
|
+
// Claude/ChatGPT always use their fixed glyph, even when the profile also has an avatar
|
|
124
|
+
// URL. Other agents (e.g. Rovo/Figma/Lovable/Replit) and users prefer the real avatar.
|
|
126
125
|
const usesFixedGlyph = isAgent && FIXED_GLYPH_AGENT_KINDS.has((_contributor$agentKin2 = contributor.agentKind) !== null && _contributor$agentKin2 !== void 0 ? _contributor$agentKin2 : 'external');
|
|
127
126
|
if (usesFixedGlyph) {
|
|
128
127
|
showContributorIcon();
|
|
@@ -4,9 +4,6 @@
|
|
|
4
4
|
* Neither `@atlaskit/icon`, `@atlaskit/icon-lab` nor `@atlaskit/logo` exposes a raw-SVG entry
|
|
5
5
|
* point, so the markup is copied here rather than kept as a React island for these glyphs. Keep in
|
|
6
6
|
* sync with the sources named on each constant.
|
|
7
|
-
*
|
|
8
|
-
* The Rovo hex is the `brand` appearance, whose `--rovo-*-color` variables resolve to `initial` in
|
|
9
|
-
* both themes — the fallbacks below are the rendered colours, so no theme observer is needed.
|
|
10
7
|
*/
|
|
11
8
|
|
|
12
9
|
/** `@atlaskit/icon/core/person`, at the 16px the avatar renders it. */
|
|
@@ -22,9 +19,6 @@ const AI_BOT_ICON_SVG = `<svg width="12" height="12" fill="none" viewBox="0 0 16
|
|
|
22
19
|
*/
|
|
23
20
|
const AI_AGENT_ICON_SVG = `<svg width="12" height="12" fill="none" viewBox="0 0 16 16" role="presentation" style="display:block"><path fill="currentcolor" fill-rule="evenodd" d="M6.971.493a2 2 0 0 1 2.058 0l5 3A2 2 0 0 1 15 5.208v5.584a2 2 0 0 1-.971 1.715l-5 3a2 2 0 0 1-2.058 0l-5-3A2 2 0 0 1 1 10.792V5.208a2 2 0 0 1 .971-1.715zm1.286 1.286a.5.5 0 0 0-.514 0l-5 3a.5.5 0 0 0-.243.429v5.584a.5.5 0 0 0 .243.429l1.098.66a4.25 4.25 0 1 1 8.318 0l1.098-.66a.5.5 0 0 0 .243-.429V5.208a.5.5 0 0 0-.243-.429zM8 8.25a2.75 2.75 0 1 0 0 5.5 2.75 2.75 0 0 0 0-5.5" clip-rule="evenodd"/></svg>`;
|
|
24
21
|
|
|
25
|
-
/** `RovoHexIcon` from `@atlaskit/logo/rovo-hex/icon`, at the 16px `xxsmall` renders. */
|
|
26
|
-
const ROVO_HEX_ICON_SVG = `<svg width="16" height="16" viewBox="0 0 24 24" role="presentation" style="display:block"><path fill="#1868db" fill-rule="evenodd" d="m13.227 16.789-7.154 4.169-3.403-1.96a2.72 2.72 0 0 1-1.362-2.355V7.366c0-.973.518-1.87 1.361-2.354l6.044-3.487-.038.114a3.6 3.6 0 0 0-.172 1.088v9.278c0 1.274.68 2.45 1.786 3.085z" clip-rule="evenodd"/><path fill="#6a9a23" fill-rule="evenodd" d="m11.296 15.671-7.193 4.153 6.607 3.812a2.73 2.73 0 0 0 2.676.026l.048-.033a2.73 2.73 0 0 0 1.232-1.525 2.7 2.7 0 0 0 .127-.822v-3.594z" clip-rule="evenodd"/><path fill="#af59e1" fill-rule="evenodd" d="m21.477 5.003-4.404-2.539-5.904 4.89 2.69 1.556a3.56 3.56 0 0 1 1.785 3.086v9.277a3.6 3.6 0 0 1-.21 1.202l6.044-3.486a2.71 2.71 0 0 0 1.362-2.355V7.357c0-.97-.521-1.87-1.363-2.354" clip-rule="evenodd"/><path fill="#fca700" fill-rule="evenodd" d="M12.74 8.266 9.353 6.312V2.718c0-.283.044-.56.127-.821A2.73 2.73 0 0 1 10.71.372V.37a.4.4 0 0 0 .048-.033 2.73 2.73 0 0 1 2.676.026l6.499 3.75z" clip-rule="evenodd"/></svg>`;
|
|
27
|
-
|
|
28
22
|
/** Claude hexagon lockup from the brand asset: the hexagon and knot glyph both baked in. */
|
|
29
23
|
const CLAUDE_ICON_SVG = `<svg width="16" height="18" viewBox="0 0 16 18" fill="none" role="presentation" style="display:block"><path fill="#D97757" d="M14.5007 3.28903L9.50384 0.402344C8.5736 -0.13506 7.42701 -0.134016 6.49774 0.405082L1.49458 3.30759C0.569434 3.8443 0 4.83297 0 5.90253V11.1804C0 12.2519 0.571497 13.2421 1.49931 13.7781L6.49931 16.6666C7.42787 17.203 8.57213 17.203 9.50069 16.6666L14.5007 13.7781C15.4285 13.2421 16 12.2519 16 11.1804V5.88671C16 4.8152 15.4285 3.82504 14.5007 3.28903Z"/><path fill="#FAF9F6" d="M5.19791 10.055L7.0123 9.03681L7.04267 8.94806L7.0123 8.89907H6.92357L6.62 8.88034L5.58321 8.85232L4.68418 8.815L3.81317 8.76826L3.59367 8.72158L3.38818 8.4507L3.4092 8.31526L3.59367 8.1915L3.85754 8.21485L4.44133 8.25455L5.317 8.31526L5.95216 8.35262L6.89321 8.4507H7.04267L7.06368 8.38999L7.0123 8.35262L6.97261 8.31526L6.06658 7.70112L5.08582 7.05196L4.5721 6.67834L4.29422 6.48919L4.15411 6.31172L4.09339 5.92409L4.34559 5.64621L4.68418 5.66956L4.77058 5.69291L5.11384 5.95678L5.84708 6.52422L6.80448 7.22943L6.94459 7.34618L7.00063 7.30649L7.00763 7.27846L6.94459 7.17338L6.42385 6.23233L5.86809 5.27492L5.62057 4.87795L5.55519 4.63977C5.53183 4.54169 5.51549 4.45996 5.51549 4.35956L5.80271 3.96959L5.9615 3.91821L6.34446 3.96959L6.50558 4.10969L6.74377 4.65378L7.12907 5.51077L7.72686 6.676L7.90199 7.0216L7.99539 7.34152L8.0304 7.43959H8.09113V7.38354L8.14018 6.72737L8.23124 5.92175L8.31999 4.88496L8.35032 4.59307L8.49511 4.24279L8.78232 4.05365L9.00649 4.16107L9.19098 4.42494L9.16533 4.5954L9.05555 5.30762L8.84073 6.42381L8.70062 7.17105H8.78232L8.87574 7.07764L9.25401 6.57559L9.88922 5.78165L10.1694 5.4664L10.4963 5.11847L10.7065 4.95267H11.1035L11.3953 5.38701L11.2646 5.83535L10.8559 6.35375L10.5173 6.79276L10.0316 7.4466L9.72807 7.96966L9.7561 8.0117L9.82849 8.00469L10.926 7.77118L11.5191 7.66376L12.2266 7.54233L12.5466 7.69178L12.5816 7.84356L12.4555 8.15414L11.6989 8.34095L10.8116 8.51842L9.48985 8.83136L9.4735 8.84303L9.49223 8.86637L10.0877 8.92241L10.3422 8.93639H10.9657L12.1262 9.02283L12.4298 9.2236L12.612 9.46881L12.5816 9.6556L12.1146 9.89382L11.4841 9.74434L10.013 9.3941L9.50858 9.26797H9.43849V9.31004L9.85882 9.721L10.6294 10.4169L11.5938 11.3136L11.6429 11.5354L11.5191 11.7106L11.3884 11.6918L10.5407 11.0544L10.2137 10.7672L9.4735 10.1436H9.42451V10.209L9.59495 10.4589L10.4963 11.8133L10.543 12.2289L10.4776 12.3644L10.2441 12.4461L9.98726 12.3994L9.45952 11.6592L8.91544 10.8255L8.47645 10.0783L8.42271 10.1086L8.16352 12.8991L8.04207 13.0416L7.76188 13.149L7.52837 12.9715L7.40461 12.6843L7.52837 12.1168L7.67781 11.3766L7.79925 10.7881L7.90899 10.0573L7.97438 9.81443L7.96971 9.79808L7.916 9.80507L7.36491 10.5617L6.5266 11.6942L5.86342 12.4041L5.70463 12.4671L5.42909 12.3247L5.45477 12.0702L5.60889 11.8436L6.5266 10.6761L7.08002 9.95217L7.4373 9.53421L7.43497 9.47349H7.41395L4.97607 11.0567L4.54174 11.1127L4.35493 10.9376L4.37828 10.6504L4.46702 10.557L5.20024 10.0526L5.19791 10.055Z"/></svg>`;
|
|
30
24
|
|
|
@@ -35,8 +29,7 @@ const markup = {
|
|
|
35
29
|
aiBot: AI_BOT_ICON_SVG,
|
|
36
30
|
chatgpt: CHATGPT_ICON_SVG,
|
|
37
31
|
claude: CLAUDE_ICON_SVG,
|
|
38
|
-
person: PERSON_ICON_SVG
|
|
39
|
-
rovoHex: ROVO_HEX_ICON_SVG
|
|
32
|
+
person: PERSON_ICON_SVG
|
|
40
33
|
};
|
|
41
34
|
|
|
42
35
|
/**
|
|
@@ -457,11 +457,14 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
|
|
|
457
457
|
};
|
|
458
458
|
}
|
|
459
459
|
}
|
|
460
|
-
// The attribute-aware encoder is
|
|
461
|
-
|
|
460
|
+
// The attribute-aware encoder is needed by the smart classifier and is gated with it.
|
|
461
|
+
// The NCS version-history path also uses it so the main diff calculation detects attribute-only
|
|
462
|
+
// node replacements, e.g. changing an emoji or mention without changing the node type.
|
|
463
|
+
var _selectTokenEncoder = selectTokenEncoder(diffType === 'smart' && fg('platform_editor_ai_smart_diff') || fg('confluence_ncs_step_diffing_version_history')),
|
|
462
464
|
tokenEncoder = _selectTokenEncoder.tokenEncoder,
|
|
463
465
|
shouldHideMarkOnlyDeletions = _selectTokenEncoder.shouldHideMarkOnlyDeletions;
|
|
464
466
|
var changes;
|
|
467
|
+
var contentChanges;
|
|
465
468
|
var attributedChanges = [];
|
|
466
469
|
var attributionColors;
|
|
467
470
|
if (attributedChangesetEnabled) {
|
|
@@ -475,6 +478,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
|
|
|
475
478
|
stepIndex: stepIndex
|
|
476
479
|
});
|
|
477
480
|
}));
|
|
481
|
+
contentChanges = changeset.changes;
|
|
478
482
|
attributedChanges = diffType === 'step' ? diffBySteps(originalDoc, simplifiedSteps, simplifiedStepAttributions) : _toConsumableArray(changeset.changes);
|
|
479
483
|
// The attributed pipeline gives no guarantee that its output ranges are disjoint — see
|
|
480
484
|
// `collapseOverlappingChanges`.
|
|
@@ -494,6 +498,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
|
|
|
494
498
|
}
|
|
495
499
|
} else {
|
|
496
500
|
var _changeset = ChangeSet.create(originalDoc, undefined, tokenEncoder).addSteps(steppedDoc, stepMaps, tr.doc);
|
|
501
|
+
contentChanges = _changeset.changes;
|
|
497
502
|
changes = getChanges({
|
|
498
503
|
changeset: _changeset,
|
|
499
504
|
originalDoc: originalDoc,
|
|
@@ -753,20 +758,52 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
|
|
|
753
758
|
changes.forEach(function (change) {
|
|
754
759
|
createDecorationsForChange(change);
|
|
755
760
|
});
|
|
756
|
-
//
|
|
757
|
-
//
|
|
758
|
-
//
|
|
759
|
-
|
|
760
|
-
getMarkChangeRanges(simplifiedSteps, simplifiedStepAttributions, fg('confluence_ncs_step_diffing_version_history') ? stepMaps : undefined).filter(function (_ref10) {
|
|
761
|
+
// Compare the content outside replacement ranges at matching positions in both documents.
|
|
762
|
+
// This preserves real formatting edits without highlighting an unchanged link mark reapplied
|
|
763
|
+
// while editing its display text.
|
|
764
|
+
var hasUnhighlightedMarkChanges = function hasUnhighlightedMarkChanges(_ref10) {
|
|
761
765
|
var fromB = _ref10.fromB,
|
|
762
766
|
toB = _ref10.toB;
|
|
763
|
-
|
|
764
|
-
|
|
767
|
+
var from = fromB;
|
|
768
|
+
var offset = 0;
|
|
769
|
+
var differs = function differs(to) {
|
|
770
|
+
return from < to && !originalDoc.slice(from + offset, to + offset).content.eq(tr.doc.slice(from, to).content);
|
|
771
|
+
};
|
|
772
|
+
var _iterator5 = _createForOfIteratorHelper(contentChanges),
|
|
773
|
+
_step5;
|
|
774
|
+
try {
|
|
775
|
+
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
|
|
776
|
+
var change = _step5.value;
|
|
777
|
+
if (change.fromB >= toB) {
|
|
778
|
+
break;
|
|
779
|
+
}
|
|
780
|
+
if (change.toB > from) {
|
|
781
|
+
if (differs(change.fromB)) {
|
|
782
|
+
return true;
|
|
783
|
+
}
|
|
784
|
+
from = change.toB;
|
|
785
|
+
}
|
|
786
|
+
offset = change.toA - change.toB;
|
|
787
|
+
}
|
|
788
|
+
} catch (err) {
|
|
789
|
+
_iterator5.e(err);
|
|
790
|
+
} finally {
|
|
791
|
+
_iterator5.f();
|
|
792
|
+
}
|
|
793
|
+
return differs(toB);
|
|
794
|
+
};
|
|
795
|
+
|
|
796
|
+
// The attribute-aware token encoder already reports mark-only changes as regular changes in the
|
|
797
|
+
// smart path and the NCS version-history path. For NCS version history, only skip the step-range
|
|
798
|
+
// highlight if the main diff covers it or the remaining content has unchanged formatting.
|
|
799
|
+
getMarkChangeRanges(simplifiedSteps, simplifiedStepAttributions, fg('confluence_ncs_step_diffing_version_history') ? stepMaps : undefined).filter(function (_ref11) {
|
|
765
800
|
var fromB = _ref11.fromB,
|
|
766
801
|
toB = _ref11.toB;
|
|
802
|
+
return !isHandledByTable(fromB, toB);
|
|
803
|
+
}).filter(function (range) {
|
|
767
804
|
return !fg('confluence_ncs_step_diffing_version_history') || !changes.some(function (change) {
|
|
768
|
-
return change.fromB
|
|
769
|
-
});
|
|
805
|
+
return change.fromB <= range.fromB && change.toB >= range.toB;
|
|
806
|
+
}) && hasUnhighlightedMarkChanges(range);
|
|
770
807
|
}).forEach(function (change) {
|
|
771
808
|
var _attributionColors$ge, _attributionColors;
|
|
772
809
|
var changeColorScheme = change.attributionKey ? (_attributionColors$ge = (_attributionColors = attributionColors) === null || _attributionColors === void 0 ? void 0 : _attributionColors.get(change.attributionKey)) !== null && _attributionColors$ge !== void 0 ? _attributionColors$ge : colorScheme : colorScheme;
|
|
@@ -790,8 +827,9 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
|
|
|
790
827
|
return !isHandledByTable(fromB, toB);
|
|
791
828
|
}).filter(function (_ref13) {
|
|
792
829
|
var fromB = _ref13.fromB,
|
|
793
|
-
toB = _ref13.toB
|
|
794
|
-
|
|
830
|
+
toB = _ref13.toB,
|
|
831
|
+
isInline = _ref13.isInline;
|
|
832
|
+
return !fg('confluence_ncs_step_diffing_version_history') || !isInline || !changes.some(function (change) {
|
|
795
833
|
return change.fromB === fromB && change.toB === toB;
|
|
796
834
|
});
|
|
797
835
|
}).forEach(function (change) {
|
|
@@ -15,7 +15,8 @@ var typeID = function typeID(type) {
|
|
|
15
15
|
*
|
|
16
16
|
* Deliberately narrower than `attrAwareTokenEncoder`: node-start tokens keep the library default
|
|
17
17
|
* and do not fold in diffable attributes, which `getAttrChangeRanges` already reports for every
|
|
18
|
-
* diff type.
|
|
18
|
+
* diff type. The NCS version-history path also uses `attrAwareTokenEncoder` so main diff calculation
|
|
19
|
+
* detects attribute-only node replacements.
|
|
19
20
|
*/
|
|
20
21
|
export var markAwareTokenEncoder = {
|
|
21
22
|
encodeCharacter: function encodeCharacter(char, marks) {
|
|
@@ -5,7 +5,7 @@ import { markAwareTokenEncoder } from './markAwareTokenEncoder';
|
|
|
5
5
|
* `computeDiffChanges` so the two cannot drift.
|
|
6
6
|
*
|
|
7
7
|
* @param useAttrAwareEncoder Caller is running the smart classifier, which needs node attrs folded
|
|
8
|
-
* into the token.
|
|
8
|
+
* into the token. Also used by the NCS version-history path to detect attribute-only node changes.
|
|
9
9
|
*/
|
|
10
10
|
export var selectTokenEncoder = function selectTokenEncoder(useAttrAwareEncoder) {
|
|
11
11
|
if (useAttrAwareEncoder) {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Single source of truth for which attributes of a node type represent a
|
|
3
5
|
* meaningful change. Shared by `attrAwareTokenEncoder` (changeset detection)
|
|
@@ -88,10 +90,13 @@ export var getRequiredIncludedDiffableAttrs = function getRequiredIncludedDiffab
|
|
|
88
90
|
* order is not stable across the two diffed documents.
|
|
89
91
|
*/
|
|
90
92
|
export var getDiffableAttrNames = function getDiffableAttrNames(nodeTypeName, attrs) {
|
|
93
|
+
// Adding a column updates existing widths, ignore this attribute change. Move this into
|
|
94
|
+
// DIFFABLE_ATTRS_BY_NODE_TYPE when cleaning up confluence_ncs_step_diffing_version_history
|
|
95
|
+
var ignoreColumnWidth = nodeTypeName === 'layoutColumn' && fg('confluence_ncs_step_diffing_version_history');
|
|
91
96
|
var rule = DIFFABLE_ATTRS_BY_NODE_TYPE[nodeTypeName];
|
|
92
97
|
if (!rule) {
|
|
93
98
|
return Object.keys(attrs).filter(function (name) {
|
|
94
|
-
return !DEFAULT_EXCLUDED_ATTRS.includes(name);
|
|
99
|
+
return !DEFAULT_EXCLUDED_ATTRS.includes(name) && !(ignoreColumnWidth && name === 'width');
|
|
95
100
|
}).sort();
|
|
96
101
|
}
|
|
97
102
|
if ('include' in rule) {
|
|
@@ -83,6 +83,11 @@ export var getAttrChangeRanges = function getAttrChangeRanges(doc, attrStepConte
|
|
|
83
83
|
var $pos = doc.resolve(finalPos);
|
|
84
84
|
var nodeAtPos = doc.nodeAt(finalPos);
|
|
85
85
|
var originalNodeAtPos = originalPos === undefined ? null : originalDoc.nodeAt(originalPos);
|
|
86
|
+
var hasChangedAttr = function hasChangedAttr(watchedAttrs) {
|
|
87
|
+
return attrsToCheck.some(function (attr) {
|
|
88
|
+
return watchedAttrs.includes(attr) && (!fg('confluence_ncs_step_diffing_version_history') || !originalNodeAtPos || originalNodeAtPos.type !== (nodeAtPos === null || nodeAtPos === void 0 ? void 0 : nodeAtPos.type) || !isEqual(originalNodeAtPos.attrs[attr], nodeAtPos === null || nodeAtPos === void 0 ? void 0 : nodeAtPos.attrs[attr]));
|
|
89
|
+
});
|
|
90
|
+
};
|
|
86
91
|
|
|
87
92
|
// The changeset path (createDecorationsForChange) handles the deletion widget via
|
|
88
93
|
// prosemirror-changeset; we only need to add the inline insertion highlight here.
|
|
@@ -90,9 +95,7 @@ export var getAttrChangeRanges = function getAttrChangeRanges(doc, attrStepConte
|
|
|
90
95
|
var nodeName = nodeAtPos.type.name;
|
|
91
96
|
if (isInlineAttrChangeNodeName(nodeName)) {
|
|
92
97
|
var watchedAttrs = inlineNodeAttrMap[nodeName];
|
|
93
|
-
if (
|
|
94
|
-
return watchedAttrs.includes(v);
|
|
95
|
-
})) {
|
|
98
|
+
if (hasChangedAttr(watchedAttrs)) {
|
|
96
99
|
return _objectSpread(_objectSpread({}, attributionKey ? {
|
|
97
100
|
attributionKey: attributionKey
|
|
98
101
|
} : {}), {}, {
|
|
@@ -124,9 +127,7 @@ export var getAttrChangeRanges = function getAttrChangeRanges(doc, attrStepConte
|
|
|
124
127
|
// (e.g. note -> warning) — highlight the new panel and, when the original node
|
|
125
128
|
// is resolvable, expose its range (fromA/toA) so the caller can render the old
|
|
126
129
|
// panel as a "deleted" widget for a before/after comparison.
|
|
127
|
-
if (
|
|
128
|
-
return panelAttrs.includes(v);
|
|
129
|
-
}) && nodeAtPos && getBaseNodeTypeName(nodeAtPos.type) === 'panel') {
|
|
130
|
+
if (hasChangedAttr(panelAttrs) && nodeAtPos && getBaseNodeTypeName(nodeAtPos.type) === 'panel') {
|
|
130
131
|
return _objectSpread(_objectSpread({}, attributionKey ? {
|
|
131
132
|
attributionKey: attributionKey
|
|
132
133
|
} : {}), {}, {
|
|
@@ -174,7 +175,9 @@ export var getAttrChangeRanges = function getAttrChangeRanges(doc, attrStepConte
|
|
|
174
175
|
// (e.g. setNodeAttribute(pos, 'text', ...) + setNodeAttribute(pos, 'color', ...))
|
|
175
176
|
// should produce only one decoration, not one per step.
|
|
176
177
|
.filter(function (range, i, arr) {
|
|
177
|
-
return arr.
|
|
178
|
+
return fg('confluence_ncs_step_diffing_version_history') ? !arr.some(function (r, nextIndex) {
|
|
179
|
+
return nextIndex > i && r.fromB === range.fromB;
|
|
180
|
+
}) : arr.findIndex(function (r) {
|
|
178
181
|
return r.fromB === range.fromB;
|
|
179
182
|
}) === i;
|
|
180
183
|
});
|
|
@@ -24,10 +24,10 @@ var SHOW_DIFF_AGENT_BRANDS = {
|
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* Brands that prefer the account's real avatar over their fixed glyph when the invoking profile
|
|
27
|
-
* has one. Claude/ChatGPT
|
|
28
|
-
*
|
|
27
|
+
* has one. Claude/ChatGPT intentionally keep their fixed glyph always (see `AGENT_KIND_ICONS` in
|
|
28
|
+
* `contributorAvatarRenderer.ts`).
|
|
29
29
|
*/
|
|
30
|
-
var AVATAR_ELIGIBLE_BRANDS = new Set(['figma', 'lovable', 'replit']);
|
|
30
|
+
var AVATAR_ELIGIBLE_BRANDS = new Set(['figma', 'lovable', 'replit', 'rovo']);
|
|
31
31
|
|
|
32
32
|
/** Known external agent types emitted by Confluence's agent identification service that carry
|
|
33
33
|
* no `@atlaskit/agent-color` brand — a generic labelled fallback. */
|
|
@@ -5,25 +5,24 @@ import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
|
|
|
5
5
|
import { getContributorTagIcon } from './contributorTagIcons';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Agent kinds with a custom contributor-tag icon
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* Agent kinds with a custom contributor-tag icon, used as a fallback glyph when no `avatarUrl` is
|
|
9
|
+
* available or its image fails to load (see `showContributorIcon`). Rovo/Figma/Lovable/Replit have
|
|
10
|
+
* no entry here — they fall back to the generic `aiAgent` glyph. The declared type stays the wider
|
|
11
11
|
* `TagContributor['agentKind']` so indexing below (with `'identified' | 'external'` in play too)
|
|
12
12
|
* stays safely partial.
|
|
13
13
|
*/
|
|
14
14
|
var AGENT_KIND_ICONS = {
|
|
15
15
|
claude: 'claude',
|
|
16
|
-
chatgpt: 'chatgpt'
|
|
17
|
-
rovo: 'rovoHex'
|
|
16
|
+
chatgpt: 'chatgpt'
|
|
18
17
|
};
|
|
19
18
|
|
|
20
19
|
/**
|
|
21
20
|
* Brands that always render their fixed glyph, even when the contributor also carries an
|
|
22
|
-
* `avatarUrl`. Figma/Lovable/Replit are excluded here and use the real avatar when
|
|
21
|
+
* `avatarUrl`. Rovo/Figma/Lovable/Replit are excluded here and use the real avatar when
|
|
23
22
|
* `resolveDiffContributors` supplies one, falling back to the generic `aiAgent` glyph on load
|
|
24
23
|
* failure.
|
|
25
24
|
*/
|
|
26
|
-
var FIXED_GLYPH_AGENT_KINDS = new Set(['claude', 'chatgpt'
|
|
25
|
+
var FIXED_GLYPH_AGENT_KINDS = new Set(['claude', 'chatgpt']);
|
|
27
26
|
|
|
28
27
|
/** The size `@atlaskit/avatar`'s `xxsmall` rendered at. */
|
|
29
28
|
var AVATAR_SIZE = AVATAR_SIZES.xxsmall;
|
|
@@ -120,8 +119,8 @@ export var contributorAvatarRenderer = function contributorAvatarRenderer(_ref)
|
|
|
120
119
|
};
|
|
121
120
|
if (contributor.avatarUrl) {
|
|
122
121
|
var _contributor$agentKin2;
|
|
123
|
-
// Claude/ChatGPT
|
|
124
|
-
//
|
|
122
|
+
// Claude/ChatGPT always use their fixed glyph, even when the profile also has an avatar
|
|
123
|
+
// URL. Other agents (e.g. Rovo/Figma/Lovable/Replit) and users prefer the real avatar.
|
|
125
124
|
var usesFixedGlyph = isAgent && FIXED_GLYPH_AGENT_KINDS.has((_contributor$agentKin2 = contributor.agentKind) !== null && _contributor$agentKin2 !== void 0 ? _contributor$agentKin2 : 'external');
|
|
126
125
|
if (usesFixedGlyph) {
|
|
127
126
|
showContributorIcon();
|
|
@@ -4,9 +4,6 @@
|
|
|
4
4
|
* Neither `@atlaskit/icon`, `@atlaskit/icon-lab` nor `@atlaskit/logo` exposes a raw-SVG entry
|
|
5
5
|
* point, so the markup is copied here rather than kept as a React island for these glyphs. Keep in
|
|
6
6
|
* sync with the sources named on each constant.
|
|
7
|
-
*
|
|
8
|
-
* The Rovo hex is the `brand` appearance, whose `--rovo-*-color` variables resolve to `initial` in
|
|
9
|
-
* both themes — the fallbacks below are the rendered colours, so no theme observer is needed.
|
|
10
7
|
*/
|
|
11
8
|
|
|
12
9
|
/** `@atlaskit/icon/core/person`, at the 16px the avatar renders it. */
|
|
@@ -22,9 +19,6 @@ var AI_BOT_ICON_SVG = "<svg width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0
|
|
|
22
19
|
*/
|
|
23
20
|
var AI_AGENT_ICON_SVG = "<svg width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 16 16\" role=\"presentation\" style=\"display:block\"><path fill=\"currentcolor\" fill-rule=\"evenodd\" d=\"M6.971.493a2 2 0 0 1 2.058 0l5 3A2 2 0 0 1 15 5.208v5.584a2 2 0 0 1-.971 1.715l-5 3a2 2 0 0 1-2.058 0l-5-3A2 2 0 0 1 1 10.792V5.208a2 2 0 0 1 .971-1.715zm1.286 1.286a.5.5 0 0 0-.514 0l-5 3a.5.5 0 0 0-.243.429v5.584a.5.5 0 0 0 .243.429l1.098.66a4.25 4.25 0 1 1 8.318 0l1.098-.66a.5.5 0 0 0 .243-.429V5.208a.5.5 0 0 0-.243-.429zM8 8.25a2.75 2.75 0 1 0 0 5.5 2.75 2.75 0 0 0 0-5.5\" clip-rule=\"evenodd\"/></svg>";
|
|
24
21
|
|
|
25
|
-
/** `RovoHexIcon` from `@atlaskit/logo/rovo-hex/icon`, at the 16px `xxsmall` renders. */
|
|
26
|
-
var ROVO_HEX_ICON_SVG = "<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" role=\"presentation\" style=\"display:block\"><path fill=\"#1868db\" fill-rule=\"evenodd\" d=\"m13.227 16.789-7.154 4.169-3.403-1.96a2.72 2.72 0 0 1-1.362-2.355V7.366c0-.973.518-1.87 1.361-2.354l6.044-3.487-.038.114a3.6 3.6 0 0 0-.172 1.088v9.278c0 1.274.68 2.45 1.786 3.085z\" clip-rule=\"evenodd\"/><path fill=\"#6a9a23\" fill-rule=\"evenodd\" d=\"m11.296 15.671-7.193 4.153 6.607 3.812a2.73 2.73 0 0 0 2.676.026l.048-.033a2.73 2.73 0 0 0 1.232-1.525 2.7 2.7 0 0 0 .127-.822v-3.594z\" clip-rule=\"evenodd\"/><path fill=\"#af59e1\" fill-rule=\"evenodd\" d=\"m21.477 5.003-4.404-2.539-5.904 4.89 2.69 1.556a3.56 3.56 0 0 1 1.785 3.086v9.277a3.6 3.6 0 0 1-.21 1.202l6.044-3.486a2.71 2.71 0 0 0 1.362-2.355V7.357c0-.97-.521-1.87-1.363-2.354\" clip-rule=\"evenodd\"/><path fill=\"#fca700\" fill-rule=\"evenodd\" d=\"M12.74 8.266 9.353 6.312V2.718c0-.283.044-.56.127-.821A2.73 2.73 0 0 1 10.71.372V.37a.4.4 0 0 0 .048-.033 2.73 2.73 0 0 1 2.676.026l6.499 3.75z\" clip-rule=\"evenodd\"/></svg>";
|
|
27
|
-
|
|
28
22
|
/** Claude hexagon lockup from the brand asset: the hexagon and knot glyph both baked in. */
|
|
29
23
|
var CLAUDE_ICON_SVG = "<svg width=\"16\" height=\"18\" viewBox=\"0 0 16 18\" fill=\"none\" role=\"presentation\" style=\"display:block\"><path fill=\"#D97757\" d=\"M14.5007 3.28903L9.50384 0.402344C8.5736 -0.13506 7.42701 -0.134016 6.49774 0.405082L1.49458 3.30759C0.569434 3.8443 0 4.83297 0 5.90253V11.1804C0 12.2519 0.571497 13.2421 1.49931 13.7781L6.49931 16.6666C7.42787 17.203 8.57213 17.203 9.50069 16.6666L14.5007 13.7781C15.4285 13.2421 16 12.2519 16 11.1804V5.88671C16 4.8152 15.4285 3.82504 14.5007 3.28903Z\"/><path fill=\"#FAF9F6\" d=\"M5.19791 10.055L7.0123 9.03681L7.04267 8.94806L7.0123 8.89907H6.92357L6.62 8.88034L5.58321 8.85232L4.68418 8.815L3.81317 8.76826L3.59367 8.72158L3.38818 8.4507L3.4092 8.31526L3.59367 8.1915L3.85754 8.21485L4.44133 8.25455L5.317 8.31526L5.95216 8.35262L6.89321 8.4507H7.04267L7.06368 8.38999L7.0123 8.35262L6.97261 8.31526L6.06658 7.70112L5.08582 7.05196L4.5721 6.67834L4.29422 6.48919L4.15411 6.31172L4.09339 5.92409L4.34559 5.64621L4.68418 5.66956L4.77058 5.69291L5.11384 5.95678L5.84708 6.52422L6.80448 7.22943L6.94459 7.34618L7.00063 7.30649L7.00763 7.27846L6.94459 7.17338L6.42385 6.23233L5.86809 5.27492L5.62057 4.87795L5.55519 4.63977C5.53183 4.54169 5.51549 4.45996 5.51549 4.35956L5.80271 3.96959L5.9615 3.91821L6.34446 3.96959L6.50558 4.10969L6.74377 4.65378L7.12907 5.51077L7.72686 6.676L7.90199 7.0216L7.99539 7.34152L8.0304 7.43959H8.09113V7.38354L8.14018 6.72737L8.23124 5.92175L8.31999 4.88496L8.35032 4.59307L8.49511 4.24279L8.78232 4.05365L9.00649 4.16107L9.19098 4.42494L9.16533 4.5954L9.05555 5.30762L8.84073 6.42381L8.70062 7.17105H8.78232L8.87574 7.07764L9.25401 6.57559L9.88922 5.78165L10.1694 5.4664L10.4963 5.11847L10.7065 4.95267H11.1035L11.3953 5.38701L11.2646 5.83535L10.8559 6.35375L10.5173 6.79276L10.0316 7.4466L9.72807 7.96966L9.7561 8.0117L9.82849 8.00469L10.926 7.77118L11.5191 7.66376L12.2266 7.54233L12.5466 7.69178L12.5816 7.84356L12.4555 8.15414L11.6989 8.34095L10.8116 8.51842L9.48985 8.83136L9.4735 8.84303L9.49223 8.86637L10.0877 8.92241L10.3422 8.93639H10.9657L12.1262 9.02283L12.4298 9.2236L12.612 9.46881L12.5816 9.6556L12.1146 9.89382L11.4841 9.74434L10.013 9.3941L9.50858 9.26797H9.43849V9.31004L9.85882 9.721L10.6294 10.4169L11.5938 11.3136L11.6429 11.5354L11.5191 11.7106L11.3884 11.6918L10.5407 11.0544L10.2137 10.7672L9.4735 10.1436H9.42451V10.209L9.59495 10.4589L10.4963 11.8133L10.543 12.2289L10.4776 12.3644L10.2441 12.4461L9.98726 12.3994L9.45952 11.6592L8.91544 10.8255L8.47645 10.0783L8.42271 10.1086L8.16352 12.8991L8.04207 13.0416L7.76188 13.149L7.52837 12.9715L7.40461 12.6843L7.52837 12.1168L7.67781 11.3766L7.79925 10.7881L7.90899 10.0573L7.97438 9.81443L7.96971 9.79808L7.916 9.80507L7.36491 10.5617L6.5266 11.6942L5.86342 12.4041L5.70463 12.4671L5.42909 12.3247L5.45477 12.0702L5.60889 11.8436L6.5266 10.6761L7.08002 9.95217L7.4373 9.53421L7.43497 9.47349H7.41395L4.97607 11.0567L4.54174 11.1127L4.35493 10.9376L4.37828 10.6504L4.46702 10.557L5.20024 10.0526L5.19791 10.055Z\"/></svg>";
|
|
30
24
|
|
|
@@ -35,8 +29,7 @@ var markup = {
|
|
|
35
29
|
aiBot: AI_BOT_ICON_SVG,
|
|
36
30
|
chatgpt: CHATGPT_ICON_SVG,
|
|
37
31
|
claude: CLAUDE_ICON_SVG,
|
|
38
|
-
person: PERSON_ICON_SVG
|
|
39
|
-
rovoHex: ROVO_HEX_ICON_SVG
|
|
32
|
+
person: PERSON_ICON_SVG
|
|
40
33
|
};
|
|
41
34
|
|
|
42
35
|
/**
|
|
@@ -4,6 +4,7 @@ import type { TokenEncoder } from 'prosemirror-changeset';
|
|
|
4
4
|
*
|
|
5
5
|
* Deliberately narrower than `attrAwareTokenEncoder`: node-start tokens keep the library default
|
|
6
6
|
* and do not fold in diffable attributes, which `getAttrChangeRanges` already reports for every
|
|
7
|
-
* diff type.
|
|
7
|
+
* diff type. The NCS version-history path also uses `attrAwareTokenEncoder` so main diff calculation
|
|
8
|
+
* detects attribute-only node replacements.
|
|
8
9
|
*/
|
|
9
10
|
export declare const markAwareTokenEncoder: TokenEncoder<string | number>;
|
|
@@ -10,6 +10,6 @@ export type TokenEncoderSelection = {
|
|
|
10
10
|
* `computeDiffChanges` so the two cannot drift.
|
|
11
11
|
*
|
|
12
12
|
* @param useAttrAwareEncoder Caller is running the smart classifier, which needs node attrs folded
|
|
13
|
-
* into the token.
|
|
13
|
+
* into the token. Also used by the NCS version-history path to detect attribute-only node changes.
|
|
14
14
|
*/
|
|
15
15
|
export declare const selectTokenEncoder: (useAttrAwareEncoder: boolean) => TokenEncoderSelection;
|
|
@@ -4,9 +4,6 @@
|
|
|
4
4
|
* Neither `@atlaskit/icon`, `@atlaskit/icon-lab` nor `@atlaskit/logo` exposes a raw-SVG entry
|
|
5
5
|
* point, so the markup is copied here rather than kept as a React island for these glyphs. Keep in
|
|
6
6
|
* sync with the sources named on each constant.
|
|
7
|
-
*
|
|
8
|
-
* The Rovo hex is the `brand` appearance, whose `--rovo-*-color` variables resolve to `initial` in
|
|
9
|
-
* both themes — the fallbacks below are the rendered colours, so no theme observer is needed.
|
|
10
7
|
*/
|
|
11
|
-
export type ContributorTagIcon = 'aiAgent' | 'aiBot' | 'chatgpt' | 'claude' | 'person'
|
|
8
|
+
export type ContributorTagIcon = 'aiAgent' | 'aiBot' | 'chatgpt' | 'claude' | 'person';
|
|
12
9
|
export declare const getContributorTagIcon: (icon: ContributorTagIcon, doc: Document) => DocumentFragment;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-show-diff",
|
|
3
|
-
"version": "21.0.
|
|
3
|
+
"version": "21.0.2",
|
|
4
4
|
"description": "ShowDiff plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"@atlaskit/adf-utils": "^20.9.0",
|
|
53
53
|
"@atlaskit/button": "^25.4.0",
|
|
54
54
|
"@atlaskit/css": "^1.1.0",
|
|
55
|
-
"@atlaskit/dropdown-menu": "^
|
|
55
|
+
"@atlaskit/dropdown-menu": "^21.0.0",
|
|
56
56
|
"@atlaskit/editor-core": "^233.0.0",
|
|
57
57
|
"@atlaskit/editor-json-transformer": "^10.0.0",
|
|
58
58
|
"@atlaskit/editor-plugins": "^16.1.0",
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"react-intl": "^7.0.0"
|
|
72
72
|
},
|
|
73
73
|
"peerDependencies": {
|
|
74
|
-
"@atlaskit/editor-common": "^127.
|
|
74
|
+
"@atlaskit/editor-common": "^127.1.0",
|
|
75
75
|
"react": "^18.2.0 || ^19.2.0",
|
|
76
76
|
"react-dom": "^18.2.0 || ^19.2.0",
|
|
77
77
|
"react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
|