@atlaskit/editor-plugin-show-diff
Version:
ShowDiff plugin for @atlaskit/editor-core
163 lines (147 loc) • 11 kB
JavaScript
/**
* Style resolution for the `wrapBlockNodeView` nodeview decorations.
*
* Every exported resolver is a single gate: the `colorSchemeRegistry` + `factory.ts`
* implementation when `platform_editor_show_diff_color_scheme_refactor` is on, and the verbatim
* pre-refactor per-scheme constants from `./wrapBlockNodeViewStyles.legacy` when it is off. The two
* paths are built to emit identical style strings for both shipped schemes, so this is a kill
* switch for a refactor rather than a behaviour experiment.
*
* On cleanup (EDITOR-8281): drop the `isExperimentEnabled` dispatch and the `*Legacy` imports,
* keeping the `*Next` bodies.
*/
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
import { fg } from '@atlaskit/platform-feature-flags/fg';
import { buildAddedCellOverlayRoundedStyle, buildAddedCellOverlayStyle, buildAddedCellOverlayStyleNew, buildDeletedCellOverlayRoundedStyle, buildDeletedCellOverlayStyle, buildDeletedInlineContentStyle, buildDeletedInlineContentStyleExtended, buildDeletedLozengeActiveStyle, buildDeletedLozengeStyle, buildDeletedNodeCSSVariables, buildDeletedQuoteNodeWithLozengeStyle, buildDeletedStrikethroughLine, buildDeletedWrappedBlockOutline, buildInsertedBlockNodeStyle, buildInsertedInlineStyle, buildInsertStyleInBlockExtended, buildInsertStyleInBlockExtendedNoUnderline, buildInsertStyleNode } from '../colorSchemes/factory';
import { colorSchemeRegistry, getLegacyColorScheme, standardScheme } from '../colorSchemes/schemes';
import { getChangedContentStyleLegacy, getChangedNodeStyleLegacy, getDeletedContentStyleLegacy, getDeletedContentStyleUnboundedLegacy, getInsertedContentStyleLegacy, hasRestingDeletedRingLegacy, resolveCellOverlayStyleLegacy, resolveNestedInsertedNodeStyleLegacy, resolveRemovedLozengeStyleLegacy } from './wrapBlockNodeViewStyles.legacy';
const getColorScheme = colorScheme => colorSchemeRegistry[colorScheme !== null && colorScheme !== void 0 ? colorScheme : 'standard'];
/**
* Preserve the historical purple nested outlines when the layout/decision diff patch is off.
*/
const nestedContentScheme = standardScheme;
/**
* Node-name classification shared by the style resolvers below and by the routing in
* `wrapBlockNodeView.ts`.
*/
export const isMultiContainerBlockNode = nodeName => {
return ['decisionList', 'layoutSection'].includes(nodeName);
};
export const isTextLikeBlockNode = nodeName => {
// When cleaning up platform_editor_ai_show_diff_patch_2 just put paragraph into the list
if (nodeName === 'paragraph') {
return fg('platform_editor_ai_show_diff_patch_2');
}
return ['heading', 'bulletList', 'orderedList', 'listItem', 'taskList', 'blockquote'].includes(nodeName);
};
const getChangedContentStyleNext = (colorScheme, isActive = false, isInserted = false, hideAddedDiffsUnderline = false) => {
const colors = getColorScheme(colorScheme);
if (isInserted) {
return buildInsertedInlineStyle(colors, isActive, hideAddedDiffsUnderline);
}
const base = buildDeletedInlineContentStyle(colors, isActive ? 'active' : 'new');
// Text-like blocks (heading, lists, blockquote) render their deleted content through this
// getter rather than `getDeletedContentStyle`, so without this they never receive the
// glyphTint background + underline that plain deleted text already gets.
if (fg('confluence_ncs_step_diffing_version_history') && colors.deletedInlineTreatment === 'glyphTint') {
return base + buildDeletedInlineContentStyleExtended(colors, isActive);
}
return base;
};
const getChangedNodeStyleNext = (nodeName, colorScheme, isInserted = false, isActive = false, hideAddedDiffsUnderline = false) => {
const colors = getColorScheme(colorScheme);
if (isInserted) {
if (isMultiContainerBlockNode(nodeName)) {
return hideAddedDiffsUnderline || fg('platform_editor_ai_show_diff_patch_1') ? buildInsertStyleInBlockExtendedNoUnderline(nestedContentScheme) : buildInsertStyleInBlockExtended(nestedContentScheme);
}
if (isTextLikeBlockNode(nodeName)) {
return undefined;
}
return buildInsertedBlockNodeStyle(colors, 'node', isActive);
}
switch (nodeName) {
case 'blockquote':
return buildDeletedQuoteNodeWithLozengeStyle(colors, isActive);
case 'expand':
case 'decisionList':
return buildDeletedWrappedBlockOutline(colors, {
isActive,
isRounded: false
});
case 'panel':
case 'codeBlock':
return buildDeletedWrappedBlockOutline(colors, {
isActive,
isRounded: true
});
default:
return undefined;
}
};
const getDeletedContentStyleUnboundedNext = (colorScheme, isActive = false) => buildDeletedStrikethroughLine(getColorScheme(colorScheme), isActive);
const getInsertedContentStyleNext = (colorScheme, isActive = false, hideAddedDiffsUnderline = false) => buildInsertedInlineStyle(getColorScheme(colorScheme), isActive, hideAddedDiffsUnderline);
const getDeletedContentStyleNext = (colorScheme, isActive = false, omitHighlight = false) => {
const colors = getColorScheme(colorScheme);
const base = buildDeletedInlineContentStyle(colors, isActive ? 'active' : 'new');
// glyphTint adds a background highlight and border-bottom over the tint; strikethrough does not.
const needsExtendedHighlight = colors.deletedInlineTreatment === 'glyphTint' && !omitHighlight;
return needsExtendedHighlight ? base + buildDeletedInlineContentStyleExtended(colors, isActive) : base;
};
const resolveCellOverlayStyleNext = ({
colorScheme,
isInserted,
isRoundedTable
}) => {
const colors = getColorScheme(colorScheme);
// Square added-cell overlays follow insertedNodeEmphasis: pressed background vs accent border.
const addedCellStyle = isRoundedTable ? buildAddedCellOverlayRoundedStyle(colors) : colors.insertedNodeEmphasis === 'stateful' ? buildAddedCellOverlayStyleNew(colors) : buildAddedCellOverlayStyle(colors);
const deletedCellStyle = isRoundedTable ? buildDeletedCellOverlayRoundedStyle(colors) : buildDeletedCellOverlayStyle(colors);
return isInserted ? addedCellStyle : deletedCellStyle;
};
const resolveRemovedLozengeStyleNext = (colorScheme, isActive) => {
const colors = getColorScheme(colorScheme);
return isActive ? buildDeletedLozengeActiveStyle(colors) : buildDeletedLozengeStyle(colors);
};
const resolveNestedInsertedNodeStyleNext = colorScheme => buildInsertStyleNode(fg('platform_editor_ai_show_diff_patch_1') ? getColorScheme(colorScheme) : nestedContentScheme);
// Only 'stateful' schemes have a resting ring.
const hasRestingDeletedRingNext = colorScheme => getColorScheme(colorScheme).deletedNodeEmphasis === 'stateful';
/** Inline content style for a changed (inserted or deleted) block node. */
export const getChangedContentStyle = (colorScheme, isActive = false, isInserted = false, hideAddedDiffsUnderline = false) => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? getChangedContentStyleNext(colorScheme, isActive, isInserted, hideAddedDiffsUnderline) : getChangedContentStyleLegacy(getLegacyColorScheme(colorScheme), isActive, isInserted, hideAddedDiffsUnderline);
/** Node-specific style for a changed block node, or `undefined` when the node type has none. */
export const getChangedNodeStyle = (nodeName, colorScheme, isInserted = false, isActive = false, hideAddedDiffsUnderline = false) => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? getChangedNodeStyleNext(nodeName, colorScheme, isInserted, isActive, hideAddedDiffsUnderline) : getChangedNodeStyleLegacy(nodeName, getLegacyColorScheme(colorScheme), isInserted, isActive, hideAddedDiffsUnderline);
/** The positioned line drawn across deleted content spanning an unbounded range. */
export const getDeletedContentStyleUnbounded = (colorScheme, isActive = false) => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? getDeletedContentStyleUnboundedNext(colorScheme, isActive) : getDeletedContentStyleUnboundedLegacy(getLegacyColorScheme(colorScheme), isActive);
/** Inline style for inserted content. */
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);
/** Inline style for deleted content. */
export const getDeletedContentStyle = (colorScheme, isActive = false,
// Set while the reveal animation is running: it paints the highlight itself so it can wipe it in
// left-to-right, and a static background here would leave nothing to reveal.
omitHighlight = false) => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? getDeletedContentStyleNext(colorScheme, isActive, omitHighlight) : getDeletedContentStyleLegacy(getLegacyColorScheme(colorScheme), isActive, omitHighlight);
/**
* Overlay style for one added or deleted table cell. Invariant across the cells of a table, so the
* `querySelectorAll('td, th')` loop in `wrapBlockNodeView.ts` resolves it once.
*/
export const resolveCellOverlayStyle = args => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? resolveCellOverlayStyleNext(args) : resolveCellOverlayStyleLegacy({
...args,
colorScheme: getLegacyColorScheme(args.colorScheme)
});
/** Inner style for the "Removed" lozenge on a deleted block node. */
export const resolveRemovedLozengeStyle = (colorScheme, isActive) => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? resolveRemovedLozengeStyleNext(colorScheme, isActive) : resolveRemovedLozengeStyleLegacy(getLegacyColorScheme(colorScheme), isActive);
/**
* Style for inserted content nested inside a multi-container or list node — the `decisionList` and
* `taskList` `li`s and the `layoutSection` columns.
*/
export const resolveNestedInsertedNodeStyle = colorScheme => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? resolveNestedInsertedNodeStyleNext(colorScheme) : resolveNestedInsertedNodeStyleLegacy();
/**
* Whether the colour scheme draws a resting (non-active) ring on a deleted media/embed node, which
* is what the `show-diff-deleted-outline-new` class styles in editor-core's smartCardStyles.
*/
export const hasRestingDeletedRing = colorScheme => isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor') ? hasRestingDeletedRingNext(colorScheme) : hasRestingDeletedRingLegacy(getLegacyColorScheme(colorScheme));
/**
* Custom properties consumed by the `show-diff-deleted-node-vars` selectors in editor-core.
*
* No `*Legacy` counterpart: the OFF cohort emits no properties at all and takes its colours from the
* per-scheme selectors instead, so the gate lives at the single caller in `wrapBlockNodeView`.
*/
export const resolveDeletedNodeCSSVariables = colorScheme => buildDeletedNodeCSSVariables(getColorScheme(colorScheme));