react-diff-viewer-continued

repository·main·Indexed 42 days ago

https://github.com/aeolun/react-diff-viewer-continued

A React component for displaying text diffs inspired by GitHub's diff viewer. Version 4.4.0 supports split and inline views, word diffs, and line highlighting. It includes performance optimizations for large files via virtualization (infiniteLoading) and specialized structural comparison methods for JSON and YAML. Customization is available through render props like renderContent for syntax highlighting, a built-in dark theme, and a styles object for UI overrides.

Tokens
7.9K
Snippets
22
Records
31
Agent score
51%

What's inside react-diff-viewer-continued

  1. Use optimized diff methods for JSON and YAML

    main

    When comparing structured data like JSON or YAML, use the dedicated DiffMethod constants. These methods are significantly faster (up to 100x) for large files because they parse the data structure and perform a structural comparison instead of a character-by-character text diff.

    • JSON: Use DiffMethod.JSON. You can pass JavaScript objects directly to oldValue and newValue.
    • YAML: Use DiffMethod.YAML. Pass YAML strings to oldValue and newValue.
    import React from 'react';
    import ReactDiffViewer, { DiffMethod } from 'react-diff-viewer-continued';
    
    // JSON Example
    function JsonDiff() {
      const oldJson = { name: "Original", items: [1, 2, 3] };
      const newJson = { name: "Updated", items: [1, 2, 3, 4] };
      return (
        <ReactDiffViewer
          oldValue={oldJson}
          newValue={newJson}
          compareMethod={DiffMethod.JSON}
          splitView={true}
        />
      );
    }
    
    // YAML Example
    function YamlDiff() {
      const oldYaml = `name: Original\nitems:\n  - 1`;
      const newYaml = `name: Updated\nitems:\n  - 1\n  - 2`;
      return (
        <ReactDiffViewer
          oldValue={oldYaml}
          newValue={newYaml}
          compareMethod={DiffMethod.YAML}
          splitView={true}
        />
      );
    }
  2. Optimize Performance for Large Diffs

    main

    For large files, use Virtualization via the infiniteLoading prop to ensure only visible rows are rendered, preventing browser lag.

    Virtualization Configuration

    Pass an object to infiniteLoading with these keys:

    • pageSize: Number of rows to render per batch.
    • containerHeight: The height of the scrollable container (e.g., '500px' or '80vh').
    • overscan (optional): Number of extra rows to render above/below the viewport (defaults to 20).

    Additional Performance Props

    • loadingElement: A function returning a ReactElement to display while diffing is in progress or during fast scrolling. Highly recommended when using infiniteLoading.
    • disableWorker: If your bundler configuration causes Web Worker loading to fail, set this to true to fallback to synchronous computation on the main thread.
  3. Optimize performance for large diffs with virtualization

    main

    For files with thousands of lines, use the infiniteLoading prop to enable virtualization. This ensures only visible rows are rendered, and word-level diffs are computed on-demand as lines become visible. You can also provide a loadingElement to show a placeholder while the initial diff is being computed.

    Key infiniteLoading options:

    • pageSize: Number of rows to load per batch.
    • containerHeight: The height of the container (e.g., '80vh').
    • overscan: Number of rows to render outside the visible area.
    <ReactDiffViewer
      oldValue={largeOldFile}
      newValue={largeNewFile}
      infiniteLoading={{
        pageSize: 20,
        containerHeight: '80vh',
        overscan: 20,
      }}
      loadingElement={() => (
        <div style={{ padding: '20px', textAlign: 'center' }}>
          Computing diff...
        </div>
      )}
    />
  4. Override styles and theme variables

    main

    React Diff Viewer uses emotion for styling. You can customize the appearance using the styles prop. The styles object allows you to override both theme variables (for light and dark modes) and specific component styles.

    New styles are merged with defaults using Object.assign(default, override). For non-variable keys, you can provide an object or use string interpolation (e.g., for hover states).

    Common style categories include:

    • variables: Contains light and dark theme color maps.
    • diffContainer, diffRemoved, diffAdded: Container and line background styles.
    • gutter, lineNumber, splitView: Layout and gutter styles.
    • wordAdded, wordRemoved: Inline word-level diff styles.
    const newStyles = {
      variables: {
        dark: {
          highlightBackground: '#fefed5',
          highlightGutterBackground: '#ffcd3c',
        },
      },
      line: {
        padding: '10px 2px',
        '&:hover': {
          background: '#a26ea1',
        },
      },
    };
    
    <ReactDiffViewer styles={newStyles} ... />
  5. Configure syntax highlighting with highlightLanguage and highlightTheme

    main

    To enable syntax highlighting, provide the highlightLanguage prop (e.g., 'javascript', 'python').

    To customize the colors of the highlighted tokens, use the highlightTheme prop. This prop merges with the default theme. You can also toggle between light and dark base themes using useDarkTheme.

    Note: When highlightLanguage is provided, it takes precedence over renderContent. If highlightLanguage is active, any custom rendering logic provided via renderContent for line content will be ignored.

  6. Configure syntax-highlighting themes

    main

    The highlightLanguage feature uses a HighlightTheme object to apply colors to code tokens. The theme is a mapping where keys are Prism token types (e.g., keyword, attr-name) and values are hex color strings.

    Colors are applied via inline styles, so they do not require external CSS imports and will not collide with your host page's styles. If a token type is not found in the theme, it falls back to the default key. Unknown or unmapped tokens use the default color.

    export type HighlightTheme = Record<string, string>;
    
    const myCustomTheme: HighlightTheme = {
      default: "#24292e",
      keyword: "#d73a49",
      string: "#032f62",
      // ... other Prism token types
    };
  7. Customize React Diff Viewer styles and themes

    main

    You can customize the appearance of the ReactDiffViewer by providing a styleOverride object. This object allows you to either override specific CSS variables (colors, backgrounds, etc.) for both light and dark themes, or provide custom Emotion Interpolation for specific component classes.

    Theme Variables

    Use the variables key within styleOverride to provide a new set of colors. You can define separate light and dark objects to target specific modes.

    Class Overrides

    You can also provide custom Emotion styles for specific structural elements (like diffContainer, gutter, line, etc.) using the Interpolation type. This is useful for changing layout properties like padding, margins, or font sizes that variables cannot reach.

    Default Themes

    The library provides defaultLightThemeVariables and defaultDarkThemeVariables which can be used as a reference for available color keys.

    ```ts
    // Example of overriding variables and specific class styles
    const styleOverride: ReactDiffViewerStylesOverride = {
      variables: {
        light: {
          diffViewerBackground: '#f0f0f0',
          addedBackground: '#e6ffed',
        },
        dark: {
          diffViewerBackground: '#1a1a1a',
        }
      },
      diffContainer: (css) => css({
        borderRadius: '8px',
        border: '1px solid red'
      }),
      gutter: (css) => css({
        minWidth: '60px'
      })
    };
    ```埋め込み
  8. Enable syntax highlighting with highlightLanguage

    main

    To enable syntax highlighting, provide a valid language name (compatible with Prism or Refractor) to the highlightLanguage prop. This takes precedence over renderContent for line content. If the language is unknown, it falls back to plain text.

    Note: Syntax highlighting is merged with word-diff marks on changed lines to ensure both are visible.

    <DiffViewer
      oldValue={oldCode}
      newValue={newCode}
      highlightLanguage="typescript"
      highlightTheme={myCustomTheme}
    />
  9. Basic usage of ReactDiffViewer

    main

    To use the component, import ReactDiffViewer from react-diff-viewer-continued. Provide the original text to the oldValue prop and the modified text to the newValue prop. You can use the splitView prop (boolean) to toggle between split view and inline view.

    import React, { PureComponent } from 'react';
    import ReactDiffViewer from 'react-diff-viewer-continued';
    
    const oldCode = `
    const a = 10
    const b = 10
    const c = () => console.log('foo')
    
    if(a > 10) {
      console.log('bar')
    }
    
    console.log('done')
    `;
    const newCode = `
    const a = 10
    const boo = 10
    
    if(a === 10) {
      console.log('bar')
    }
    `;
    
    class Diff extends PureComponent {
      render = () => {
        return (
          <ReactDiffViewer oldValue={oldCode} newValue={newCode} splitView={true} />
        );
      };
    }
  10. Reset expanded code blocks with `resetCodeBlocks()`

    main

    The resetCodeBlocks() instance method resets all expanded code blocks to their initial state. It returns true if the reset was successful and false if it failed.

    // Usage depends on accessing the instance of ReactDiffViewer
    instance.resetCodeBlocks();
    // Returns true or false
  11. Implement syntax highlighting with `renderContent`

    main

    To add syntax highlighting, use the renderContent render prop. This prop accepts a function with the signature renderContent(content: string) => JSX.Element. You can integrate libraries like Prism JS or Highlight.js within this function to wrap the diffed text in styled elements.

    import React, { PureComponent } from 'react';
    import ReactDiffViewer from 'react-diff-viewer-continued';
    
    class Diff extends PureComponent {
      highlightSyntax = (str) => (
        <pre
          style={{ display: 'inline' }}
          dangerouslySetInnerHTML={{
            __html: Prism.highlight(str, Prism.languages.javascript),
          }}
        />
      );
    
      render = () => {
        return (
          <ReactDiffViewer
            oldValue={oldCode}
            newValue={newCode}
            splitView={true}
            renderContent={this.highlightSyntax}
          />
        );
      };
    }