Browse Source

ref(ts): Convert splitDiff to typescript (#20545)

Scott Cooper 4 years ago
parent
commit
7c6e4dbb33

+ 8 - 1
docs-ui/components/splitDiff.stories.js

@@ -1,4 +1,5 @@
 import React from 'react';
+import {select} from '@storybook/addon-knobs';
 import {withInfo} from '@storybook/addon-info';
 
 import SplitDiff from 'app/components/splitDiff';
@@ -113,7 +114,13 @@ export default {
 
 export const _SplitDiff = withInfo(
   'Diffs two strings, split by newlines if present'
-)(() => <SplitDiff base={base} target={target} />);
+)(() => (
+  <SplitDiff
+    base={base}
+    target={target}
+    type={select('Type', ['lines', 'words', 'chars'], 'lines')}
+  />
+));
 
 _SplitDiff.story = {
   name: 'SplitDiff',

+ 2 - 1
package.json

@@ -30,6 +30,7 @@
     "@types/clipboard": "^2.0.1",
     "@types/color": "^3.0.0",
     "@types/create-react-class": "^15.6.2",
+    "@types/diff": "4.0.2",
     "@types/dompurify": "^2.0.1",
     "@types/echarts": "^4.4.3",
     "@types/jest": "^24.0.17",
@@ -65,7 +66,7 @@
     "create-react-class": "^15.6.2",
     "crypto-js": "4.0.0",
     "css-loader": "^2.0.1",
-    "diff": "^3.5.0",
+    "diff": "4.0.2",
     "dompurify": "^2.0.7",
     "echarts": "4.7.0",
     "echarts-for-react": "2.0.16",

+ 0 - 117
src/sentry/static/sentry/app/components/splitDiff.jsx

@@ -1,117 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import styled from '@emotion/styled';
-import {diffChars, diffWords, diffLines} from 'diff';
-
-const diffFnMap = {
-  chars: diffChars,
-  words: diffWords,
-  lines: diffLines,
-};
-
-class SplitDiff extends React.Component {
-  static propTypes = {
-    base: PropTypes.string,
-    target: PropTypes.string,
-    type: PropTypes.oneOf(['lines', 'words', 'chars']),
-  };
-
-  static defaultProps = {
-    type: 'lines',
-  };
-
-  render() {
-    const {className, type, base, target} = this.props;
-    const diffFn = diffFnMap[type];
-
-    if (typeof diffFn !== 'function') {
-      return null;
-    }
-
-    const baseLines = base.split('\n');
-    const targetLines = target.split('\n');
-    const [largerArray] =
-      baseLines.length > targetLines.length
-        ? [baseLines, targetLines]
-        : [targetLines, baseLines];
-    const results = largerArray.map((_line, index) =>
-      diffFn(baseLines[index] || '', targetLines[index] || '', {newlineIsToken: true})
-    );
-
-    return (
-      <SplitTable className={className}>
-        <SplitBody>
-          {results.map((line, j) => {
-            const highlightAdded = line.find(result => result.added);
-            const highlightRemoved = line.find(result => result.removed);
-
-            return (
-              <tr key={j}>
-                <Cell isRemoved={highlightRemoved}>
-                  <Line>
-                    {line
-                      .filter(result => !result.added)
-                      .map((result, i) => (
-                        <Word key={i} isRemoved={result.removed}>
-                          {result.value}
-                        </Word>
-                      ))}
-                  </Line>
-                </Cell>
-
-                <Gap />
-
-                <Cell isAdded={highlightAdded}>
-                  <Line>
-                    {line
-                      .filter(result => !result.removed)
-                      .map((result, i) => (
-                        <Word key={i} isAdded={result.added}>
-                          {result.value}
-                        </Word>
-                      ))}
-                  </Line>
-                </Cell>
-              </tr>
-            );
-          })}
-        </SplitBody>
-      </SplitTable>
-    );
-  }
-}
-
-const SplitTable = styled('table')`
-  table-layout: fixed;
-  border-collapse: collapse;
-  width: 100%;
-`;
-
-const SplitBody = styled('tbody')`
-  font-family: Monaco, Consolas, 'Courier New', monospace;
-  font-size: 13px;
-`;
-
-const Cell = styled('td')`
-  vertical-align: top;
-  ${p => p.isRemoved && `background-color: ${p.theme.diff.removedRow}`};
-  ${p => p.isAdded && `background-color: ${p.theme.diff.addedRow}`};
-`;
-
-const Gap = styled('td')`
-  width: 20px;
-`;
-
-const Line = styled('div')`
-  display: flex;
-  flex-wrap: wrap;
-`;
-
-const Word = styled('span')`
-  white-space: pre-wrap;
-  word-break: break-all;
-  ${p => p.isRemoved && `background-color: ${p.theme.diff.removed}`};
-  ${p => p.isAdded && `background-color: ${p.theme.diff.added}`};
-`;
-
-export default SplitDiff;

+ 113 - 0
src/sentry/static/sentry/app/components/splitDiff.tsx

@@ -0,0 +1,113 @@
+import PropTypes from 'prop-types';
+import React from 'react';
+import styled from '@emotion/styled';
+import {diffChars, diffWords, diffLines, Change} from 'diff';
+
+const diffFnMap = {
+  chars: diffChars,
+  words: diffWords,
+  lines: diffLines,
+} as const;
+
+type Props = {
+  base: string;
+  target: string;
+  type?: keyof typeof diffFnMap;
+  className?: string;
+};
+
+const SplitDiff = ({className, type = 'lines', base, target}: Props) => {
+  const diffFn = diffFnMap[type];
+
+  const baseLines = base.split('\n');
+  const targetLines = target.split('\n');
+  const [largerArray] =
+    baseLines.length > targetLines.length
+      ? [baseLines, targetLines]
+      : [targetLines, baseLines];
+  const results = largerArray.map((_line, index) =>
+    diffFn(baseLines[index] || '', targetLines[index] || '', {newlineIsToken: true})
+  );
+
+  return (
+    <SplitTable className={className}>
+      <SplitBody>
+        {results.map((line, j) => {
+          const highlightAdded = line.find(result => result.added);
+          const highlightRemoved = line.find(result => result.removed);
+
+          return (
+            <tr key={j}>
+              <Cell isRemoved={highlightRemoved}>
+                <Line>
+                  {line
+                    .filter(result => !result.added)
+                    .map((result, i) => (
+                      <Word key={i} isRemoved={result.removed}>
+                        {result.value}
+                      </Word>
+                    ))}
+                </Line>
+              </Cell>
+
+              <Gap />
+
+              <Cell isAdded={highlightAdded}>
+                <Line>
+                  {line
+                    .filter(result => !result.removed)
+                    .map((result, i) => (
+                      <Word key={i} isAdded={result.added}>
+                        {result.value}
+                      </Word>
+                    ))}
+                </Line>
+              </Cell>
+            </tr>
+          );
+        })}
+      </SplitBody>
+    </SplitTable>
+  );
+};
+
+SplitDiff.propTypes = {
+  base: PropTypes.string,
+  target: PropTypes.string,
+  type: PropTypes.oneOf(['lines', 'words', 'chars']),
+};
+
+const SplitTable = styled('table')`
+  table-layout: fixed;
+  border-collapse: collapse;
+  width: 100%;
+`;
+
+const SplitBody = styled('tbody')`
+  font-family: ${p => p.theme.text.familyMono};
+  font-size: ${p => p.theme.fontSizeSmall};
+`;
+
+const Cell = styled('td')<{isRemoved?: Change; isAdded?: Change}>`
+  vertical-align: top;
+  ${p => p.isRemoved && `background-color: ${p.theme.diff.removedRow}`};
+  ${p => p.isAdded && `background-color: ${p.theme.diff.addedRow}`};
+`;
+
+const Gap = styled('td')`
+  width: 20px;
+`;
+
+const Line = styled('div')`
+  display: flex;
+  flex-wrap: wrap;
+`;
+
+const Word = styled('span')<{isRemoved?: boolean; isAdded?: boolean}>`
+  white-space: pre-wrap;
+  word-break: break-all;
+  ${p => p.isRemoved && `background-color: ${p.theme.diff.removed}`};
+  ${p => p.isAdded && `background-color: ${p.theme.diff.added}`};
+`;
+
+export default SplitDiff;

+ 9 - 4
yarn.lock

@@ -2801,6 +2801,11 @@
   dependencies:
     "@types/react" "*"
 
+"@types/diff@4.0.2":
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/@types/diff/-/diff-4.0.2.tgz#2e9bb89f9acc3ab0108f0f3dc4dbdcf2fff8a99c"
+  integrity sha512-mIenTfsIe586/yzsyfql69KRnA75S8SVXQbTLpDejRrjH0QSJcpu3AUOi/Vjnt9IOsXKxPhJfGpQUNMueIU1fQ==
+
 "@types/dompurify@^2.0.1":
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/@types/dompurify/-/dompurify-2.0.1.tgz#0bf3a9f8ee21d81adb20b8c374ab034d6a74dbf7"
@@ -6320,10 +6325,10 @@ diff-sequences@^24.9.0:
   resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5"
   integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==
 
-diff@^3.5.0:
-  version "3.5.0"
-  resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
-  integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
+diff@4.0.2:
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
+  integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
 
 diffie-hellman@^5.0.0:
   version "5.0.3"