@atlaskit/editor-plugin-show-diff
Version:
ShowDiff plugin for @atlaskit/editor-core
165 lines (164 loc) • 8.55 kB
JavaScript
import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
import { Decoration } from '@atlaskit/editor-prosemirror/view';
import { fg } from '@atlaskit/platform-feature-flags';
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
import { standardDecorationMarkerVariable, editingStyleQuoteNode, editingStyleRuleNode, editingStyleCardBlockNode, editingStyleNode, deletedContentStyleNew, deletedStyleQuoteNode, addedCellOverlayStyle, deletedCellOverlayStyle } from './colorSchemes/standard';
import { traditionalDecorationMarkerVariable, traditionalDecorationMarkerVariableActive, traditionalDecorationMarkerVariableNew, traditionalDeletedDecorationMarkerVariable, traditionalDeletedDecorationMarkerVariableActive, traditionalDeletedDecorationMarkerVariableNew, traditionalStyleQuoteNode, traditionalStyleQuoteNodeActive, traditionalStyleQuoteNodeNew, traditionalStyleRuleNode, traditionalStyleRuleNodeActive, traditionalStyleRuleNodeNew, traditionalStyleCardBlockNode, traditionalStyleCardBlockNodeActive, traditionalStyleCardBlockNodeNew, traditionalStyleNode, traditionalStyleNodeActive, traditionalStyleNodeNew, getDeletedTraditionalInlineStyle, deletedTraditionalStyleQuoteNode, traditionalAddedCellOverlayStyle, deletedTraditionalCellOverlayStyle } from './colorSchemes/traditional';
const displayNoneStyle = convertToInlineCss({
display: 'none'
});
const getNodeClass = name => {
switch (name) {
case 'extension':
return 'show-diff-changed-decoration-node';
default:
return undefined;
}
};
const getBlockNodeStyle = ({
nodeName,
colorScheme,
isInserted = true,
isActive = false
}) => {
const isTraditional = colorScheme === 'traditional';
if (['mediaSingle', 'mediaGroup', 'table',
// Handle table separately to avoid border issues
'tableRow', 'paragraph',
// Paragraph and heading nodes do not need special styling
'heading', 'hardBreak', 'decisionList', 'taskList', 'taskItem', 'bulletList', 'orderedList', 'layoutSection'].includes(nodeName)) {
// Layout nodes do not need special styling
return undefined;
}
if (['tableCell', 'tableHeader'].includes(nodeName)) {
if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
// This is used for positioning the cell overlay widget decorations
return convertToInlineCss({
position: 'relative'
});
}
// When gate is off, it should return undefined as above
return undefined;
}
if (['extension', 'embedCard', 'listItem'].includes(nodeName)) {
if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
if (isInserted) {
return isTraditional && isActive ? traditionalDecorationMarkerVariableActive : isTraditional ? fg('platform_editor_show_diff_scroll_navigation') ? traditionalDecorationMarkerVariableNew : traditionalDecorationMarkerVariable : standardDecorationMarkerVariable;
} else {
return isTraditional && isActive ? traditionalDeletedDecorationMarkerVariableActive : isTraditional ? fg('platform_editor_show_diff_scroll_navigation') ? traditionalDeletedDecorationMarkerVariableNew : traditionalDeletedDecorationMarkerVariable : deletedContentStyleNew;
}
}
return isTraditional && isActive ? traditionalDecorationMarkerVariableActive : isTraditional ? fg('platform_editor_show_diff_scroll_navigation') ? traditionalDecorationMarkerVariableNew : traditionalDecorationMarkerVariable : standardDecorationMarkerVariable;
}
if (nodeName === 'blockquote') {
if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
if (isInserted) {
return isTraditional ? isActive ? traditionalStyleQuoteNodeActive : fg('platform_editor_show_diff_scroll_navigation') ? traditionalStyleQuoteNodeNew : traditionalStyleQuoteNode : editingStyleQuoteNode;
} else {
return isTraditional ? deletedTraditionalStyleQuoteNode : deletedStyleQuoteNode;
}
}
return isTraditional ? isActive ? traditionalStyleQuoteNodeActive : fg('platform_editor_show_diff_scroll_navigation') ? traditionalStyleQuoteNodeNew : traditionalStyleQuoteNode : editingStyleQuoteNode;
}
if (nodeName === 'rule') {
if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
if (isInserted) {
return isTraditional ? isActive ? traditionalStyleRuleNodeActive : fg('platform_editor_show_diff_scroll_navigation') ? traditionalStyleRuleNodeNew : traditionalStyleRuleNode : editingStyleRuleNode;
} else {
return isTraditional ? getDeletedTraditionalInlineStyle(false) : deletedContentStyleNew;
}
}
return isTraditional ? isActive ? traditionalStyleRuleNodeActive : fg('platform_editor_show_diff_scroll_navigation') ? traditionalStyleRuleNodeNew : traditionalStyleRuleNode : editingStyleRuleNode;
}
if (nodeName === 'blockCard') {
if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
if (isInserted) {
return isTraditional ? isActive ? traditionalStyleCardBlockNodeActive : fg('platform_editor_show_diff_scroll_navigation') ? traditionalStyleCardBlockNodeNew : traditionalStyleCardBlockNode : editingStyleCardBlockNode;
} else {
return isTraditional ? getDeletedTraditionalInlineStyle(false) : deletedContentStyleNew;
}
}
return isTraditional ? isActive ? traditionalStyleCardBlockNodeActive : fg('platform_editor_show_diff_scroll_navigation') ? traditionalStyleCardBlockNodeNew : traditionalStyleCardBlockNode : editingStyleCardBlockNode;
}
if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
if (isInserted) {
return isTraditional ? isActive ? traditionalStyleNodeActive : fg('platform_editor_show_diff_scroll_navigation') ? traditionalStyleNodeNew : traditionalStyleNode : editingStyleNode;
} else {
return isTraditional ? getDeletedTraditionalInlineStyle(false) : deletedContentStyleNew;
}
}
return isTraditional ? isActive ? traditionalStyleNodeActive : fg('platform_editor_show_diff_scroll_navigation') ? traditionalStyleNodeNew : traditionalStyleNode : editingStyleNode;
};
/**
* Node decoration used for block-level insertions. When isActive, uses emphasised (pressed) styling.
*
* @param change Node range and name
* @param colorScheme Optional color scheme
* @param isActive Whether this node is part of the currently active/focused change
* @returns Prosemirror node decoration or undefined
*/
export const createBlockChangedDecoration = ({
change,
colorScheme,
isInserted = true,
isActive = false,
shouldHideDeleted = false
}) => {
const decorations = [];
if (shouldHideDeleted) {
return [Decoration.node(change.from, change.to, {
style: displayNoneStyle
}, {
key: 'diff-block',
nodeName: change.name
})];
}
let style;
if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) && ['tableCell', 'tableHeader'].includes(change.name)) {
const cellOverlay = document.createElement('div');
const cellOverlayStyle = isInserted ? colorScheme === 'traditional' ? traditionalAddedCellOverlayStyle : addedCellOverlayStyle : colorScheme === 'traditional' ? deletedTraditionalCellOverlayStyle : deletedCellOverlayStyle;
cellOverlay.setAttribute('style', cellOverlayStyle);
decorations.push(
// change.to - 1 to position the overlay inside the end of the cell
Decoration.widget(change.to - 1, cellOverlay, {
key: `diff-widget-cell-overlay-${change.to}`
}));
}
if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
style = getBlockNodeStyle({
nodeName: change.name,
colorScheme,
isInserted,
isActive
});
} else {
style = getBlockNodeStyle({
nodeName: change.name,
colorScheme,
isActive
});
}
const className = getNodeClass(change.name);
if (fg('platform_editor_show_diff_scroll_navigation')) {
if (style || className) {
decorations.push(Decoration.node(change.from, change.to, {
style: style,
'data-testid': 'show-diff-changed-decoration-node',
class: className
}, {
key: 'diff-block',
nodeName: change.name
}));
}
} else {
decorations.push(Decoration.node(change.from, change.to, {
style,
'data-testid': 'show-diff-changed-decoration-node',
class: className
}, {
key: 'diff-block',
nodeName: change.name
}));
}
return decorations;
};