@atlaskit/editor-plugin-show-diff 14.0.4 → 14.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +215 -103
- package/dist/cjs/pm-plugins/calculateDiff/diffBySteps.js +20 -9
- package/dist/cjs/pm-plugins/calculateDiff/simplifyChangesWithAttribution.js +89 -0
- package/dist/cjs/pm-plugins/calculateDiff/simplifySteps.js +81 -4
- package/dist/cjs/pm-plugins/decorations/colorSchemes/attributions.js +68 -0
- package/dist/cjs/pm-plugins/decorations/colorSchemes/schemes.js +26 -2
- package/dist/cjs/pm-plugins/decorations/colorSchemes/types.js +5 -1
- package/dist/cjs/pm-plugins/decorations/createBlockChangedDecoration.js +7 -2
- package/dist/cjs/pm-plugins/decorations/createChangedRowDecorationWidgets.js +2 -2
- package/dist/cjs/pm-plugins/decorations/createInlineChangedDecoration.js +4 -2
- package/dist/cjs/pm-plugins/decorations/utils/getAttrChangeRanges.js +59 -30
- package/dist/cjs/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.js +14 -10
- package/dist/cjs/pm-plugins/main.js +1 -0
- package/dist/cjs/showDiffPlugin.js +36 -14
- package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +130 -22
- package/dist/es2019/pm-plugins/calculateDiff/diffBySteps.js +17 -9
- package/dist/es2019/pm-plugins/calculateDiff/simplifyChangesWithAttribution.js +64 -0
- package/dist/es2019/pm-plugins/calculateDiff/simplifySteps.js +64 -1
- package/dist/es2019/pm-plugins/decorations/colorSchemes/attributions.js +37 -0
- package/dist/es2019/pm-plugins/decorations/colorSchemes/schemes.js +19 -2
- package/dist/es2019/pm-plugins/decorations/colorSchemes/types.js +1 -0
- package/dist/es2019/pm-plugins/decorations/createBlockChangedDecoration.js +6 -3
- package/dist/es2019/pm-plugins/decorations/createChangedRowDecorationWidgets.js +3 -3
- package/dist/es2019/pm-plugins/decorations/createInlineChangedDecoration.js +6 -3
- package/dist/es2019/pm-plugins/decorations/utils/getAttrChangeRanges.js +55 -30
- package/dist/es2019/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.js +12 -9
- package/dist/es2019/pm-plugins/main.js +1 -0
- package/dist/es2019/showDiffPlugin.js +23 -1
- package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +216 -104
- package/dist/esm/pm-plugins/calculateDiff/diffBySteps.js +20 -9
- package/dist/esm/pm-plugins/calculateDiff/simplifyChangesWithAttribution.js +82 -0
- package/dist/esm/pm-plugins/calculateDiff/simplifySteps.js +79 -5
- package/dist/esm/pm-plugins/decorations/colorSchemes/attributions.js +61 -0
- package/dist/esm/pm-plugins/decorations/colorSchemes/schemes.js +24 -1
- package/dist/esm/pm-plugins/decorations/colorSchemes/types.js +1 -0
- package/dist/esm/pm-plugins/decorations/createBlockChangedDecoration.js +8 -3
- package/dist/esm/pm-plugins/decorations/createChangedRowDecorationWidgets.js +3 -3
- package/dist/esm/pm-plugins/decorations/createInlineChangedDecoration.js +5 -3
- package/dist/esm/pm-plugins/decorations/utils/getAttrChangeRanges.js +59 -30
- package/dist/esm/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.js +14 -9
- package/dist/esm/pm-plugins/main.js +1 -0
- package/dist/esm/showDiffPlugin.js +36 -14
- package/dist/types/entry-points/show-diff-plugin-type.d.ts +1 -1
- package/dist/types/pm-plugins/calculateDiff/diffBySteps.d.ts +2 -1
- package/dist/types/pm-plugins/calculateDiff/simplifyChangesWithAttribution.d.ts +7 -0
- package/dist/types/pm-plugins/calculateDiff/simplifySteps.d.ts +10 -0
- package/dist/types/pm-plugins/decorations/colorSchemes/attributions.d.ts +12 -0
- package/dist/types/pm-plugins/decorations/colorSchemes/schemes.d.ts +5 -3
- package/dist/types/pm-plugins/decorations/colorSchemes/types.d.ts +6 -1
- package/dist/types/pm-plugins/decorations/createBlockChangedDecoration.d.ts +2 -1
- package/dist/types/pm-plugins/decorations/createChangedRowDecorationWidgets.d.ts +2 -1
- package/dist/types/pm-plugins/decorations/createInlineChangedDecoration.d.ts +2 -1
- package/dist/types/pm-plugins/decorations/createNodeChangedDecorationWidget.d.ts +2 -1
- package/dist/types/pm-plugins/decorations/utils/getAttrChangeRanges.d.ts +12 -2
- package/dist/types/pm-plugins/decorations/utils/wrapBlockNodeView.d.ts +2 -1
- package/dist/types/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.d.ts +2 -1
- package/dist/types/pm-plugins/main.d.ts +3 -1
- package/dist/types/showDiffPluginType.d.ts +29 -1
- package/package.json +10 -7
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AnalyticsStep } from '@atlaskit/adf-schema/steps';
|
|
2
2
|
import { areNodesEqualIgnoreAttrs } from '@atlaskit/editor-common/utils/document';
|
|
3
3
|
import { ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
|
|
4
|
-
|
|
4
|
+
import { getAttributionKey } from '../decorations/colorSchemes/attributions';
|
|
5
5
|
/**
|
|
6
6
|
* Attempts to merge two consecutive ReplaceStep operations.
|
|
7
7
|
* This merges steps where:
|
|
@@ -41,6 +41,69 @@ export function simplifySteps(steps, originalDoc) {
|
|
|
41
41
|
return acc;
|
|
42
42
|
}, []);
|
|
43
43
|
}
|
|
44
|
+
const mergeAttributions = (first, second) => {
|
|
45
|
+
var _second$wasOffline;
|
|
46
|
+
if (!first) {
|
|
47
|
+
return second;
|
|
48
|
+
}
|
|
49
|
+
if (!second) {
|
|
50
|
+
return first;
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
...first,
|
|
54
|
+
...second,
|
|
55
|
+
wasOffline: first.wasOffline === true || second.wasOffline === true ? true : (_second$wasOffline = second.wasOffline) !== null && _second$wasOffline !== void 0 ? _second$wasOffline : first.wasOffline
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Attribution-preserving variant of `simplifySteps`.
|
|
61
|
+
*
|
|
62
|
+
* Steps may only merge when they have the same effective actor identity. Keeping the attribution
|
|
63
|
+
* coupled to the step also ensures filtering a no-op/analytics step cannot shift array indexes.
|
|
64
|
+
*/
|
|
65
|
+
export function simplifyStepsWithAttribution(steps, stepAttributions, originalDoc) {
|
|
66
|
+
const stepsToFilter = removeUnusedAttributedSteps(steps.map((step, index) => ({
|
|
67
|
+
step,
|
|
68
|
+
stepAttribution: stepAttributions[index]
|
|
69
|
+
})), originalDoc);
|
|
70
|
+
return stepsToFilter.filter(({
|
|
71
|
+
step
|
|
72
|
+
}) => !(step instanceof AnalyticsStep)).reduce((acc, current) => {
|
|
73
|
+
var _previous$step$merge, _previous$step$merge2, _previous$step;
|
|
74
|
+
const previous = acc[acc.length - 1];
|
|
75
|
+
const isSameIdentity = previous && getAttributionKey(previous.stepAttribution) === getAttributionKey(current.stepAttribution);
|
|
76
|
+
const merged = isSameIdentity ? (_previous$step$merge = (_previous$step$merge2 = (_previous$step = previous.step).merge) === null || _previous$step$merge2 === void 0 ? void 0 : _previous$step$merge2.call(_previous$step, current.step)) !== null && _previous$step$merge !== void 0 ? _previous$step$merge : mergeReplaceSteps(previous.step, current.step) : null;
|
|
77
|
+
if (merged) {
|
|
78
|
+
acc[acc.length - 1] = {
|
|
79
|
+
step: merged,
|
|
80
|
+
stepAttribution: mergeAttributions(previous.stepAttribution, current.stepAttribution)
|
|
81
|
+
};
|
|
82
|
+
} else {
|
|
83
|
+
acc.push(current);
|
|
84
|
+
}
|
|
85
|
+
return acc;
|
|
86
|
+
}, []);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Does a first pass to remove steps that don't impact the document
|
|
91
|
+
*/
|
|
92
|
+
function removeUnusedAttributedSteps(stepsWithAttribution, originalDoc) {
|
|
93
|
+
const finalSteps = [];
|
|
94
|
+
let firstPassDoc = originalDoc;
|
|
95
|
+
for (const stepWithAttribution of stepsWithAttribution) {
|
|
96
|
+
const {
|
|
97
|
+
step
|
|
98
|
+
} = stepWithAttribution;
|
|
99
|
+
const result = step.apply(firstPassDoc);
|
|
100
|
+
if (result.failed === null && result.doc && !areNodesEqualIgnoreAttrs(firstPassDoc, result.doc, ['localId'])) {
|
|
101
|
+
finalSteps.push(stepWithAttribution);
|
|
102
|
+
firstPassDoc = result.doc;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return finalSteps;
|
|
106
|
+
}
|
|
44
107
|
|
|
45
108
|
/**
|
|
46
109
|
* Does a first pass to remove steps that don't impact the document
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
|
|
2
|
+
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
3
|
+
const ATTRIBUTION_COLOR_PALETTE = ['purple', 'blue', 'teal', 'magenta', 'orange', 'green'];
|
|
4
|
+
|
|
5
|
+
/** `userId` is primary; `agentId`, or `agentType` as its fallback, separates shared users. */
|
|
6
|
+
export const getAttributionKey = attribution => {
|
|
7
|
+
var _attribution$userId, _attribution$agentId, _attribution$agentTyp;
|
|
8
|
+
const userId = attribution === null || attribution === void 0 ? void 0 : (_attribution$userId = attribution.userId) === null || _attribution$userId === void 0 ? void 0 : _attribution$userId.trim();
|
|
9
|
+
const agentId = attribution === null || attribution === void 0 ? void 0 : (_attribution$agentId = attribution.agentId) === null || _attribution$agentId === void 0 ? void 0 : _attribution$agentId.trim();
|
|
10
|
+
const agentType = attribution === null || attribution === void 0 ? void 0 : (_attribution$agentTyp = attribution.agentType) === null || _attribution$agentTyp === void 0 ? void 0 : _attribution$agentTyp.trim();
|
|
11
|
+
if (!userId && !agentId && !agentType) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
const agentIdentity = agentId || (agentType ? `type:${agentType}` : '');
|
|
15
|
+
return `user:${userId !== null && userId !== void 0 ? userId : ''}|agent:${agentIdentity}`;
|
|
16
|
+
};
|
|
17
|
+
export const areAttributionColorGatesEnabled = () => fg('confluence_ncs_step_diffing_version_history') && isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor');
|
|
18
|
+
export const isAttributionColoringEnabled = stepAttributions => areAttributionColorGatesEnabled() && (stepAttributions === null || stepAttributions === void 0 ? void 0 : stepAttributions.some(attribution => getAttributionKey(attribution) !== undefined)) === true;
|
|
19
|
+
export const createAttributionColorMap = stepAttributions => {
|
|
20
|
+
const keys = Array.from(new Set(stepAttributions.map(getAttributionKey).filter(key => key !== undefined))).sort();
|
|
21
|
+
return new Map(keys.map((key, index) => [key, ATTRIBUTION_COLOR_PALETTE[index % ATTRIBUTION_COLOR_PALETTE.length]]));
|
|
22
|
+
};
|
|
23
|
+
const getLatestAttribution = changes => {
|
|
24
|
+
const data = changes.flatMap(change => [...change.deleted, ...change.inserted]).map(span => span.data).filter(value => typeof value === 'object' && value !== null && 'stepIndex' in value && typeof value.stepIndex === 'number');
|
|
25
|
+
return data.reduce((latest, attribution) => !latest || attribution.stepIndex > latest.stepIndex ? attribution : latest, undefined);
|
|
26
|
+
};
|
|
27
|
+
const rangesOverlap = (fromA, toA, fromB, toB) => fromA < toB && fromB < toA;
|
|
28
|
+
const changesOverlap = (change, attributedChange) => {
|
|
29
|
+
const insertedOverlap = change.inserted.length > 0 && attributedChange.inserted.length > 0 && rangesOverlap(change.fromB, change.toB, attributedChange.fromB, attributedChange.toB);
|
|
30
|
+
const deletedOverlap = change.deleted.length > 0 && attributedChange.deleted.length > 0 && rangesOverlap(change.fromA, change.toA, attributedChange.fromA, attributedChange.toA);
|
|
31
|
+
return insertedOverlap || deletedOverlap;
|
|
32
|
+
};
|
|
33
|
+
export const getColorSchemeForChange = (change, attributedChanges, attributionColors, fallback) => {
|
|
34
|
+
var _attributionColors$ge;
|
|
35
|
+
const key = getAttributionKey(getLatestAttribution(attributedChanges.filter(attributedChange => changesOverlap(change, attributedChange))));
|
|
36
|
+
return key ? (_attributionColors$ge = attributionColors.get(key)) !== null && _attributionColors$ge !== void 0 ? _attributionColors$ge : fallback : fallback;
|
|
37
|
+
};
|
|
@@ -52,9 +52,26 @@ export const standardScheme = {
|
|
|
52
52
|
deletedQuoteNodeActiveTone: 'borderAccent',
|
|
53
53
|
strikesDeletedEmbedCard: false
|
|
54
54
|
};
|
|
55
|
+
const createAttributionScheme = color => ({
|
|
56
|
+
...standardScheme,
|
|
57
|
+
insertColor: color,
|
|
58
|
+
insertActiveColor: color,
|
|
59
|
+
deleteColor: color,
|
|
60
|
+
deleteActiveColor: color,
|
|
61
|
+
deletedCellColor: color
|
|
62
|
+
});
|
|
55
63
|
|
|
56
|
-
/** Maps
|
|
64
|
+
/** Maps public schemes and attribution-only accents to their data objects. */
|
|
57
65
|
export const colorSchemeRegistry = {
|
|
66
|
+
blue: createAttributionScheme('blue'),
|
|
67
|
+
green: createAttributionScheme('green'),
|
|
68
|
+
magenta: createAttributionScheme('magenta'),
|
|
69
|
+
orange: createAttributionScheme('orange'),
|
|
70
|
+
purple: createAttributionScheme('purple'),
|
|
71
|
+
teal: createAttributionScheme('teal'),
|
|
58
72
|
traditional: traditionalScheme,
|
|
59
73
|
standard: standardScheme
|
|
60
|
-
};
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/** Attribution accents are impossible in the refactor-off cohort; fall back defensively. */
|
|
77
|
+
export const getLegacyColorScheme = colorScheme => colorScheme === 'standard' || colorScheme === 'traditional' ? colorScheme : undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -4,7 +4,7 @@ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-e
|
|
|
4
4
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
5
5
|
import { isExtendedEnabled } from '../isExtendedEnabled';
|
|
6
6
|
import { buildAddedCellOverlayRoundedStyle, buildAddedCellOverlayStyle, buildDeletedBlockNodeStyle, buildDeletedCellOverlayRoundedStyle, buildDeletedCellOverlayStyle, buildInsertedBlockNodeStyle } from './colorSchemes/factory';
|
|
7
|
-
import { colorSchemeRegistry } from './colorSchemes/schemes';
|
|
7
|
+
import { colorSchemeRegistry, getLegacyColorScheme } from './colorSchemes/schemes';
|
|
8
8
|
import { createBlockIndicatorAnchorWidgets } from './createAnchorDecorationWidgets';
|
|
9
9
|
import { buildDiffDecorationSpec } from './decorationKeys';
|
|
10
10
|
import { getBlockNodeStyleLegacy, resolveCellOverlayStyleLegacy } from './createBlockChangedDecoration.styles.legacy';
|
|
@@ -95,7 +95,10 @@ const getBlockNodeStyleNext = ({
|
|
|
95
95
|
* OFF cohort of `platform_editor_show_diff_color_scheme_refactor`. Both are built to emit the
|
|
96
96
|
* same style strings for both shipped schemes; see EDITOR-8281.
|
|
97
97
|
*/
|
|
98
|
-
const getBlockNodeStyle = props => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? getBlockNodeStyleNext(props) : getBlockNodeStyleLegacy(
|
|
98
|
+
const getBlockNodeStyle = props => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? getBlockNodeStyleNext(props) : getBlockNodeStyleLegacy({
|
|
99
|
+
...props,
|
|
100
|
+
colorScheme: getLegacyColorScheme(props.colorScheme)
|
|
101
|
+
});
|
|
99
102
|
|
|
100
103
|
/**
|
|
101
104
|
* A table cell is "empty" only when it has no content at all — no text AND no
|
|
@@ -165,7 +168,7 @@ export const createBlockChangedDecoration = ({
|
|
|
165
168
|
const isEmptyCellBeingFilled = !isInserted && !!cellNode && isCellEmpty(cellNode);
|
|
166
169
|
const useAddedStyle = isInserted || isEmptyCellBeingFilled;
|
|
167
170
|
const cellOverlayStyle = isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? useAddedStyle ? isRoundedTable ? buildAddedCellOverlayRoundedStyle(colors) : buildAddedCellOverlayStyle(colors) : isRoundedTable ? buildDeletedCellOverlayRoundedStyle(colors) : buildDeletedCellOverlayStyle(colors) : resolveCellOverlayStyleLegacy({
|
|
168
|
-
colorScheme,
|
|
171
|
+
colorScheme: getLegacyColorScheme(colorScheme),
|
|
169
172
|
isRoundedTable,
|
|
170
173
|
useAddedStyle
|
|
171
174
|
});
|
|
@@ -6,7 +6,7 @@ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-e
|
|
|
6
6
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
7
7
|
import { isExtendedEnabled } from '../isExtendedEnabled';
|
|
8
8
|
import { buildAddedCellOverlayRoundedStyle, buildAddedCellOverlayStyle, buildDeletedCellOverlayRoundedStyle, buildDeletedCellOverlayStyle, buildDeletedRowStyle } from './colorSchemes/factory';
|
|
9
|
-
import { colorSchemeRegistry } from './colorSchemes/schemes';
|
|
9
|
+
import { colorSchemeRegistry, getLegacyColorScheme } from './colorSchemes/schemes';
|
|
10
10
|
import { resolveCellOverlayStyleLegacy, resolveDeletedRowStyleLegacy } from './createChangedRowDecorationWidgets.styles.legacy';
|
|
11
11
|
import { buildDiffDecorationSpec } from './decorationKeys';
|
|
12
12
|
import { findSafeInsertPos } from './utils/findSafeInsertPos';
|
|
@@ -120,7 +120,7 @@ const createChangedRowDOM = (rowNode, cellEdgeAttrs, nodeViewSerializer, colorSc
|
|
|
120
120
|
|
|
121
121
|
// Inserted rows keep their natural styling; the row strikethrough is deletions only.
|
|
122
122
|
if (!isExtendedEnabled(diffType) || !isInserted) {
|
|
123
|
-
tr.setAttribute('style', isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? buildDeletedRowStyle(colors) : resolveDeletedRowStyleLegacy(colorScheme));
|
|
123
|
+
tr.setAttribute('style', isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? buildDeletedRowStyle(colors) : resolveDeletedRowStyleLegacy(getLegacyColorScheme(colorScheme)));
|
|
124
124
|
}
|
|
125
125
|
tr.setAttribute('data-testid', 'show-diff-deleted-row');
|
|
126
126
|
|
|
@@ -136,7 +136,7 @@ const createChangedRowDOM = (rowNode, cellEdgeAttrs, nodeViewSerializer, colorSc
|
|
|
136
136
|
const overlay = document.createElement('span');
|
|
137
137
|
const isRoundedTable = expValEquals('platform_editor_table_diff_rounded_corners', 'isEnabled', true);
|
|
138
138
|
const overlayStyle = isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? isInserted ? isRoundedTable ? buildAddedCellOverlayRoundedStyle(colors) : buildAddedCellOverlayStyle(colors) : isRoundedTable ? buildDeletedCellOverlayRoundedStyle(colors) : buildDeletedCellOverlayStyle(colors) : resolveCellOverlayStyleLegacy({
|
|
139
|
-
colorScheme,
|
|
139
|
+
colorScheme: getLegacyColorScheme(colorScheme),
|
|
140
140
|
isInserted,
|
|
141
141
|
isRoundedTable
|
|
142
142
|
});
|
|
@@ -3,7 +3,7 @@ import { Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
|
3
3
|
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
|
|
4
4
|
import { isExtendedEnabled } from '../isExtendedEnabled';
|
|
5
5
|
import { buildAtomicInlineChangedCSSVariables, buildDeletedInlineContentStyleExtended, buildDeletedInlineStyle, buildDeletedInlineStyleStandard, buildInsertStyle, buildInsertStyleActive, buildInsertStyleExtended, buildInsertStyleExtendedActive, buildInsertStyleExtendedNoUnderline, buildInsertStyleExtendedNoUnderlineActive } from './colorSchemes/factory';
|
|
6
|
-
import { colorSchemeRegistry } from './colorSchemes/schemes';
|
|
6
|
+
import { colorSchemeRegistry, getLegacyColorScheme } from './colorSchemes/schemes';
|
|
7
7
|
import { createInlineIndicatorAnchorWidgets } from './createAnchorDecorationWidgets';
|
|
8
8
|
import { getAtomicInlineNodeClassNameLegacy, resolveInlineChangedStyleLegacy } from './createInlineChangedDecoration.styles.legacy';
|
|
9
9
|
import { buildDiffDecorationSpec } from './decorationKeys';
|
|
@@ -64,7 +64,10 @@ const resolveInlineChangedStyleRefactored = ({
|
|
|
64
64
|
* Single gate for the inline `style` string: registry + factory when the refactor is on, the
|
|
65
65
|
* verbatim pre-refactor per-scheme constants when it is off.
|
|
66
66
|
*/
|
|
67
|
-
const resolveInlineChangedStyle = args => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? resolveInlineChangedStyleRefactored(args) : resolveInlineChangedStyleLegacy(
|
|
67
|
+
const resolveInlineChangedStyle = args => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? resolveInlineChangedStyleRefactored(args) : resolveInlineChangedStyleLegacy({
|
|
68
|
+
...args,
|
|
69
|
+
colorScheme: getLegacyColorScheme(args.colorScheme)
|
|
70
|
+
});
|
|
68
71
|
|
|
69
72
|
/**
|
|
70
73
|
* Single gate for the atomic-inline-node decoration attributes. The two cohorts differ in the DOM:
|
|
@@ -76,7 +79,7 @@ const resolveAtomicInlineAttrs = (inlineNodeName, colorScheme, colors) => isExpe
|
|
|
76
79
|
className: getAtomicInlineNodeClassName(inlineNodeName),
|
|
77
80
|
styleSuffix: buildAtomicInlineChangedCSSVariables(colors)
|
|
78
81
|
} : {
|
|
79
|
-
className: getAtomicInlineNodeClassNameLegacy(inlineNodeName, colorScheme),
|
|
82
|
+
className: getAtomicInlineNodeClassNameLegacy(inlineNodeName, getLegacyColorScheme(colorScheme)),
|
|
80
83
|
styleSuffix: ''
|
|
81
84
|
};
|
|
82
85
|
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import isEqual from 'lodash/isEqual';
|
|
2
|
+
import omit from 'lodash/omit';
|
|
1
3
|
import { SetAttrsStep } from '@atlaskit/adf-schema/steps';
|
|
2
4
|
import { isExperimentEnabled } from '@atlaskit/editor-common/deprecated-platform-feature-experiments';
|
|
3
5
|
import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
|
|
4
6
|
import { AttrStep } from '@atlaskit/editor-prosemirror/transform';
|
|
7
|
+
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
5
8
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
6
9
|
import { getRequiredIncludedDiffableAttrs, isDiffableAttr } from './diffableAttrs';
|
|
7
10
|
const filterUndefined = x => !!x;
|
|
@@ -27,29 +30,49 @@ const isInlineAttrChangeNodeName = nodeName => nodeName in inlineNodeAttrMap;
|
|
|
27
30
|
// Extension node type names. Their "any attr except localId" exclude rule lives
|
|
28
31
|
// in the shared `diffableAttrs` map and is applied via `isDiffableAttr` below.
|
|
29
32
|
const extensionNodeNames = ['extension', 'inlineExtension', 'bodiedExtension'];
|
|
33
|
+
const transientExtensionAttrPaths = ['localId', 'parameters.macroParams._parentId'];
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Removes extension metadata that can change between document versions without changing the
|
|
37
|
+
* extension's user-visible configuration.
|
|
38
|
+
*/
|
|
39
|
+
const getComparableExtensionAttrs = node => omit(node.attrs, transientExtensionAttrPaths);
|
|
40
|
+
const haveSameRelevantExtensionAttrs = (beforeNode, afterNode) => isEqual(getComparableExtensionAttrs(beforeNode), getComparableExtensionAttrs(afterNode));
|
|
30
41
|
const getStepAttrs = step => {
|
|
31
42
|
if (step instanceof AttrStep) {
|
|
32
43
|
return [step.attr];
|
|
33
44
|
}
|
|
34
|
-
if (step
|
|
45
|
+
if (step.attrs) {
|
|
35
46
|
return Object.keys(step.attrs);
|
|
36
47
|
}
|
|
37
48
|
return [];
|
|
38
49
|
};
|
|
39
|
-
export const getAttrChangeRanges = (doc,
|
|
40
|
-
return
|
|
50
|
+
export const getAttrChangeRanges = (doc, attrStepContexts, originalDoc) => {
|
|
51
|
+
return attrStepContexts.map(attrStepContext => {
|
|
52
|
+
const {
|
|
53
|
+
afterNode,
|
|
54
|
+
beforeNode,
|
|
55
|
+
finalPos,
|
|
56
|
+
originalPos,
|
|
57
|
+
step
|
|
58
|
+
} = attrStepContext;
|
|
41
59
|
if (!(step instanceof AttrStep) && !(step instanceof SetAttrsStep)) {
|
|
42
60
|
return undefined;
|
|
43
61
|
}
|
|
44
62
|
const stepAttrs = getStepAttrs(step);
|
|
45
|
-
|
|
46
|
-
|
|
63
|
+
// SetAttrsStep contains the complete replacement attrs, not only the attrs that changed.
|
|
64
|
+
// Keep the legacy payload-based checks until the rollout gate is enabled, and fall back
|
|
65
|
+
// to them if either step-time node is unavailable.
|
|
66
|
+
const attrsToCheck = fg('platform_editor_reduce_diff_attr_sensitivity') && beforeNode && afterNode ? stepAttrs.filter(attrName => !isEqual(beforeNode.attrs[attrName], afterNode.attrs[attrName])) : stepAttrs;
|
|
67
|
+
const $pos = doc.resolve(finalPos);
|
|
68
|
+
const nodeAtPos = doc.nodeAt(finalPos);
|
|
69
|
+
const originalNodeAtPos = originalPos === undefined ? null : originalDoc.nodeAt(originalPos);
|
|
47
70
|
|
|
48
71
|
// date node: timestamp attribute change — highlight the date node itself (inline)
|
|
49
|
-
if (
|
|
72
|
+
if (attrsToCheck.some(v => dateAttrs.includes(v)) && (nodeAtPos === null || nodeAtPos === void 0 ? void 0 : nodeAtPos.type.name) === 'date' && !isExperimentEnabled('platform_editor_improve_inline_diffs', () => expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true))) {
|
|
50
73
|
return {
|
|
51
|
-
fromB:
|
|
52
|
-
toB:
|
|
74
|
+
fromB: finalPos,
|
|
75
|
+
toB: finalPos + nodeAtPos.nodeSize,
|
|
53
76
|
isInline: true,
|
|
54
77
|
inlineNodeName: 'date'
|
|
55
78
|
};
|
|
@@ -62,16 +85,15 @@ export const getAttrChangeRanges = (doc, steps, originalDoc) => {
|
|
|
62
85
|
const nodeName = nodeAtPos.type.name;
|
|
63
86
|
if (isInlineAttrChangeNodeName(nodeName)) {
|
|
64
87
|
const watchedAttrs = inlineNodeAttrMap[nodeName];
|
|
65
|
-
if (
|
|
66
|
-
const originalNodeAtPos = originalDoc === null || originalDoc === void 0 ? void 0 : originalDoc.nodeAt(step.pos);
|
|
88
|
+
if (attrsToCheck.some(v => watchedAttrs.includes(v))) {
|
|
67
89
|
return {
|
|
68
|
-
fromB:
|
|
69
|
-
toB:
|
|
90
|
+
fromB: finalPos,
|
|
91
|
+
toB: finalPos + nodeAtPos.nodeSize,
|
|
70
92
|
isInline: true,
|
|
71
93
|
inlineNodeName: nodeName,
|
|
72
|
-
...(originalNodeAtPos && {
|
|
73
|
-
fromA:
|
|
74
|
-
toA:
|
|
94
|
+
...(originalPos !== undefined && originalNodeAtPos && {
|
|
95
|
+
fromA: originalPos,
|
|
96
|
+
toA: originalPos + originalNodeAtPos.nodeSize
|
|
75
97
|
})
|
|
76
98
|
};
|
|
77
99
|
}
|
|
@@ -79,10 +101,10 @@ export const getAttrChangeRanges = (doc, steps, originalDoc) => {
|
|
|
79
101
|
}
|
|
80
102
|
|
|
81
103
|
// taskItem node: state attribute change — highlight the taskItem node
|
|
82
|
-
if (
|
|
104
|
+
if (attrsToCheck.some(v => taskItemAttrs.includes(v)) && (nodeAtPos === null || nodeAtPos === void 0 ? void 0 : nodeAtPos.type.name) === 'taskItem') {
|
|
83
105
|
return {
|
|
84
|
-
fromB:
|
|
85
|
-
toB:
|
|
106
|
+
fromB: finalPos,
|
|
107
|
+
toB: finalPos + nodeAtPos.nodeSize
|
|
86
108
|
};
|
|
87
109
|
}
|
|
88
110
|
|
|
@@ -90,30 +112,33 @@ export const getAttrChangeRanges = (doc, steps, originalDoc) => {
|
|
|
90
112
|
// (e.g. note -> warning) — highlight the new panel and, when the original node
|
|
91
113
|
// is resolvable, expose its range (fromA/toA) so the caller can render the old
|
|
92
114
|
// panel as a "deleted" widget for a before/after comparison.
|
|
93
|
-
if (
|
|
94
|
-
const originalNodeAtPos = originalDoc === null || originalDoc === void 0 ? void 0 : originalDoc.nodeAt(step.pos);
|
|
115
|
+
if (attrsToCheck.some(v => panelAttrs.includes(v)) && nodeAtPos && getBaseNodeTypeName(nodeAtPos.type) === 'panel') {
|
|
95
116
|
return {
|
|
96
|
-
fromB:
|
|
97
|
-
toB:
|
|
98
|
-
...(originalNodeAtPos && {
|
|
99
|
-
fromA:
|
|
100
|
-
toA:
|
|
117
|
+
fromB: finalPos,
|
|
118
|
+
toB: finalPos + nodeAtPos.nodeSize,
|
|
119
|
+
...(originalPos !== undefined && originalNodeAtPos && {
|
|
120
|
+
fromA: originalPos,
|
|
121
|
+
toA: originalPos + originalNodeAtPos.nodeSize
|
|
101
122
|
})
|
|
102
123
|
};
|
|
103
124
|
}
|
|
104
125
|
|
|
105
|
-
//
|
|
106
|
-
|
|
126
|
+
// Extension nodes: highlight changes to user-visible configuration. When enabled,
|
|
127
|
+
// transient extension metadata is ignored by the comparison below.
|
|
128
|
+
if (nodeAtPos && extensionNodeNames.includes(nodeAtPos.type.name) && attrsToCheck.some(v => isDiffableAttr(nodeAtPos.type.name, v))) {
|
|
129
|
+
if (fg('platform_editor_reduce_diff_attr_sensitivity') && beforeNode && afterNode && beforeNode.type === afterNode.type && haveSameRelevantExtensionAttrs(beforeNode, afterNode)) {
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
107
132
|
const isInline = nodeAtPos.type.name === 'inlineExtension';
|
|
108
133
|
return {
|
|
109
|
-
fromB:
|
|
110
|
-
toB:
|
|
134
|
+
fromB: finalPos,
|
|
135
|
+
toB: finalPos + nodeAtPos.nodeSize,
|
|
111
136
|
isInline
|
|
112
137
|
};
|
|
113
138
|
}
|
|
114
139
|
|
|
115
140
|
// media node: id/collection/url attribute change — highlight the mediaSingle parent
|
|
116
|
-
if (
|
|
141
|
+
if (attrsToCheck.some(v => mediaAttrs.includes(v)) && $pos.parent.type === doc.type.schema.nodes.mediaSingle) {
|
|
117
142
|
const startPos = $pos.pos + $pos.parentOffset;
|
|
118
143
|
return {
|
|
119
144
|
fromB: startPos,
|
|
@@ -14,7 +14,7 @@ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-e
|
|
|
14
14
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
15
15
|
import { isExtendedEnabled } from '../../isExtendedEnabled';
|
|
16
16
|
import { buildAddedCellOverlayRoundedStyle, buildAddedCellOverlayStyle, buildAddedCellOverlayStyleNew, buildDeletedCellOverlayRoundedStyle, buildDeletedCellOverlayStyle, buildDeletedInlineContentStyle, buildDeletedInlineContentStyleExtended, buildDeletedLozengeActiveStyle, buildDeletedLozengeStyle, buildDeletedNodeCSSVariables, buildDeletedQuoteNodeWithLozengeStyle, buildDeletedStrikethroughLine, buildDeletedWrappedBlockOutline, buildInsertedBlockNodeStyle, buildInsertedInlineStyle, buildInsertStyleInBlockExtended, buildInsertStyleInBlockExtendedNoUnderline, buildInsertStyleNode } from '../colorSchemes/factory';
|
|
17
|
-
import { colorSchemeRegistry, standardScheme } from '../colorSchemes/schemes';
|
|
17
|
+
import { colorSchemeRegistry, getLegacyColorScheme, standardScheme } from '../colorSchemes/schemes';
|
|
18
18
|
import { getChangedContentStyleLegacy, getChangedNodeStyleLegacy, getDeletedContentStyleLegacy, getDeletedContentStyleUnboundedLegacy, getInsertedContentStyleLegacy, hasRestingDeletedRingLegacy, resolveCellOverlayStyleLegacy, resolveNestedInsertedNodeStyleLegacy, resolveRemovedLozengeStyleLegacy } from './wrapBlockNodeViewStyles.legacy';
|
|
19
19
|
const DEFAULT_COLOR_SCHEME = 'standard';
|
|
20
20
|
const getColorScheme = colorScheme => colorSchemeRegistry[colorScheme !== null && colorScheme !== void 0 ? colorScheme : DEFAULT_COLOR_SCHEME];
|
|
@@ -108,28 +108,31 @@ const resolveNestedInsertedNodeStyleNext = () => buildInsertStyleNode(nestedCont
|
|
|
108
108
|
const hasRestingDeletedRingNext = colorScheme => getColorScheme(colorScheme).deletedNodeEmphasis === 'stateful';
|
|
109
109
|
|
|
110
110
|
/** Inline content style for a changed (inserted or deleted) block node. */
|
|
111
|
-
export const getChangedContentStyle = (colorScheme, isActive = false, isInserted = false, diffType, hideAddedDiffsUnderline = false) => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? getChangedContentStyleNext(colorScheme, isActive, isInserted, diffType, hideAddedDiffsUnderline) : getChangedContentStyleLegacy(colorScheme, isActive, isInserted, diffType, hideAddedDiffsUnderline);
|
|
111
|
+
export const getChangedContentStyle = (colorScheme, isActive = false, isInserted = false, diffType, hideAddedDiffsUnderline = false) => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? getChangedContentStyleNext(colorScheme, isActive, isInserted, diffType, hideAddedDiffsUnderline) : getChangedContentStyleLegacy(getLegacyColorScheme(colorScheme), isActive, isInserted, diffType, hideAddedDiffsUnderline);
|
|
112
112
|
|
|
113
113
|
/** Node-specific style for a changed block node, or `undefined` when the node type has none. */
|
|
114
|
-
export const getChangedNodeStyle = (nodeName, colorScheme, isInserted = false, isActive = false, diffType, hideAddedDiffsUnderline = false) => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? getChangedNodeStyleNext(nodeName, colorScheme, isInserted, isActive, diffType, hideAddedDiffsUnderline) : getChangedNodeStyleLegacy(nodeName, colorScheme, isInserted, isActive, diffType, hideAddedDiffsUnderline);
|
|
114
|
+
export const getChangedNodeStyle = (nodeName, colorScheme, isInserted = false, isActive = false, diffType, hideAddedDiffsUnderline = false) => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? getChangedNodeStyleNext(nodeName, colorScheme, isInserted, isActive, diffType, hideAddedDiffsUnderline) : getChangedNodeStyleLegacy(nodeName, getLegacyColorScheme(colorScheme), isInserted, isActive, diffType, hideAddedDiffsUnderline);
|
|
115
115
|
|
|
116
116
|
/** The positioned line drawn across deleted content spanning an unbounded range. */
|
|
117
|
-
export const getDeletedContentStyleUnbounded = (colorScheme, isActive = false) => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? getDeletedContentStyleUnboundedNext(colorScheme, isActive) : getDeletedContentStyleUnboundedLegacy(colorScheme, isActive);
|
|
117
|
+
export const getDeletedContentStyleUnbounded = (colorScheme, isActive = false) => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? getDeletedContentStyleUnboundedNext(colorScheme, isActive) : getDeletedContentStyleUnboundedLegacy(getLegacyColorScheme(colorScheme), isActive);
|
|
118
118
|
|
|
119
119
|
/** Inline style for inserted content. */
|
|
120
|
-
export const getInsertedContentStyle = (colorScheme, isActive = false, hideAddedDiffsUnderline = false) => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? getInsertedContentStyleNext(colorScheme, isActive, hideAddedDiffsUnderline) : getInsertedContentStyleLegacy(colorScheme, isActive, hideAddedDiffsUnderline);
|
|
120
|
+
export const getInsertedContentStyle = (colorScheme, isActive = false, hideAddedDiffsUnderline = false) => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? getInsertedContentStyleNext(colorScheme, isActive, hideAddedDiffsUnderline) : getInsertedContentStyleLegacy(getLegacyColorScheme(colorScheme), isActive, hideAddedDiffsUnderline);
|
|
121
121
|
|
|
122
122
|
/** Inline style for deleted content. */
|
|
123
|
-
export const getDeletedContentStyle = (colorScheme, isActive = false, diffType) => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? getDeletedContentStyleNext(colorScheme, isActive, diffType) : getDeletedContentStyleLegacy(colorScheme, isActive, diffType);
|
|
123
|
+
export const getDeletedContentStyle = (colorScheme, isActive = false, diffType) => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? getDeletedContentStyleNext(colorScheme, isActive, diffType) : getDeletedContentStyleLegacy(getLegacyColorScheme(colorScheme), isActive, diffType);
|
|
124
124
|
|
|
125
125
|
/**
|
|
126
126
|
* Overlay style for one added or deleted table cell. Invariant across the cells of a table, so the
|
|
127
127
|
* `querySelectorAll('td, th')` loop in `wrapBlockNodeView.ts` resolves it once.
|
|
128
128
|
*/
|
|
129
|
-
export const resolveCellOverlayStyle = args => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? resolveCellOverlayStyleNext(args) : resolveCellOverlayStyleLegacy(
|
|
129
|
+
export const resolveCellOverlayStyle = args => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? resolveCellOverlayStyleNext(args) : resolveCellOverlayStyleLegacy({
|
|
130
|
+
...args,
|
|
131
|
+
colorScheme: getLegacyColorScheme(args.colorScheme)
|
|
132
|
+
});
|
|
130
133
|
|
|
131
134
|
/** Inner style for the "Removed" lozenge on a deleted block node. */
|
|
132
|
-
export const resolveRemovedLozengeStyle = (colorScheme, isActive) => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? resolveRemovedLozengeStyleNext(colorScheme, isActive) : resolveRemovedLozengeStyleLegacy(colorScheme, isActive);
|
|
135
|
+
export const resolveRemovedLozengeStyle = (colorScheme, isActive) => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? resolveRemovedLozengeStyleNext(colorScheme, isActive) : resolveRemovedLozengeStyleLegacy(getLegacyColorScheme(colorScheme), isActive);
|
|
133
136
|
|
|
134
137
|
/**
|
|
135
138
|
* Style for inserted content nested inside a multi-container or list node — the `decisionList` and
|
|
@@ -142,7 +145,7 @@ export const resolveNestedInsertedNodeStyle = () => isExperimentEnabled('platfor
|
|
|
142
145
|
* Whether the colour scheme draws a resting (non-active) ring on a deleted media/embed node, which
|
|
143
146
|
* is what the `show-diff-deleted-outline-new` class styles in editor-core's smartCardStyles.
|
|
144
147
|
*/
|
|
145
|
-
export const hasRestingDeletedRing = colorScheme => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? hasRestingDeletedRingNext(colorScheme) : hasRestingDeletedRingLegacy(colorScheme);
|
|
148
|
+
export const hasRestingDeletedRing = colorScheme => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? hasRestingDeletedRingNext(colorScheme) : hasRestingDeletedRingLegacy(getLegacyColorScheme(colorScheme));
|
|
146
149
|
|
|
147
150
|
/**
|
|
148
151
|
* Custom properties consumed by the `show-diff-deleted-node-vars` selectors in editor-core.
|
|
@@ -27,6 +27,7 @@ export const createPlugin = (config, getIntl, api, onEditorView) => {
|
|
|
27
27
|
const defaultDiffType = getDefaultDiffType();
|
|
28
28
|
return {
|
|
29
29
|
steps: [],
|
|
30
|
+
stepAttributions: [],
|
|
30
31
|
originalDoc: undefined,
|
|
31
32
|
decorations: DecorationSet.empty,
|
|
32
33
|
isDisplayingChanges: false,
|
|
@@ -4,6 +4,27 @@ import { getDeletedWidgets } from './pm-plugins/getDeletedWidgets';
|
|
|
4
4
|
import { getScrollableDecorations } from './pm-plugins/getScrollableDecorations';
|
|
5
5
|
import { createPlugin, showDiffPluginKey } from './pm-plugins/main';
|
|
6
6
|
import { IndicatorBarContentComponent } from './ui/IndicatorBar/IndicatorBarContentComponent';
|
|
7
|
+
const normalizeShowDiffParams = params => {
|
|
8
|
+
if (!params || !('stepsWithAttribution' in params)) {
|
|
9
|
+
return params ? {
|
|
10
|
+
...params,
|
|
11
|
+
stepAttributions: []
|
|
12
|
+
} : params;
|
|
13
|
+
}
|
|
14
|
+
const {
|
|
15
|
+
stepsWithAttribution,
|
|
16
|
+
...rest
|
|
17
|
+
} = params;
|
|
18
|
+
return {
|
|
19
|
+
...rest,
|
|
20
|
+
steps: stepsWithAttribution.map(({
|
|
21
|
+
step
|
|
22
|
+
}) => step),
|
|
23
|
+
stepAttributions: stepsWithAttribution.map(({
|
|
24
|
+
stepAttribution
|
|
25
|
+
}) => stepAttribution)
|
|
26
|
+
};
|
|
27
|
+
};
|
|
7
28
|
export const showDiffPlugin = ({
|
|
8
29
|
api,
|
|
9
30
|
config
|
|
@@ -30,7 +51,7 @@ export const showDiffPlugin = ({
|
|
|
30
51
|
});
|
|
31
52
|
}
|
|
32
53
|
return tr.setMeta(showDiffPluginKey, {
|
|
33
|
-
...params,
|
|
54
|
+
...normalizeShowDiffParams(params),
|
|
34
55
|
action: 'SHOW_DIFF'
|
|
35
56
|
});
|
|
36
57
|
},
|
|
@@ -45,6 +66,7 @@ export const showDiffPlugin = ({
|
|
|
45
66
|
}
|
|
46
67
|
return tr.setMeta(showDiffPluginKey, {
|
|
47
68
|
steps: [],
|
|
69
|
+
stepAttributions: [],
|
|
48
70
|
action: 'HIDE_DIFF'
|
|
49
71
|
});
|
|
50
72
|
},
|