Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[8.17] [Security Solution] Fix incorrect changes highlighting in diff view (#205138) #205611

Merged
merged 1 commit into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import React from 'react';
import type { Story } from '@storybook/react';
import type { DiffViewProps } from './diff_view';
import { DiffView } from './diff_view';
import { DiffMethod } from './mark_edits';

export default {
component: DiffView,
title: 'Rule Management/Prebuilt Rules/Upgrade Flyout/ThreeWayDiff/DiffView',
argTypes: {
oldSource: {
control: 'text',
},
newSource: {
control: 'text',
},
diffMethod: {
control: 'select',
options: [
DiffMethod.WORDS_WITH_SPACE,
DiffMethod.WORDS,
DiffMethod.CHARS,
DiffMethod.LINES,
DiffMethod.SENTENCES,
],
defaultValue: DiffMethod.WORDS_WITH_SPACE,
},
zip: {
control: 'boolean',
defaultValue: false,
},
},
};

const Template: Story<DiffViewProps> = ({ oldSource, newSource, diffMethod, zip }) => {
return (
<DiffView
oldSource={oldSource}
newSource={newSource}
diffMethod={diffMethod}
zip={zip}
viewType="unified"
/>
);
};

export const Default = Template.bind({});
Default.args = {
oldSource:
'from logs-endpoint.alerts-*\n| where event.code in ("malicious_file", "memory_signature", "shellcode_thread") and rule.name is not null\n| keep host.id, rule.name, event.code\n| stats hosts = count_distinct(host.id) by rule.name, event.code\n| where hosts >= 3',
newSource:
'from logs-endpoint.alerts-*\n| where event.code in ("malicious_file", "memory_signature", "shellcode_thread")\n| stats hosts = count_distinct(host.id)\n| where hosts >= 3',
};
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import type {
HunkTokens,
} from 'react-diff-view';
import unidiff from 'unidiff';
import type { Change } from 'diff';
import { useEuiTheme, COLOR_MODES_STANDARD } from '@elastic/eui';
import { Hunks } from './hunks';
import { markEdits, DiffMethod } from './mark_edits';
Expand Down Expand Up @@ -89,7 +88,7 @@ const useTokens = (

try {
/*
Synchroniously apply all the enhancers to the hunks and return an array of tokens.
Synchronously apply all the enhancers to the hunks and return an array of tokens.
*/
return tokenize(hunks, options);
} catch (ex) {
Expand Down Expand Up @@ -128,7 +127,7 @@ const convertChangesToUnifiedDiffString = (changes: Change[]): string => {
return unifiedDiff;
};

const convertToDiffFile = (oldSource: string, newSource: string) => {
const convertToDiffFile = (oldSource: string, newSource: string, zip?: boolean) => {
/*
"diffLines" call converts two strings of text into an array of Change objects.
*/
Expand Down Expand Up @@ -156,7 +155,7 @@ const convertToDiffFile = (oldSource: string, newSource: string) => {
Hunks represent changed lines of code plus a few unchanged lines above and below for context.
*/
const [diffFile] = parseDiff(unifiedDiff, {
nearbySequences: 'zip',
nearbySequences: zip ? 'zip' : undefined,
});

return diffFile;
Expand Down Expand Up @@ -255,18 +254,25 @@ const CustomStyles: FC<PropsWithChildren<unknown>> = ({ children }) => {
);
};

interface DiffViewProps extends Partial<DiffProps> {
export interface DiffViewProps extends Partial<DiffProps> {
oldSource: string;
newSource: string;
diffMethod?: DiffMethod;
viewType?: 'split' | 'unified';
/*
When "zip" is set to true, the change lines will be rendered in an interlaced style.
For an example, refer to:
https://github.com/otakustay/react-diff-view/blob/8a2dbdf97af0890aff6e563ed435e7da13c5e7b1/README.md#parse-diff-text
*/
zip?: boolean;
}

export const DiffView = ({
oldSource,
newSource,
diffMethod = DiffMethod.WORDS,
diffMethod = DiffMethod.WORDS_WITH_SPACE,
viewType = 'split',
zip = false,
}: DiffViewProps) => {
/*
"react-diff-view" components consume diffs not as a strings, but as something they call "hunks".
Expand All @@ -277,7 +283,10 @@ export const DiffView = ({
/*
"diffFile" is essentially an object containing an array of hunks plus some metadata.
*/
const diffFile = useMemo(() => convertToDiffFile(oldSource, newSource), [oldSource, newSource]);
const diffFile = useMemo(
() => convertToDiffFile(oldSource, newSource, zip),
[oldSource, newSource, zip]
);

/*
Sections of diff without changes are hidden by default, because they are not present in the "hunks" array.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ export enum DiffMethod {
WORDS = 'diffWords',
WORDS_WITH_SPACE = 'diffWordsWithSpace',
LINES = 'diffLines',
TRIMMED_LINES = 'diffTrimmedLines',
SENTENCES = 'diffSentences',
CSS = 'diffCss',
}
Expand Down Expand Up @@ -262,7 +261,7 @@ function diffChangeBlock(
* The format of the strings is as follows:
*/
export function markEdits(hunks: HunkData[], diffMethod: DiffMethod): TokenizeEnhancer {
/*
/*
changeBlocks is an array that contains information about the lines that have changes (additions or deletions).
Unchanged lines are not included.
*/
Expand Down
Loading