@@ -193,13 +193,15 @@ protected function renderTableBlockReplace(array $block): string
193193 // if the line counts changes, we treat the old and the new as
194194 // "a line with \n in it" and then do one-line-to-one-line diff
195195 if ($ oldLinesCount !== $ newLinesCount ) {
196- [$ oldLines , $ newLines ] = $ this ->diffReplaceBlock ($ oldLines , $ newLines );
196+ [$ oldLines , $ newLines ] = $ this ->markReplaceBlockDiff ($ oldLines , $ newLines );
197197 $ oldLinesCount = $ newLinesCount = 1 ;
198198 }
199199
200200 // 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+ }
203205
204206 // now $oldLines must has the same line counts with $newlines
205207 for ($ no = 0 ; $ no < $ newLinesCount ; ++$ no ) {
@@ -215,10 +217,11 @@ protected function renderTableBlockReplace(array $block): string
215217 }
216218
217219 /**
218- * Merge two "replace" lines into one line.
220+ * Merge two "replace"-type lines into a single line.
219221 *
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.
222225 *
223226 * @param string $oldLine the old line
224227 * @param string $newLine the new line
@@ -242,8 +245,8 @@ protected function mergeReplaceLines(string $oldLine, string $newLine): string
242245 // create a sorted merged parts array
243246 $ mergedParts = \array_merge ($ delParts , $ insParts );
244247 \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 ' ]
247250 ?: ($ a ['type ' ] === SequenceMatcher::OP_DEL ? -1 : 1 );
248251 });
249252
@@ -269,7 +272,7 @@ protected function mergeReplaceLines(string $oldLine, string $newLine): string
269272 $ part ['offset ' ],
270273 $ part ['length ' ]
271274 ),
272- $ part ['offsetBiased ' ],
275+ $ part ['offsetClean ' ],
273276 0 // insertion
274277 );
275278 }
@@ -282,18 +285,13 @@ protected function mergeReplaceLines(string $oldLine, string $newLine): string
282285 *
283286 * Such as
284287 * 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"
288289 *
289290 * @param string $ld the left delimiter
290291 * @param string $rd the right delimiter
291292 * @param string $line the line
292293 * @param int $type the line type
293294 *
294- * @see https://stackoverflow.com/a/27078384/12866913 (this method)
295- * @see https://stackoverflow.com/a/27071699/4643765 (preg_match_all)
296- *
297295 * @return array[] the closure informations
298296 */
299297 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
303301
304302 $ parts = [];
305303 $ partStart = $ partEnd = 0 ;
306- $ offsetBias = 0 ;
304+ $ partLengthSum = 0 ;
307305
306+ // find the next left delimiter
308307 while (false !== ($ partStart = \strpos ($ line , $ ld , $ partEnd ))) {
308+ // find the corresponding right delimiter
309309 if (false === ($ partEnd = \strpos ($ line , $ rd , $ partStart + $ ldLength ))) {
310310 break ;
311311 }
@@ -315,13 +315,14 @@ protected function analyzeClosureParts(string $ld, string $rd, string $line, int
315315
316316 $ parts [] = [
317317 'type ' => $ type ,
318+ // the offset in the line
318319 'offset ' => $ partStart ,
319320 'length ' => $ partLength ,
320321 // the offset in the cleaned line (i.e., the line with closure parts removed)
321- 'offsetBiased ' => $ partStart - $ offsetBias ,
322+ 'offsetClean ' => $ partStart - $ partLengthSum ,
322323 ];
323324
324- $ offsetBias += $ partLength ;
325+ $ partLengthSum += $ partLength ;
325326 }
326327
327328 return $ parts ;
@@ -337,7 +338,7 @@ protected function analyzeClosureParts(string $ld, string $rd, string $line, int
337338 *
338339 * @return string[][] the value of [[$oldLine], [$newLine]]
339340 */
340- protected function diffReplaceBlock (array $ oldBlock , array $ newBlock ): array
341+ protected function markReplaceBlockDiff (array $ oldBlock , array $ newBlock ): array
341342 {
342343 static $ isInitiated = false , $ mbOld , $ mbNew , $ lineRenderer ;
343344
0 commit comments