diff2html

repository·master·Indexed 25 days ago

https://github.com/rtfpessoa/diff2html

A library for generating high-quality, GitHub-style HTML diff visualizations from git or unified diff text. It provides a low-level parser and generator, as well as a high-level UI wrapper (Diff2HtmlUI) with features like syntax highlighting, synchronized scrolling, and support for both line-by-line and side-by-side display modes. Available for Node.js, NPM, and as browser bundles via jsdelivr.

Tokens
6.1K
Snippets
15
Records
39
Agent score
86%

What's inside diff2html

  1. Overview of diff2html features

    master

    diff2html is a tool that generates visually appealing HTML diffs from git diff or unified diff output.

    Key features include:

    • Support for both git and unified diff formats.
    • Display modes: Line by line and Side by side.
    • Visual indicators for new/old line numbers and inserted/removed lines.
    • GitHub-like visual style.
    • Integrated code syntax highlighting.
    • Line similarity matching and easy code selection.
  2. Use Diff2HtmlUI in the browser

    master

    Diff2HtmlUI is a wrapper for browser-based diff rendering. It handles DOM injection, code highlighting, and UI effects like collapsible file lists.

    Mandatory Imports

    Include the following CSS and JS via CDN:

    <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/diff2html/bundles/css/diff2html.min.css" />
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/diff2html/bundles/js/diff2html-ui.min.js"></script>

    Initialization and Rendering

    1. Identify a target HTMLElement where the diff will be injected.
    2. Create a new Diff2HtmlUI instance passing the target, the diff input (string or DiffFile[]), and an optional configuration object.
    3. Call .draw() to render the diff.
    const targetElement = document.getElementById('destination-elem-id');
    const configuration = { drawFileList: true, matching: 'lines' };
    const diff2htmlUi = new Diff2HtmlUI(targetElement, diffString, configuration);
    
    diff2htmlUi.draw();
    const targetElement = document.getElementById('destination-elem-id');
    const configuration = { drawFileList: true, matching: 'lines' };
    
    const diff2htmlUi = new Diff2HtmlUI(targetElement, diffString, configuration);
    // or
    const diff2htmlUi = new Diff2HtmlUI(targetElement, diffJson, configuration);
    
    diff2htmlUi.draw();
  3. Enable syntax highlighting in Diff2HtmlUI

    master

    To use syntax highlighting, you must provide a highlight.js CSS theme.

    CRITICAL: The highlight.js CSS must be imported before the diff2html CSS.

    Implementation Steps

    1. Import highlight.js styles.
    2. Import diff2html styles.
    3. Either set highlight: true in your configuration OR call diff2htmlUi.highlightCode() after diff2htmlUi.draw().

    Handling Light/Dark Modes

    If using the auto color scheme, specify both themes using media queries:

    <link rel="stylesheet" href=".../github.min.css" media="screen and (prefers-color-scheme: light)" />
    <link rel="stylesheet" href=".../github-dark.min.css" media="screen and (prefers-color-scheme: dark)" />
    document.addEventListener('DOMContentLoaded', () => {
      const diffString = `diff --git a/sample.js b/sample.js\nindex 0000001..0ddf2ba\n--- a/sample.js\n+++ b/sample.js\n@@ -1 +1 @@\n-console.log("Hello World!")\n+console.log("Hello from Diff2Html!")`;
      const targetElement = document.getElementById('myDiffElement');
      const configuration = { drawFileList: true, matching: 'lines', highlight: true };
      const diff2htmlUi = new Diff2HtmlUI(targetElement, diffString, configuration);
      diff2htmlUi.draw();
      diff2htmlUi.highlightCode();
    });
  4. Integrate Diff2Html in the Browser

    master

    To use Diff2Html directly in a web browser, include the CSS and JavaScript bundles via CDN. The library will be available under the global Diff2Html variable.

    Note: You must include the stylesheet in your HTML for the diff to render correctly.

    <!-- CSS -->
    <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/diff2html/bundles/css/diff2html.min.css" />
    
    <!-- Javascripts -->
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/diff2html/bundles/js/diff2html.min.js"></script>
    
    <script>
    document.addEventListener('DOMContentLoaded', () => {
      var diffHtml = Diff2Html.html('<Unified Diff String>', {
        drawFileList: true,
        matching: 'lines',
        outputFormat: 'side-by-side',
      });
      document.getElementById('destination-elem-id').innerHTML = diffHtml;
    });
    </script>
  5. Prepare diff text input for diff2html

    master

    diff2html accepts the text content of a unified diff or the git diff format (specifically the superset format, excluding combined or word diffs).

    To process multiple files in a single input, simply concatenate the diffs together, mimicking the standard output of the git diff command.

  6. Configure Diff2Html output options

    master

    You can pass a configuration object to the html function to customize the output. Key options include:

    • outputFormat: 'line-by-line' (default) or 'side-by-side'.
    • drawFileList: true (default) or false to show/hide the file list.
    • matching: Matching level: 'lines', 'words', or 'none' (default is 'none').
    • diffStyle: Difference level per line: 'word' (default) or 'char'.
    • colorScheme: 'light' (default), 'dark', or 'auto' (uses browser preference).
    • srcPrefix / dstPrefix: Add prefixes to source/destination filepaths.
    • diffMaxChanges / diffMaxLineLength: Thresholds to skip rendering files that are too large.
    • diffTooBigMessage: Custom function to return a string message when a file is skipped.
    • matchWordsThreshold: Similarity threshold for word matching (default: 0.25).
    • renderNothingWhenEmpty: If true, renders nothing if there are no changes (default: false).
    • highlightLanguages: A Map of extension to language name for overriding default detection.
  7. Configure Diff2HtmlUI options

    master

    The Diff2HtmlUI constructor accepts a configuration object. Note that all standard Diff2Html options are also valid.

    Diff2HtmlUI Specific Options

    • synchronisedScroll: (boolean, default: true) Scrolls both panes simultaneously in side-by-side mode.
    • highlight: (boolean, default: true) Enables syntax highlighting for the code in the diff.
    • fileListToggle: (boolean, default: true) Allows the file summary list to be toggled.
    • fileListStartVisible: (boolean, default: false) Determines if the file summary list is visible on load.
    • fileContentToggle: (boolean, default: true) Allows individual file contents to be toggled.
    • stickyFileHeaders: (boolean, default: true) Makes file headers sticky during scroll.
  8. Use Diff2Html in Node.js

    master

    Install the package and require it to parse diff strings into JSON or render them directly to HTML.

    const Diff2html = require('diff2html');
    const diffJson = Diff2html.parse('<Unified Diff String>');
    const diffHtml = Diff2html.html(diffJson, { drawFileList: true });
    console.log(diffHtml);
  9. Integrate Diff2HtmlUI with StimulusJS and TypeScript

    master

    To use diff2html-ui-slim in a Stimulus controller with TypeScript, ensure you install highlight.js via npm and import the necessary CSS files.

    import { Controller } from '@hotwired/stimulus';
    import { Diff2HtmlUI, Diff2HtmlUIConfig } from 'diff2html/lib/ui/js/diff2html-ui-slim.js';
    
    import 'highlight.js/styles/github.css';
    import 'diff2html/bundles/css/diff2html.min.css';
    
    export default class extends Controller {
      connect(): void {
        const diff2htmlUi = new Diff2HtmlUI(this.diffElement, this.unifiedDiff, this.diffConfiguration);
        diff2htmlUi.draw();
      }
    
      get unifiedDiff(): string {
        return this.data.get('unifiedDiff') || '';
      }
    
      get diffElement(): HTMLElement {
        return this.element as HTMLElement;
      }
    
      get diffConfiguration(): Diff2HtmlUIConfig {
        return {
          drawFileList: true,
          matching: 'lines',
        };
      }
    }
    import { Controller } from '@hotwired/stimulus';
    
    import { Diff2HtmlUI, Diff2HtmlUIConfig } from 'diff2html/lib/ui/js/diff2html-ui-slim.js';
    
    // Requires `npm install highlight.js`
    import 'highlight.js/styles/github.css';
    import 'diff2html/bundles/css/diff2html.min.css';
    
    export default class extends Controller {
      connect(): void {
        const diff2htmlUi = new Diff2HtmlUI(this.diffElement, this.unifiedDiff, this.diffConfiguration);
    
        diff2htmlUi.draw();
      }
    
      get unifiedDiff(): string {
        return this.data.get('unifiedDiff') || '';
      }
    
      get diffElement(): HTMLElement {
        return this.element as HTMLElement;
      }
    
      get diffConfiguration(): Diff2HtmlUIConfig {
        return {
          drawFileList: true,
          matching: 'lines',
        };
      }
    }
  10. Use Diff2HtmlUI API methods

    master

    Constructor

    new Diff2HtmlUI(target: HTMLElement, diffInput?: string | DiffFile[], config: Diff2HtmlUIConfig = {}, hljs?: HighlightJS)

    Instance Methods

    • draw(): void: Generates and injects the Pretty HTML representation of the diff into the target element.
    • synchronisedScroll(): void: Enables synchronized scrolling for side-by-side mode.
    • fileListToggle(startVisible: boolean): void: Toggles the visibility of the file summary list.
    • highlightCode(): void: Manually triggers syntax highlighting on the rendered diff.
    • stickyFileHeaders(): void: Enables sticky file headers.
  11. Use the Diff2Html API to parse and render diffs

    master

    The Diff2Html API provides two primary functions for processing diff data:

    1. parse(diffInput, configuration): Converts a unified diff string into a JSON representation (DiffFile[]).
    2. html(diffInput, configuration): Converts either a unified diff string or a DiffFile[] array into a pretty HTML string.

    Both functions accept an optional Diff2HtmlConfig object.

    function parse(diffInput: string, configuration: Diff2HtmlConfig = {}): DiffFile[];
    
    function html(diffInput: string | DiffFile[], configuration: Diff2HtmlConfig = {}): string;