@atlaskit/editor-plugin-show-diff 15.0.0 → 15.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 +35 -0
- package/afm-cc/tsconfig.json +0 -12
- package/afm-products/tsconfig.json +0 -12
- package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +131 -79
- package/dist/cjs/pm-plugins/decorations/colorSchemes/factory.js +32 -0
- package/dist/cjs/pm-plugins/decorations/createBlockChangedDecoration.js +87 -25
- package/dist/cjs/pm-plugins/decorations/createContributorTagWidget.js +27 -4
- package/dist/cjs/pm-plugins/decorations/createInlineChangedDecoration.js +17 -3
- package/dist/cjs/pm-plugins/decorations/createNodeChangedDecorationWidget.js +5 -3
- package/dist/cjs/pm-plugins/decorations/extractContributorTags.js +43 -14
- package/dist/cjs/pm-plugins/decorations/revealStyles.js +156 -0
- package/dist/cjs/pm-plugins/decorations/utils/wrapBlockNodeView.js +25 -5
- package/dist/cjs/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.js +4 -2
- package/dist/cjs/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.legacy.js +2 -1
- package/dist/cjs/pm-plugins/main.js +28 -10
- package/dist/cjs/pm-plugins/resolveDiffContributors.js +4 -0
- package/dist/cjs/pm-plugins/revealAnimation.js +524 -0
- package/dist/cjs/showDiffPlugin.js +42 -7
- package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +59 -9
- package/dist/es2019/pm-plugins/decorations/colorSchemes/factory.js +30 -0
- package/dist/es2019/pm-plugins/decorations/createBlockChangedDecoration.js +62 -4
- package/dist/es2019/pm-plugins/decorations/createContributorTagWidget.js +25 -3
- package/dist/es2019/pm-plugins/decorations/createInlineChangedDecoration.js +18 -1
- package/dist/es2019/pm-plugins/decorations/createNodeChangedDecorationWidget.js +5 -3
- package/dist/es2019/pm-plugins/decorations/extractContributorTags.js +36 -9
- package/dist/es2019/pm-plugins/decorations/revealStyles.js +139 -0
- package/dist/es2019/pm-plugins/decorations/utils/wrapBlockNodeView.js +25 -6
- package/dist/es2019/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.js +6 -3
- package/dist/es2019/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.legacy.js +5 -2
- package/dist/es2019/pm-plugins/main.js +28 -9
- package/dist/es2019/pm-plugins/resolveDiffContributors.js +4 -0
- package/dist/es2019/pm-plugins/revealAnimation.js +495 -0
- package/dist/es2019/showDiffPlugin.js +37 -7
- package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +131 -79
- package/dist/esm/pm-plugins/decorations/colorSchemes/factory.js +30 -0
- package/dist/esm/pm-plugins/decorations/createBlockChangedDecoration.js +87 -25
- package/dist/esm/pm-plugins/decorations/createContributorTagWidget.js +27 -4
- package/dist/esm/pm-plugins/decorations/createInlineChangedDecoration.js +17 -3
- package/dist/esm/pm-plugins/decorations/createNodeChangedDecorationWidget.js +5 -3
- package/dist/esm/pm-plugins/decorations/extractContributorTags.js +43 -14
- package/dist/esm/pm-plugins/decorations/revealStyles.js +149 -0
- package/dist/esm/pm-plugins/decorations/utils/wrapBlockNodeView.js +25 -5
- package/dist/esm/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.js +4 -2
- package/dist/esm/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.legacy.js +2 -1
- package/dist/esm/pm-plugins/main.js +28 -10
- package/dist/esm/pm-plugins/resolveDiffContributors.js +4 -0
- package/dist/esm/pm-plugins/revealAnimation.js +518 -0
- package/dist/esm/showDiffPlugin.js +42 -7
- package/dist/types/entry-points/show-diff-plugin-type.d.ts +1 -1
- package/dist/types/pm-plugins/calculateDiff/calculateDiffDecorations.d.ts +2 -1
- package/dist/types/pm-plugins/decorations/colorSchemes/factory.d.ts +24 -0
- package/dist/types/pm-plugins/decorations/createBlockChangedDecoration.d.ts +5 -1
- package/dist/types/pm-plugins/decorations/createContributorTagWidget.d.ts +9 -3
- package/dist/types/pm-plugins/decorations/createInlineChangedDecoration.d.ts +3 -2
- package/dist/types/pm-plugins/decorations/createNodeChangedDecorationWidget.d.ts +3 -2
- package/dist/types/pm-plugins/decorations/revealStyles.d.ts +49 -0
- package/dist/types/pm-plugins/decorations/utils/wrapBlockNodeView.d.ts +4 -3
- package/dist/types/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.d.ts +1 -1
- package/dist/types/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.legacy.d.ts +1 -1
- package/dist/types/pm-plugins/main.d.ts +6 -1
- package/dist/types/pm-plugins/revealAnimation.d.ts +33 -0
- package/dist/types/showDiffPluginType.d.ts +29 -1
- package/package.json +10 -4
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
|
|
2
|
+
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
|
|
3
|
+
import { buildDeletedInlineStyleStandard, getDeletedInlineRevealColors, getInsertedInlineRevealColors } from './colorSchemes/factory';
|
|
4
|
+
import { colorSchemeRegistry } from './colorSchemes/schemes';
|
|
5
|
+
import { deletedContentStyle, deletedContentStyleActive } from './colorSchemes/standard';
|
|
6
|
+
/**
|
|
7
|
+
* Painting strategy for reveal highlights. Highlights are `linear-gradient`s with animated
|
|
8
|
+
* `background-size` for the wipe effect. Colours live on elements as custom properties so the
|
|
9
|
+
* attribution palette works per-contributor.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/** Marks an element as taking part in the reveal, and says which side it represents. */
|
|
13
|
+
export const REVEAL_ATTR = 'data-show-diff-reveal';
|
|
14
|
+
/** Wipe colour, read by the animation as the gradient's colour stop. */
|
|
15
|
+
export const REVEAL_BG_VAR = '--show-diff-reveal-bg';
|
|
16
|
+
|
|
17
|
+
/** Underline colour, brought in on the same schedule as the highlight. */
|
|
18
|
+
export const REVEAL_BORDER_VAR = '--show-diff-reveal-border';
|
|
19
|
+
|
|
20
|
+
/** Only schemes with background highlights can be revealed; 'traditional' uses underline only. */
|
|
21
|
+
const schemeSupportsReveal = colorScheme => colorScheme !== 'traditional';
|
|
22
|
+
|
|
23
|
+
/** Convert a flat background colour into a wipeable gradient (zero width initially). */
|
|
24
|
+
export const buildWipeableBackground = color => convertToInlineCss({
|
|
25
|
+
backgroundColor: 'transparent',
|
|
26
|
+
backgroundImage: `linear-gradient(${color}, ${color})`,
|
|
27
|
+
backgroundRepeat: 'no-repeat',
|
|
28
|
+
backgroundSize: '0% 100%',
|
|
29
|
+
backgroundPosition: '0 0',
|
|
30
|
+
// Each line fragment of a wrapped highlight gets its own background box, so they wipe
|
|
31
|
+
// together rather than the gradient stretching across the whole wrapped run.
|
|
32
|
+
WebkitBoxDecorationBreak: 'clone',
|
|
33
|
+
boxDecorationBreak: 'clone'
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
/** Base padding and transparent underline placeholder (no layout shift on reveal). */
|
|
37
|
+
const revealBaseStyle = convertToInlineCss({
|
|
38
|
+
padding: `1px 0 2px`,
|
|
39
|
+
borderBottom: `2px solid transparent`
|
|
40
|
+
});
|
|
41
|
+
const buildRevealVariables = ({
|
|
42
|
+
background,
|
|
43
|
+
border
|
|
44
|
+
}) => convertToInlineCss({
|
|
45
|
+
[REVEAL_BG_VAR]: background,
|
|
46
|
+
[REVEAL_BORDER_VAR]: border
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
/** Configuration that affects both resting state and reveal endpoint. */
|
|
50
|
+
|
|
51
|
+
/** Reveal colours from the refactored scheme registry (attribution palette ready). */
|
|
52
|
+
const revealColorsRefactored = (colors, {
|
|
53
|
+
hideAddedDiffsUnderline,
|
|
54
|
+
isActive,
|
|
55
|
+
isInserted
|
|
56
|
+
}) => isInserted ? getInsertedInlineRevealColors(colors, isActive, hideAddedDiffsUnderline) : getDeletedInlineRevealColors(colors);
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Legacy cohort reveal colours. Values MUST match `revealColorsRefactored()` output for
|
|
60
|
+
* `standard` scheme (test: `revealStyles.ts` in test package).
|
|
61
|
+
*/
|
|
62
|
+
const revealColorsLegacy = ({
|
|
63
|
+
hideAddedDiffsUnderline,
|
|
64
|
+
isActive,
|
|
65
|
+
isInserted
|
|
66
|
+
}) => isInserted ? {
|
|
67
|
+
// Mirrors `editingStyleExtended` / `editingStyleActiveExtended` and their
|
|
68
|
+
// `*NoUnderline` variants in `colorSchemes/standard.ts`.
|
|
69
|
+
background: isActive ? "var(--ds-background-accent-purple-subtler-pressed, #D8A0F7)" : "var(--ds-background-accent-purple-subtlest, #F8EEFE)",
|
|
70
|
+
border: hideAddedDiffsUnderline ? 'transparent' : "var(--ds-border-accent-purple, #AF59E1)"
|
|
71
|
+
} : {
|
|
72
|
+
// Mirrors `deletedInlineContentStyleExtended` in `colorSchemes/standard.ts`.
|
|
73
|
+
background: "var(--ds-background-accent-gray-subtlest, #F0F1F2)",
|
|
74
|
+
border: "var(--ds-border-accent-gray, #7D818A)"
|
|
75
|
+
};
|
|
76
|
+
const resolveRevealColors = (colors, variant) => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? revealColorsRefactored(colors, variant) : revealColorsLegacy(variant);
|
|
77
|
+
const getColorScheme = colorScheme => colorSchemeRegistry[colorScheme !== null && colorScheme !== void 0 ? colorScheme : 'standard'];
|
|
78
|
+
|
|
79
|
+
/** Deleted text appearance (grey and strikethrough) without the highlight. */
|
|
80
|
+
const deletedTextOnlyStyle = (colors, isActive) => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? buildDeletedInlineStyleStandard(colors, isActive ? 'active' : 'default') : isActive ? deletedContentStyleActive : deletedContentStyle;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Resolve reveal attribute and style for a decoration. Returned style REPLACES the decoration's
|
|
84
|
+
* highlight (not an addition) so the animation has something to wipe. Gate resolved in showDiff
|
|
85
|
+
* command for single shared answer between decorations and animation.
|
|
86
|
+
*/
|
|
87
|
+
export const resolveRevealStyle = ({
|
|
88
|
+
colorScheme,
|
|
89
|
+
hideAddedDiffsUnderline = false,
|
|
90
|
+
includeDeletedTextStyle = true,
|
|
91
|
+
isActive,
|
|
92
|
+
isInserted,
|
|
93
|
+
reveal
|
|
94
|
+
}) => {
|
|
95
|
+
if ((reveal === null || reveal === void 0 ? void 0 : reveal.mode) !== 'phased' || !schemeSupportsReveal(colorScheme)) {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
const colors = getColorScheme(colorScheme);
|
|
99
|
+
const {
|
|
100
|
+
background,
|
|
101
|
+
border
|
|
102
|
+
} = resolveRevealColors(colors, {
|
|
103
|
+
hideAddedDiffsUnderline,
|
|
104
|
+
isActive,
|
|
105
|
+
isInserted
|
|
106
|
+
});
|
|
107
|
+
return {
|
|
108
|
+
role: isInserted ? 'added' : 'deleted',
|
|
109
|
+
style: (isInserted || !includeDeletedTextStyle ? '' : deletedTextOnlyStyle(colors, isActive)) + revealBaseStyle + buildWipeableBackground(background) + buildRevealVariables({
|
|
110
|
+
background,
|
|
111
|
+
border
|
|
112
|
+
})
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/** Reveal style for imperatively-built elements (deleted-content widget wrappers). */
|
|
117
|
+
export const applyRevealToElement = ({
|
|
118
|
+
colorScheme,
|
|
119
|
+
element,
|
|
120
|
+
hideAddedDiffsUnderline,
|
|
121
|
+
isActive,
|
|
122
|
+
isInserted,
|
|
123
|
+
reveal
|
|
124
|
+
}) => {
|
|
125
|
+
const resolved = resolveRevealStyle({
|
|
126
|
+
colorScheme,
|
|
127
|
+
hideAddedDiffsUnderline,
|
|
128
|
+
isActive,
|
|
129
|
+
isInserted,
|
|
130
|
+
reveal,
|
|
131
|
+
// The widget supplies the deleted text's own grey/strikethrough styling already.
|
|
132
|
+
includeDeletedTextStyle: false
|
|
133
|
+
});
|
|
134
|
+
if (!resolved) {
|
|
135
|
+
return '';
|
|
136
|
+
}
|
|
137
|
+
element.setAttribute(REVEAL_ATTR, resolved.role);
|
|
138
|
+
return resolved.style;
|
|
139
|
+
};
|
|
@@ -4,6 +4,7 @@ import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-uti
|
|
|
4
4
|
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
|
|
5
5
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
6
6
|
import { isExtendedEnabled } from '../../isExtendedEnabled';
|
|
7
|
+
import { applyRevealToElement } from '../revealStyles';
|
|
7
8
|
import { getAtomicInlineChangedAttrs } from '../createInlineChangedDecoration';
|
|
8
9
|
import { applyTableCellEdgeAttrs } from './tableCellEdgeAttrs';
|
|
9
10
|
import { isInlineAttrChangeNodeName } from './getAttrChangeRanges';
|
|
@@ -600,10 +601,18 @@ export const injectInnerWrapper = ({
|
|
|
600
601
|
colorScheme,
|
|
601
602
|
isActive,
|
|
602
603
|
isInserted,
|
|
603
|
-
diffType
|
|
604
|
+
diffType,
|
|
605
|
+
reveal
|
|
604
606
|
}) => {
|
|
605
607
|
const wrapper = document.createElement('span');
|
|
606
|
-
|
|
608
|
+
const revealStyle = applyRevealToElement({
|
|
609
|
+
colorScheme,
|
|
610
|
+
element: wrapper,
|
|
611
|
+
isActive: isActive !== null && isActive !== void 0 ? isActive : false,
|
|
612
|
+
isInserted: isInserted !== null && isInserted !== void 0 ? isInserted : false,
|
|
613
|
+
reveal
|
|
614
|
+
});
|
|
615
|
+
wrapper.setAttribute('style', (isInserted ? getInsertedContentStyle(colorScheme, isActive) : getDeletedContentStyle(colorScheme, isActive, diffType, Boolean(revealStyle))) + revealStyle);
|
|
607
616
|
[...node.childNodes].forEach(child => {
|
|
608
617
|
const removedChild = node.removeChild(child);
|
|
609
618
|
wrapper.append(removedChild);
|
|
@@ -615,23 +624,33 @@ export const injectInnerWrapper = ({
|
|
|
615
624
|
/**
|
|
616
625
|
* Creates a styled span wrapper for inline content within a change decoration.
|
|
617
626
|
*/
|
|
618
|
-
export const createContentWrapper = (colorScheme, isActive = false, isInserted = false, diffType) => {
|
|
627
|
+
export const createContentWrapper = (colorScheme, isActive = false, isInserted = false, diffType, reveal) => {
|
|
619
628
|
const wrapper = document.createElement('span');
|
|
620
629
|
const baseStyle = convertToInlineCss({
|
|
621
630
|
position: 'relative',
|
|
622
631
|
width: 'fit-content'
|
|
623
632
|
});
|
|
633
|
+
// Empty unless the reveal is running, in which case the static highlight below is withheld so
|
|
634
|
+
// the animation can wipe it in instead.
|
|
635
|
+
const revealStyle = applyRevealToElement({
|
|
636
|
+
colorScheme,
|
|
637
|
+
element: wrapper,
|
|
638
|
+
isActive,
|
|
639
|
+
isInserted,
|
|
640
|
+
reveal
|
|
641
|
+
});
|
|
642
|
+
const deletedStyle = getDeletedContentStyle(colorScheme, isActive, diffType, Boolean(revealStyle));
|
|
624
643
|
if (isExtendedEnabled(diffType)) {
|
|
625
644
|
if (isInserted) {
|
|
626
|
-
wrapper.setAttribute('style', `${baseStyle}${getInsertedContentStyle(colorScheme, isActive)}`);
|
|
645
|
+
wrapper.setAttribute('style', `${baseStyle}${getInsertedContentStyle(colorScheme, isActive)}${revealStyle}`);
|
|
627
646
|
} else {
|
|
628
|
-
wrapper.setAttribute('style', `${baseStyle}${
|
|
647
|
+
wrapper.setAttribute('style', `${baseStyle}${deletedStyle}${revealStyle}`);
|
|
629
648
|
const strikethrough = document.createElement('span');
|
|
630
649
|
strikethrough.setAttribute('style', getDeletedContentStyleUnbounded(colorScheme, isActive));
|
|
631
650
|
wrapper.append(strikethrough);
|
|
632
651
|
}
|
|
633
652
|
} else {
|
|
634
|
-
wrapper.setAttribute('style', `${baseStyle}${
|
|
653
|
+
wrapper.setAttribute('style', `${baseStyle}${deletedStyle}${revealStyle}`);
|
|
635
654
|
const strikethrough = document.createElement('span');
|
|
636
655
|
strikethrough.setAttribute('style', getDeletedContentStyleUnbounded(colorScheme, isActive));
|
|
637
656
|
wrapper.append(strikethrough);
|
|
@@ -77,12 +77,12 @@ const getChangedNodeStyleNext = (nodeName, colorScheme, isInserted = false, isAc
|
|
|
77
77
|
};
|
|
78
78
|
const getDeletedContentStyleUnboundedNext = (colorScheme, isActive = false) => buildDeletedStrikethroughLine(getColorScheme(colorScheme), isActive);
|
|
79
79
|
const getInsertedContentStyleNext = (colorScheme, isActive = false, hideAddedDiffsUnderline = false) => buildInsertedInlineStyle(getColorScheme(colorScheme), isActive, hideAddedDiffsUnderline);
|
|
80
|
-
const getDeletedContentStyleNext = (colorScheme, isActive = false, diffType) => {
|
|
80
|
+
const getDeletedContentStyleNext = (colorScheme, isActive = false, diffType, omitHighlight = false) => {
|
|
81
81
|
const colors = getColorScheme(colorScheme);
|
|
82
82
|
const base = buildDeletedInlineContentStyle(colors, isActive ? 'active' : 'new');
|
|
83
83
|
|
|
84
84
|
// glyphTint adds a background highlight and border-bottom over the tint; strikethrough does not.
|
|
85
|
-
const needsExtendedHighlight = colors.deletedInlineTreatment === 'glyphTint' && isExtendedEnabled(diffType);
|
|
85
|
+
const needsExtendedHighlight = colors.deletedInlineTreatment === 'glyphTint' && isExtendedEnabled(diffType) && !omitHighlight;
|
|
86
86
|
return needsExtendedHighlight ? base + buildDeletedInlineContentStyleExtended(colors) : base;
|
|
87
87
|
};
|
|
88
88
|
const resolveCellOverlayStyleNext = ({
|
|
@@ -119,7 +119,10 @@ export const getDeletedContentStyleUnbounded = (colorScheme, isActive = false) =
|
|
|
119
119
|
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);
|
|
120
120
|
|
|
121
121
|
/** Inline style for deleted content. */
|
|
122
|
-
export const getDeletedContentStyle = (colorScheme, isActive = false, diffType
|
|
122
|
+
export const getDeletedContentStyle = (colorScheme, isActive = false, diffType,
|
|
123
|
+
// Set while the reveal animation is running: it paints the highlight itself so it can wipe it in
|
|
124
|
+
// left-to-right, and a static background here would leave nothing to reveal.
|
|
125
|
+
omitHighlight = false) => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? getDeletedContentStyleNext(colorScheme, isActive, diffType, omitHighlight) : getDeletedContentStyleLegacy(getLegacyColorScheme(colorScheme), isActive, diffType, omitHighlight);
|
|
123
126
|
|
|
124
127
|
/**
|
|
125
128
|
* Overlay style for one added or deleted table cell. Invariant across the cells of a table, so the
|
|
@@ -151,11 +151,14 @@ export const getInsertedContentStyleLegacy = (colorScheme, isActive = false, hid
|
|
|
151
151
|
};
|
|
152
152
|
|
|
153
153
|
/** Pre-refactor inline style for deleted content. */
|
|
154
|
-
export const getDeletedContentStyleLegacy = (colorScheme, isActive = false, diffType
|
|
154
|
+
export const getDeletedContentStyleLegacy = (colorScheme, isActive = false, diffType,
|
|
155
|
+
// The reveal animation paints the highlight itself so it can wipe it in; a static one here would
|
|
156
|
+
// cover the whole span and leave nothing to reveal. Mirrors the same option on the Next variant.
|
|
157
|
+
omitHighlight = false) => {
|
|
155
158
|
if (colorScheme === 'traditional') {
|
|
156
159
|
return getDeletedTraditionalInlineStyle(isActive);
|
|
157
160
|
}
|
|
158
|
-
if (isExtendedEnabled(diffType)) {
|
|
161
|
+
if (isExtendedEnabled(diffType) && !omitHighlight) {
|
|
159
162
|
return (isActive ? deletedContentStyleActive : deletedContentStyleNew) + deletedInlineContentStyleExtended;
|
|
160
163
|
}
|
|
161
164
|
return isActive ? deletedContentStyleActive : deletedContentStyleNew;
|
|
@@ -10,6 +10,7 @@ import { enforceCustomStepRegisters } from './enforceCustomStepRegisters';
|
|
|
10
10
|
import { getScrollableDecorations } from './getScrollableDecorations';
|
|
11
11
|
import { getDefaultDiffType, isExtendedEnabled } from './isExtendedEnabled';
|
|
12
12
|
import { NodeViewSerializer } from './NodeViewSerializer';
|
|
13
|
+
import { rebindReveal } from './revealAnimation';
|
|
13
14
|
import { scrollToDecoration } from './scrollToDiff';
|
|
14
15
|
export const showDiffPluginKey = new PluginKey('showDiffPlugin');
|
|
15
16
|
/**
|
|
@@ -80,14 +81,24 @@ export const createPlugin = (config, getIntl, api, onEditorView) => {
|
|
|
80
81
|
const meta = tr.getMeta(showDiffPluginKey);
|
|
81
82
|
let newPluginState = currentPluginState;
|
|
82
83
|
if (meta) {
|
|
83
|
-
if ((meta === null || meta === void 0 ? void 0 : meta.action) === 'SHOW_DIFF') {
|
|
84
|
-
var _newPluginState, _newPluginState2, _newPluginState3, _newPluginState4, _newPluginState5, _newPluginState6, _newPluginState7, _newPluginState8, _newPluginState9, _newPluginState0;
|
|
85
|
-
//
|
|
86
|
-
|
|
84
|
+
if ((meta === null || meta === void 0 ? void 0 : meta.action) === 'SHOW_DIFF' || (meta === null || meta === void 0 ? void 0 : meta.action) === 'REVEAL_COMPLETE') {
|
|
85
|
+
var _newPluginState, _newPluginState2, _newPluginState3, _newPluginState4, _newPluginState5, _newPluginState6, _newPluginState7, _newPluginState8, _newPluginState9, _newPluginState0, _newPluginState1;
|
|
86
|
+
// REVEAL_COMPLETE repaints with the reveal dropped, so the decorations render their
|
|
87
|
+
// ordinary resting style. Without it the reveal stays in state indefinitely and the
|
|
88
|
+
// next unrelated repaint re-emits the hidden, zero-width highlight with no animation
|
|
89
|
+
// left to bring it in — the highlight simply vanishes.
|
|
90
|
+
newPluginState = meta.action === 'REVEAL_COMPLETE' ? {
|
|
91
|
+
...currentPluginState,
|
|
92
|
+
reveal: undefined
|
|
93
|
+
} : {
|
|
87
94
|
...currentPluginState,
|
|
88
95
|
...meta,
|
|
89
96
|
isDisplayingChanges: true,
|
|
90
|
-
activeIndex: undefined
|
|
97
|
+
activeIndex: undefined,
|
|
98
|
+
// Explicit rather than left to the spread: an absent key in `meta` would let
|
|
99
|
+
// the previous paint's choreography leak into this one, so closing the diff
|
|
100
|
+
// would animate too.
|
|
101
|
+
reveal: meta.reveal
|
|
91
102
|
};
|
|
92
103
|
// Calculate and store decorations in state
|
|
93
104
|
const {
|
|
@@ -111,13 +122,16 @@ export const createPlugin = (config, getIntl, api, onEditorView) => {
|
|
|
111
122
|
showIndicators: (_newPluginState6 = newPluginState) === null || _newPluginState6 === void 0 ? void 0 : _newPluginState6.showIndicators,
|
|
112
123
|
smartThresholds: (_newPluginState7 = newPluginState) === null || _newPluginState7 === void 0 ? void 0 : _newPluginState7.smartThresholds,
|
|
113
124
|
deletedDiffPlacement: (_newPluginState8 = newPluginState) === null || _newPluginState8 === void 0 ? void 0 : _newPluginState8.deletedDiffPlacement,
|
|
114
|
-
inlineDeletedDiffPlacement: (_newPluginState9 = newPluginState) === null || _newPluginState9 === void 0 ? void 0 : _newPluginState9.inlineDeletedDiffPlacement
|
|
125
|
+
inlineDeletedDiffPlacement: (_newPluginState9 = newPluginState) === null || _newPluginState9 === void 0 ? void 0 : _newPluginState9.inlineDeletedDiffPlacement,
|
|
126
|
+
// SHOW_DIFF only. The scroll-to-next recalculation further down deliberately
|
|
127
|
+
// omits this so stepping through changes cannot replay the choreography.
|
|
128
|
+
reveal: (_newPluginState0 = newPluginState) === null || _newPluginState0 === void 0 ? void 0 : _newPluginState0.reveal
|
|
115
129
|
} : {})
|
|
116
130
|
});
|
|
117
131
|
// Update the decorations and their ids
|
|
118
132
|
newPluginState.decorations = decorations;
|
|
119
133
|
newPluginState.contributorTags = contributorTags;
|
|
120
|
-
if (isExtendedEnabled((
|
|
134
|
+
if (isExtendedEnabled((_newPluginState1 = newPluginState) === null || _newPluginState1 === void 0 ? void 0 : _newPluginState1.diffType)) {
|
|
121
135
|
newPluginState.diffDescriptors = diffDescriptors;
|
|
122
136
|
}
|
|
123
137
|
} else if ((meta === null || meta === void 0 ? void 0 : meta.action) === 'HIDE_DIFF') {
|
|
@@ -128,6 +142,7 @@ export const createPlugin = (config, getIntl, api, onEditorView) => {
|
|
|
128
142
|
isDisplayingChanges: false,
|
|
129
143
|
activeIndex: undefined,
|
|
130
144
|
contributorTags: [],
|
|
145
|
+
reveal: undefined,
|
|
131
146
|
/**
|
|
132
147
|
* Reset isInverted & diffType state when hiding diffs
|
|
133
148
|
* Otherwise this should persist for the diff-showing session
|
|
@@ -141,9 +156,9 @@ export const createPlugin = (config, getIntl, api, onEditorView) => {
|
|
|
141
156
|
} : {})
|
|
142
157
|
};
|
|
143
158
|
} else if ((meta === null || meta === void 0 ? void 0 : meta.action) === 'SCROLL_TO_NEXT' || (meta === null || meta === void 0 ? void 0 : meta.action) === 'SCROLL_TO_PREVIOUS') {
|
|
144
|
-
var
|
|
159
|
+
var _newPluginState10;
|
|
145
160
|
// Update the active index in plugin state and recalculate decorations
|
|
146
|
-
const decorations = getScrollableDecorations(currentPluginState.decorations, newState.doc, (
|
|
161
|
+
const decorations = getScrollableDecorations(currentPluginState.decorations, newState.doc, (_newPluginState10 = newPluginState) === null || _newPluginState10 === void 0 ? void 0 : _newPluginState10.diffType);
|
|
147
162
|
if (decorations.length > 0) {
|
|
148
163
|
var _currentPluginState$a;
|
|
149
164
|
// Initialize to -1 if undefined so that the first "next" scroll takes us to index 0 (first change).
|
|
@@ -238,6 +253,10 @@ export const createPlugin = (config, getIntl, api, onEditorView) => {
|
|
|
238
253
|
}
|
|
239
254
|
const pluginState = showDiffPluginKey.getState(view.state);
|
|
240
255
|
|
|
256
|
+
// A repaint rebuilds inline decorations, destroying any animation bound to them, so
|
|
257
|
+
// an in-flight reveal has to be re-attached to the new nodes. No-op when idle.
|
|
258
|
+
rebindReveal(view, view.dom);
|
|
259
|
+
|
|
241
260
|
// Scroll to the first decoration when scrollIntoView was requested.
|
|
242
261
|
// Use the same filtered/position-sorted list as the active-index path
|
|
243
262
|
// so "first" reliably means the topmost scrollable diff in the document.
|
|
@@ -62,6 +62,10 @@ const resolveAgent = (attribution, profilesByAccountId) => {
|
|
|
62
62
|
* reads as "nobody touched this", so the whole list is dropped and the plain diff renders instead.
|
|
63
63
|
*/
|
|
64
64
|
export const resolveDiffContributors = (stepsWithAttribution, profiles) => {
|
|
65
|
+
// Profiles opt callers into contributor tags; attribution alone still supplies diff colours.
|
|
66
|
+
if (profiles === undefined) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
65
69
|
const profilesByAccountId = toProfilesByAccountId(profiles);
|
|
66
70
|
const contributors = [];
|
|
67
71
|
/** Keyed as the plugin keys changes, so no two entries can collapse onto one another. */
|