diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4ef251e13267797ca567a1f72b113736739d8acf..8bf3fcbae466597046617ca799ed7147f2efd848 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,11 @@ This project uses a custom versioning scheme (and not [Semantic Versioning](http
 
 ## [Unreleased]
 
+* minor bug fixes
+* optional include equal parts of original and revised data
+* **API** change: removed DiffException completely
+* added possibility to **process diffs** to for instance show whitespace characters
+
 ## [4.4] – 2019-11-06
 
 ### Changed
@@ -82,8 +87,10 @@ This project uses a custom versioning scheme (and not [Semantic Versioning](http
 * Ant build script
 * Generate output in unified diff format (thanks for Bill James)
 
-[Unreleased]: https://github.com/java-diff-utils/java-diff-utils/compare/java-diff-utils-4.0...HEAD
-[4.0]: https://github.com/java-diff-utils/java-diff-utils/compare/diff-utils-3.0...java-diff-utils-4.0
-[3.0]: https://github.com/java-diff-utils/java-diff-utils/compare/diff-utils-2.2...diff-utils-3.0
-[2.2]: https://github.com/java-diff-utils/java-diff-utils/compare/diff-utils-2.0...diff-utils-2.2
+[Unreleased]: https://github.com/java-diff-utils/java-diff-utils/compare/java-diff-utils-parent-4.5...HEAD
+[4.5]: https://github.com/java-diff-utils/java-diff-utils/compare/java-diff-utils-parent-4.4...java-diff-utils-parent-4.5
+[4.4]: https://github.com/java-diff-utils/java-diff-utils/compare/java-diff-utils-4.0...java-diff-utils-parent-4.4
+[4.0]: https://github.com/java-diff-utils/java-diff-utils/compare/diffutils-3.0...java-diff-utils-4.0
+[3.0]: https://github.com/java-diff-utils/java-diff-utils/compare/diffutils-2.2...diffutils-3.0
+[2.2]: https://github.com/java-diff-utils/java-diff-utils/compare/diffutils-2.0...diffutils-2.2
 
diff --git a/README.md b/README.md
index b7c890c618d38cba5549fde05c1ed63e3948bfe1..9e5221ef05a95d531301675d15d4cddc1895c661 100644
--- a/README.md
+++ b/README.md
@@ -80,7 +80,7 @@ Just add the code below to your maven dependencies:
 <dependency>
     <groupId>io.github.java-diff-utils</groupId>
     <artifactId>java-diff-utils</artifactId>
-    <version>4.4</version>
+    <version>4.5</version>
 </dependency>
 ```
 
@@ -88,5 +88,5 @@ or using gradle:
 
 ```groovy
 // https://mvnrepository.com/artifact/io.github.java-diff-utils/java-diff-utils
-implementation "io.github.java-diff-utils:java-diff-utils:4.4"
+implementation "io.github.java-diff-utils:java-diff-utils:4.5"
 ```
diff --git a/java-diff-utils-jgit/nb-configuration.xml b/java-diff-utils-jgit/nb-configuration.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ec4540cb4e72b42ea3a6e50c3b725e2e497af260
--- /dev/null
+++ b/java-diff-utils-jgit/nb-configuration.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-shared-configuration>
+    <!--
+This file contains additional configuration written by modules in the NetBeans IDE.
+The configuration is intended to be shared among all the users of project and
+therefore it is assumed to be part of version control checkout.
+Without this configuration present, some functionality in the IDE may be limited or fail altogether.
+-->
+    <properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
+        <!--
+Properties that influence various parts of the IDE, especially code formatting and the like. 
+You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
+That way multiple projects can share the same settings (useful for formatting rules for example).
+Any value defined here will override the pom.xml file value but is only applicable to the current project.
+-->
+        <netbeans.compile.on.save>none</netbeans.compile.on.save>
+    </properties>
+</project-shared-configuration>
diff --git a/java-diff-utils-jgit/pom.xml b/java-diff-utils-jgit/pom.xml
index 4bc8e7c66d8a66af223d23006d99ed5a982ed0bd..deeef10e8adb0ef8b51137dc50bfab70bd629a50 100644
--- a/java-diff-utils-jgit/pom.xml
+++ b/java-diff-utils-jgit/pom.xml
@@ -4,19 +4,17 @@
     <parent>
         <groupId>io.github.java-diff-utils</groupId>
         <artifactId>java-diff-utils-parent</artifactId>
-        <version>4.5</version>
+        <version>4.7</version>
     </parent>
     <artifactId>java-diff-utils-jgit</artifactId>
     <name>java-diff-utils-jgit</name>
     <packaging>jar</packaging>
     <description>This is an extension of java-diff-utils using jgit to use its implementation of
-some difference algorithms.</description>
+        some difference algorithms.</description>
     <dependencies>
         <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <version>4.12</version>
-            <type>jar</type>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
diff --git a/java-diff-utils-jgit/src/test/java/com/github/difflib/algorithm/jgit/HistogramDiffTest.java b/java-diff-utils-jgit/src/test/java/com/github/difflib/algorithm/jgit/HistogramDiffTest.java
index e1030242a5969140c6d0bfff795829d9b97fb082..d4487c232a2e3f19a6ba5d5e76775f4d40e881e3 100644
--- a/java-diff-utils-jgit/src/test/java/com/github/difflib/algorithm/jgit/HistogramDiffTest.java
+++ b/java-diff-utils-jgit/src/test/java/com/github/difflib/algorithm/jgit/HistogramDiffTest.java
@@ -21,12 +21,9 @@ import com.github.difflib.patch.PatchFailedException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import org.junit.After;
-import org.junit.AfterClass;
-import static org.junit.Assert.*;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import org.junit.jupiter.api.Test;
 
 /**
  *
@@ -37,22 +34,6 @@ public class HistogramDiffTest {
     public HistogramDiffTest() {
     }
 
-    @BeforeClass
-    public static void setUpClass() {
-    }
-
-    @AfterClass
-    public static void tearDownClass() {
-    }
-
-    @Before
-    public void setUp() {
-    }
-
-    @After
-    public void tearDown() {
-    }
-
     /**
      * Test of diff method, of class HistogramDiff.
      */
diff --git a/java-diff-utils-jgit/src/test/java/com/github/difflib/algorithm/jgit/LRHistogramDiffTest.java b/java-diff-utils-jgit/src/test/java/com/github/difflib/algorithm/jgit/LRHistogramDiffTest.java
index 02dfe85d141b5853a6325412dd0ae2c2c7709755..9bb0a8f48130c4570f24d74b38ced1bab4f90161 100644
--- a/java-diff-utils-jgit/src/test/java/com/github/difflib/algorithm/jgit/LRHistogramDiffTest.java
+++ b/java-diff-utils-jgit/src/test/java/com/github/difflib/algorithm/jgit/LRHistogramDiffTest.java
@@ -28,12 +28,9 @@ import java.util.ArrayList;
 import java.util.List;
 import static java.util.stream.Collectors.toList;
 import java.util.zip.ZipFile;
-import org.junit.After;
-import org.junit.AfterClass;
-import static org.junit.Assert.*;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.junit.jupiter.api.Test;
 
 /**
  *
@@ -41,25 +38,6 @@ import org.junit.Test;
  */
 public class LRHistogramDiffTest {
 
-    public LRHistogramDiffTest() {
-    }
-
-    @BeforeClass
-    public static void setUpClass() {
-    }
-
-    @AfterClass
-    public static void tearDownClass() {
-    }
-
-    @Before
-    public void setUp() {
-    }
-
-    @After
-    public void tearDown() {
-    }
-
     @Test
     public void testPossibleDiffHangOnLargeDatasetDnaumenkoIssue26() throws IOException, PatchFailedException {
         ZipFile zip = new ZipFile("target/test-classes/mocks/large_dataset1.zip");
diff --git a/java-diff-utils/nb-configuration.xml b/java-diff-utils/nb-configuration.xml
index a65c4514a3d97bc9851e99794ec52135faa6fef5..b01ee9a66fe5b1b5974e784c75b43892cd87840d 100644
--- a/java-diff-utils/nb-configuration.xml
+++ b/java-diff-utils/nb-configuration.xml
@@ -14,5 +14,6 @@ That way multiple projects can share the same settings (useful for formatting ru
 Any value defined here will override the pom.xml file value but is only applicable to the current project.
 -->
         <netbeans.hint.jdkPlatform>JDK_1.8</netbeans.hint.jdkPlatform>
+        <netbeans.compile.on.save>none</netbeans.compile.on.save>
     </properties>
 </project-shared-configuration>
diff --git a/java-diff-utils/pom.xml b/java-diff-utils/pom.xml
index 2abcaf29cac6786e8972e862d7d79720a22291aa..5cbff43893586f19517334e43fcef9ddc831f79e 100644
--- a/java-diff-utils/pom.xml
+++ b/java-diff-utils/pom.xml
@@ -7,7 +7,7 @@
     <parent>
         <groupId>io.github.java-diff-utils</groupId>
         <artifactId>java-diff-utils-parent</artifactId>
-        <version>4.5</version>
+        <version>4.7</version>
     </parent>
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -15,16 +15,13 @@
 
     <dependencies>
         <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <version>4.12</version>
-            <type>jar</type>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.assertj</groupId>
             <artifactId>assertj-core</artifactId>
-            <version>3.11.1</version>
             <scope>test</scope>
         </dependency>
     </dependencies>
diff --git a/java-diff-utils/src/main/java/com/github/difflib/DiffUtils.java b/java-diff-utils/src/main/java/com/github/difflib/DiffUtils.java
index b57a0d2f2e1db628e149e43d5addc88069e9a413..f85b6178956e5e094f818948f58df78e192327c9 100644
--- a/java-diff-utils/src/main/java/com/github/difflib/DiffUtils.java
+++ b/java-diff-utils/src/main/java/com/github/difflib/DiffUtils.java
@@ -17,7 +17,6 @@ package com.github.difflib;
 
 import com.github.difflib.algorithm.DiffAlgorithmI;
 import com.github.difflib.algorithm.DiffAlgorithmListener;
-import com.github.difflib.algorithm.DiffException;
 import com.github.difflib.algorithm.myers.MyersDiff;
 import com.github.difflib.patch.AbstractDelta;
 import com.github.difflib.patch.Patch;
@@ -31,50 +30,56 @@ import java.util.function.BiPredicate;
 
 /**
  * Implements the difference and patching engine
- *
- * @author <a href="dm.naumenko@gmail.com">Dmitry Naumenko</a>
  */
 public final class DiffUtils {
 
     /**
-     * Computes the difference between the original and revised list of elements with default diff algorithm
+     * Computes the difference between the original and revised list of elements with default diff
+     * algorithm
      *
+     * @param <T> types to be diffed
      * @param original The original text. Must not be {@code null}.
      * @param revised The revised text. Must not be {@code null}.
      * @param progress progress listener
-     * @return The patch describing the difference between the original and revised sequences. Never {@code null}.
-     * @throws com.github.difflib.algorithm.DiffException
+     * @return The patch describing the difference between the original and revised sequences. Never
+     * {@code null}.
      */
-    public static <T> Patch<T> diff(List<T> original, List<T> revised, DiffAlgorithmListener progress) throws DiffException {
+    public static <T> Patch<T> diff(List<T> original, List<T> revised, DiffAlgorithmListener progress) {
         return DiffUtils.diff(original, revised, new MyersDiff<>(), progress);
     }
-    
-    public static <T> Patch<T> diff(List<T> original, List<T> revised) throws DiffException {
+
+    public static <T> Patch<T> diff(List<T> original, List<T> revised) {
         return DiffUtils.diff(original, revised, new MyersDiff<>(), null);
     }
+    
+    public static <T> Patch<T> diff(List<T> original, List<T> revised, boolean includeEqualParts) {
+        return DiffUtils.diff(original, revised, new MyersDiff<>(), null, includeEqualParts);
+    }
 
     /**
      * Computes the difference between the original and revised text.
      */
     public static Patch<String> diff(String sourceText, String targetText,
-            DiffAlgorithmListener progress) throws DiffException {
+            DiffAlgorithmListener progress) {
         return DiffUtils.diff(
-                 Arrays.asList(sourceText.split("\n")), 
-                 Arrays.asList(targetText.split("\n")), progress);
+                Arrays.asList(sourceText.split("\n")),
+                Arrays.asList(targetText.split("\n")), progress);
     }
 
     /**
-     * Computes the difference between the original and revised list of elements with default diff algorithm
+     * Computes the difference between the original and revised list of elements with default diff
+     * algorithm
      *
      * @param source The original text. Must not be {@code null}.
      * @param target The revised text. Must not be {@code null}.
      *
-     * @param equalizer the equalizer object to replace the default compare algorithm (Object.equals). If {@code null}
-     * the default equalizer of the default algorithm is used..
-     * @return The patch describing the difference between the original and revised sequences. Never {@code null}.
+     * @param equalizer the equalizer object to replace the default compare algorithm
+     * (Object.equals). If {@code null} the default equalizer of the default algorithm is used..
+     * @return The patch describing the difference between the original and revised sequences. Never
+     * {@code null}.
      */
     public static <T> Patch<T> diff(List<T> source, List<T> target,
-            BiPredicate<T, T> equalizer) throws DiffException {
+            BiPredicate<T, T> equalizer) {
         if (equalizer != null) {
             return DiffUtils.diff(source, target,
                     new MyersDiff<>(equalizer));
@@ -82,46 +87,57 @@ public final class DiffUtils {
         return DiffUtils.diff(source, target, new MyersDiff<>());
     }
 
+    public static <T> Patch<T> diff(List<T> original, List<T> revised,
+            DiffAlgorithmI<T> algorithm, DiffAlgorithmListener progress) {
+        return diff(original, revised, algorithm, progress, false);
+    }
+    
     /**
-     * Computes the difference between the original and revised list of elements with default diff algorithm
+     * Computes the difference between the original and revised list of elements with default diff
+     * algorithm
      *
      * @param original The original text. Must not be {@code null}.
      * @param revised The revised text. Must not be {@code null}.
      * @param algorithm The diff algorithm. Must not be {@code null}.
      * @param progress The diff algorithm listener.
-     * @return The patch describing the difference between the original and revised sequences. Never {@code null}.
+     * @param includeEqualParts Include equal data parts into the patch.
+     * @return The patch describing the difference between the original and revised sequences. Never
+     * {@code null}.
      */
     public static <T> Patch<T> diff(List<T> original, List<T> revised,
-            DiffAlgorithmI<T> algorithm, DiffAlgorithmListener progress) throws DiffException {
+            DiffAlgorithmI<T> algorithm, DiffAlgorithmListener progress, 
+            boolean includeEqualParts) {
         Objects.requireNonNull(original, "original must not be null");
         Objects.requireNonNull(revised, "revised must not be null");
         Objects.requireNonNull(algorithm, "algorithm must not be null");
 
-        return Patch.generate(original, revised, algorithm.computeDiff(original, revised, progress));
+        return Patch.generate(original, revised, algorithm.computeDiff(original, revised, progress), includeEqualParts);
     }
-    
+
     /**
-     * Computes the difference between the original and revised list of elements with default diff algorithm
+     * Computes the difference between the original and revised list of elements with default diff
+     * algorithm
      *
      * @param original The original text. Must not be {@code null}.
      * @param revised The revised text. Must not be {@code null}.
      * @param algorithm The diff algorithm. Must not be {@code null}.
-     * @return The patch describing the difference between the original and revised sequences. Never {@code null}.
+     * @return The patch describing the difference between the original and revised sequences. Never
+     * {@code null}.
      */
-     public static <T> Patch<T> diff(List<T> original, List<T> revised,
-            DiffAlgorithmI<T> algorithm) throws DiffException {
-         return diff(original, revised, algorithm, null);
-     }
+    public static <T> Patch<T> diff(List<T> original, List<T> revised, DiffAlgorithmI<T> algorithm) {
+        return diff(original, revised, algorithm, null);
+    }
 
     /**
-     * Computes the difference between the given texts inline. This one uses the "trick" to make out of texts lists of
-     * characters, like DiffRowGenerator does and merges those changes at the end together again.
+     * Computes the difference between the given texts inline. This one uses the "trick" to make out
+     * of texts lists of characters, like DiffRowGenerator does and merges those changes at the end
+     * together again.
      *
      * @param original
      * @param revised
      * @return
      */
-    public static Patch<String> diffInline(String original, String revised) throws DiffException {
+    public static Patch<String> diffInline(String original, String revised) {
         List<String> origList = new ArrayList<>();
         List<String> revList = new ArrayList<>();
         for (Character character : original.toCharArray()) {
diff --git a/java-diff-utils/src/main/java/com/github/difflib/UnifiedDiffUtils.java b/java-diff-utils/src/main/java/com/github/difflib/UnifiedDiffUtils.java
index d5812c3193c587ee103f9565cb2aa9ab15e326bb..9d7908b912e64aa20393455912f72331893a940f 100644
--- a/java-diff-utils/src/main/java/com/github/difflib/UnifiedDiffUtils.java
+++ b/java-diff-utils/src/main/java/com/github/difflib/UnifiedDiffUtils.java
@@ -21,6 +21,7 @@ import com.github.difflib.patch.AbstractDelta;
 import com.github.difflib.patch.Patch;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -59,25 +60,7 @@ public final class UnifiedDiffUtils {
             Matcher m = UNIFIED_DIFF_CHUNK_REGEXP.matcher(line);
             if (m.find()) {
                 // Process the lines in the previous chunk
-                if (!rawChunk.isEmpty()) {
-                    List<String> oldChunkLines = new ArrayList<>();
-                    List<String> newChunkLines = new ArrayList<>();
-
-                    for (String[] raw_line : rawChunk) {
-                        tag = raw_line[0];
-                        rest = raw_line[1];
-                        if (" ".equals(tag) || "-".equals(tag)) {
-                            oldChunkLines.add(rest);
-                        }
-                        if (" ".equals(tag) || "+".equals(tag)) {
-                            newChunkLines.add(rest);
-                        }
-                    }
-                    patch.addDelta(new ChangeDelta<>(new Chunk<>(
-                            old_ln - 1, oldChunkLines), new Chunk<>(
-                            new_ln - 1, newChunkLines)));
-                    rawChunk.clear();
-                }
+                processLinesInPrevChunk(rawChunk, patch, old_ln, new_ln);
                 // Parse the @@ header
                 old_ln = m.group(1) == null ? 1 : Integer.parseInt(m.group(1));
                 new_ln = m.group(3) == null ? 1 : Integer.parseInt(m.group(3));
@@ -102,6 +85,14 @@ public final class UnifiedDiffUtils {
         }
 
         // Process the lines in the last chunk
+        processLinesInPrevChunk(rawChunk, patch, old_ln, new_ln);
+
+        return patch;
+    }
+
+    private static void processLinesInPrevChunk(List<String[]> rawChunk, Patch<String> patch, int old_ln, int new_ln) {
+        String tag;
+        String rest;
         if (!rawChunk.isEmpty()) {
             List<String> oldChunkLines = new ArrayList<>();
             List<String> newChunkLines = new ArrayList<>();
@@ -116,19 +107,16 @@ public final class UnifiedDiffUtils {
                     newChunkLines.add(rest);
                 }
             }
-
             patch.addDelta(new ChangeDelta<>(new Chunk<>(
-                    old_ln - 1, oldChunkLines), new Chunk<>(new_ln - 1,
-                    newChunkLines)));
+                    old_ln - 1, oldChunkLines), new Chunk<>(
+                    new_ln - 1, newChunkLines)));
             rawChunk.clear();
         }
-
-        return patch;
     }
 
     /**
-     * generateUnifiedDiff takes a Patch and some other arguments, returning the Unified Diff format text representing
-     * the Patch.
+     * generateUnifiedDiff takes a Patch and some other arguments, returning the Unified Diff format
+     * text representing the Patch.
      *
      * @param originalFileName - Filename of the original (unrevised file)
      * @param revisedFileName - Filename of the revised file
@@ -143,8 +131,8 @@ public final class UnifiedDiffUtils {
             int contextSize) {
         if (!patch.getDeltas().isEmpty()) {
             List<String> ret = new ArrayList<>();
-            ret.add("--- " + originalFileName);
-            ret.add("+++ " + revisedFileName);
+            ret.add("--- " + Optional.ofNullable(originalFileName).orElse(""));
+            ret.add("+++ " + Optional.ofNullable(revisedFileName).orElse(""));
 
             List<AbstractDelta<String>> patchDeltas = new ArrayList<>(
                     patch.getDeltas());
@@ -179,7 +167,7 @@ public final class UnifiedDiffUtils {
                         // then create a new set and add the current Delta to
                         // it.
                         List<String> curBlock = processDeltas(originalLines,
-                                deltas, contextSize);
+                                deltas, contextSize, false);
                         ret.addAll(curBlock);
                         deltas.clear();
                         deltas.add(nextDelta);
@@ -190,7 +178,7 @@ public final class UnifiedDiffUtils {
             }
             // don't forget to process the last set of Deltas
             List<String> curBlock = processDeltas(originalLines, deltas,
-                    contextSize);
+                    contextSize, patchDeltas.size() == 1 && originalFileName == null);
             ret.addAll(curBlock);
             return ret;
         }
@@ -198,7 +186,8 @@ public final class UnifiedDiffUtils {
     }
 
     /**
-     * processDeltas takes a list of Deltas and outputs them together in a single block of Unified-Diff-format text.
+     * processDeltas takes a list of Deltas and outputs them together in a single block of
+     * Unified-Diff-format text.
      *
      * @param origLines - the lines of the original file
      * @param deltas - the Deltas to be output as a single block
@@ -207,18 +196,22 @@ public final class UnifiedDiffUtils {
      * @author Bill James (tankerbay@gmail.com)
      */
     private static List<String> processDeltas(List<String> origLines,
-            List<AbstractDelta<String>> deltas, int contextSize) {
+            List<AbstractDelta<String>> deltas, int contextSize, boolean newFile) {
         List<String> buffer = new ArrayList<>();
         int origTotal = 0; // counter for total lines output from Original
         int revTotal = 0; // counter for total lines output from Original
         int line;
 
         AbstractDelta<String> curDelta = deltas.get(0);
-
-        // NOTE: +1 to overcome the 0-offset Position
-        int origStart = curDelta.getSource().getPosition() + 1 - contextSize;
-        if (origStart < 1) {
-            origStart = 1;
+        int origStart;
+        if (newFile) {
+            origStart = 0;
+        } else {
+            // NOTE: +1 to overcome the 0-offset Position
+            origStart = curDelta.getSource().getPosition() + 1 - contextSize;
+            if (origStart < 1) {
+                origStart = 1;
+            }
         }
 
         int revStart = curDelta.getTarget().getPosition() + 1 - contextSize;
diff --git a/java-diff-utils/src/main/java/com/github/difflib/algorithm/DiffAlgorithmI.java b/java-diff-utils/src/main/java/com/github/difflib/algorithm/DiffAlgorithmI.java
index d923629020cf85a505444cd8cdaad334a7e45ddb..117656e444fa957ff5ca69fbba65e7803d723c7a 100644
--- a/java-diff-utils/src/main/java/com/github/difflib/algorithm/DiffAlgorithmI.java
+++ b/java-diff-utils/src/main/java/com/github/difflib/algorithm/DiffAlgorithmI.java
@@ -22,6 +22,7 @@ import java.util.List;
  * Interface of a diff algorithm.
  *
  * @author Tobias Warneke (t.warneke@gmx.net)
+ * @param <T> type of data that is diffed.
  */
 public interface DiffAlgorithmI<T> {
 
@@ -32,9 +33,8 @@ public interface DiffAlgorithmI<T> {
      * @param target target data
      * @param progress progress listener
      * @return
-     * @throws DiffException
      */
-    List<Change> computeDiff(List<T> source, List<T> target, DiffAlgorithmListener progress) throws DiffException;
+    List<Change> computeDiff(List<T> source, List<T> target, DiffAlgorithmListener progress);
 
     /**
      * Simple extension to compute a changeset using arrays.
@@ -43,9 +43,8 @@ public interface DiffAlgorithmI<T> {
      * @param target
      * @param progress
      * @return
-     * @throws com.github.difflib.algorithm.DiffException
      */
-    default List<Change> computeDiff(T[] source, T[] target, DiffAlgorithmListener progress) throws DiffException {
+    default List<Change> computeDiff(T[] source, T[] target, DiffAlgorithmListener progress) {
         return computeDiff(Arrays.asList(source), Arrays.asList(target), progress);
     }
 }
diff --git a/java-diff-utils/src/main/java/com/github/difflib/algorithm/DiffException.java b/java-diff-utils/src/main/java/com/github/difflib/algorithm/DiffException.java
deleted file mode 100644
index d36d16fb8cb51ee1df3fedfdd4b4b53e43bc8384..0000000000000000000000000000000000000000
--- a/java-diff-utils/src/main/java/com/github/difflib/algorithm/DiffException.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2009-2017 java-diff-utils.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.github.difflib.algorithm;
-
-public class DiffException extends Exception {
-
-    private static final long serialVersionUID = 1L;
-
-    public DiffException() {
-    }
-
-    public DiffException(String msg) {
-        super(msg);
-    }
-}
diff --git a/java-diff-utils/src/main/java/com/github/difflib/algorithm/DifferentiationFailedException.java b/java-diff-utils/src/main/java/com/github/difflib/algorithm/DifferentiationFailedException.java
deleted file mode 100644
index e201e440a8b586ce94473797ce0583e22fcc1c48..0000000000000000000000000000000000000000
--- a/java-diff-utils/src/main/java/com/github/difflib/algorithm/DifferentiationFailedException.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2009-2017 java-diff-utils.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.github.difflib.algorithm;
-
-/**
- * Thrown whenever the differencing engine cannot produce the differences between two revisions of ta text.
- *
- * @see com.github.difflib.algorithm.myers.MyersDiff
- * @see DiffAlgorithmI
- */
-public class DifferentiationFailedException extends DiffException {
-
-    private static final long serialVersionUID = 1L;
-
-    public DifferentiationFailedException() {
-    }
-
-    public DifferentiationFailedException(String msg) {
-        super(msg);
-    }
-}
diff --git a/java-diff-utils/src/main/java/com/github/difflib/algorithm/myers/MyersDiff.java b/java-diff-utils/src/main/java/com/github/difflib/algorithm/myers/MyersDiff.java
index abcf31e229f06cc538157bd38d9b896a341e34c8..631bc38c634c5325262b2c985e7a522ff9330583 100644
--- a/java-diff-utils/src/main/java/com/github/difflib/algorithm/myers/MyersDiff.java
+++ b/java-diff-utils/src/main/java/com/github/difflib/algorithm/myers/MyersDiff.java
@@ -18,8 +18,6 @@ package com.github.difflib.algorithm.myers;
 import com.github.difflib.algorithm.Change;
 import com.github.difflib.algorithm.DiffAlgorithmI;
 import com.github.difflib.algorithm.DiffAlgorithmListener;
-import com.github.difflib.algorithm.DiffException;
-import com.github.difflib.algorithm.DifferentiationFailedException;
 import com.github.difflib.patch.DeltaType;
 import com.github.difflib.patch.Patch;
 import java.util.ArrayList;
@@ -50,7 +48,7 @@ public final class MyersDiff<T> implements DiffAlgorithmI<T> {
      * Return empty diff if get the error while procession the difference.
      */
     @Override
-    public List<Change> computeDiff(final List<T> source, final List<T> target, DiffAlgorithmListener progress) throws DiffException {
+    public List<Change> computeDiff(final List<T> source, final List<T> target, DiffAlgorithmListener progress) {
         Objects.requireNonNull(source, "source list must not be null");
         Objects.requireNonNull(target, "target list must not be null");
 
@@ -74,8 +72,7 @@ public final class MyersDiff<T> implements DiffAlgorithmI<T> {
      * @return A minimum {@link PathNode Path} accross the differences graph.
      * @throws DifferentiationFailedException if a diff path could not be found.
      */
-    private PathNode buildPath(final List<T> orig, final List<T> rev, DiffAlgorithmListener progress)
-            throws DifferentiationFailedException {
+    private PathNode buildPath(final List<T> orig, final List<T> rev, DiffAlgorithmListener progress) {
         Objects.requireNonNull(orig, "original sequence is null");
         Objects.requireNonNull(rev, "revised sequence is null");
 
@@ -132,7 +129,7 @@ public final class MyersDiff<T> implements DiffAlgorithmI<T> {
             diagonal[middle + d - 1] = null;
         }
         // According to Myers, this cannot happen
-        throw new DifferentiationFailedException("could not find a diff path");
+        throw new IllegalStateException("could not find a diff path");
     }
 
     /**
diff --git a/java-diff-utils/src/main/java/com/github/difflib/patch/AbstractDelta.java b/java-diff-utils/src/main/java/com/github/difflib/patch/AbstractDelta.java
index 9f1fb451aaae9f38daa57c9517f4f8a3f767caab..e98874e8aff447058fdaf35e7be8b972d93f1f79 100644
--- a/java-diff-utils/src/main/java/com/github/difflib/patch/AbstractDelta.java
+++ b/java-diff-utils/src/main/java/com/github/difflib/patch/AbstractDelta.java
@@ -60,6 +60,11 @@ public abstract class AbstractDelta<T> {
     public abstract void applyTo(List<T> target) throws PatchFailedException;
     
     public abstract void restore(List<T> target);
+    
+    /**
+     * Create a new delta of the actual instance with customized chunk data.
+     */
+    public abstract AbstractDelta<T> withChunks(Chunk<T> original, Chunk<T> revised);
 
     @Override
     public int hashCode() {
diff --git a/java-diff-utils/src/main/java/com/github/difflib/patch/ChangeDelta.java b/java-diff-utils/src/main/java/com/github/difflib/patch/ChangeDelta.java
index 7c1cd98bb95347819a71c9b5824f9c544b4883d7..eddb279db4178223bb6efad6a2804f5373674549 100644
--- a/java-diff-utils/src/main/java/com/github/difflib/patch/ChangeDelta.java
+++ b/java-diff-utils/src/main/java/com/github/difflib/patch/ChangeDelta.java
@@ -72,4 +72,9 @@ public final class ChangeDelta<T> extends AbstractDelta<T> {
         return "[ChangeDelta, position: " + getSource().getPosition() + ", lines: "
                 + getSource().getLines() + " to " + getTarget().getLines() + "]";
     }
+
+    @Override
+    public AbstractDelta<T> withChunks(Chunk<T> original, Chunk<T> revised) {
+        return new ChangeDelta(original, revised);
+    }
 }
diff --git a/java-diff-utils/src/main/java/com/github/difflib/patch/DeleteDelta.java b/java-diff-utils/src/main/java/com/github/difflib/patch/DeleteDelta.java
index cfbc427cc455cd05183ae5095ea08fc6e1f03df3..b33114fe89ec1740e7ed14e412592600dcb85355 100644
--- a/java-diff-utils/src/main/java/com/github/difflib/patch/DeleteDelta.java
+++ b/java-diff-utils/src/main/java/com/github/difflib/patch/DeleteDelta.java
@@ -59,4 +59,9 @@ public final class DeleteDelta<T> extends AbstractDelta<T> {
         return "[DeleteDelta, position: " + getSource().getPosition() + ", lines: "
                 + getSource().getLines() + "]";
     }
+    
+    @Override
+    public AbstractDelta<T> withChunks(Chunk<T> original, Chunk<T> revised) {
+        return new DeleteDelta(original, revised);
+    }
 }
diff --git a/java-diff-utils/src/main/java/com/github/difflib/patch/EqualDelta.java b/java-diff-utils/src/main/java/com/github/difflib/patch/EqualDelta.java
new file mode 100644
index 0000000000000000000000000000000000000000..dbfdf46ab203dac8f0331bb5ad6ce29931e45082
--- /dev/null
+++ b/java-diff-utils/src/main/java/com/github/difflib/patch/EqualDelta.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2020 java-diff-utils.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.github.difflib.patch;
+
+import java.util.List;
+
+/**
+ * This delta contains equal lines of data. Therefore nothing is to do in applyTo and restore.
+ * @author tobens
+ */
+public class EqualDelta<T> extends AbstractDelta<T> {
+
+    public EqualDelta(Chunk<T> source, Chunk<T> target) {
+        super(DeltaType.EQUAL, source, target);
+    }
+
+    @Override
+    public void applyTo(List<T> target) throws PatchFailedException {
+        verifyChunk(target);
+    }
+
+    @Override
+    public void restore(List<T> target) {
+    }
+
+    @Override
+    public String toString() {
+        return "[EqualDelta, position: " + getSource().getPosition() + ", lines: "
+                + getSource().getLines() + "]";
+    }
+    
+    @Override
+    public AbstractDelta<T> withChunks(Chunk<T> original, Chunk<T> revised) {
+        return new EqualDelta(original, revised);
+    }
+}
diff --git a/java-diff-utils/src/main/java/com/github/difflib/patch/InsertDelta.java b/java-diff-utils/src/main/java/com/github/difflib/patch/InsertDelta.java
index 12164fa481ead79413eae856e61ded6fa763eb95..16742d25011e49e23d3240a0e90e51f180bf2f2b 100644
--- a/java-diff-utils/src/main/java/com/github/difflib/patch/InsertDelta.java
+++ b/java-diff-utils/src/main/java/com/github/difflib/patch/InsertDelta.java
@@ -59,4 +59,9 @@ public final class InsertDelta<T> extends AbstractDelta<T> {
         return "[InsertDelta, position: " + getSource().getPosition()
                 + ", lines: " + getTarget().getLines() + "]";
     }
+    
+    @Override
+    public AbstractDelta<T> withChunks(Chunk<T> original, Chunk<T> revised) {
+        return new InsertDelta(original, revised);
+    }
 }
diff --git a/java-diff-utils/src/main/java/com/github/difflib/patch/Patch.java b/java-diff-utils/src/main/java/com/github/difflib/patch/Patch.java
index 688e9f16ec758f682ab98d4d8a67c0ce73374935..161293eb62772cf277a8c820cb87196b21ef7216 100644
--- a/java-diff-utils/src/main/java/com/github/difflib/patch/Patch.java
+++ b/java-diff-utils/src/main/java/com/github/difflib/patch/Patch.java
@@ -22,6 +22,7 @@ package com.github.difflib.patch;
 import static java.util.Comparator.comparing;
 import com.github.difflib.algorithm.Change;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.ListIterator;
 
@@ -100,10 +101,35 @@ public final class Patch<T> {
     }
 
     public static <T> Patch<T> generate(List<T> original, List<T> revised, List<Change> changes) {
-        Patch<T> patch = new Patch<>(changes.size());
+        return generate(original, revised, changes, false);
+    }
+
+    private static <T> Chunk<T> buildChunk(int start, int end, List<T> data) {
+        return new Chunk<>(start, new ArrayList<>(data.subList(start, end)));
+    }
+
+    public static <T> Patch<T> generate(List<T> original, List<T> revised, List<Change> _changes, boolean includeEquals) {
+        Patch<T> patch = new Patch<>(_changes.size());
+        int startOriginal = 0;
+        int startRevised = 0;
+        
+        List<Change> changes = _changes;
+        
+        if (includeEquals) {
+            changes = new ArrayList<Change>(_changes);
+            Collections.sort(changes, comparing(d -> d.startOriginal));
+        }
+        
         for (Change change : changes) {
-            Chunk<T> orgChunk = new Chunk<>(change.startOriginal, new ArrayList<>(original.subList(change.startOriginal, change.endOriginal)));
-            Chunk<T> revChunk = new Chunk<>(change.startRevised, new ArrayList<>(revised.subList(change.startRevised, change.endRevised)));
+
+            if (includeEquals && startOriginal < change.startOriginal) {
+                patch.addDelta(new EqualDelta(
+                        buildChunk(startOriginal, change.startOriginal, original),
+                        buildChunk(startRevised, change.startRevised, revised)));
+            }
+
+            Chunk<T> orgChunk = buildChunk(change.startOriginal, change.endOriginal, original);
+            Chunk<T> revChunk = buildChunk(change.startRevised, change.endRevised, revised);
             switch (change.deltaType) {
                 case DELETE:
                     patch.addDelta(new DeleteDelta<>(orgChunk, revChunk));
@@ -115,7 +141,17 @@ public final class Patch<T> {
                     patch.addDelta(new ChangeDelta<>(orgChunk, revChunk));
                     break;
             }
+
+            startOriginal = change.endOriginal;
+            startRevised = change.endRevised;
         }
+
+        if (includeEquals && startOriginal < original.size()) {
+            patch.addDelta(new EqualDelta(
+                    buildChunk(startOriginal, original.size(), original),
+                    buildChunk(startRevised, revised.size(), revised)));
+        }
+
         return patch;
     }
 }
diff --git a/java-diff-utils/src/main/java/com/github/difflib/text/DiffRowGenerator.java b/java-diff-utils/src/main/java/com/github/difflib/text/DiffRowGenerator.java
index 4f963cd7d4f477a1be75c9be0462c085719e1210..350bef5b3f03c38ad47789c4442af531afe5f431 100644
--- a/java-diff-utils/src/main/java/com/github/difflib/text/DiffRowGenerator.java
+++ b/java-diff-utils/src/main/java/com/github/difflib/text/DiffRowGenerator.java
@@ -16,15 +16,13 @@
 package com.github.difflib.text;
 
 import com.github.difflib.DiffUtils;
-import com.github.difflib.algorithm.DiffException;
 import com.github.difflib.patch.AbstractDelta;
-import com.github.difflib.patch.ChangeDelta;
 import com.github.difflib.patch.Chunk;
-import com.github.difflib.patch.DeleteDelta;
-import com.github.difflib.patch.InsertDelta;
+import com.github.difflib.patch.DeltaType;
 import com.github.difflib.patch.Patch;
 import com.github.difflib.text.DiffRow.Tag;
 import java.util.*;
+import java.util.function.BiFunction;
 import java.util.function.BiPredicate;
 import java.util.function.Function;
 import java.util.regex.Matcher;
@@ -32,9 +30,10 @@ import java.util.regex.Pattern;
 import static java.util.stream.Collectors.toList;
 
 /**
- * This class for generating DiffRows for side-by-sidy view. You can customize the way of generating. For example, show
- * inline diffs on not, ignoring white spaces or/and blank lines and so on. All parameters for generating are optional.
- * If you do not specify them, the class will use the default values.
+ * This class for generating DiffRows for side-by-sidy view. You can customize the way of
+ * generating. For example, show inline diffs on not, ignoring white spaces or/and blank lines and
+ * so on. All parameters for generating are optional. If you do not specify them, the class will use
+ * the default values.
  *
  * These values are: showInlineDiffs = false; ignoreWhiteSpaces = true; ignoreBlankLines = true; ...
  *
@@ -52,7 +51,6 @@ public final class DiffRowGenerator {
 
     public static final Function<String, String> LINE_NORMALIZER_FOR_HTML = StringUtils::normalize;
 
-
     /**
      * Splitting lines by character to achieve char by char diff checking.
      */
@@ -101,12 +99,14 @@ public final class DiffRowGenerator {
     /**
      * Wrap the elements in the sequence with the given tag
      *
-     * @param startPosition the position from which tag should start. The counting start from a zero.
+     * @param startPosition the position from which tag should start. The counting start from a
+     * zero.
      * @param endPosition the position before which tag should should be closed.
      * @param tagGenerator the tag generator
      */
     static void wrapInTag(List<String> sequence, int startPosition,
-            int endPosition, Function<Boolean, String> tagGenerator) {
+            int endPosition, Tag tag, BiFunction<Tag, Boolean, String> tagGenerator,
+            Function<String, String> processDiffs) {
         int endPos = endPosition;
 
         while (endPos >= startPosition) {
@@ -123,7 +123,11 @@ public final class DiffRowGenerator {
                 break;
             }
 
-            sequence.add(endPos, tagGenerator.apply(false));
+            sequence.add(endPos, tagGenerator.apply(tag, false));
+            if (processDiffs != null) {
+                sequence.set(endPos - 1,
+                        processDiffs.apply(sequence.get(endPos - 1)));
+            }
             endPos--;
 
             //search position for end tag
@@ -131,25 +135,28 @@ public final class DiffRowGenerator {
                 if ("\n".equals(sequence.get(endPos - 1))) {
                     break;
                 }
+                if (processDiffs != null) {
+                    sequence.set(endPos - 1,
+                            processDiffs.apply(sequence.get(endPos - 1)));
+                }
                 endPos--;
             }
 
-            sequence.add(endPos, tagGenerator.apply(true));
+            sequence.add(endPos, tagGenerator.apply(tag, true));
             endPos--;
         }
-
-//        sequence.add(endPosition, tagGenerator.apply(false));
-//        sequence.add(startPosition, tagGenerator.apply(true));
     }
+
     private final int columnWidth;
     private final BiPredicate<String, String> equalizer;
     private final boolean ignoreWhiteSpaces;
     private final Function<String, List<String>> inlineDiffSplitter;
     private final boolean mergeOriginalRevised;
-    private final Function<Boolean, String> newTag;
-    private final Function<Boolean, String> oldTag;
+    private final BiFunction<Tag, Boolean, String> newTag;
+    private final BiFunction<Tag, Boolean, String> oldTag;
     private final boolean reportLinesUnchanged;
     private final Function<String, String> lineNormalizer;
+    private final Function<String, String> processDiffs;
 
     private final boolean showInlineDiffs;
 
@@ -161,35 +168,42 @@ public final class DiffRowGenerator {
         columnWidth = builder.columnWidth;
         mergeOriginalRevised = builder.mergeOriginalRevised;
         inlineDiffSplitter = builder.inlineDiffSplitter;
-        equalizer = ignoreWhiteSpaces ? IGNORE_WHITESPACE_EQUALIZER : DEFAULT_EQUALIZER;
+
+        if (builder.equalizer != null) {
+            equalizer = builder.equalizer;
+        } else {
+            equalizer = ignoreWhiteSpaces ? IGNORE_WHITESPACE_EQUALIZER : DEFAULT_EQUALIZER;
+        }
+
         reportLinesUnchanged = builder.reportLinesUnchanged;
         lineNormalizer = builder.lineNormalizer;
+        processDiffs = builder.processDiffs;
 
         Objects.requireNonNull(inlineDiffSplitter);
         Objects.requireNonNull(lineNormalizer);
     }
 
     /**
-     * Get the DiffRows describing the difference between original and revised texts using the given patch. Useful for
-     * displaying side-by-side diff.
+     * Get the DiffRows describing the difference between original and revised texts using the given
+     * patch. Useful for displaying side-by-side diff.
      *
      * @param original the original text
      * @param revised the revised text
      * @return the DiffRows between original and revised texts
      */
-    public List<DiffRow> generateDiffRows(List<String> original, List<String> revised) throws DiffException {
+    public List<DiffRow> generateDiffRows(List<String> original, List<String> revised) {
         return generateDiffRows(original, DiffUtils.diff(original, revised, equalizer));
     }
 
     /**
-     * Generates the DiffRows describing the difference between original and revised texts using the given patch. Useful
-     * for displaying side-by-side diff.
+     * Generates the DiffRows describing the difference between original and revised texts using the
+     * given patch. Useful for displaying side-by-side diff.
      *
      * @param original the original text
      * @param patch the given patch
      * @return the DiffRows between original and revised texts
      */
-    public List<DiffRow> generateDiffRows(final List<String> original, Patch<String> patch) throws DiffException {
+    public List<DiffRow> generateDiffRows(final List<String> original, Patch<String> patch) {
         List<DiffRow> diffRows = new ArrayList<>();
         int endPos = 0;
         final List<AbstractDelta<String>> deltaList = patch.getDeltas();
@@ -202,7 +216,7 @@ public final class DiffRowGenerator {
             }
 
             // Inserted DiffRow
-            if (delta instanceof InsertDelta) {
+            if (delta.getType() == DeltaType.INSERT) {
                 endPos = orig.last() + 1;
                 for (String line : rev.getLines()) {
                     diffRows.add(buildDiffRow(Tag.INSERT, "", line));
@@ -211,7 +225,7 @@ public final class DiffRowGenerator {
             }
 
             // Deleted DiffRow
-            if (delta instanceof DeleteDelta) {
+            if (delta.getType() == DeltaType.DELETE) {
                 endPos = orig.last() + 1;
                 for (String line : orig.getLines()) {
                     diffRows.add(buildDiffRow(Tag.DELETE, line, ""));
@@ -245,15 +259,15 @@ public final class DiffRowGenerator {
             String wrapOrg = preprocessLine(orgline);
             if (Tag.DELETE == type) {
                 if (mergeOriginalRevised || showInlineDiffs) {
-                    wrapOrg = oldTag.apply(true) + wrapOrg + oldTag.apply(false);
+                    wrapOrg = oldTag.apply(type, true) + wrapOrg + oldTag.apply(type, false);
                 }
             }
             String wrapNew = preprocessLine(newline);
             if (Tag.INSERT == type) {
                 if (mergeOriginalRevised) {
-                    wrapOrg = newTag.apply(true) + wrapNew + newTag.apply(false);
+                    wrapOrg = newTag.apply(type, true) + wrapNew + newTag.apply(type, false);
                 } else if (showInlineDiffs) {
-                    wrapNew = newTag.apply(true) + wrapNew + newTag.apply(false);
+                    wrapNew = newTag.apply(type, true) + wrapNew + newTag.apply(type, false);
                 }
             }
             return new DiffRow(type, wrapOrg, wrapNew);
@@ -279,7 +293,7 @@ public final class DiffRowGenerator {
      *
      * @param delta the given delta
      */
-    private List<DiffRow> generateInlineDiffs(AbstractDelta<String> delta) throws DiffException {
+    private List<DiffRow> generateInlineDiffs(AbstractDelta<String> delta) {
         List<String> orig = normalizeLines(delta.getSource().getLines());
         List<String> rev = normalizeLines(delta.getTarget().getLines());
         List<String> origList;
@@ -290,41 +304,45 @@ public final class DiffRowGenerator {
         origList = inlineDiffSplitter.apply(joinedOrig);
         revList = inlineDiffSplitter.apply(joinedRev);
 
-        List<AbstractDelta<String>> inlineDeltas = DiffUtils.diff(origList, revList).getDeltas();
+        List<AbstractDelta<String>> inlineDeltas = DiffUtils.diff(origList, revList, equalizer).getDeltas();
 
         Collections.reverse(inlineDeltas);
         for (AbstractDelta<String> inlineDelta : inlineDeltas) {
             Chunk<String> inlineOrig = inlineDelta.getSource();
             Chunk<String> inlineRev = inlineDelta.getTarget();
-            if (inlineDelta instanceof DeleteDelta) {
+            if (inlineDelta.getType() == DeltaType.DELETE) {
                 wrapInTag(origList, inlineOrig.getPosition(), inlineOrig
                         .getPosition()
-                        + inlineOrig.size(), oldTag);
-            } else if (inlineDelta instanceof InsertDelta) {
+                        + inlineOrig.size(), Tag.DELETE, oldTag, processDiffs);
+            } else if (inlineDelta.getType() == DeltaType.INSERT) {
                 if (mergeOriginalRevised) {
                     origList.addAll(inlineOrig.getPosition(),
-                            revList.subList(inlineRev.getPosition(), inlineRev.getPosition()
-                                    + inlineRev.size()));
-                    wrapInTag(origList, inlineOrig.getPosition(), inlineOrig.getPosition()
-                            + inlineRev.size(), newTag);
+                            revList.subList(inlineRev.getPosition(),
+                                    inlineRev.getPosition() + inlineRev.size()));
+                    wrapInTag(origList, inlineOrig.getPosition(),
+                            inlineOrig.getPosition() + inlineRev.size(),
+                            Tag.INSERT, newTag, processDiffs);
                 } else {
-                    wrapInTag(revList, inlineRev.getPosition(), inlineRev.getPosition()
-                            + inlineRev.size(), newTag);
+                    wrapInTag(revList, inlineRev.getPosition(),
+                            inlineRev.getPosition() + inlineRev.size(),
+                            Tag.INSERT, newTag, processDiffs);
                 }
-            } else if (inlineDelta instanceof ChangeDelta) {
+            } else if (inlineDelta.getType() == DeltaType.CHANGE) {
                 if (mergeOriginalRevised) {
                     origList.addAll(inlineOrig.getPosition() + inlineOrig.size(),
-                            revList.subList(inlineRev.getPosition(), inlineRev.getPosition()
-                                    + inlineRev.size()));
-                    wrapInTag(origList, inlineOrig.getPosition() + inlineOrig.size(), inlineOrig.getPosition() + inlineOrig.size()
-                            + inlineRev.size(), newTag);
+                            revList.subList(inlineRev.getPosition(),
+                                    inlineRev.getPosition() + inlineRev.size()));
+                    wrapInTag(origList, inlineOrig.getPosition() + inlineOrig.size(),
+                            inlineOrig.getPosition() + inlineOrig.size() + inlineRev.size(),
+                            Tag.CHANGE, newTag, processDiffs);
                 } else {
-                    wrapInTag(revList, inlineRev.getPosition(), inlineRev.getPosition()
-                            + inlineRev.size(), newTag);
+                    wrapInTag(revList, inlineRev.getPosition(),
+                            inlineRev.getPosition() + inlineRev.size(),
+                            Tag.CHANGE, newTag, processDiffs);
                 }
-                wrapInTag(origList, inlineOrig.getPosition(), inlineOrig
-                        .getPosition()
-                        + inlineOrig.size(), oldTag);
+                wrapInTag(origList, inlineOrig.getPosition(),
+                        inlineOrig.getPosition() + inlineOrig.size(),
+                        Tag.CHANGE, oldTag, processDiffs);
             }
         }
         StringBuilder origResult = new StringBuilder();
@@ -367,14 +385,18 @@ public final class DiffRowGenerator {
         private boolean showInlineDiffs = false;
         private boolean ignoreWhiteSpaces = false;
 
-        private Function<Boolean, String> oldTag = f -> f ? "<span class=\"editOldInline\">" : "</span>";
-        private Function<Boolean, String> newTag = f -> f ? "<span class=\"editNewInline\">" : "</span>";
+        private BiFunction<Tag, Boolean, String> oldTag = 
+                (tag, f) -> f ? "<span class=\"editOldInline\">" : "</span>";
+        private BiFunction<Tag, Boolean, String> newTag = 
+                (tag, f) -> f ? "<span class=\"editNewInline\">" : "</span>";
 
         private int columnWidth = 0;
         private boolean mergeOriginalRevised = false;
         private boolean reportLinesUnchanged = false;
         private Function<String, List<String>> inlineDiffSplitter = SPLITTER_BY_CHARACTER;
         private Function<String, String> lineNormalizer = LINE_NORMALIZER_FOR_HTML;
+        private Function<String, String> processDiffs = null;
+        private BiPredicate<String, String> equalizer = null;
 
         private Builder() {
         }
@@ -402,8 +424,8 @@ public final class DiffRowGenerator {
         }
 
         /**
-         * Give the originial old and new text lines to Diffrow without any additional processing and without any tags to
-         * highlight the change.
+         * Give the originial old and new text lines to Diffrow without any additional processing
+         * and without any tags to highlight the change.
          *
          * @param val the value to set. Default: false.
          * @return builder with configured reportLinesUnWrapped parameter
@@ -419,10 +441,21 @@ public final class DiffRowGenerator {
          * @param generator the tag generator
          * @return builder with configured ignoreBlankLines parameter
          */
-        public Builder oldTag(Function<Boolean, String> generator) {
+        public Builder oldTag(BiFunction<Tag, Boolean, String> generator) {
             this.oldTag = generator;
             return this;
         }
+        
+        /**
+         * Generator for Old-Text-Tags.
+         *
+         * @param generator the tag generator
+         * @return builder with configured ignoreBlankLines parameter
+         */
+        public Builder oldTag(Function<Boolean, String> generator) {
+            this.oldTag = (tag, f) -> generator.apply(f);
+            return this;
+        }
 
         /**
          * Generator for New-Text-Tags.
@@ -430,16 +463,39 @@ public final class DiffRowGenerator {
          * @param generator
          * @return
          */
-        public Builder newTag(Function<Boolean, String> generator) {
+        public Builder newTag(BiFunction<Tag, Boolean, String> generator) {
             this.newTag = generator;
             return this;
         }
+        
+        /**
+         * Generator for New-Text-Tags.
+         *
+         * @param generator
+         * @return
+         */
+        public Builder newTag(Function<Boolean, String> generator) {
+            this.newTag = (tag, f) -> generator.apply(f);
+            return this;
+        }
+
+        /**
+         * Processor for diffed text parts. Here e.g. whitecharacters could be replaced by something
+         * visible.
+         *
+         * @param processDiffs
+         * @return
+         */
+        public Builder processDiffs(Function<String, String> processDiffs) {
+            this.processDiffs = processDiffs;
+            return this;
+        }
 
         /**
          * Set the column width of generated lines of original and revised texts.
          *
-         * @param width the width to set. Making it < 0 doesn't have any sense. Default 80. @return builder with config
-         * ured ignoreBlankLines parameter
+         * @param width the width to set. Making it < 0 doesn't have any sense. Default 80. @return
+         * builder with config ured ignoreBlankLines parameter
          */
         public Builder columnWidth(int width) {
             if (width >= 0) {
@@ -458,7 +514,8 @@ public final class DiffRowGenerator {
         }
 
         /**
-         * Merge the complete result within the original text. This makes sense for one line display.
+         * Merge the complete result within the original text. This makes sense for one line
+         * display.
          *
          * @param mergeOriginalRevised
          * @return
@@ -469,8 +526,9 @@ public final class DiffRowGenerator {
         }
 
         /**
-         * Per default each character is separatly processed. This variant introduces processing by word, which does not
-         * deliver in word changes. Therefore the whole word will be tagged as changed:
+         * Per default each character is separatly processed. This variant introduces processing by
+         * word, which does not deliver in word changes. Therefore the whole word will be tagged as
+         * changed:
          *
          * <pre>
          * false:    (aBa : aba) --  changed: a(B)a : a(b)a
@@ -483,8 +541,8 @@ public final class DiffRowGenerator {
         }
 
         /**
-         * To provide some customized splitting a splitter can be provided. Here someone could think about sentence splitter,
-         * comma splitter or stuff like that.
+         * To provide some customized splitting a splitter can be provided. Here someone could think
+         * about sentence splitter, comma splitter or stuff like that.
          *
          * @param inlineDiffSplitter
          * @return
@@ -495,8 +553,9 @@ public final class DiffRowGenerator {
         }
 
         /**
-         * By default DiffRowGenerator preprocesses lines for HTML output. Tabs and special HTML characters like "&lt;"
-         * are replaced with its encoded value. To change this you can provide a customized line normalizer here.
+         * By default DiffRowGenerator preprocesses lines for HTML output. Tabs and special HTML
+         * characters like "&lt;" are replaced with its encoded value. To change this you can
+         * provide a customized line normalizer here.
          *
          * @param lineNormalizer
          * @return
@@ -505,5 +564,16 @@ public final class DiffRowGenerator {
             this.lineNormalizer = lineNormalizer;
             return this;
         }
+
+        /**
+         * Provide an equalizer for diff processing.
+         *
+         * @param equalizer equalizer for diff processing.
+         * @return builder with configured equalizer parameter
+         */
+        public Builder equalizer(BiPredicate<String, String> equalizer) {
+            this.equalizer = equalizer;
+            return this;
+        }
     }
 }
diff --git a/java-diff-utils/src/main/java/com/github/difflib/unifieddiff/UnifiedDiffWriter.java b/java-diff-utils/src/main/java/com/github/difflib/unifieddiff/UnifiedDiffWriter.java
index c9488f9c0aac7474aec91e0fde6842437e8b6f8f..54259f771923d586a1e50e9888b9682fffb2d263 100644
--- a/java-diff-utils/src/main/java/com/github/difflib/unifieddiff/UnifiedDiffWriter.java
+++ b/java-diff-utils/src/main/java/com/github/difflib/unifieddiff/UnifiedDiffWriter.java
@@ -20,6 +20,7 @@ import java.io.IOException;
 import java.io.Writer;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.logging.Level;
@@ -34,6 +35,7 @@ public class UnifiedDiffWriter {
     private static final Logger LOG = Logger.getLogger(UnifiedDiffWriter.class.getName());
 
     public static void write(UnifiedDiff diff, Function<String, List<String>> originalLinesProvider, Writer writer, int contextSize) throws IOException {
+        Objects.requireNonNull(originalLinesProvider, "original lines provider needs to be specified");
         write(diff, originalLinesProvider, line -> {
             try {
                 writer.append(line).append("\n");
@@ -44,7 +46,9 @@ public class UnifiedDiffWriter {
     }
 
     public static void write(UnifiedDiff diff, Function<String, List<String>> originalLinesProvider, Consumer<String> writer, int contextSize) throws IOException {
-        writer.accept(diff.getHeader());
+        if (diff.getHeader() != null) {
+            writer.accept(diff.getHeader());
+        }
 
         for (UnifiedDiffFile file : diff.getFiles()) {
             List<AbstractDelta<String>> patchDeltas = new ArrayList<>(
@@ -54,9 +58,9 @@ public class UnifiedDiffWriter {
                 if (file.getIndex() != null) {
                     writer.accept("index " + file.getIndex());
                 }
-                if (file.getFromFile() != null) {
-                    writer.accept("--- " + file.getFromFile());
-                }
+
+                writer.accept("--- " + file.getFromFile());
+
                 if (file.getToFile() != null) {
                     writer.accept("+++ " + file.getToFile());
                 }
@@ -83,7 +87,7 @@ public class UnifiedDiffWriter {
                             // if it isn't, output the current set,
                             // then create a new set and add the current Delta to
                             // it.
-                            processDeltas(writer, originalLines, deltas, contextSize);
+                            processDeltas(writer, originalLines, deltas, contextSize, false);
                             deltas.clear();
                             deltas.add(nextDelta);
                         }
@@ -92,7 +96,8 @@ public class UnifiedDiffWriter {
 
                 }
                 // don't forget to process the last set of Deltas
-                processDeltas(writer, originalLines, deltas, contextSize);
+                processDeltas(writer, originalLines, deltas, contextSize, 
+                        patchDeltas.size() == 1 && file.getFromFile() == null);
             }
 
         }
@@ -104,7 +109,7 @@ public class UnifiedDiffWriter {
 
     private static void processDeltas(Consumer<String> writer,
             List<String> origLines, List<AbstractDelta<String>> deltas,
-            int contextSize) {
+            int contextSize, boolean newFile) {
         List<String> buffer = new ArrayList<>();
         int origTotal = 0; // counter for total lines output from Original
         int revTotal = 0; // counter for total lines output from Original
@@ -112,10 +117,15 @@ public class UnifiedDiffWriter {
 
         AbstractDelta<String> curDelta = deltas.get(0);
 
-        // NOTE: +1 to overcome the 0-offset Position
-        int origStart = curDelta.getSource().getPosition() + 1 - contextSize;
-        if (origStart < 1) {
-            origStart = 1;
+        int origStart;
+        if (newFile) {
+            origStart = 0;
+        } else {
+            // NOTE: +1 to overcome the 0-offset Position
+            origStart = curDelta.getSource().getPosition() + 1 - contextSize;
+            if (origStart < 1) {
+                origStart = 1;
+            }
         }
 
         int revStart = curDelta.getTarget().getPosition() + 1 - contextSize;
@@ -130,7 +140,8 @@ public class UnifiedDiffWriter {
         }
 
         // output the context before the first Delta
-        for (line = contextStart; line < curDelta.getSource().getPosition(); line++) { //
+        for (line = contextStart; line < curDelta.getSource().getPosition()
+                && line < origLines.size(); line++) { //
             buffer.add(" " + origLines.get(line));
             origTotal++;
             revTotal++;
@@ -145,8 +156,8 @@ public class UnifiedDiffWriter {
             AbstractDelta<String> nextDelta = deltas.get(deltaIndex);
             int intermediateStart = curDelta.getSource().getPosition()
                     + curDelta.getSource().getLines().size();
-            for (line = intermediateStart; line < nextDelta.getSource()
-                    .getPosition(); line++) {
+            for (line = intermediateStart; line < nextDelta.getSource().getPosition() 
+                    && line < origLines.size(); line++) {
                 // output the code between the last Delta and this one
                 buffer.add(" " + origLines.get(line));
                 origTotal++;
diff --git a/java-diff-utils/src/test/java/com/github/difflib/DiffUtilsTest.java b/java-diff-utils/src/test/java/com/github/difflib/DiffUtilsTest.java
index 28a37219af29ae7b190dc0bd5e3b211c11448d30..c02c44469bc1584aba7a2ecd9a1da292a44c8ba5 100644
--- a/java-diff-utils/src/test/java/com/github/difflib/DiffUtilsTest.java
+++ b/java-diff-utils/src/test/java/com/github/difflib/DiffUtilsTest.java
@@ -1,10 +1,10 @@
 package com.github.difflib;
 
-import com.github.difflib.algorithm.DiffException;
 import com.github.difflib.patch.ChangeDelta;
 import com.github.difflib.patch.Chunk;
 import com.github.difflib.patch.DeleteDelta;
 import com.github.difflib.patch.AbstractDelta;
+import com.github.difflib.patch.EqualDelta;
 import com.github.difflib.patch.InsertDelta;
 import com.github.difflib.patch.Patch;
 import java.io.BufferedReader;
@@ -19,16 +19,17 @@ import java.util.Collections;
 import java.util.List;
 import static java.util.stream.Collectors.toList;
 import java.util.zip.ZipFile;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import org.junit.Ignore;
-import org.junit.Test;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
 
 public class DiffUtilsTest {
 
     @Test
-    public void testDiff_Insert() throws DiffException {
+    public void testDiff_Insert() {
         final Patch<String> patch = DiffUtils.diff(Arrays.asList("hhh"), Arrays.
                 asList("hhh", "jjj", "kkk"));
         assertNotNull(patch);
@@ -40,7 +41,7 @@ public class DiffUtilsTest {
     }
 
     @Test
-    public void testDiff_Delete() throws DiffException {
+    public void testDiff_Delete() {
         final Patch<String> patch = DiffUtils.diff(Arrays.asList("ddd", "fff", "ggg"), Arrays.
                 asList("ggg"));
         assertNotNull(patch);
@@ -52,7 +53,7 @@ public class DiffUtilsTest {
     }
 
     @Test
-    public void testDiff_Change() throws DiffException {
+    public void testDiff_Change() {
         final List<String> changeTest_from = Arrays.asList("aaa", "bbb", "ccc");
         final List<String> changeTest_to = Arrays.asList("aaa", "zzz", "ccc");
 
@@ -66,14 +67,14 @@ public class DiffUtilsTest {
     }
 
     @Test
-    public void testDiff_EmptyList() throws DiffException {
+    public void testDiff_EmptyList() {
         final Patch<String> patch = DiffUtils.diff(new ArrayList<>(), new ArrayList<>());
         assertNotNull(patch);
         assertEquals(0, patch.getDeltas().size());
     }
 
     @Test
-    public void testDiff_EmptyListWithNonEmpty() throws DiffException {
+    public void testDiff_EmptyListWithNonEmpty() {
         final Patch<String> patch = DiffUtils.diff(new ArrayList<>(), Arrays.asList("aaa"));
         assertNotNull(patch);
         assertEquals(1, patch.getDeltas().size());
@@ -82,7 +83,7 @@ public class DiffUtilsTest {
     }
 
     @Test
-    public void testDiffInline() throws DiffException {
+    public void testDiffInline() {
         final Patch<String> patch = DiffUtils.diffInline("", "test");
         assertEquals(1, patch.getDeltas().size());
         assertTrue(patch.getDeltas().get(0) instanceof InsertDelta);
@@ -92,7 +93,7 @@ public class DiffUtilsTest {
     }
 
     @Test
-    public void testDiffInline2() throws DiffException {
+    public void testDiffInline2() {
         final Patch<String> patch = DiffUtils.diffInline("es", "fest");
         assertEquals(2, patch.getDeltas().size());
         assertTrue(patch.getDeltas().get(0) instanceof InsertDelta);
@@ -105,7 +106,7 @@ public class DiffUtilsTest {
     }
 
     @Test
-    public void testDiffIntegerList() throws DiffException {
+    public void testDiffIntegerList() {
         List<Integer> original = Arrays.asList(1, 2, 3, 4, 5);
         List<Integer> revised = Arrays.asList(2, 3, 4, 6);
 
@@ -121,7 +122,7 @@ public class DiffUtilsTest {
     }
 
     @Test
-    public void testDiffMissesChangeForkDnaumenkoIssue31() throws DiffException {
+    public void testDiffMissesChangeForkDnaumenkoIssue31() {
         List<String> original = Arrays.asList("line1", "line2", "line3");
         List<String> revised = Arrays.asList("line1", "line2-2", "line4");
 
@@ -134,8 +135,8 @@ public class DiffUtilsTest {
      * To test this, the greedy meyer algorithm is not suitable.
      */
     @Test
-    @Ignore
-    public void testPossibleDiffHangOnLargeDatasetDnaumenkoIssue26() throws IOException, DiffException {
+    @Disabled
+    public void testPossibleDiffHangOnLargeDatasetDnaumenkoIssue26() throws IOException {
         ZipFile zip = new ZipFile(TestConstants.MOCK_FOLDER + "/large_dataset1.zip");
 
         Patch<String> patch = DiffUtils.diff(
@@ -154,10 +155,76 @@ public class DiffUtilsTest {
     }
 
     @Test
-    public void testDiffMyersExample1() throws DiffException {
+    public void testDiffMyersExample1() {
         final Patch<String> patch = DiffUtils.diff(Arrays.asList("A", "B", "C", "A", "B", "B", "A"), Arrays.asList("C", "B", "A", "B", "A", "C"));
         assertNotNull(patch);
         assertEquals(4, patch.getDeltas().size());
         assertEquals("Patch{deltas=[[DeleteDelta, position: 0, lines: [A, B]], [InsertDelta, position: 3, lines: [B]], [DeleteDelta, position: 5, lines: [B]], [InsertDelta, position: 7, lines: [C]]]}", patch.toString());
     }
+
+    @Test
+    public void testDiff_Equal() {
+        final Patch<String> patch = DiffUtils.diff(
+                Arrays.asList("hhh", "jjj", "kkk"),
+                Arrays.asList("hhh", "jjj", "kkk"), true);
+        assertNotNull(patch);
+        assertEquals(1, patch.getDeltas().size());
+        final AbstractDelta<String> delta = patch.getDeltas().get(0);
+        assertTrue(delta instanceof EqualDelta);
+        assertEquals(new Chunk<>(0, Arrays.asList("hhh", "jjj", "kkk")), delta.getSource());
+        assertEquals(new Chunk<>(0, Arrays.asList("hhh", "jjj", "kkk")), delta.getTarget());
+    }
+
+    @Test
+    public void testDiff_InsertWithEqual() {
+        final Patch<String> patch = DiffUtils.diff(Arrays.asList("hhh"), Arrays.
+                asList("hhh", "jjj", "kkk"), true);
+        assertNotNull(patch);
+        assertEquals(2, patch.getDeltas().size());
+
+        AbstractDelta<String> delta = patch.getDeltas().get(0);
+        assertTrue(delta instanceof EqualDelta);
+        assertEquals(new Chunk<>(0, Arrays.asList("hhh")), delta.getSource());
+        assertEquals(new Chunk<>(0, Arrays.asList("hhh")), delta.getTarget());
+
+        delta = patch.getDeltas().get(1);
+        assertTrue(delta instanceof InsertDelta);
+        assertEquals(new Chunk<>(1, Collections.<String>emptyList()), delta.getSource());
+        assertEquals(new Chunk<>(1, Arrays.asList("jjj", "kkk")), delta.getTarget());
+    }
+
+    @Test
+    public void testDiff_ProblemIssue42() {
+        final Patch<String> patch = DiffUtils.diff(
+                Arrays.asList("The", "dog", "is", "brown"),
+                Arrays.asList("The", "fox", "is", "down"), true);
+
+        System.out.println(patch);
+        assertNotNull(patch);
+        assertEquals(4, patch.getDeltas().size());
+
+        
+        assertThat(patch.getDeltas()).extracting(d -> d.getType().name())
+                .containsExactly("EQUAL", "CHANGE", "EQUAL", "CHANGE");
+        
+        AbstractDelta<String> delta = patch.getDeltas().get(0);
+        assertTrue(delta instanceof EqualDelta);
+        assertEquals(new Chunk<>(0, Arrays.asList("The")), delta.getSource());
+        assertEquals(new Chunk<>(0, Arrays.asList("The")), delta.getTarget());
+
+        delta = patch.getDeltas().get(1);
+        assertTrue(delta instanceof ChangeDelta);
+        assertEquals(new Chunk<>(1, Arrays.asList("dog")), delta.getSource());
+        assertEquals(new Chunk<>(1, Arrays.asList("fox")), delta.getTarget());
+        
+        delta = patch.getDeltas().get(2);
+        assertTrue(delta instanceof EqualDelta);
+        assertEquals(new Chunk<>(2, Arrays.asList("is")), delta.getSource());
+        assertEquals(new Chunk<>(2, Arrays.asList("is")), delta.getTarget());
+        
+        delta = patch.getDeltas().get(3);
+        assertTrue(delta instanceof ChangeDelta);
+        assertEquals(new Chunk<>(3, Arrays.asList("brown")), delta.getSource());
+        assertEquals(new Chunk<>(3, Arrays.asList("down")), delta.getTarget());
+    }
 }
diff --git a/java-diff-utils/src/test/java/com/github/difflib/GenerateUnifiedDiffTest.java b/java-diff-utils/src/test/java/com/github/difflib/GenerateUnifiedDiffTest.java
index c6bfc4eca2f546eb11e5680f4ab113b343cf8f71..8c023c965cc80152eeb4f0daa741a9f162821092 100644
--- a/java-diff-utils/src/test/java/com/github/difflib/GenerateUnifiedDiffTest.java
+++ b/java-diff-utils/src/test/java/com/github/difflib/GenerateUnifiedDiffTest.java
@@ -1,6 +1,5 @@
 package com.github.difflib;
 
-import com.github.difflib.algorithm.DiffException;
 import com.github.difflib.patch.Patch;
 import com.github.difflib.patch.PatchFailedException;
 import java.io.BufferedReader;
@@ -11,9 +10,9 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import static java.util.stream.Collectors.joining;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-import org.junit.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+import org.junit.jupiter.api.Test;
 
 public class GenerateUnifiedDiffTest {
 
@@ -29,7 +28,7 @@ public class GenerateUnifiedDiffTest {
     }
 
     @Test
-    public void testGenerateUnified() throws DiffException, IOException {
+    public void testGenerateUnified() throws IOException {
         List<String> origLines = fileToLines(TestConstants.MOCK_FOLDER + "original.txt");
         List<String> revLines = fileToLines(TestConstants.MOCK_FOLDER + "revised.txt");
 
@@ -37,7 +36,7 @@ public class GenerateUnifiedDiffTest {
     }
 
     @Test
-    public void testGenerateUnifiedWithOneDelta() throws DiffException, IOException {
+    public void testGenerateUnifiedWithOneDelta() throws IOException {
         List<String> origLines = fileToLines(TestConstants.MOCK_FOLDER + "one_delta_test_original.txt");
         List<String> revLines = fileToLines(TestConstants.MOCK_FOLDER + "one_delta_test_revised.txt");
 
@@ -45,7 +44,7 @@ public class GenerateUnifiedDiffTest {
     }
 
     @Test
-    public void testGenerateUnifiedDiffWithoutAnyDeltas() throws DiffException {
+    public void testGenerateUnifiedDiffWithoutAnyDeltas() {
         List<String> test = Arrays.asList("abc");
         Patch<String> patch = DiffUtils.diff(test, test);
         UnifiedDiffUtils.generateUnifiedDiff("abc", "abc", test, patch, 0);
@@ -67,14 +66,14 @@ public class GenerateUnifiedDiffTest {
      * Issue 12
      */
     @Test
-    public void testPatchWithNoDeltas() throws DiffException, IOException {
+    public void testPatchWithNoDeltas() throws IOException {
         final List<String> lines1 = fileToLines(TestConstants.MOCK_FOLDER + "issue11_1.txt");
         final List<String> lines2 = fileToLines(TestConstants.MOCK_FOLDER + "issue11_2.txt");
         verify(lines1, lines2, "issue11_1.txt", "issue11_2.txt");
     }
 
     @Test
-    public void testDiff5() throws DiffException, IOException {
+    public void testDiff5() throws IOException {
         final List<String> lines1 = fileToLines(TestConstants.MOCK_FOLDER + "5A.txt");
         final List<String> lines2 = fileToLines(TestConstants.MOCK_FOLDER + "5B.txt");
         verify(lines1, lines2, "5A.txt", "5B.txt");
@@ -84,7 +83,7 @@ public class GenerateUnifiedDiffTest {
      * Issue 19
      */
     @Test
-    public void testDiffWithHeaderLineInText() throws DiffException {
+    public void testDiffWithHeaderLineInText() {
         List<String> original = new ArrayList<>();
         List<String> revised = new ArrayList<>();
 
@@ -104,9 +103,31 @@ public class GenerateUnifiedDiffTest {
                 original, patch, 10);
         UnifiedDiffUtils.parseUnifiedDiff(udiff);
     }
+    
+    /**
+     * Issue 47
+     */
+    @Test
+    public void testNewFileCreation() {
+        List<String> original = new ArrayList<>();
+        List<String> revised = new ArrayList<>();
+
+        revised.add("line1");
+        revised.add("line2");
+
+        Patch<String> patch = DiffUtils.diff(original, revised);
+        List<String> udiff = UnifiedDiffUtils.generateUnifiedDiff(null, "revised",
+                original, patch, 10);
+        
+        assertEquals("--- ", udiff.get(0));
+        assertEquals("+++ revised", udiff.get(1));
+        assertEquals("@@ -0,0 +1,2 @@", udiff.get(2));
+        
+        UnifiedDiffUtils.parseUnifiedDiff(udiff);
+    }
 
     private void verify(List<String> origLines, List<String> revLines,
-            String originalFile, String revisedFile) throws DiffException {
+            String originalFile, String revisedFile) {
         Patch<String> patch = DiffUtils.diff(origLines, revLines);
         List<String> unifiedDiff = UnifiedDiffUtils.generateUnifiedDiff(originalFile, revisedFile,
                 origLines, patch, 10);
diff --git a/java-diff-utils/src/test/java/com/github/difflib/algorithm/myers/MyersDiffTest.java b/java-diff-utils/src/test/java/com/github/difflib/algorithm/myers/MyersDiffTest.java
index ea9b0dccb5ec9aea67274e3c7fb46c69ec5aace8..5b8348e6fddfd9b94ecbd803f73470fa585361f7 100644
--- a/java-diff-utils/src/test/java/com/github/difflib/algorithm/myers/MyersDiffTest.java
+++ b/java-diff-utils/src/test/java/com/github/difflib/algorithm/myers/MyersDiffTest.java
@@ -16,13 +16,13 @@
 package com.github.difflib.algorithm.myers;
 
 import com.github.difflib.algorithm.DiffAlgorithmListener;
-import com.github.difflib.algorithm.DiffException;
 import com.github.difflib.patch.Patch;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import static org.junit.Assert.*;
-import org.junit.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import org.junit.jupiter.api.Test;
 
 /**
  *
@@ -31,7 +31,7 @@ import org.junit.Test;
 public class MyersDiffTest {
 
     @Test
-    public void testDiffMyersExample1Forward() throws DiffException {
+    public void testDiffMyersExample1Forward() {
         List<String> original = Arrays.asList("A", "B", "C", "A", "B", "B", "A");
         List<String> revised = Arrays.asList("C", "B", "A", "B", "A", "C");
         final Patch<String> patch = Patch.generate(original, revised, new MyersDiff<String>().computeDiff(original, revised, null));
@@ -41,7 +41,7 @@ public class MyersDiffTest {
     }
     
     @Test
-    public void testDiffMyersExample1ForwardWithListener() throws DiffException {
+    public void testDiffMyersExample1ForwardWithListener() {
         List<String> original = Arrays.asList("A", "B", "C", "A", "B", "B", "A");
         List<String> revised = Arrays.asList("C", "B", "A", "B", "A", "C");
         
diff --git a/java-diff-utils/src/test/java/com/github/difflib/examples/ComputeDifference.java b/java-diff-utils/src/test/java/com/github/difflib/examples/ComputeDifference.java
index bd6af94f679f9074507af50dc577cad2a55e4d41..f665e66242c3bd182a6294cbb8f7213b34787744 100644
--- a/java-diff-utils/src/test/java/com/github/difflib/examples/ComputeDifference.java
+++ b/java-diff-utils/src/test/java/com/github/difflib/examples/ComputeDifference.java
@@ -2,7 +2,6 @@ package com.github.difflib.examples;
 
 import com.github.difflib.DiffUtils;
 import com.github.difflib.TestConstants;
-import com.github.difflib.algorithm.DiffException;
 import com.github.difflib.patch.AbstractDelta;
 import com.github.difflib.patch.Patch;
 import java.io.File;
@@ -15,7 +14,7 @@ public class ComputeDifference {
     private static final String ORIGINAL = TestConstants.MOCK_FOLDER + "original.txt";
     private static final String RIVISED = TestConstants.MOCK_FOLDER + "revised.txt";
 
-    public static void main(String[] args) throws DiffException, IOException {
+    public static void main(String[] args) throws IOException {
         List<String> original = Files.readAllLines(new File(ORIGINAL).toPath());
         List<String> revised = Files.readAllLines(new File(RIVISED).toPath());
 
diff --git a/java-diff-utils/src/test/java/com/github/difflib/patch/PatchTest.java b/java-diff-utils/src/test/java/com/github/difflib/patch/PatchTest.java
index 792785eb9cc0a785b437c259fa5828ba1a63bf18..e2d1abac064c65457f2ca0216741702c6b640fa4 100644
--- a/java-diff-utils/src/test/java/com/github/difflib/patch/PatchTest.java
+++ b/java-diff-utils/src/test/java/com/github/difflib/patch/PatchTest.java
@@ -1,17 +1,16 @@
 package com.github.difflib.patch;
 
 import com.github.difflib.DiffUtils;
-import com.github.difflib.algorithm.DiffException;
 import java.util.Arrays;
 import java.util.List;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-import org.junit.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+import org.junit.jupiter.api.Test;
 
 public class PatchTest {
 
     @Test
-    public void testPatch_Insert() throws DiffException {
+    public void testPatch_Insert() {
         final List<String> insertTest_from = Arrays.asList("hhh");
         final List<String> insertTest_to = Arrays.asList("hhh", "jjj", "kkk", "lll");
 
@@ -24,7 +23,7 @@ public class PatchTest {
     }
 
     @Test
-    public void testPatch_Delete() throws DiffException {
+    public void testPatch_Delete() {
         final List<String> deleteTest_from = Arrays.asList("ddd", "fff", "ggg", "hhh");
         final List<String> deleteTest_to = Arrays.asList("ggg");
 
@@ -37,7 +36,7 @@ public class PatchTest {
     }
 
     @Test
-    public void testPatch_Change() throws DiffException {
+    public void testPatch_Change() {
         final List<String> changeTest_from = Arrays.asList("aaa", "bbb", "ccc", "ddd");
         final List<String> changeTest_to = Arrays.asList("aaa", "bxb", "cxc", "ddd");
 
diff --git a/java-diff-utils/src/test/java/com/github/difflib/text/DiffRowGeneratorTest.java b/java-diff-utils/src/test/java/com/github/difflib/text/DiffRowGeneratorTest.java
index c667b251885acee8b119f01fab94e9c00992b90d..a1450f3d14257d08a3cea7e6faba90baaeb20693 100644
--- a/java-diff-utils/src/test/java/com/github/difflib/text/DiffRowGeneratorTest.java
+++ b/java-diff-utils/src/test/java/com/github/difflib/text/DiffRowGeneratorTest.java
@@ -1,6 +1,5 @@
 package com.github.difflib.text;
 
-import com.github.difflib.algorithm.DiffException;
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
@@ -9,14 +8,15 @@ import java.util.Collections;
 import java.util.List;
 import java.util.regex.Pattern;
 import static java.util.stream.Collectors.toList;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import org.junit.Test;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import org.junit.jupiter.api.Test;
 
 public class DiffRowGeneratorTest {
 
     @Test
-    public void testGenerator_Default() throws DiffException {
+    public void testGenerator_Default() {
         String first = "anything \n \nother";
         String second = "anything\n\nother";
 
@@ -40,7 +40,7 @@ public class DiffRowGeneratorTest {
     }
 
     @Test
-    public void testGenerator_Default2() throws DiffException {
+    public void testGenerator_Default2() {
         String first = "anything \n \nother";
         String second = "anything\n\nother";
 
@@ -54,7 +54,7 @@ public class DiffRowGeneratorTest {
     }
 
     @Test
-    public void testGenerator_InlineDiff() throws DiffException {
+    public void testGenerator_InlineDiff() {
         String first = "anything \n \nother";
         String second = "anything\n\nother";
 
@@ -70,7 +70,7 @@ public class DiffRowGeneratorTest {
     }
 
     @Test
-    public void testGenerator_IgnoreWhitespaces() throws DiffException {
+    public void testGenerator_IgnoreWhitespaces() {
         String first = "anything \n \nother\nmore lines";
         String second = "anything\n\nother\nsome more lines";
 
@@ -99,7 +99,7 @@ public class DiffRowGeneratorTest {
     }
 
     @Test
-    public void testGeneratorWithWordWrap() throws DiffException {
+    public void testGeneratorWithWordWrap() {
         String first = "anything \n \nother";
         String second = "anything\n\nother";
 
@@ -116,7 +116,7 @@ public class DiffRowGeneratorTest {
     }
 
     @Test
-    public void testGeneratorWithMerge() throws DiffException {
+    public void testGeneratorWithMerge() {
         String first = "anything \n \nother";
         String second = "anything\n\nother";
 
@@ -134,7 +134,7 @@ public class DiffRowGeneratorTest {
     }
 
     @Test
-    public void testGeneratorWithMerge2() throws DiffException {
+    public void testGeneratorWithMerge2() {
         DiffRowGenerator generator = DiffRowGenerator.create()
                 .showInlineDiffs(true)
                 .mergeOriginalRevised(true)
@@ -147,7 +147,7 @@ public class DiffRowGeneratorTest {
     }
 
     @Test
-    public void testGeneratorWithMerge3() throws DiffException {
+    public void testGeneratorWithMerge3() {
         String first = "test\nanything \n \nother";
         String second = "anything\n\nother\ntest\ntest2";
 
@@ -168,7 +168,7 @@ public class DiffRowGeneratorTest {
     }
 
     @Test
-    public void testGeneratorWithMergeByWord4() throws DiffException {
+    public void testGeneratorWithMergeByWord4() {
         DiffRowGenerator generator = DiffRowGenerator.create()
                 .showInlineDiffs(true)
                 .mergeOriginalRevised(true)
@@ -182,7 +182,7 @@ public class DiffRowGeneratorTest {
     }
 
     @Test
-    public void testGeneratorWithMergeByWord5() throws DiffException {
+    public void testGeneratorWithMergeByWord5() {
         DiffRowGenerator generator = DiffRowGenerator.create()
                 .showInlineDiffs(true)
                 .mergeOriginalRevised(true)
@@ -220,7 +220,7 @@ public class DiffRowGeneratorTest {
     }
 
     @Test
-    public void testGeneratorExample1() throws DiffException {
+    public void testGeneratorExample1() {
         DiffRowGenerator generator = DiffRowGenerator.create()
                 .showInlineDiffs(true)
                 .mergeOriginalRevised(true)
@@ -239,7 +239,7 @@ public class DiffRowGeneratorTest {
     }
 
     @Test
-    public void testGeneratorExample2() throws DiffException {
+    public void testGeneratorExample2() {
         DiffRowGenerator generator = DiffRowGenerator.create()
                 .showInlineDiffs(true)
                 .inlineDiffByWord(true)
@@ -262,7 +262,7 @@ public class DiffRowGeneratorTest {
     }
 
     @Test
-    public void testGeneratorUnchanged() throws DiffException {
+    public void testGeneratorUnchanged() {
         String first = "anything \n \nother";
         String second = "anything\n\nother";
 
@@ -280,7 +280,7 @@ public class DiffRowGeneratorTest {
     }
 
     @Test
-    public void testGeneratorIssue14() throws DiffException {
+    public void testGeneratorIssue14() {
         DiffRowGenerator generator = DiffRowGenerator.create()
                 .showInlineDiffs(true)
                 .mergeOriginalRevised(true)
@@ -299,7 +299,7 @@ public class DiffRowGeneratorTest {
     }
 
     @Test
-    public void testGeneratorIssue15() throws DiffException, IOException {
+    public void testGeneratorIssue15() throws IOException {
         DiffRowGenerator generator = DiffRowGenerator.create()
                 .showInlineDiffs(true) //show the ~ ~ and ** ** symbols on each difference
                 .inlineDiffByWord(true) //show the ~ ~ and ** ** around each different word instead of each letter
@@ -328,7 +328,7 @@ public class DiffRowGeneratorTest {
     }
 
     @Test
-    public void testGeneratorIssue22() throws DiffException {
+    public void testGeneratorIssue22() {
         DiffRowGenerator generator = DiffRowGenerator.create()
                 .showInlineDiffs(true)
                 .inlineDiffByWord(true)
@@ -352,7 +352,7 @@ public class DiffRowGeneratorTest {
     }
 
     @Test
-    public void testGeneratorIssue22_2() throws DiffException {
+    public void testGeneratorIssue22_2() {
         DiffRowGenerator generator = DiffRowGenerator.create()
                 .showInlineDiffs(true)
                 .inlineDiffByWord(true)
@@ -370,7 +370,7 @@ public class DiffRowGeneratorTest {
     }
 
     @Test
-    public void testGeneratorIssue22_3() throws DiffException {
+    public void testGeneratorIssue22_3() {
         DiffRowGenerator generator = DiffRowGenerator.create()
                 .showInlineDiffs(true)
                 .inlineDiffByWord(true)
@@ -388,7 +388,7 @@ public class DiffRowGeneratorTest {
     }
 
     @Test
-    public void testGeneratorIssue41DefaultNormalizer() throws DiffException {
+    public void testGeneratorIssue41DefaultNormalizer() {
         DiffRowGenerator generator = DiffRowGenerator.create()
                 .build();
         List<DiffRow> rows = generator.generateDiffRows(Arrays.asList("<"), Arrays.asList("<"));
@@ -396,7 +396,7 @@ public class DiffRowGeneratorTest {
     }
 
     @Test
-    public void testGeneratorIssue41UserNormalizer() throws DiffException {
+    public void testGeneratorIssue41UserNormalizer() {
         DiffRowGenerator generator = DiffRowGenerator.create()
                 .lineNormalizer(str -> str.replace("\t", "    "))
                 .build();
@@ -407,7 +407,7 @@ public class DiffRowGeneratorTest {
     }
 
     @Test
-    public void testGenerationIssue44reportLinesUnchangedProblem() throws DiffException {
+    public void testGenerationIssue44reportLinesUnchangedProblem() {
         DiffRowGenerator generator = DiffRowGenerator.create()
                 .showInlineDiffs(true)
                 .reportLinesUnchanged(true)
@@ -417,4 +417,85 @@ public class DiffRowGeneratorTest {
         List<DiffRow> rows = generator.generateDiffRows(Arrays.asList("<dt>To do</dt>"), Arrays.asList("<dt>Done</dt>"));
         assertEquals("[[CHANGE,<dt>~~T~~o~~ do~~</dt>,<dt>**D**o**ne**</dt>]]", rows.toString());
     }
+
+    @Test
+    public void testIgnoreWhitespaceIssue66() {
+        DiffRowGenerator generator = DiffRowGenerator.create()
+                .showInlineDiffs(true)
+                .inlineDiffByWord(true)
+                .ignoreWhiteSpaces(true)
+                .mergeOriginalRevised(true)
+                .oldTag(f -> "~") //introduce markdown style for strikethrough
+                .newTag(f -> "**") //introduce markdown style for bold
+                .build();
+
+        //compute the differences for two test texts.
+        //CHECKSTYLE:OFF
+        List<DiffRow> rows = generator.generateDiffRows(
+                Arrays.asList("This\tis\ta\ttest."),
+                Arrays.asList("This is a test"));
+        //CHECKSTYLE:ON
+
+        assertEquals("This    is    a    test~.~", rows.get(0).getOldLine());
+    }
+
+    @Test
+    public void testIgnoreWhitespaceIssue66_2() {
+        DiffRowGenerator generator = DiffRowGenerator.create()
+                .showInlineDiffs(true)
+                .inlineDiffByWord(true)
+                .ignoreWhiteSpaces(true)
+                .mergeOriginalRevised(true)
+                .oldTag(f -> "~") //introduce markdown style for strikethrough
+                .newTag(f -> "**") //introduce markdown style for bold
+                .build();
+
+        //compute the differences for two test texts.
+        List<DiffRow> rows = generator.generateDiffRows(
+                Arrays.asList("This  is  a  test."),
+                Arrays.asList("This is a test"));
+
+        assertEquals("This  is  a  test~.~", rows.get(0).getOldLine());
+    }
+
+    @Test
+    public void testIgnoreWhitespaceIssue64() {
+        DiffRowGenerator generator = DiffRowGenerator.create()
+                .showInlineDiffs(true)
+                .inlineDiffByWord(true)
+                .ignoreWhiteSpaces(true)
+                .mergeOriginalRevised(true)
+                .oldTag(f -> "~") //introduce markdown style for strikethrough
+                .newTag(f -> "**") //introduce markdown style for bold
+                .build();
+
+        //compute the differences for two test texts.
+        List<DiffRow> rows = generator.generateDiffRows(
+                Arrays.asList("test\n\ntestline".split("\n")),
+                Arrays.asList("A new text line\n\nanother one".split("\n")));
+
+        assertThat(rows).extracting(item -> item.getOldLine())
+                .containsExactly("~test~**A new text line**",
+                        "",
+                        "~testline~**another one**");
+    }
+
+    @Test
+    public void testReplaceDiffsIssue63() {
+        DiffRowGenerator generator = DiffRowGenerator.create()
+                .showInlineDiffs(true)
+                .inlineDiffByWord(true)
+                .mergeOriginalRevised(true)
+                .oldTag(f -> "~") //introduce markdown style for strikethrough
+                .newTag(f -> "**") //introduce markdown style for bold
+                .processDiffs(str -> str.replace(" ", "/"))
+                .build();
+
+        //compute the differences for two test texts.
+        List<DiffRow> rows = generator.generateDiffRows(
+                Arrays.asList("This  is  a  test."),
+                Arrays.asList("This is a test"));
+
+        assertEquals("This~//~**/**is~//~**/**a~//~**/**test~.~", rows.get(0).getOldLine());
+    }
 }
diff --git a/java-diff-utils/src/test/java/com/github/difflib/text/StringUtilsTest.java b/java-diff-utils/src/test/java/com/github/difflib/text/StringUtilsTest.java
index 93076cc1d6df8609886395d467f0443ea0f575a3..c4b2accece738fa194b1889acf4297101d8aecf6 100644
--- a/java-diff-utils/src/test/java/com/github/difflib/text/StringUtilsTest.java
+++ b/java-diff-utils/src/test/java/com/github/difflib/text/StringUtilsTest.java
@@ -15,8 +15,9 @@
  */
 package com.github.difflib.text;
 
-import static org.junit.Assert.*;
-import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.junit.jupiter.api.Test;
 
 /**
  *
@@ -50,9 +51,10 @@ public class StringUtilsTest {
         assertEquals("test", StringUtils.wrapText("test", 10));
     }
 
-    @Test(expected = IllegalArgumentException.class)
+    @Test
     public void testWrapText_String_int_zero() {
-        assertEquals("test", StringUtils.wrapText("test", -1));
+        Assertions.assertThrows(IllegalArgumentException.class, 
+                () -> StringUtils.wrapText("test", -1));
     }
 
 }
diff --git a/java-diff-utils/src/test/java/com/github/difflib/unifieddiff/UnifiedDiffReaderTest.java b/java-diff-utils/src/test/java/com/github/difflib/unifieddiff/UnifiedDiffReaderTest.java
index 1414562b02f146c46ed397cde5525a32ab9fb1f7..a7c67533d3b818d34868a1c7221db50ee2267f11 100644
--- a/java-diff-utils/src/test/java/com/github/difflib/unifieddiff/UnifiedDiffReaderTest.java
+++ b/java-diff-utils/src/test/java/com/github/difflib/unifieddiff/UnifiedDiffReaderTest.java
@@ -19,10 +19,10 @@ import com.github.difflib.patch.AbstractDelta;
 import java.io.IOException;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-import static org.assertj.core.api.Java6Assertions.assertThat;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import org.junit.Test;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import org.junit.jupiter.api.Test;
 
 /**
  *
diff --git a/java-diff-utils/src/test/java/com/github/difflib/unifieddiff/UnifiedDiffRoundTripTest.java b/java-diff-utils/src/test/java/com/github/difflib/unifieddiff/UnifiedDiffRoundTripTest.java
index c8fc82fc632f486b2e7e59144cc369bd3aac23b5..acc84e9aa6b196df31afc8f02bc7c5e230d990f0 100644
--- a/java-diff-utils/src/test/java/com/github/difflib/unifieddiff/UnifiedDiffRoundTripTest.java
+++ b/java-diff-utils/src/test/java/com/github/difflib/unifieddiff/UnifiedDiffRoundTripTest.java
@@ -2,7 +2,6 @@ package com.github.difflib.unifieddiff;
 
 import com.github.difflib.DiffUtils;
 import com.github.difflib.TestConstants;
-import com.github.difflib.algorithm.DiffException;
 import com.github.difflib.patch.Patch;
 import com.github.difflib.patch.PatchFailedException;
 import java.io.BufferedReader;
@@ -15,10 +14,10 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import static java.util.stream.Collectors.joining;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-import org.junit.Ignore;
-import org.junit.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
 
 public class UnifiedDiffRoundTripTest {
 
@@ -34,7 +33,7 @@ public class UnifiedDiffRoundTripTest {
     }
 
     @Test
-    public void testGenerateUnified() throws DiffException, IOException {
+    public void testGenerateUnified() throws IOException {
         List<String> origLines = fileToLines(TestConstants.MOCK_FOLDER + "original.txt");
         List<String> revLines = fileToLines(TestConstants.MOCK_FOLDER + "revised.txt");
 
@@ -42,7 +41,7 @@ public class UnifiedDiffRoundTripTest {
     }
 
     @Test
-    public void testGenerateUnifiedWithOneDelta() throws DiffException, IOException {
+    public void testGenerateUnifiedWithOneDelta() throws IOException {
         List<String> origLines = fileToLines(TestConstants.MOCK_FOLDER + "one_delta_test_original.txt");
         List<String> revLines = fileToLines(TestConstants.MOCK_FOLDER + "one_delta_test_revised.txt");
 
@@ -50,7 +49,7 @@ public class UnifiedDiffRoundTripTest {
     }
 
     @Test
-    public void testGenerateUnifiedDiffWithoutAnyDeltas() throws DiffException, IOException {
+    public void testGenerateUnifiedDiffWithoutAnyDeltas() throws IOException {
         List<String> test = Arrays.asList("abc");
         Patch<String> patch = DiffUtils.diff(test, test);
         StringWriter writer = new StringWriter();
@@ -84,15 +83,15 @@ public class UnifiedDiffRoundTripTest {
      * Issue 12
      */
     @Test
-    @Ignore
-    public void testPatchWithNoDeltas() throws DiffException, IOException {
+    @Disabled
+    public void testPatchWithNoDeltas() throws IOException {
         final List<String> lines1 = fileToLines(TestConstants.MOCK_FOLDER + "issue11_1.txt");
         final List<String> lines2 = fileToLines(TestConstants.MOCK_FOLDER + "issue11_2.txt");
         verify(lines1, lines2, "issue11_1.txt", "issue11_2.txt");
     }
 
     @Test
-    public void testDiff5() throws DiffException, IOException {
+    public void testDiff5() throws IOException {
         final List<String> lines1 = fileToLines(TestConstants.MOCK_FOLDER + "5A.txt");
         final List<String> lines2 = fileToLines(TestConstants.MOCK_FOLDER + "5B.txt");
         verify(lines1, lines2, "5A.txt", "5B.txt");
@@ -102,7 +101,7 @@ public class UnifiedDiffRoundTripTest {
      * Issue 19
      */
     @Test
-    public void testDiffWithHeaderLineInText() throws DiffException, IOException {
+    public void testDiffWithHeaderLineInText() throws IOException {
         List<String> original = new ArrayList<>();
         List<String> revised = new ArrayList<>();
 
@@ -130,7 +129,7 @@ public class UnifiedDiffRoundTripTest {
     }
 
     private void verify(List<String> origLines, List<String> revLines,
-            String originalFile, String revisedFile) throws DiffException, IOException {
+            String originalFile, String revisedFile) throws IOException {
         Patch<String> patch = DiffUtils.diff(origLines, revLines);
 
         StringWriter writer = new StringWriter();
diff --git a/java-diff-utils/src/test/java/com/github/difflib/unifieddiff/UnifiedDiffWriterTest.java b/java-diff-utils/src/test/java/com/github/difflib/unifieddiff/UnifiedDiffWriterTest.java
index 1972ab3978d85a8e0ed341b11e5e1637d1afce8d..a89d02758a0e9666a0ef2099b93b5e5405760aec 100644
--- a/java-diff-utils/src/test/java/com/github/difflib/unifieddiff/UnifiedDiffWriterTest.java
+++ b/java-diff-utils/src/test/java/com/github/difflib/unifieddiff/UnifiedDiffWriterTest.java
@@ -15,6 +15,8 @@
  */
 package com.github.difflib.unifieddiff;
 
+import com.github.difflib.DiffUtils;
+import com.github.difflib.patch.Patch;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.StringWriter;
@@ -23,7 +25,11 @@ import java.net.URISyntaxException;
 import java.nio.charset.Charset;
 import java.nio.file.Files;
 import java.nio.file.Paths;
-import org.junit.Test;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.junit.jupiter.api.Test;
 
 /**
  *
@@ -40,8 +46,35 @@ public class UnifiedDiffWriterTest {
         UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(new ByteArrayInputStream(str.getBytes()));
 
         StringWriter writer = new StringWriter();
-//        UnifiedDiffWriter.write(diff, writer);
-//        System.out.println(writer.toString());
+        UnifiedDiffWriter.write(diff, f -> Collections.EMPTY_LIST, writer, 5);
+        System.out.println(writer.toString());
+    }
+    
+    /**
+     * Issue 47
+     */
+    @Test
+    public void testWriteWithNewFile() throws URISyntaxException, IOException {
+        
+        List<String> original = new ArrayList<>();
+        List<String> revised = new ArrayList<>();
+
+        revised.add("line1");
+        revised.add("line2");
+
+        Patch<String> patch = DiffUtils.diff(original, revised);
+        UnifiedDiff diff = new UnifiedDiff();
+        diff.addFile( UnifiedDiffFile.from(null, "revised", patch) );
+
+        StringWriter writer = new StringWriter();
+        UnifiedDiffWriter.write(diff, f -> original, writer, 5);
+        System.out.println(writer.toString());
+        
+        String[] lines = writer.toString().split("\\n");
+        
+        assertEquals("--- null", lines[0]);
+        assertEquals("+++ revised", lines[1]);
+        assertEquals("@@ -0,0 +1,2 @@", lines[2]);
     }
 
     static String readFile(URI path, Charset encoding)
diff --git a/pom.xml b/pom.xml
index 0c94d0e9251e7f49d23d1167a9014f23dfe9139c..b6b3d5f5f890f1753630bad05f90702f9aa1a88f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>io.github.java-diff-utils</groupId>
     <artifactId>java-diff-utils-parent</artifactId>
-    <version>4.5</version>
+    <version>4.7</version>
     <name>java-diff-utils-parent</name>
     <packaging>pom</packaging>
     <modules>
@@ -29,7 +29,7 @@
         <connection>scm:git:https://github.com/java-diff-utils/java-diff-utils.git</connection>
         <developerConnection>scm:git:ssh://git@github.com:java-diff-utils/java-diff-utils.git</developerConnection>
         <url>https://github.com/java-diff-utils/java-diff-utils.git</url>
-        <tag>java-diff-utils-parent-4.5</tag>
+        <tag>java-diff-utils-parent-4.7</tag>
     </scm>
     <issueManagement>
         <system>GitHub Issues</system>
@@ -60,6 +60,22 @@
         <maven.compiler.source>1.8</maven.compiler.source>
         <maven.compiler.target>1.8</maven.compiler.target>
     </properties>
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.junit.jupiter</groupId>
+                <artifactId>junit-jupiter</artifactId>
+                <version>5.6.2</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.assertj</groupId>
+                <artifactId>assertj-core</artifactId>
+                <version>3.15.0</version>
+                <scope>test</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
     <build>
         <plugins>
             <plugin>
@@ -89,9 +105,10 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-javadoc-plugin</artifactId>
-                <version>2.10.4</version>
+                <version>3.1.1</version>
                 <configuration>
                     <additionalparam>${javadoc.opts}</additionalparam>
+                    <doclint>none</doclint>
                 </configuration>
                 <executions>
                     <execution>
@@ -105,7 +122,7 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-checkstyle-plugin</artifactId>
-                <version>2.17</version>
+                <version>3.1.0</version>
                 <executions>
                     <execution>
                         <id>verify-style</id>
@@ -118,12 +135,13 @@
                 <configuration>
                     <logViolationsToConsole>true</logViolationsToConsole>
                     <includeTestSourceDirectory>true</includeTestSourceDirectory>
-                    <sourceDirectory>${project.build.sourceDirectory}</sourceDirectory>
+                    <sourceDirectories>${project.build.sourceDirectory}</sourceDirectories>
                     <checkstyleRules>
                         <module name="Checker">
                             <module name="SuppressWarningsFilter" />
                             <module name="FileTabCharacter" />
                             <module name="TreeWalker">
+                                <module name="SuppressionCommentFilter" />
                                 <module name="AvoidNestedBlocks" />
                                 <module name="ConstantName" />
                                 <module name="EmptyCatchBlock" />
@@ -151,14 +169,14 @@
                     <dependency>
                         <groupId>com.puppycrawl.tools</groupId>
                         <artifactId>checkstyle</artifactId>
-                        <version>8.18</version>
+                        <version>8.29</version>
                     </dependency>
                 </dependencies>
             </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-surefire-plugin</artifactId>
-                <version>2.22.1</version>
+                <version>3.0.0-M4</version>
                 <configuration>
                     <excludes>
                         <exclude>**/LR*.java</exclude>
@@ -224,4 +242,4 @@
             </build>
         </profile>
     </profiles>
-</project>
\ No newline at end of file
+</project>