From 6a181e3651a2880f4de082001e57f9ee3447b716 Mon Sep 17 00:00:00 2001
From: moshe-blox <89339422+moshe-blox@users.noreply.github.com>
Date: Wed, 11 Sep 2024 16:00:26 +0300
Subject: [PATCH 01/35] fix: (differ) incorrect diffs (#1719)
* fix: (differ) incorrect diffs
* fix: funcs without param names
* revert differ scope
---
scripts/differ/diff.go | 97 +++++++++++++++++++++++++
scripts/differ/go.mod | 3 +-
scripts/differ/go.sum | 6 +-
scripts/differ/main.go | 14 ++--
scripts/differ/parser.go | 3 +
scripts/differ/ui/package-lock.json | 105 +++++++++++++++-------------
scripts/differ/ui/package.json | 5 +-
scripts/differ/ui/pages/index.tsx | 103 +++++++++++++++------------
8 files changed, 226 insertions(+), 110 deletions(-)
create mode 100644 scripts/differ/diff.go
diff --git a/scripts/differ/diff.go b/scripts/differ/diff.go
new file mode 100644
index 0000000000..26c0af0a8e
--- /dev/null
+++ b/scripts/differ/diff.go
@@ -0,0 +1,97 @@
+package main
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "os"
+ "os/exec"
+ "path/filepath"
+)
+
+// Diff returns the output of git diff between two given sources, excluding the diff header.
+func Diff(leftName, rightName string, left, right []byte, contextLines int) ([]byte, error) {
+ expectChanges := !bytes.Equal(left, right)
+
+ // Save the sources to temporary files.
+ dir, err := os.MkdirTemp("", "differ-git-diff")
+ if err != nil {
+ return nil, fmt.Errorf("failed to create temp dir: %w", err)
+ }
+ defer func() {
+ if err := os.RemoveAll(dir); err != nil {
+ fmt.Printf("failed to remove temp dir: %v", err)
+ }
+ }()
+
+ leftPath := filepath.Join(dir, "left")
+ if err := os.WriteFile(leftPath, left, 0600); err != nil {
+ return nil, fmt.Errorf("failed to write left file: %w", err)
+ }
+ rightPath := filepath.Join(dir, "right")
+ if err := os.WriteFile(rightPath, right, 0600); err != nil {
+ return nil, fmt.Errorf("failed to write right file: %w", err)
+ }
+
+ // Run git diff.
+ hasChanges := false
+ diff, err := exec.Command("git", "diff", "--no-index", fmt.Sprintf("-U%d", contextLines), leftPath, rightPath).CombinedOutput() // #nosec G204
+ if err != nil {
+ var exitErr *exec.ExitError
+ if errors.As(err, &exitErr) {
+ hasChanges = exitErr.ExitCode() == 1
+ } else {
+ return nil, fmt.Errorf("failed to execute git diff (%w): %s", err, string(diff))
+ }
+ }
+ if expectChanges {
+ if !hasChanges {
+ return nil, fmt.Errorf("git diff claims no changes, but sources are different")
+ }
+ if len(diff) == 0 {
+ return nil, fmt.Errorf("git diff returned empty diff despite claiming changes")
+ }
+ } else {
+ if hasChanges {
+ return nil, fmt.Errorf("git diff claims changes, but sources are equal")
+ }
+ if len(diff) != 0 {
+ return nil, fmt.Errorf("git diff returned non-empty diff despite claiming no changes")
+ }
+ return nil, nil
+ }
+
+ // Verify header.
+ const header1 = "diff --git "
+ const header2 = "index "
+ const header3 = "--- "
+ const header4 = "+++ "
+
+ parts := bytes.SplitN(diff, []byte("\n"), 5)
+ if len(parts) != 5 {
+ return nil, fmt.Errorf("unexpected number of lines in git diff output: %d", len(parts))
+ }
+ if !bytes.HasPrefix(parts[0], []byte(header1)) {
+ return nil, fmt.Errorf("unexpected header line 1 in git diff output: %q", parts[1])
+ }
+ if !bytes.HasPrefix(parts[1], []byte(header2)) {
+ return nil, fmt.Errorf("unexpected header line 2 in git diff output: %q", parts[2])
+ }
+ if !bytes.HasPrefix(parts[2], []byte(header3)) {
+ return nil, fmt.Errorf("unexpected header line 3 in git diff output: %q", parts[2])
+ }
+ if !bytes.HasPrefix(parts[3], []byte(header4)) {
+ return nil, fmt.Errorf("unexpected header line 4 in git diff output: %q", parts[2])
+ }
+
+ // Reconstruct the diff without the header.
+ b := bytes.NewBuffer(nil)
+ fmt.Fprintf(b, "--- %s\n+++ %s\n", leftName, rightName)
+ b.Write(parts[4])
+ diff = b.Bytes()
+ if len(diff) == 0 {
+ return nil, fmt.Errorf("empty diff")
+ }
+
+ return diff, nil
+}
diff --git a/scripts/differ/go.mod b/scripts/differ/go.mod
index 141e2a4aee..5117dcb831 100644
--- a/scripts/differ/go.mod
+++ b/scripts/differ/go.mod
@@ -5,10 +5,9 @@ go 1.19
require (
github.com/alecthomas/kong v0.7.1
github.com/aquasecurity/table v1.8.0
- github.com/aymanbagabas/go-udiff v0.1.2
github.com/cespare/xxhash/v2 v2.2.0
github.com/pkg/errors v0.9.1
- github.com/stretchr/testify v1.7.1
+ github.com/stretchr/testify v1.8.0
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1
gopkg.in/yaml.v3 v3.0.1
)
diff --git a/scripts/differ/go.sum b/scripts/differ/go.sum
index 997e40da0d..3a3d8d958e 100644
--- a/scripts/differ/go.sum
+++ b/scripts/differ/go.sum
@@ -4,8 +4,6 @@ github.com/alecthomas/kong v0.7.1/go.mod h1:n1iCIO2xS46oE8ZfYCNDqdR0b0wZNrXAIAqr
github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE=
github.com/aquasecurity/table v1.8.0 h1:9ntpSwrUfjrM6/YviArlx/ZBGd6ix8W+MtojQcM7tv0=
github.com/aquasecurity/table v1.8.0/go.mod h1:eqOmvjjB7AhXFgFqpJUEE/ietg7RrMSJZXyTN8E/wZw=
-github.com/aymanbagabas/go-udiff v0.1.2 h1:+GXvyNIKR4HdzSfJagEXgmK/rWjFoaOAQ1UwgeYP52c=
-github.com/aymanbagabas/go-udiff v0.1.2/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -21,8 +19,10 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
diff --git a/scripts/differ/main.go b/scripts/differ/main.go
index 2626fbd1fe..34ec82238d 100644
--- a/scripts/differ/main.go
+++ b/scripts/differ/main.go
@@ -11,8 +11,6 @@ import (
"github.com/alecthomas/kong"
"github.com/aquasecurity/table"
- "github.com/aymanbagabas/go-udiff"
- "github.com/aymanbagabas/go-udiff/myers"
"github.com/cespare/xxhash/v2"
"github.com/pkg/errors"
"golang.org/x/exp/maps"
@@ -135,16 +133,14 @@ func run() (changes int, err error) {
if !approved {
leftName := fmt.Sprintf("a/%s@%s", left.Path, left.Name)
rightName := fmt.Sprintf("b/%s@%s", right.Path, right.Name)
- edits := myers.ComputeEdits(left.Code, right.Code)
- udiff.SortEdits(edits)
- if len(edits) == 0 {
+ diff, err := Diff(leftName, rightName, []byte(left.Code), []byte(right.Code), 100)
+ if err != nil {
+ return 0, errors.Wrap(err, "failed to generate diff")
+ }
+ if len(diff) == 0 {
// No changes.
approved = true
} else {
- diff, err := udiff.ToUnifiedDiff(leftName, rightName, left.Code, edits)
- if err != nil {
- return 0, errors.Wrap(err, "failed to generate unified diff")
- }
fmt.Fprintf(diffFile, "diff --git %s %s\nindex %s..2222222\n%s",
leftName, rightName, diffID, diff)
}
diff --git a/scripts/differ/parser.go b/scripts/differ/parser.go
index fd77418dcc..9c1d9ed379 100644
--- a/scripts/differ/parser.go
+++ b/scripts/differ/parser.go
@@ -143,6 +143,9 @@ func (p *Parser) transformFuncDecl(funcDecl *ast.FuncDecl) {
if funcDecl.Type.Params != nil {
newList := []*ast.Field{}
for _, field := range funcDecl.Type.Params.List {
+ if len(field.Names) == 0 {
+ continue
+ }
if !p.containsIdent(field.Names[0].Name) {
newList = append(newList, field)
}
diff --git a/scripts/differ/ui/package-lock.json b/scripts/differ/ui/package-lock.json
index 431404e6cc..b725394cc3 100644
--- a/scripts/differ/ui/package-lock.json
+++ b/scripts/differ/ui/package-lock.json
@@ -1,5 +1,5 @@
{
- "name": "diff-viewer",
+ "name": "ui",
"lockfileVersion": 2,
"requires": true,
"packages": {
@@ -8,10 +8,11 @@
"next": "latest",
"prism-themes": "^1.9.0",
"react": "^18.2.0",
- "react-diff-view": "^3.0.3",
+ "react-diff-view": "^3.2.1",
"react-dom": "^18.2.0",
"refractor": "^3.6.0",
- "styled-components": "^5.3.10"
+ "styled-components": "^5.3.10",
+ "unidiff": "^1.0.4"
},
"devDependencies": {
"@types/node": "^12.12.21",
@@ -922,6 +923,14 @@
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
"dev": true
},
+ "node_modules/diff": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz",
+ "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
"node_modules/diff-match-patch": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz",
@@ -1044,6 +1053,11 @@
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
},
+ "node_modules/gitdiff-parser": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/gitdiff-parser/-/gitdiff-parser-0.3.1.tgz",
+ "integrity": "sha512-YQJnY8aew65id8okGxKCksH3efDCJ9HzV7M9rsvd65habf39Pkh4cgYJ27AaoDMqo1X98pgNJhNMrm/kpV7UVQ=="
+ },
"node_modules/glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
@@ -1479,6 +1493,7 @@
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -1710,23 +1725,6 @@
"node": ">=6"
}
},
- "node_modules/prop-types": {
- "version": "15.8.1",
- "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
- "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
- "peer": true,
- "dependencies": {
- "loose-envify": "^1.4.0",
- "object-assign": "^4.1.1",
- "react-is": "^16.13.1"
- }
- },
- "node_modules/prop-types/node_modules/react-is": {
- "version": "16.13.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
- "peer": true
- },
"node_modules/property-information": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz",
@@ -1771,18 +1769,19 @@
}
},
"node_modules/react-diff-view": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/react-diff-view/-/react-diff-view-3.0.3.tgz",
- "integrity": "sha512-orETYmQbptfMbOnbkSHH61Ew5RBTYWAO2M1MDx2ZvsEDHPygn6U8mWh7kUCm/z40YzVKmd3+8hpH872Y0uioIg==",
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/react-diff-view/-/react-diff-view-3.2.1.tgz",
+ "integrity": "sha512-JoDahgiyeReeH9W9lrI3Z4c4esbd/HNAOdThj6Pce/ZAukFBmXSbZ4Qv8ayo7yow+fTpRNfqtQ9gX5nArEi08w==",
"dependencies": {
"classnames": "^2.3.2",
"diff-match-patch": "^1.0.5",
+ "gitdiff-parser": "^0.3.1",
+ "lodash": "^4.17.21",
"shallow-equal": "^3.1.0",
"warning": "^4.0.3"
},
"peerDependencies": {
- "prop-types": ">=15.6",
- "react": ">=16.8"
+ "react": ">=16.14.0"
}
},
"node_modules/react-dom": {
@@ -2130,6 +2129,14 @@
"node": ">=4.2.0"
}
},
+ "node_modules/unidiff": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/unidiff/-/unidiff-1.0.4.tgz",
+ "integrity": "sha512-ynU0vsAXw0ir8roa+xPCUHmnJ5goc5BTM2Kuc3IJd8UwgaeRs7VSD5+eeaQL+xp1JtB92hu/Zy/Lgy7RZcr1pQ==",
+ "dependencies": {
+ "diff": "^5.1.0"
+ }
+ },
"node_modules/update-browserslist-db": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz",
@@ -2830,6 +2837,11 @@
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
"dev": true
},
+ "diff": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz",
+ "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A=="
+ },
"diff-match-patch": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz",
@@ -2925,6 +2937,11 @@
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
},
+ "gitdiff-parser": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/gitdiff-parser/-/gitdiff-parser-0.3.1.tgz",
+ "integrity": "sha512-YQJnY8aew65id8okGxKCksH3efDCJ9HzV7M9rsvd65habf39Pkh4cgYJ27AaoDMqo1X98pgNJhNMrm/kpV7UVQ=="
+ },
"glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
@@ -3221,7 +3238,8 @@
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "dev": true
},
"object-hash": {
"version": "3.0.0",
@@ -3360,25 +3378,6 @@
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz",
"integrity": "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA=="
},
- "prop-types": {
- "version": "15.8.1",
- "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
- "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
- "peer": true,
- "requires": {
- "loose-envify": "^1.4.0",
- "object-assign": "^4.1.1",
- "react-is": "^16.13.1"
- },
- "dependencies": {
- "react-is": {
- "version": "16.13.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
- "peer": true
- }
- }
- },
"property-information": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz",
@@ -3402,12 +3401,14 @@
}
},
"react-diff-view": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/react-diff-view/-/react-diff-view-3.0.3.tgz",
- "integrity": "sha512-orETYmQbptfMbOnbkSHH61Ew5RBTYWAO2M1MDx2ZvsEDHPygn6U8mWh7kUCm/z40YzVKmd3+8hpH872Y0uioIg==",
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/react-diff-view/-/react-diff-view-3.2.1.tgz",
+ "integrity": "sha512-JoDahgiyeReeH9W9lrI3Z4c4esbd/HNAOdThj6Pce/ZAukFBmXSbZ4Qv8ayo7yow+fTpRNfqtQ9gX5nArEi08w==",
"requires": {
"classnames": "^2.3.2",
"diff-match-patch": "^1.0.5",
+ "gitdiff-parser": "^0.3.1",
+ "lodash": "^4.17.21",
"shallow-equal": "^3.1.0",
"warning": "^4.0.3"
}
@@ -3648,6 +3649,14 @@
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
"dev": true
},
+ "unidiff": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/unidiff/-/unidiff-1.0.4.tgz",
+ "integrity": "sha512-ynU0vsAXw0ir8roa+xPCUHmnJ5goc5BTM2Kuc3IJd8UwgaeRs7VSD5+eeaQL+xp1JtB92hu/Zy/Lgy7RZcr1pQ==",
+ "requires": {
+ "diff": "^5.1.0"
+ }
+ },
"update-browserslist-db": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz",
diff --git a/scripts/differ/ui/package.json b/scripts/differ/ui/package.json
index e88024a35f..2dcf37ffed 100644
--- a/scripts/differ/ui/package.json
+++ b/scripts/differ/ui/package.json
@@ -10,10 +10,11 @@
"next": "latest",
"prism-themes": "^1.9.0",
"react": "^18.2.0",
- "react-diff-view": "^3.0.3",
+ "react-diff-view": "^3.2.1",
"react-dom": "^18.2.0",
"refractor": "^3.6.0",
- "styled-components": "^5.3.10"
+ "styled-components": "^5.3.10",
+ "unidiff": "^1.0.4"
},
"devDependencies": {
"@types/node": "^12.12.21",
diff --git a/scripts/differ/ui/pages/index.tsx b/scripts/differ/ui/pages/index.tsx
index 1617c89263..e2cc402d78 100644
--- a/scripts/differ/ui/pages/index.tsx
+++ b/scripts/differ/ui/pages/index.tsx
@@ -34,7 +34,7 @@ const Home: React.FC = () => {
);
}
- const files = parseDiff(diffString);
+ const files = parseDiff(diffString, { nearbySequences: "zip" });
const renderFile = ({
oldPath,
@@ -57,54 +57,63 @@ const Home: React.FC = () => {
const tokens = tokenize(hunks, options);
return (
-
-
-
-