Skip to content

Commit

Permalink
feat: support custom line className with generateLineClassName
Browse files Browse the repository at this point in the history
  • Loading branch information
xyJen authored and otakustay committed Nov 21, 2024
1 parent 20241a0 commit 3d1e35a
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 3 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ Here is the full list of its props:
- `{boolean} optimizeSelection`: Whether to optimize selection to a single column, when this prop is set to `true` in split mode, user can only select code from either old or new side, this can help copy and paste lines of code. This feature can cause some performance dropdown when the diff is extremely large, so it is turned off by default.
- `{Function} renderToken`: A function to render customized syntax tokens, see [Pick ranges](#pick-ranges) section for detail.
- `{Function} renderGutter`: A function to render content in gutter cells, see [Customize gutter](#customize-gutter) section for detail.
- `{Function} generateLineClassName`: A function to provide extra classNames for specific lines, such as rebase diff line, source file content, see [Customize line class name](#customize-lineClassName) section for detail.

#### Key of change

Expand Down Expand Up @@ -539,6 +540,25 @@ const renderGutter = ({change, side, renderDefault, wrapInAnchor, inHoverState})
};
```

### customize-lineClassName

The `generateLineClassName` function prop will receive a single object argument with following properties:

- `{Change} changes`: an array of changes incurrent line.
- `{Function} defaultGenerate`: A default render function which returns lineClassName.


```jsx
const generateLineClassName = ({changes, defaultGenerate}) => {
if (viewType === 'inline') {
const [change] = changes;
return defaultGenerate();
}
const [oldChange, newChange] = changes;
return 'rebase-line-change';
}
```

## Utilities

`react-diff-view` comes with some utility functions to help simplify common issues:
Expand Down
12 changes: 12 additions & 0 deletions site/components/DiffView/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
DiffType,
GutterOptions,
EventMap,
ChangeData,
} from 'react-diff-view';
import 'react-diff-view/styles/index.css';
import {useConfiguration} from '../../context/configuration';
Expand Down Expand Up @@ -172,6 +173,16 @@ export default function DiffView(props: Props) {
},
[addComment, viewType]
);

const generateLineClassName = useCallback(
({changes, defaultGenerate}: { changes: ChangeData[], defaultGenerate: () => string }) => {
if (changes.length === 1) {
return `diff-line-${changes[0].type}`;
}
return defaultGenerate();
},
[]
);
const events: EventMap = {
onClick: toggleSelection,
};
Expand Down Expand Up @@ -227,6 +238,7 @@ export default function DiffView(props: Props) {
codeEvents={events}
gutterEvents={events}
renderGutter={renderGutter}
generateLineClassName={generateLineClassName}
>
{hunks => hunks.reduce(renderHunk, [])}
</Diff>
Expand Down
4 changes: 4 additions & 0 deletions src/Diff/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export interface DiffProps {
className?: string;
hunkClassName?: string;
lineClassName?: string;
generateLineClassName?: (params: {changes: ChangeData[], defaultGenerate: () => string}) => string | undefined;
gutterClassName?: string;
codeClassName?: string;
tokens?: HunkTokens | null;
Expand Down Expand Up @@ -70,6 +71,7 @@ function Diff(props: DiffProps) {
className,
hunkClassName = DEFAULT_CONTEXT_VALUE.hunkClassName,
lineClassName = DEFAULT_CONTEXT_VALUE.lineClassName,
generateLineClassName = DEFAULT_CONTEXT_VALUE.generateLineClassName,
gutterClassName = DEFAULT_CONTEXT_VALUE.gutterClassName,
codeClassName = DEFAULT_CONTEXT_VALUE.codeClassName,
gutterType = DEFAULT_CONTEXT_VALUE.gutterType,
Expand Down Expand Up @@ -158,6 +160,7 @@ function Diff(props: DiffProps) {
return {
hunkClassName,
lineClassName,
generateLineClassName,
gutterClassName,
codeClassName,
monotonous,
Expand All @@ -184,6 +187,7 @@ function Diff(props: DiffProps) {
hideGutter,
hunkClassName,
lineClassName,
generateLineClassName,
monotonous,
renderGutter,
renderToken,
Expand Down
11 changes: 9 additions & 2 deletions src/Hunk/SplitHunk/SplitChange.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ function SplitChange(props: SplitChangeProps) {
codeEvents,
hideGutter,
generateAnchorID,
generateLineClassName,
gutterAnchor,
renderToken,
renderGutter,
Expand All @@ -167,6 +168,12 @@ function SplitChange(props: SplitChangeProps) {
const newCodeEvents = useCallbackOnSide('new', setHover, newChange, codeEvents);
const oldAnchorID = oldChange && generateAnchorID(oldChange);
const newAnchorID = newChange && generateAnchorID(newChange);

const lineClassName = generateLineClassName({
changes: [oldChange!, newChange!],
defaultGenerate: () => className,
});

const commons = {
monotonous,
hideGutter,
Expand Down Expand Up @@ -206,7 +213,7 @@ function SplitChange(props: SplitChangeProps) {

if (monotonous) {
return (
<tr className={classNames('diff-line', className)}>
<tr className={classNames('diff-line', lineClassName)}>
{renderCells(oldChange ? oldArgs : newArgs)}
</tr>
);
Expand All @@ -229,7 +236,7 @@ function SplitChange(props: SplitChangeProps) {
})(oldChange, newChange);

return (
<tr className={classNames('diff-line', lineTypeClassName, className)}>
<tr className={classNames('diff-line', lineTypeClassName, lineClassName)}>
{renderCells(oldArgs)}
{renderCells(newArgs)}
</tr>
Expand Down
8 changes: 7 additions & 1 deletion src/Hunk/UnifiedHunk/UnifiedChange.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ function UnifiedChange(props: UnifiedChangeProps) {
selected,
tokens,
className,
generateLineClassName,
gutterClassName,
codeClassName,
gutterEvents,
Expand All @@ -86,6 +87,11 @@ function UnifiedChange(props: UnifiedChangeProps) {
const boundCodeEvents = useBoundCallbacks(codeEvents, eventArg, hoverOn, hoverOff);

const anchorID = generateAnchorID(change);
const lineClassName = generateLineClassName({
changes: [change],
defaultGenerate: () => className,
});

const gutterClassNameValue = classNames(
'diff-gutter',
`diff-gutter-${type}`,
Expand All @@ -100,7 +106,7 @@ function UnifiedChange(props: UnifiedChangeProps) {
);

return (
<tr id={anchorID} className={classNames('diff-line', className)}>
<tr id={anchorID} className={classNames('diff-line', lineClassName)}>
{
!hideGutter && renderGutterCell(
gutterClassNameValue,
Expand Down
1 change: 1 addition & 0 deletions src/Hunk/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface SharedProps {
gutterAnchor: boolean;
monotonous: boolean;
generateAnchorID: (change: ChangeData) => string | undefined;
generateLineClassName: (params: {changes: ChangeData[], defaultGenerate: () => string}) => string | undefined;
renderToken?: RenderToken;
renderGutter: RenderGutter;
}
Expand Down
2 changes: 2 additions & 0 deletions src/context/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export interface ContextProps {
selectedChanges: string[];
tokens?: HunkTokens | null;
generateAnchorID: (change: ChangeData) => string | undefined;
generateLineClassName: (params: {changes: ChangeData[], defaultGenerate: () => string}) => string | undefined;
renderToken?: RenderToken;
renderGutter: RenderGutter;
gutterEvents: EventMap;
Expand All @@ -72,6 +73,7 @@ export const DEFAULT_CONTEXT_VALUE: ContextProps = {
hideGutter: false,
selectedChanges: [],
generateAnchorID: () => undefined,
generateLineClassName: () => undefined,
renderGutter: ({renderDefault, wrapInAnchor}) => wrapInAnchor(renderDefault()),
codeEvents: {},
gutterEvents: {},
Expand Down

0 comments on commit 3d1e35a

Please sign in to comment.