Replies: 6 comments 6 replies
-
Can you provide the raw git diff for me to investigate this problem? |
Beta Was this translation helpful? Give feedback.
-
Just find one from this repo's history: diff --git a/src/Diff/index.tsx b/src/Diff/index.tsx
index 6171c89..ca6962b 100644
--- a/src/Diff/index.tsx
+++ b/src/Diff/index.tsx
@@ -1,10 +1,9 @@
-import {memo, useRef, useCallback, ReactElement, MouseEvent, useMemo} from 'react';
+import {memo, useRef, useCallback, ReactElement, MouseEvent, useMemo, ReactNode} from 'react';
import classNames from 'classnames';
import {
ContextProps,
EventMap,
GutterType,
- HunkTokens,
Provider,
ViewType,
RenderToken,
@@ -13,6 +12,7 @@ import {
} from '../context';
import Hunk from '../Hunk';
import {ChangeData, HunkData} from '../utils';
+import {HunkTokens} from '../tokenize';
export type DiffType = 'add' | 'delete' | 'modify' | 'rename' | 'copy';
@@ -23,14 +23,14 @@ export interface DiffProps {
gutterType?: GutterType;
generateAnchorID?: (change: ChangeData) => string | undefined;
selectedChanges?: string[];
- widgets?: Record<string, ReactElement>;
+ widgets?: Record<string, ReactNode>;
optimizeSelection?: boolean;
className?: string;
hunkClassName?: string;
lineClassName?: string;
gutterClassName?: string;
codeClassName?: string;
- tokens?: HunkTokens;
+ tokens?: HunkTokens | null;
renderToken?: RenderToken;
renderGutter?: RenderGutter;
gutterEvents?: EventMap;
diff --git a/src/Hunk/SplitHunk/SplitWidget.tsx b/src/Hunk/SplitHunk/SplitWidget.tsx
index 639558e..5bf671f 100644
--- a/src/Hunk/SplitHunk/SplitWidget.tsx
+++ b/src/Hunk/SplitHunk/SplitWidget.tsx
@@ -1,9 +1,9 @@
-import {ReactElement} from 'react';
+import {ReactNode} from 'react';
export interface SplitWidgetProps {
hideGutter: boolean;
- oldElement: ReactElement | null;
- newElement: ReactElement | null;
+ oldElement: ReactNode | null;
+ newElement: ReactNode | null;
monotonous: boolean;
}
diff --git a/src/Hunk/SplitHunk/index.tsx b/src/Hunk/SplitHunk/index.tsx
index 31d179d..22c6f5b 100644
--- a/src/Hunk/SplitHunk/index.tsx
+++ b/src/Hunk/SplitHunk/index.tsx
@@ -1,5 +1,5 @@
import classNames from 'classnames';
-import {ReactElement} from 'react';
+import {ReactNode} from 'react';
import {
getChangeKey,
computeOldLineNumber,
@@ -15,7 +15,7 @@ import SplitWidget from './SplitWidget';
type ChangeContext = ['change', string, ChangeData | null, ChangeData | null];
-type WidgetContext = ['widget', string, ReactElement | null, ReactElement | null];
+type WidgetContext = ['widget', string, ReactNode | null, ReactNode | null];
type ElementContext = ChangeContext | WidgetContext;
@@ -25,7 +25,7 @@ function keyForPair(x: ChangeData | null, y: ChangeData | null) {
return keyForX + keyForY;
}
-function groupElements(changes: ChangeData[], widgets: Record<string, ReactElement>) {
+function groupElements(changes: ChangeData[], widgets: Record<string, ReactNode>) {
const findWidget = (change: ChangeData | null) => {
if (!change) {
return null;
diff --git a/src/Hunk/UnifiedHunk/UnifiedWidget.tsx b/src/Hunk/UnifiedHunk/UnifiedWidget.tsx
index 1074475..a84053f 100644
--- a/src/Hunk/UnifiedHunk/UnifiedWidget.tsx
+++ b/src/Hunk/UnifiedHunk/UnifiedWidget.tsx
@@ -1,8 +1,8 @@
-import {ReactElement} from 'react';
+import {ReactNode} from 'react';
export interface UnifiedWidgetProps {
hideGutter: boolean;
- element: ReactElement;
+ element: ReactNode;
}
export default function UnifiedWidget({hideGutter, element}: UnifiedWidgetProps) {
diff --git a/src/Hunk/UnifiedHunk/index.tsx b/src/Hunk/UnifiedHunk/index.tsx
index 8a2d48b..4d31f7f 100644
--- a/src/Hunk/UnifiedHunk/index.tsx
+++ b/src/Hunk/UnifiedHunk/index.tsx
@@ -1,13 +1,13 @@
import classNames from 'classnames';
-import {ReactElement} from 'react';
+import {ReactNode} from 'react';
import {getChangeKey, computeOldLineNumber, computeNewLineNumber, ChangeData, isDelete} from '../../utils';
import {ActualHunkProps} from '../interface';
import UnifiedChange from './UnifiedChange';
import UnifiedWidget from './UnifiedWidget';
-type ElementContext = ['change', string, ChangeData] | ['widget', string, ReactElement];
+type ElementContext = ['change', string, ChangeData] | ['widget', string, ReactNode];
-function groupElements(changes: ChangeData[], widgets: Record<string, ReactElement>) {
+function groupElements(changes: ChangeData[], widgets: Record<string, ReactNode>) {
return changes.reduce<ElementContext[]>(
(elements, change) => {
const key = getChangeKey(change);
diff --git a/src/Hunk/interface.ts b/src/Hunk/interface.ts
index 94e2646..90ece27 100644
--- a/src/Hunk/interface.ts
+++ b/src/Hunk/interface.ts
@@ -1,6 +1,7 @@
-import {ReactElement} from 'react';
+import {ReactNode} from 'react';
import {ChangeData, HunkData} from '../utils';
-import {EventMap, HunkTokens, RenderGutter, RenderToken} from '../context';
+import {EventMap, RenderGutter, RenderToken} from '../context';
+import {HunkTokens} from '../tokenize';
export interface SharedProps {
hideGutter: boolean;
@@ -22,8 +23,8 @@ export interface ActualHunkProps extends ChangeSharedProps {
className: string;
lineClassName: string;
hunk: HunkData;
- widgets: Record<string, ReactElement>;
+ widgets: Record<string, ReactNode>;
hideGutter: boolean;
selectedChanges: string[];
- tokens?: HunkTokens;
+ tokens?: HunkTokens | null;
}
diff --git a/src/context/index.ts b/src/context/index.ts
index 35a909b..8ca3654 100644
--- a/src/context/index.ts
+++ b/src/context/index.ts
@@ -1,6 +1,6 @@
-import {createContext, DOMAttributes, ReactElement, ReactNode, useContext} from 'react';
+import {createContext, DOMAttributes, ReactNode, useContext} from 'react';
import {ChangeData} from '../utils/parse';
-import {TokenNode} from '../tokenize';
+import {HunkTokens, TokenNode} from '../tokenize';
import {Side} from '../interface';
export type DefaultRenderToken = (token: TokenNode, index: number) => ReactNode;
@@ -17,11 +17,6 @@ export interface GutterOptions {
export type RenderGutter = (options: GutterOptions) => ReactNode;
-export interface HunkTokens {
- old: TokenNode[][];
- new: TokenNode[][];
-}
-
export type ViewType = 'unified' | 'split';
export type GutterType = 'default' | 'none' | 'anchor';
@@ -54,10 +49,10 @@ export interface ContextProps {
monotonous: boolean;
gutterType: GutterType;
viewType: ViewType;
- widgets: Record<string, ReactElement>;
+ widgets: Record<string, ReactNode>;
hideGutter: boolean;
selectedChanges: string[];
- tokens?: HunkTokens;
+ tokens?: HunkTokens | null;
generateAnchorID: (change: ChangeData) => string | undefined;
renderToken?: RenderToken;
renderGutter: RenderGutter;
diff --git a/src/hooks/useMinCollapsedLines.ts b/src/hooks/useMinCollapsedLines.ts
index 5ba0fa7..3e6941e 100644
--- a/src/hooks/useMinCollapsedLines.ts
+++ b/src/hooks/useMinCollapsedLines.ts
@@ -1,7 +1,7 @@
import {useMemo} from 'react';
import {expandCollapsedBlockBy, HunkData, Source} from '../utils';
-export default function useMinCollapsedLines(minLinesExclusive: number, hunks: HunkData[], oldSource: Source) {
+export default function useMinCollapsedLines(minLinesExclusive: number, hunks: HunkData[], oldSource: Source | null) {
const renderingHunks = useMemo(
() => {
if (!oldSource) {
diff --git a/src/hooks/useSourceExpansion.ts b/src/hooks/useSourceExpansion.ts
index 7448e4f..0fb276e 100644
--- a/src/hooks/useSourceExpansion.ts
+++ b/src/hooks/useSourceExpansion.ts
@@ -2,12 +2,12 @@ import {useEffect, useMemo} from 'react';
import {expandFromRawCode, HunkData, Source} from '../utils';
import {useCollection} from './helpers';
-export default function useSourceExpansion(hunks: HunkData[], oldSource: Source) {
+export default function useSourceExpansion(hunks: HunkData[], oldSource: Source | null) {
const {collection: expandedRanges, clear, push} = useCollection<[number, number]>();
// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(clear, [hunks, oldSource]);
const linesOfOldSource = useMemo(
- () => (typeof oldSource === 'string' ? oldSource.split('\n') : oldSource),
+ () => (Array.isArray(oldSource) ? oldSource : (oldSource || '').split('\n')),
[oldSource]
);
const renderingHunks = useMemo(
diff --git a/src/hooks/useTokenizeWorker.ts b/src/hooks/useTokenizeWorker.ts
index fb43304..9b6accc 100644
--- a/src/hooks/useTokenizeWorker.ts
+++ b/src/hooks/useTokenizeWorker.ts
@@ -3,7 +3,7 @@ import {shallowEqualArrays, shallowEqualObjects} from 'shallow-equal';
import {flatMap} from 'lodash';
import {useCustomEqualIdentifier} from './helpers';
import {HunkData, isNormal} from '../utils';
-import {TokenNode} from '../tokenize';
+import {HunkTokens} from '../tokenize';
const uid = (() => {
let current = 0;
@@ -27,7 +27,7 @@ function areHunksEqual(xHunks: HunkData[], yHunks: HunkData[]) {
export interface TokenizePayload {
hunks: HunkData[];
- oldSource: string;
+ oldSource: string | null;
}
export type ShouldTokenize<P extends TokenizePayload> = (current: P, prev: P | undefined) => boolean;
@@ -59,7 +59,7 @@ export interface TokenizeWorkerOptions<P extends TokenizePayload> {
interface WorkerResultSuccess {
success: true;
id: string;
- tokens: TokenNode[];
+ tokens: HunkTokens;
}
interface WorkerResultFail {
@@ -73,7 +73,7 @@ interface WorkerMessageData {
}
export interface TokenizeResult {
- tokens: TokenNode[] | null;
+ tokens: HunkTokens | null;
tokenizationFailReason: string | null;
}
diff --git a/src/index.ts b/src/index.ts
index 0c693cc..36df276 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -25,9 +25,28 @@ export {useChangeSelect, useMinCollapsedLines, useSourceExpansion, useTokenizeWo
export type {DiffProps, DiffType} from './Diff';
export type {HunkProps} from './Hunk';
export type {DecorationProps} from './Decoration';
-export type {EventMap, HunkTokens, GutterType, ViewType, RenderToken, RenderGutter} from './context';
+export type {
+ EventMap,
+ GutterType,
+ ViewType,
+ RenderToken,
+ RenderGutter,
+ ChangeEventArgs,
+ GutterOptions,
+} from './context';
export type {ChangeData, FileData, HunkData, ParseOptions, Source} from './utils';
-export type {Pair, RangeTokenNode, TextNode, TokenNode, TokenPath, TokenizeEnhancer, TokenizeOptions} from './tokenize';
+export type {
+ Pair,
+ RangeTokenNode,
+ TextNode,
+ TokenNode,
+ TokenPath,
+ TokenizeEnhancer,
+ TokenizeOptions,
+ MarkEditsOptions,
+ MarkEditsType,
+ HunkTokens,
+} from './tokenize';
export type {
ShouldTokenize,
TokenizePayload,
diff --git a/src/tokenize/index.ts b/src/tokenize/index.ts
index 84d6ddc..36b40bc 100644
--- a/src/tokenize/index.ts
+++ b/src/tokenize/index.ts
@@ -2,17 +2,23 @@ import toTokenTrees, {ToTokenTreeOptions} from './toTokenTrees';
import normalizeToLines from './normalizeToLines';
import backToTree from './backToTree';
import {HunkData} from '../utils';
-import {TokenizeEnhancer, TokenPath} from './interface';
+import {TokenizeEnhancer, TokenNode, TokenPath} from './interface';
export {default as pickRanges} from './pickRanges';
export {default as markEdits} from './markEdits';
export {default as markWord} from './markWord';
export type {Pair, TextNode, TokenNode, TokenPath, TokenizeEnhancer} from './interface';
+export type {MarkEditsOptions, MarkEditsType} from './markEdits';
export type {RangeTokenNode} from './pickRanges';
export type TokenizeOptions = ToTokenTreeOptions & {enhancers?: TokenizeEnhancer[]};
-export const tokenize = (hunks: HunkData[], {enhancers = [], ...options}: TokenizeOptions = {}) => {
+export interface HunkTokens {
+ old: TokenNode[][];
+ new: TokenNode[][];
+}
+
+export const tokenize = (hunks: HunkData[], {enhancers = [], ...options}: TokenizeOptions = {}): HunkTokens => {
const [oldTokenTree, newTokenTree] = toTokenTrees(hunks, options);
const [oldLinesOfPaths, newLinesOfPaths] = [normalizeToLines(oldTokenTree), normalizeToLines(newTokenTree)];
@@ -23,7 +29,7 @@ export const tokenize = (hunks: HunkData[], {enhancers = [], ...options}: Tokeni
const [oldEnhanced, newEnhanced] = enhance([oldLinesOfPaths, newLinesOfPaths]);
const [oldTrees, newTrees] = [oldEnhanced.map(backToTree), newEnhanced.map(backToTree)];
return {
- old: oldTrees.map(root => root.children),
- new: newTrees.map(root => root.children),
+ old: oldTrees.map(root => root.children ?? []),
+ new: newTrees.map(root => root.children ?? []),
};
}; |
Beta Was this translation helpful? Give feedback.
-
The header is not rendered by default, in demo site I use |
Beta Was this translation helpful? Give feedback.
-
I was hoping to render the entire header such as Is that possible? (Sorry if I'm missing something in the sandbox) |
Beta Was this translation helpful? Give feedback.
-
If you are refering to the Out internal apps's backend provides insertion and deletion count on a diff, however you can also calculate it from hunks with a little overhead, I updated that sandbox to implement it, see |
Beta Was this translation helpful? Give feedback.
-
According to my normalize function, unified diff will be converted to a git diff, but you need the timestamp part in order to make |
Beta Was this translation helpful? Give feedback.
-
I used a git diff with the proper headers and the basic example React code shown in the README, but each Hunk or File was just displayed one after another without the headers I see in the example screenshots. Am I missing something?
Beta Was this translation helpful? Give feedback.
All reactions