4747 * </code>
4848 */
4949public class DiffRowGenerator {
50+
5051 public static final Pattern SPLIT_BY_WORD_PATTERN = Pattern .compile ("\\ s+|[,.\\ [\\ ](){}/\\ \\ *+\\ -#]" );
51-
52+
5253 public static final BiPredicate <String , String > IGNORE_WHITESPACE_EQUALIZER = (original , revised )
5354 -> original .trim ().replaceAll ("\\ s+" , " " ).equals (revised .trim ().replaceAll ("\\ s+" , " " ));
54-
55+
5556 public static final BiPredicate <String , String > DEFAULT_EQUALIZER = Object ::equals ;
56-
57+
5758 /**
5859 * Splitting lines by word to achieve word by word diff checking.
5960 */
@@ -69,7 +70,7 @@ public class DiffRowGenerator {
6970 }
7071 return list ;
7172 };
72-
73+
7374 private final boolean showInlineDiffs ;
7475 private final boolean ignoreWhiteSpaces ;
7576 private final Function <Boolean , String > oldTag ;
@@ -195,11 +196,10 @@ public Builder mergeOriginalRevised(boolean mergeOriginalRevised) {
195196 * deliver no in word changes.
196197 */
197198 public Builder inlineDiffByWord (boolean inlineDiffByWord ) {
198- inlineDiffSplitter = inlineDiffByWord ? SPLITTER_BY_WORD : SPLITTER_BY_CHARACTER ;
199+ inlineDiffSplitter = inlineDiffByWord ? SPLITTER_BY_WORD : SPLITTER_BY_CHARACTER ;
199200 return this ;
200201 }
201-
202-
202+
203203 public Builder inlineDiffBySplitter (Function <String , List <String >> inlineDiffSplitter ) {
204204 this .inlineDiffSplitter = inlineDiffSplitter ;
205205 return this ;
@@ -220,7 +220,7 @@ private DiffRowGenerator(Builder builder) {
220220 inlineDiffSplitter = builder .inlineDiffSplitter ;
221221 equalizer = ignoreWhiteSpaces ? IGNORE_WHITESPACE_EQUALIZER : DEFAULT_EQUALIZER ;
222222 reportLinesUnchanged = builder .reportLinesUnchanged ;
223-
223+
224224 Objects .requireNonNull (inlineDiffSplitter );
225225 }
226226
@@ -356,32 +356,32 @@ private List<DiffRow> generateInlineDiffs(AbstractDelta<String> delta) throws Di
356356 if (inlineDelta instanceof DeleteDelta ) {
357357 wrapInTag (origList , inlineOrig .getPosition (), inlineOrig
358358 .getPosition ()
359- + inlineOrig .size () + 1 , oldTag );
359+ + inlineOrig .size (), oldTag );
360360 } else if (inlineDelta instanceof InsertDelta ) {
361361 if (mergeOriginalRevised ) {
362362 origList .addAll (inlineOrig .getPosition (),
363363 revList .subList (inlineRev .getPosition (), inlineRev .getPosition ()
364364 + inlineRev .size ()));
365365 wrapInTag (origList , inlineOrig .getPosition (), inlineOrig .getPosition ()
366- + inlineRev .size () + 1 , newTag );
366+ + inlineRev .size (), newTag );
367367 } else {
368368 wrapInTag (revList , inlineRev .getPosition (), inlineRev .getPosition ()
369- + inlineRev .size () + 1 , newTag );
369+ + inlineRev .size (), newTag );
370370 }
371371 } else if (inlineDelta instanceof ChangeDelta ) {
372372 if (mergeOriginalRevised ) {
373373 origList .addAll (inlineOrig .getPosition () + inlineOrig .size (),
374374 revList .subList (inlineRev .getPosition (), inlineRev .getPosition ()
375375 + inlineRev .size ()));
376376 wrapInTag (origList , inlineOrig .getPosition () + inlineOrig .size (), inlineOrig .getPosition () + inlineOrig .size ()
377- + inlineRev .size () + 1 , newTag );
377+ + inlineRev .size (), newTag );
378378 } else {
379379 wrapInTag (revList , inlineRev .getPosition (), inlineRev .getPosition ()
380- + inlineRev .size () + 1 , newTag );
380+ + inlineRev .size (), newTag );
381381 }
382382 wrapInTag (origList , inlineOrig .getPosition (), inlineOrig
383383 .getPosition ()
384- + inlineOrig .size () + 1 , oldTag );
384+ + inlineOrig .size (), oldTag );
385385 }
386386 }
387387 StringBuilder origResult = new StringBuilder ();
@@ -413,10 +413,41 @@ private List<DiffRow> generateInlineDiffs(AbstractDelta<String> delta) throws Di
413413 * @param tag the tag name without angle brackets, just a word
414414 * @param cssClass the optional css class
415415 */
416- private static void wrapInTag (List <String > sequence , int startPosition ,
417- int endPosition , Function <Boolean , String > generator ) {
418- sequence .add (startPosition , generator .apply (true ));
419- sequence .add (endPosition , generator .apply (false ));
416+ static void wrapInTag (List <String > sequence , int startPosition ,
417+ int endPosition , Function <Boolean , String > tagGenerator ) {
418+ int endPos = endPosition ;
419+
420+ while (endPos >= startPosition ) {
421+
422+ //search position for end tag
423+ while (endPos > startPosition ) {
424+ if (!"\n " .equals (sequence .get (endPos - 1 ))) {
425+ break ;
426+ }
427+ endPos --;
428+ }
429+
430+ if (endPos == startPosition ) {
431+ break ;
432+ }
433+
434+ sequence .add (endPos , tagGenerator .apply (false ));
435+ endPos --;
436+
437+ //search position for end tag
438+ while (endPos > startPosition ) {
439+ if ("\n " .equals (sequence .get (endPos - 1 ))) {
440+ break ;
441+ }
442+ endPos --;
443+ }
444+
445+ sequence .add (endPos , tagGenerator .apply (true ));
446+ endPos --;
447+ }
448+
449+ // sequence.add(endPosition, tagGenerator.apply(false));
450+ // sequence.add(startPosition, tagGenerator.apply(true));
420451 }
421452
422453 protected final static List <String > splitStringPreserveDelimiter (String str , Pattern SPLIT_PATTERN ) {
0 commit comments