{
body = (
{fileAnnotations}
-
+
{(hunks: HunkType[]) => this.concat(hunks.map(this.renderHunk))}
-
+
);
}
diff --git a/scm-ui/ui-components/src/repos/DiffTypes.ts b/scm-ui/ui-components/src/repos/DiffTypes.ts
index 49e9785d29..813322529e 100644
--- a/scm-ui/ui-components/src/repos/DiffTypes.ts
+++ b/scm-ui/ui-components/src/repos/DiffTypes.ts
@@ -18,6 +18,7 @@ export type File = {
oldPath: string;
oldRevision?: string;
type: FileChangeType;
+ language?: string;
// TODO does this property exists?
isBinary?: boolean;
};
diff --git a/scm-ui/ui-components/src/repos/Tokenize.worker.ts b/scm-ui/ui-components/src/repos/Tokenize.worker.ts
new file mode 100644
index 0000000000..d64df14c11
--- /dev/null
+++ b/scm-ui/ui-components/src/repos/Tokenize.worker.ts
@@ -0,0 +1,29 @@
+/* eslint-disable no-restricted-globals */
+// @ts-ignore we have no types for react-diff-view
+import { tokenize } from "react-diff-view";
+import refractor from "./refractorAdapter";
+
+self.addEventListener("message", ({ data: { id, payload } }) => {
+ const { hunks, language } = payload;
+ const options = {
+ highlight: language !== "text",
+ language: language,
+ refractor
+ };
+ try {
+ const tokens = tokenize(hunks, options);
+ const payload = {
+ success: true,
+ tokens: tokens
+ };
+ // @ts-ignore seems to use wrong typing
+ self.postMessage({ id, payload });
+ } catch (ex) {
+ const payload = {
+ success: false,
+ reason: ex.message
+ };
+ // @ts-ignore seems to use wrong typing
+ self.postMessage({ id, payload });
+ }
+});
diff --git a/scm-ui/ui-components/src/repos/TokenizedDiffView.tsx b/scm-ui/ui-components/src/repos/TokenizedDiffView.tsx
new file mode 100644
index 0000000000..fcc3397cb8
--- /dev/null
+++ b/scm-ui/ui-components/src/repos/TokenizedDiffView.tsx
@@ -0,0 +1,62 @@
+import React, { FC } from "react";
+import styled from "styled-components";
+// @ts-ignore we have no typings for react-diff-view
+import { Diff, useTokenizeWorker } from "react-diff-view";
+// @ts-ignore we use webpack worker-loader to load the web worker
+import TokenizeWorker from "./Tokenize.worker";
+import { File } from "./DiffTypes";
+
+// styling for the diff tokens
+// this must be aligned with th style, which is used in the SyntaxHighlighter component
+import "highlight.js/styles/arduino-light.css";
+
+const DiffView = styled(Diff)`
+ /* align line numbers */
+ & .diff-gutter {
+ text-align: right;
+ }
+ /* column sizing */
+ > colgroup .diff-gutter-col {
+ width: 3.25rem;
+ }
+ /* prevent following content from moving down */
+ > .diff-gutter:empty:hover::after {
+ font-size: 0.7rem;
+ }
+ /* smaller font size for code */
+ & .diff-line {
+ font-size: 0.75rem;
+ }
+ /* comment padding for sidebyside view */
+ &.split .diff-widget-content .is-indented-line {
+ padding-left: 3.25rem;
+ }
+ /* comment padding for combined view */
+ &.unified .diff-widget-content .is-indented-line {
+ padding-left: 6.5rem;
+ }
+`;
+
+// WebWorker which creates tokens for syntax highlighting
+const tokenize = new TokenizeWorker();
+
+type Props = {
+ file: File;
+ viewType: "split" | "unified";
+ className?: string;
+};
+
+const TokenizedDiffView: FC = ({ file, viewType, className, children }) => {
+ const { tokens } = useTokenizeWorker(tokenize, {
+ hunks: file.hunks,
+ language: file.language || "text"
+ });
+
+ return (
+
+ {children}
+
+ );
+};
+
+export default TokenizedDiffView;
diff --git a/scm-ui/ui-components/src/repos/refractorAdapter.ts b/scm-ui/ui-components/src/repos/refractorAdapter.ts
new file mode 100644
index 0000000000..3e0425aad8
--- /dev/null
+++ b/scm-ui/ui-components/src/repos/refractorAdapter.ts
@@ -0,0 +1,14 @@
+import lowlight from "lowlight";
+
+// adapter to let lowlight look like refractor
+// this is required because react-diff-view does only support refractor,
+// but we want same highlighting as in the source code browser.
+
+const refractorAdapter = {
+ ...lowlight,
+ highlight: (value: string, language: string) => {
+ return lowlight.highlight(language, value).value;
+ }
+};
+
+export default refractorAdapter;
diff --git a/scm-ui/ui-scripts/package.json b/scm-ui/ui-scripts/package.json
index 4b2564b419..c53d2eff98 100644
--- a/scm-ui/ui-scripts/package.json
+++ b/scm-ui/ui-scripts/package.json
@@ -24,6 +24,7 @@
"script-loader": "^0.7.2",
"style-loader": "^1.0.0",
"thread-loader": "^2.1.3",
+ "worker-loader": "^2.0.0",
"webpack": "^4.41.5",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.10.1"
diff --git a/scm-ui/ui-scripts/src/webpack.config.js b/scm-ui/ui-scripts/src/webpack.config.js
index b4c32fc680..5c8595e505 100644
--- a/scm-ui/ui-scripts/src/webpack.config.js
+++ b/scm-ui/ui-scripts/src/webpack.config.js
@@ -30,6 +30,10 @@ module.exports = [
systemjs: false
}
},
+ {
+ test: /\.worker\.(j|t)s$/,
+ use: { loader: "worker-loader" }
+ },
{
test: /\.(js|ts|jsx|tsx)$/i,
exclude: /node_modules/,
diff --git a/yarn.lock b/yarn.lock
index ef120d73f6..1594f5a8ba 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2758,6 +2758,11 @@
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.149.tgz#1342d63d948c6062838fbf961012f74d4e638440"
integrity sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==
+"@types/lowlight@^0.0.0":
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/@types/lowlight/-/lowlight-0.0.0.tgz#eef9ff807ff29bbf9f2fe55d0488fb9fc9d89df6"
+ integrity sha1-7vn/gH/ym7+fL+VdBIj7n8nYnfY=
+
"@types/minimatch@*":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
@@ -7672,6 +7677,11 @@ highlight.js@~9.13.0:
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.13.1.tgz#054586d53a6863311168488a0f58d6c505ce641e"
integrity sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A==
+highlight.js@~9.16.0:
+ version "9.16.2"
+ resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.16.2.tgz#68368d039ffe1c6211bcc07e483daf95de3e403e"
+ integrity sha512-feMUrVLZvjy0oC7FVJQcSQRqbBq9kwqnYE4+Kj9ZjbHh3g+BisiPgF49NyQbVLNdrL/qqZr3Ca9yOKwgn2i/tw==
+
history@^4.10.1, history@^4.9.0:
version "4.10.1"
resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3"
@@ -9435,7 +9445,7 @@ loader-runner@^2.3.1, loader-runner@^2.4.0:
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==
-loader-utils@1.2.3, loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3:
+loader-utils@1.2.3, loader-utils@^1.0.0, loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7"
integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==
@@ -9602,6 +9612,14 @@ lower-case@^1.1.1:
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw=
+lowlight@^1.13.0:
+ version "1.13.0"
+ resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.13.0.tgz#9b4fd00559985e40e11c916ccab14c7c0cf4320d"
+ integrity sha512-bFXLa+UO1eM3zieFAcNqf6rTQ1D5ERFv64/euQbbH/LT3U9XXwH6tOrgUAGWDsQ1QgN3ZhgOcv8p3/S+qKGdTQ==
+ dependencies:
+ fault "^1.0.2"
+ highlight.js "~9.16.0"
+
lowlight@~1.11.0:
version "1.11.0"
resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.11.0.tgz#1304d83005126d4e8b1dc0f07981e9b689ec2efc"
@@ -12989,6 +13007,14 @@ scheduler@^0.18.0:
loose-envify "^1.1.0"
object-assign "^4.1.1"
+schema-utils@^0.4.0:
+ version "0.4.7"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.7.tgz#ba74f597d2be2ea880131746ee17d0a093c68187"
+ integrity sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==
+ dependencies:
+ ajv "^6.1.0"
+ ajv-keywords "^3.1.0"
+
schema-utils@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770"
@@ -14972,6 +14998,14 @@ worker-farm@^1.7.0:
dependencies:
errno "~0.1.7"
+worker-loader@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/worker-loader/-/worker-loader-2.0.0.tgz#45fda3ef76aca815771a89107399ee4119b430ac"
+ integrity sha512-tnvNp4K3KQOpfRnD20m8xltE3eWh89Ye+5oj7wXEEHKac1P4oZ6p9oTj8/8ExqoSBnk9nu5Pr4nKfQ1hn2APJw==
+ dependencies:
+ loader-utils "^1.0.0"
+ schema-utils "^0.4.0"
+
worker-rpc@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/worker-rpc/-/worker-rpc-0.1.1.tgz#cb565bd6d7071a8f16660686051e969ad32f54d5"