@@ -193,13 +193,15 @@ protected function renderTableBlockReplace(array $block): string
193
193
// if the line counts changes, we treat the old and the new as
194
194
// "a line with \n in it" and then do one-line-to-one-line diff
195
195
if ($ oldLinesCount !== $ newLinesCount ) {
196
- [$ oldLines , $ newLines ] = $ this ->diffReplaceBlock ($ oldLines , $ newLines );
196
+ [$ oldLines , $ newLines ] = $ this ->markReplaceBlockDiff ($ oldLines , $ newLines );
197
197
$ oldLinesCount = $ newLinesCount = 1 ;
198
198
}
199
199
200
200
// fix for "detailLevel" is "none"
201
- $ this ->fixLinesForNoClosure ($ oldLines , RendererConstant::HTML_CLOSURES_DEL );
202
- $ this ->fixLinesForNoClosure ($ newLines , RendererConstant::HTML_CLOSURES_INS );
201
+ if ($ this ->options ['detailLevel ' ] === 'none ' ) {
202
+ $ this ->fixLinesForNoClosure ($ oldLines , RendererConstant::HTML_CLOSURES_DEL );
203
+ $ this ->fixLinesForNoClosure ($ newLines , RendererConstant::HTML_CLOSURES_INS );
204
+ }
203
205
204
206
// now $oldLines must has the same line counts with $newlines
205
207
for ($ no = 0 ; $ no < $ newLinesCount ; ++$ no ) {
@@ -215,10 +217,11 @@ protected function renderTableBlockReplace(array $block): string
215
217
}
216
218
217
219
/**
218
- * Merge two "replace" lines into one line.
220
+ * Merge two "replace"-type lines into a single line.
219
221
*
220
- * - Extract newPart in "SOME CONTENT <ins>newPart</ins> SOME CONTENT"
221
- * - Place "<ins>newPart</ins>" after "<del>oldPart</del>"
222
+ * The implementation concept is that if we remove all closure parts from
223
+ * the old and the new, the rest of them (cleaned line) should be the same.
224
+ * And then, we add back those removed closure parts in a correct order.
222
225
*
223
226
* @param string $oldLine the old line
224
227
* @param string $newLine the new line
@@ -242,8 +245,8 @@ protected function mergeReplaceLines(string $oldLine, string $newLine): string
242
245
// create a sorted merged parts array
243
246
$ mergedParts = \array_merge ($ delParts , $ insParts );
244
247
\usort ($ mergedParts , function (array $ a , array $ b ): int {
245
- // first sort by "offsetBiased " then by "type"
246
- return $ a ['offsetBiased ' ] <=> $ b ['offsetBiased ' ]
248
+ // first sort by "offsetClean " then by "type"
249
+ return $ a ['offsetClean ' ] <=> $ b ['offsetClean ' ]
247
250
?: ($ a ['type ' ] === SequenceMatcher::OP_DEL ? -1 : 1 );
248
251
});
249
252
@@ -269,7 +272,7 @@ protected function mergeReplaceLines(string $oldLine, string $newLine): string
269
272
$ part ['offset ' ],
270
273
$ part ['length ' ]
271
274
),
272
- $ part ['offsetBiased ' ],
275
+ $ part ['offsetClean ' ],
273
276
0 // insertion
274
277
);
275
278
}
@@ -282,18 +285,13 @@ protected function mergeReplaceLines(string $oldLine, string $newLine): string
282
285
*
283
286
* Such as
284
287
* extract informations for "<ins>part 1</ins>" and "<ins>part 2</ins>"
285
- * from "<ins>part 1</ins>SOME OTHER TEXT<ins>part 2</ins>"
286
- *
287
- * Note that preg_match_all() is handy but slow.
288
+ * from "Hello <ins>part 1</ins>SOME OTHER TEXT<ins>part 2</ins> World"
288
289
*
289
290
* @param string $ld the left delimiter
290
291
* @param string $rd the right delimiter
291
292
* @param string $line the line
292
293
* @param int $type the line type
293
294
*
294
- * @see https://stackoverflow.com/a/27078384/12866913 (this method)
295
- * @see https://stackoverflow.com/a/27071699/4643765 (preg_match_all)
296
- *
297
295
* @return array[] the closure informations
298
296
*/
299
297
protected function analyzeClosureParts (string $ ld , string $ rd , string $ line , int $ type ): array
@@ -303,9 +301,11 @@ protected function analyzeClosureParts(string $ld, string $rd, string $line, int
303
301
304
302
$ parts = [];
305
303
$ partStart = $ partEnd = 0 ;
306
- $ offsetBias = 0 ;
304
+ $ partLengthSum = 0 ;
307
305
306
+ // find the next left delimiter
308
307
while (false !== ($ partStart = \strpos ($ line , $ ld , $ partEnd ))) {
308
+ // find the corresponding right delimiter
309
309
if (false === ($ partEnd = \strpos ($ line , $ rd , $ partStart + $ ldLength ))) {
310
310
break ;
311
311
}
@@ -315,13 +315,14 @@ protected function analyzeClosureParts(string $ld, string $rd, string $line, int
315
315
316
316
$ parts [] = [
317
317
'type ' => $ type ,
318
+ // the offset in the line
318
319
'offset ' => $ partStart ,
319
320
'length ' => $ partLength ,
320
321
// the offset in the cleaned line (i.e., the line with closure parts removed)
321
- 'offsetBiased ' => $ partStart - $ offsetBias ,
322
+ 'offsetClean ' => $ partStart - $ partLengthSum ,
322
323
];
323
324
324
- $ offsetBias += $ partLength ;
325
+ $ partLengthSum += $ partLength ;
325
326
}
326
327
327
328
return $ parts ;
@@ -337,7 +338,7 @@ protected function analyzeClosureParts(string $ld, string $rd, string $line, int
337
338
*
338
339
* @return string[][] the value of [[$oldLine], [$newLine]]
339
340
*/
340
- protected function diffReplaceBlock (array $ oldBlock , array $ newBlock ): array
341
+ protected function markReplaceBlockDiff (array $ oldBlock , array $ newBlock ): array
341
342
{
342
343
static $ isInitiated = false , $ mbOld , $ mbNew , $ lineRenderer ;
343
344
0 commit comments