Skip to content

Commit

Permalink
[8.12] [Security Solution] JSON diff view for prebuilt rule upgrade f…
Browse files Browse the repository at this point in the history
…low (#172535) (#172957)

# Backport

This will backport the following commits from `main` to `8.12`:
- [[Security Solution] JSON diff view for prebuilt rule upgrade flow
(#172535)](#172535)

<!--- Backport version: 8.9.7 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Nikita
Indik","email":"[email protected]"},"sourceCommit":{"committedDate":"2023-12-08T15:16:42Z","message":"[Security
Solution] JSON diff view for prebuilt rule upgrade flow (#172535)\n\n##
Summary\r\n\r\n**Resolves:
https://github.com/elastic/kibana/issues/169160**\r\n**Resolves:
https://github.com/elastic/kibana/issues/166164**\r\n**Docs issue:
https://github.com/elastic/security-docs/issues/4371**\r\n\r\nThis PR
adds a new \"Updates\" tab to the prebuilt rules upgrade flyout.\r\nThis
tab shows a diff between the installed and updated rule
JSON\r\nrepresentations.\r\n\r\n<img width=\"1313\"
alt=\"Scherm­afbeelding 2023-12-05 om 02 48
37\"\r\nsrc=\"https://github.com/elastic/kibana/assets/15949146/ec0f95c6-22c6-4ce6-a6cc-0ceee974c6f7\">\r\n\r\n\r\n\r\n###
Checklist\r\n\r\nDelete any items that are not applicable to this
PR.\r\n\r\n- [x] Any text added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[x] Functional changes are communicated to the Docs team. A ticket
or\r\nPR is opened in https://github.com/elastic/security-docs. The
following\r\ninformation is included: any feature flags used, affected
environments\r\n(Serverless, ESS, or both).
([Docs\r\nissue](https://github.com/elastic/security-docs/issues/4371))\r\n-
[
]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials
([Docs\r\nissue](https://github.com/elastic/security-docs/issues/4371))\r\n-
[ ] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios (will be added\r\nin
a follow-up PR)\r\n- [ ] Functional changes are covered with a test plan
and automated\r\ntests (will be added in a follow-up PR)\r\n- [x] Any UI
touched in this PR is usable by keyboard only (learn more\r\nabout
[keyboard accessibility](https://webaim.org/techniques/keyboard/))\r\n-
[x] Any UI touched in this PR does not create any new axe
failures\r\n(run axe in
browser:\r\n[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),\r\n[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))\r\n-
[x] This renders correctly on smaller devices using a
responsive\r\nlayout. (Doesn't look great on phone screen, because
viewing diff\r\nrequires a lot of horizontal space. Tablets are fine
though.)\r\n- [x] This was checked for
[cross-browser\r\ncompatibility](https://www.elastic.co/support/matrix#matrix_browsers)\r\n-
[x] Functional changes are hidden behind a feature flag. If
not\r\nhidden, the PR explains why these changes are being implemented
in a\r\nlong-living feature branch.\r\n- [x] Comprehensive manual
testing is done by two engineers: the PR\r\nauthor and one of the PR
reviewers. Changes are tested in both ESS
and\r\nServerless.\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine
<[email protected]>\r\nCo-authored-by:
Georgii Gorbachev
<[email protected]>","sha":"e5a6b978b8eca4ac275b72e88415e2238315a241","branchLabelMapping":{"^v8.13.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Team:Detections
and Resp","Team:
SecuritySolution","release_note:feature","Team:Detection Rule
Management","Feature:Prebuilt Detection
Rules","v8.12.0","v8.13.0"],"number":172535,"url":"https://github.com/elastic/kibana/pull/172535","mergeCommit":{"message":"[Security
Solution] JSON diff view for prebuilt rule upgrade flow (#172535)\n\n##
Summary\r\n\r\n**Resolves:
https://github.com/elastic/kibana/issues/169160**\r\n**Resolves:
https://github.com/elastic/kibana/issues/166164**\r\n**Docs issue:
https://github.com/elastic/security-docs/issues/4371**\r\n\r\nThis PR
adds a new \"Updates\" tab to the prebuilt rules upgrade flyout.\r\nThis
tab shows a diff between the installed and updated rule
JSON\r\nrepresentations.\r\n\r\n<img width=\"1313\"
alt=\"Scherm­afbeelding 2023-12-05 om 02 48
37\"\r\nsrc=\"https://github.com/elastic/kibana/assets/15949146/ec0f95c6-22c6-4ce6-a6cc-0ceee974c6f7\">\r\n\r\n\r\n\r\n###
Checklist\r\n\r\nDelete any items that are not applicable to this
PR.\r\n\r\n- [x] Any text added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[x] Functional changes are communicated to the Docs team. A ticket
or\r\nPR is opened in https://github.com/elastic/security-docs. The
following\r\ninformation is included: any feature flags used, affected
environments\r\n(Serverless, ESS, or both).
([Docs\r\nissue](https://github.com/elastic/security-docs/issues/4371))\r\n-
[
]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials
([Docs\r\nissue](https://github.com/elastic/security-docs/issues/4371))\r\n-
[ ] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios (will be added\r\nin
a follow-up PR)\r\n- [ ] Functional changes are covered with a test plan
and automated\r\ntests (will be added in a follow-up PR)\r\n- [x] Any UI
touched in this PR is usable by keyboard only (learn more\r\nabout
[keyboard accessibility](https://webaim.org/techniques/keyboard/))\r\n-
[x] Any UI touched in this PR does not create any new axe
failures\r\n(run axe in
browser:\r\n[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),\r\n[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))\r\n-
[x] This renders correctly on smaller devices using a
responsive\r\nlayout. (Doesn't look great on phone screen, because
viewing diff\r\nrequires a lot of horizontal space. Tablets are fine
though.)\r\n- [x] This was checked for
[cross-browser\r\ncompatibility](https://www.elastic.co/support/matrix#matrix_browsers)\r\n-
[x] Functional changes are hidden behind a feature flag. If
not\r\nhidden, the PR explains why these changes are being implemented
in a\r\nlong-living feature branch.\r\n- [x] Comprehensive manual
testing is done by two engineers: the PR\r\nauthor and one of the PR
reviewers. Changes are tested in both ESS
and\r\nServerless.\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine
<[email protected]>\r\nCo-authored-by:
Georgii Gorbachev
<[email protected]>","sha":"e5a6b978b8eca4ac275b72e88415e2238315a241"}},"sourceBranch":"main","suggestedTargetBranches":["8.12"],"targetPullRequestStates":[{"branch":"8.12","label":"v8.12.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.13.0","labelRegex":"^v8.13.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/172535","number":172535,"mergeCommit":{"message":"[Security
Solution] JSON diff view for prebuilt rule upgrade flow (#172535)\n\n##
Summary\r\n\r\n**Resolves:
https://github.com/elastic/kibana/issues/169160**\r\n**Resolves:
https://github.com/elastic/kibana/issues/166164**\r\n**Docs issue:
https://github.com/elastic/security-docs/issues/4371**\r\n\r\nThis PR
adds a new \"Updates\" tab to the prebuilt rules upgrade flyout.\r\nThis
tab shows a diff between the installed and updated rule
JSON\r\nrepresentations.\r\n\r\n<img width=\"1313\"
alt=\"Scherm­afbeelding 2023-12-05 om 02 48
37\"\r\nsrc=\"https://github.com/elastic/kibana/assets/15949146/ec0f95c6-22c6-4ce6-a6cc-0ceee974c6f7\">\r\n\r\n\r\n\r\n###
Checklist\r\n\r\nDelete any items that are not applicable to this
PR.\r\n\r\n- [x] Any text added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[x] Functional changes are communicated to the Docs team. A ticket
or\r\nPR is opened in https://github.com/elastic/security-docs. The
following\r\ninformation is included: any feature flags used, affected
environments\r\n(Serverless, ESS, or both).
([Docs\r\nissue](https://github.com/elastic/security-docs/issues/4371))\r\n-
[
]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials
([Docs\r\nissue](https://github.com/elastic/security-docs/issues/4371))\r\n-
[ ] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios (will be added\r\nin
a follow-up PR)\r\n- [ ] Functional changes are covered with a test plan
and automated\r\ntests (will be added in a follow-up PR)\r\n- [x] Any UI
touched in this PR is usable by keyboard only (learn more\r\nabout
[keyboard accessibility](https://webaim.org/techniques/keyboard/))\r\n-
[x] Any UI touched in this PR does not create any new axe
failures\r\n(run axe in
browser:\r\n[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),\r\n[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))\r\n-
[x] This renders correctly on smaller devices using a
responsive\r\nlayout. (Doesn't look great on phone screen, because
viewing diff\r\nrequires a lot of horizontal space. Tablets are fine
though.)\r\n- [x] This was checked for
[cross-browser\r\ncompatibility](https://www.elastic.co/support/matrix#matrix_browsers)\r\n-
[x] Functional changes are hidden behind a feature flag. If
not\r\nhidden, the PR explains why these changes are being implemented
in a\r\nlong-living feature branch.\r\n- [x] Comprehensive manual
testing is done by two engineers: the PR\r\nauthor and one of the PR
reviewers. Changes are tested in both ESS
and\r\nServerless.\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine
<[email protected]>\r\nCo-authored-by:
Georgii Gorbachev
<[email protected]>","sha":"e5a6b978b8eca4ac275b72e88415e2238315a241"}}]}]
BACKPORT-->

Co-authored-by: Nikita Indik <[email protected]>
  • Loading branch information
kibanamachine and nikitaindik authored Dec 8, 2023
1 parent 2307225 commit 692bde9
Show file tree
Hide file tree
Showing 19 changed files with 1,004 additions and 70 deletions.
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,7 @@
"deep-freeze-strict": "^1.1.1",
"deepmerge": "^4.2.2",
"del": "^6.1.0",
"diff": "^5.1.0",
"elastic-apm-node": "^4.2.0",
"email-addresses": "^5.0.0",
"execa": "^5.1.1",
Expand Down Expand Up @@ -1029,6 +1030,7 @@
"react": "^17.0.2",
"react-ace": "^7.0.5",
"react-color": "^2.13.8",
"react-diff-view": "^3.2.0",
"react-dom": "^17.0.2",
"react-dropzone": "^4.2.9",
"react-fast-compare": "^2.0.4",
Expand Down Expand Up @@ -1089,6 +1091,7 @@
"type-detect": "^4.0.8",
"typescript-fsa": "^3.0.0",
"typescript-fsa-reducers": "^1.2.2",
"unidiff": "^1.0.4",
"unified": "9.2.2",
"use-resize-observer": "^9.1.0",
"usng.js": "^0.4.5",
Expand Down Expand Up @@ -1345,6 +1348,7 @@
"@types/dedent": "^0.7.0",
"@types/deep-freeze-strict": "^1.1.0",
"@types/delete-empty": "^2.0.0",
"@types/diff": "^5.0.8",
"@types/ejs": "^3.0.6",
"@types/enzyme": "^3.10.12",
"@types/eslint": "^8.44.2",
Expand Down Expand Up @@ -1508,7 +1512,6 @@
"debug": "^2.6.9",
"delete-empty": "^2.0.0",
"dependency-check": "^4.1.0",
"diff": "^4.0.1",
"dpdm": "3.9.0",
"ejs": "^3.1.8",
"enzyme": "^3.11.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ it('rewrites ftr reports with minimal changes', async () => {
reportPath: Path.resolve(__dirname, './__fixtures__/ftr_report.xml'),
});

expect(createPatch('ftr.xml', FTR_REPORT, xml, { context: 0 })).toMatchInlineSnapshot(`
expect(createPatch('ftr.xml', FTR_REPORT, xml)).toMatchInlineSnapshot(`
Index: ftr.xml
===================================================================
--- ftr.xml [object Object]
--- ftr.xml
+++ ftr.xml
@@ -1,53 +1,56 @@
‹?xml version="1.0" encoding="utf-8"?›
Expand Down Expand Up @@ -149,10 +149,10 @@ it('rewrites jest reports with minimal changes', async () => {
reportPath: Path.resolve(__dirname, './__fixtures__/jest_report.xml'),
});

expect(createPatch('jest.xml', JEST_REPORT, xml, { context: 0 })).toMatchInlineSnapshot(`
expect(createPatch('jest.xml', JEST_REPORT, xml)).toMatchInlineSnapshot(`
Index: jest.xml
===================================================================
--- jest.xml [object Object]
--- jest.xml
+++ jest.xml
@@ -3,13 +3,17 @@
‹testsuite name="x-pack/legacy/plugins/code/server/lsp/abstract_launcher.test.ts" timestamp="2019-06-07T03:42:21" time="14.504" tests="5" failures="1" skipped="0" file="/var/lib/jenkins/workspace/elastic+kibana+master/JOB/x-pack-intake/node/immutable/kibana/x-pack/legacy/plugins/code/server/lsp/abstract_launcher.test.ts"›
Expand Down Expand Up @@ -196,10 +196,10 @@ it('rewrites mocha reports with minimal changes', async () => {
reportPath: Path.resolve(__dirname, './__fixtures__/mocha_report.xml'),
});

expect(createPatch('mocha.xml', MOCHA_REPORT, xml, { context: 0 })).toMatchInlineSnapshot(`
expect(createPatch('mocha.xml', MOCHA_REPORT, xml)).toMatchInlineSnapshot(`
Index: mocha.xml
===================================================================
--- mocha.xml [object Object]
--- mocha.xml
+++ mocha.xml
@@ -1,13 +1,16 @@
‹?xml version="1.0" encoding="utf-8"?›
Expand Down Expand Up @@ -273,10 +273,10 @@ it('rewrites cypress reports with minimal changes', async () => {
reportPath: Path.resolve(__dirname, './__fixtures__/cypress_report.xml'),
});

expect(createPatch('cypress.xml', CYPRESS_REPORT, xml, { context: 0 })).toMatchInlineSnapshot(`
expect(createPatch('cypress.xml', CYPRESS_REPORT, xml)).toMatchInlineSnapshot(`
Index: cypress.xml
===================================================================
--- cypress.xml [object Object]
--- cypress.xml
+++ cypress.xml
@@ -1,25 +1,16 @@
-‹?xml version="1.0" encoding="UTF-8"?›
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,13 @@ export const allowedExperimentalValues = Object.freeze({
* Enables SentinelOne manual host manipulation actions
*/
sentinelOneManualHostActionsEnabled: false,

/*
* Enables experimental "Updates" tab in the prebuilt rule upgrade flyout.
* This tab shows the JSON diff between the installed prebuilt rule
* version and the latest available version.
*/
jsonPrebuiltRulesDiffingEnabled: false,
});

type ExperimentalConfigKeys = Array<keyof ExperimentalFeatures>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
* 2.0.
*/

export const DESCRIPTION_LIST_COLUMN_WIDTHS: [string, string] = ['50%', '50%'];
export const DEFAULT_DESCRIPTION_LIST_COLUMN_WIDTHS: [string, string] = ['50%', '50%'];
export const LARGE_DESCRIPTION_LIST_COLUMN_WIDTHS: [string, string] = ['30%', '70%'];
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
/*
* 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, { useMemo } from 'react';
import { css, Global } from '@emotion/react';
import {
Diff,
useSourceExpansion,
useMinCollapsedLines,
parseDiff,
tokenize,
} from 'react-diff-view';
import 'react-diff-view/style/index.css';
import type {
RenderGutter,
HunkData,
TokenizeOptions,
DiffProps,
HunkTokens,
} from 'react-diff-view';
import unidiff from 'unidiff';
import { useEuiTheme } from '@elastic/eui';
import { Hunks } from './hunks';
import { markEdits, DiffMethod } from './mark_edits';

interface UseExpandReturn {
expandRange: (start: number, end: number) => void;
hunks: HunkData[];
}

/**
* @param {HunkData[]} hunks - An array of hunk objects representing changes in a section of a string. Sections normally span multiple lines.
* @param {string} oldSource - Original string, before changes
* @returns {UseExpandReturn} - "expandRange" is function that triggers expansion, "hunks" is an array of hunks with hidden section expanded.
*
* @description
* Sections of diff without changes are hidden by default, because they are not present in the "hunks" array.
* "useExpand" allows to show these hidden sections when user clicks on "Expand hidden <number> lines" button.
* Calling "expandRange" basically merges two adjacent hunks into one:
* - takes first hunk
* - appends all the lines between the first hunk and the second hunk
* - finally appends the second hunk
* returned "hunks" is the resulting array of hunks with hidden section expanded.
*/
const useExpand = (hunks: HunkData[], oldSource: string): UseExpandReturn => {
const [hunksWithSourceExpanded, expandRange] = useSourceExpansion(hunks, oldSource);
const hunksWithMinLinesCollapsed = useMinCollapsedLines(0, hunksWithSourceExpanded, oldSource);

return {
expandRange,
hunks: hunksWithMinLinesCollapsed,
};
};

const useTokens = (
hunks: HunkData[],
diffMethod: DiffMethod,
oldSource: string
): HunkTokens | undefined => {
if (!hunks) {
return undefined;
}

const options: TokenizeOptions = {
oldSource,
highlight: false,
enhancers: [
/*
This custom "markEdits" function is a slightly modified version of "markEdits"
enhancer from react-diff-view with added support for word-level highlighting.
*/
markEdits(hunks, diffMethod),
],
};

try {
/*
Synchroniously apply all the enhancers to the hunks and return an array of tokens.
*/
return tokenize(hunks, options);
} catch (ex) {
return undefined;
}
};

const renderGutter: RenderGutter = ({ change }) => {
/*
Custom gutter: rendering "+" or "-" so the diff is readable by colorblind people.
*/
if (change.type === 'insert') {
return <span>{'+'}</span>;
}

if (change.type === 'delete') {
return <span>{'-'}</span>;
}

return null;
};

const convertToDiffFile = (oldSource: string, newSource: string) => {
/*
"diffLines" call converts two strings of text into an array of Change objects.
*/
const changes = unidiff.diffLines(oldSource, newSource);

/*
Then "formatLines" takes an array of Change objects and turns it into a single "unified diff" string.
More info about the "unified diff" format: https://en.wikipedia.org/wiki/Diff_utility#Unified_format
Unified diff is a string with change markers added. Looks something like:
`
@@ -3,16 +3,15 @@
"author": ["Elastic"],
- "from": "now-540s",
+ "from": "now-9m",
"history_window_start": "now-14d",
`
*/
const unifiedDiff: string = unidiff.formatLines(changes, {
context: 3,
});

/*
"parseDiff" converts a unified diff string into a gitdiff-parser File object.
File object contains some metadata and the "hunks" property - an array of Hunk objects.
Hunks represent changed lines of code plus a few unchanged lines above and below for context.
*/
const [diffFile] = parseDiff(unifiedDiff, {
nearbySequences: 'zip',
});

return diffFile;
};

const TABLE_CLASS_NAME = 'rule-update-diff-table';
const CODE_CLASS_NAME = 'rule-update-diff-code';
const GUTTER_CLASS_NAME = 'rule-update-diff-gutter';

const CustomStyles: React.FC = ({ children }) => {
const { euiTheme } = useEuiTheme();

const customCss = css`
.${TABLE_CLASS_NAME} .diff-gutter-col {
width: ${euiTheme.size.xl};
}
.${CODE_CLASS_NAME}.diff-code, .${GUTTER_CLASS_NAME}.diff-gutter {
background: transparent;
}
.${GUTTER_CLASS_NAME}:nth-child(3) {
border-left: 1px solid ${euiTheme.colors.mediumShade};
}
.${GUTTER_CLASS_NAME}.diff-gutter-delete {
color: ${euiTheme.colors.dangerText};
font-weight: bold;
}
.${GUTTER_CLASS_NAME}.diff-gutter-insert {
color: ${euiTheme.colors.successText};
font-weight: bold;
}
.${CODE_CLASS_NAME}.diff-code {
padding: 0 ${euiTheme.size.l} 0 ${euiTheme.size.m};
}
.${CODE_CLASS_NAME}.diff-code-delete .diff-code-edit,
.${CODE_CLASS_NAME}.diff-code-insert .diff-code-edit {
background: transparent;
}
.${CODE_CLASS_NAME}.diff-code-delete .diff-code-edit {
color: ${euiTheme.colors.dangerText};
text-decoration: line-through;
}
.${CODE_CLASS_NAME}.diff-code-insert .diff-code-edit {
color: ${euiTheme.colors.successText};
text-decoration: underline;
}
`;

return (
<>
<Global styles={customCss} />
{children}
</>
);
};

interface DiffViewProps extends Partial<DiffProps> {
oldSource: string;
newSource: string;
diffMethod?: DiffMethod;
}

export const DiffView = ({
oldSource,
newSource,
diffMethod = DiffMethod.WORDS,
}: DiffViewProps) => {
/*
"react-diff-view" components consume diffs not as a strings, but as something they call "hunks".
So we first need to convert our "before" and "after" strings into these "hunk" objects.
"hunks" describe changed sections of code plus a few unchanged lines above and below for context.
*/

/*
"diffFile" is essentially an object containing an array of hunks plus some metadata.
*/
const diffFile = useMemo(() => convertToDiffFile(oldSource, newSource), [oldSource, newSource]);

/*
Sections of diff without changes are hidden by default, because they are not present in the "hunks" array.
"useExpand" allows to show these hidden sections when a user clicks on "Expand hidden <number> lines" button.
*/
const { expandRange, hunks } = useExpand(diffFile.hunks, oldSource);

/*
Go over each hunk and extract tokens from it. For example, split strings into words or characters,
so we can highlight them later.
*/
const tokens = useTokens(hunks, diffMethod, oldSource);

return (
<CustomStyles>
<Diff
/*
"diffType": can be either 'add', 'delete', 'modify', 'rename' or 'copy'.
Passing 'add' or 'delete' would skip rendering one of the sides in split view.
*/
diffType={diffFile.type}
hunks={hunks}
renderGutter={renderGutter}
tokens={tokens}
className={TABLE_CLASS_NAME}
gutterClassName={GUTTER_CLASS_NAME}
codeClassName={CODE_CLASS_NAME}
>
{/* eslint-disable-next-line @typescript-eslint/no-shadow */}
{(hunks) => <Hunks hunks={hunks} oldSource={oldSource} expandRange={expandRange} />}
</Diff>
</CustomStyles>
);
};
Loading

0 comments on commit 692bde9

Please sign in to comment.