PHP 中的文本版本控制,具有差异突出显示

发布于 2024-10-24 04:39:04 字数 285 浏览 1 评论 0原文

如果您曾经在 StackOverflow 上编辑过问题,您可能已经注意到它会跟踪问题所应用的确切更改。它以一种形式显示,突出显示文本中已删除的红色部分和自特定编辑以来添加的绿色部分。我的问题是如何自己实现这样一个系统。我正在尝试使用 PHP 和 MySQL 创建一个自定义 CMS,这似乎是一个非常酷的功能。

有什么建议,或者也许有开源库已经可以做到这一点,我可以分析他们是如何做到这一点的?

演示

这里我添加了一些文本,如果您单击编辑链接查看更改,这些文本将显示为绿色。

If you ever edited a question right here on StackOverflow, you have probably noticed that it keeps track of what exact changed were applied to a question. It is displayed in a form by highlighting red portion of a text which were removed and green which were added since at a particular edit. My question is how to implement such a system myself. I am trying to make a custom CMS in PHP with MySQL and this seems like a very cool feature to tackle.

Any advice or maybe there are open source libraries which can do this already and I can just analyze how they do it?

Demonstration

Here I added some text which will show green if you click on the edit link to see the changes.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

誰認得朕 2024-10-31 04:39:04
/*
    Paul's Simple Diff Algorithm v 0.1
    (C) Paul Butler 2007 <http://www.paulbutler.org/>
    May be used and distributed under the zlib/libpng license.

    This code is intended for learning purposes; it was written with short
    code taking priority over performance. It could be used in a practical
    application, but there are a few ways it could be optimized.

    Given two arrays, the function diff will return an array of the changes.
    I won't describe the format of the array, but it will be obvious
    if you use print_r() on the result of a diff on some test data.

    htmlDiff is a wrapper for the diff command, it takes two strings and
    returns the differences in HTML. The tags used are <ins> and <del>,
    which can easily be styled with CSS.
*/

function diff($old, $new){
    $maxlen = 0;
    foreach($old as $oindex => $ovalue){
        $nkeys = array_keys($new, $ovalue);
        foreach($nkeys as $nindex){
            $matrix[$oindex][$nindex] = isset($matrix[$oindex - 1][$nindex - 1]) ?
                $matrix[$oindex - 1][$nindex - 1] + 1 : 1;
            if($matrix[$oindex][$nindex] > $maxlen){
                $maxlen = $matrix[$oindex][$nindex];
                $omax = $oindex + 1 - $maxlen;
                $nmax = $nindex + 1 - $maxlen;
            }
        }
    }
    if($maxlen == 0) return array(array('d'=>$old, 'i'=>$new));
    return array_merge(
        diff(array_slice($old, 0, $omax), array_slice($new, 0, $nmax)),
        array_slice($new, $nmax, $maxlen),
        diff(array_slice($old, $omax + $maxlen), array_slice($new, $nmax + $maxlen)));
}

function htmlDiff($old, $new){
    $ret = '';
    $diff = diff(explode(' ', $old), explode(' ', $new));
    foreach($diff as $k){
        if(is_array($k))
            $ret .= (!empty($k['d'])?'<del>'.implode(' ',$k['d']).'</del> ':'').
                (!empty($k['i'])?'<ins>'.implode(' ',$k['i']).'</ins> ':'');
        else $ret .= $k . ' ';
    }
    return $ret;
}

我很确定我改变了其中的某些内容。除此之外,它应该可以完美地工作。

使用示例:

$a='abc defg h 12345';
$b='acb defg ikl 66 123 456';
echo htmlDiff($a,$b);

结果:

<del>abc</del> <ins>acb</ins> defg <del>h 12345</del> <ins>ikl 66 123 456</ins> 

显然:

<块引用>

abc acb defg h 12345 ikl 66 123 456

/*
    Paul's Simple Diff Algorithm v 0.1
    (C) Paul Butler 2007 <http://www.paulbutler.org/>
    May be used and distributed under the zlib/libpng license.

    This code is intended for learning purposes; it was written with short
    code taking priority over performance. It could be used in a practical
    application, but there are a few ways it could be optimized.

    Given two arrays, the function diff will return an array of the changes.
    I won't describe the format of the array, but it will be obvious
    if you use print_r() on the result of a diff on some test data.

    htmlDiff is a wrapper for the diff command, it takes two strings and
    returns the differences in HTML. The tags used are <ins> and <del>,
    which can easily be styled with CSS.
*/

function diff($old, $new){
    $maxlen = 0;
    foreach($old as $oindex => $ovalue){
        $nkeys = array_keys($new, $ovalue);
        foreach($nkeys as $nindex){
            $matrix[$oindex][$nindex] = isset($matrix[$oindex - 1][$nindex - 1]) ?
                $matrix[$oindex - 1][$nindex - 1] + 1 : 1;
            if($matrix[$oindex][$nindex] > $maxlen){
                $maxlen = $matrix[$oindex][$nindex];
                $omax = $oindex + 1 - $maxlen;
                $nmax = $nindex + 1 - $maxlen;
            }
        }
    }
    if($maxlen == 0) return array(array('d'=>$old, 'i'=>$new));
    return array_merge(
        diff(array_slice($old, 0, $omax), array_slice($new, 0, $nmax)),
        array_slice($new, $nmax, $maxlen),
        diff(array_slice($old, $omax + $maxlen), array_slice($new, $nmax + $maxlen)));
}

function htmlDiff($old, $new){
    $ret = '';
    $diff = diff(explode(' ', $old), explode(' ', $new));
    foreach($diff as $k){
        if(is_array($k))
            $ret .= (!empty($k['d'])?'<del>'.implode(' ',$k['d']).'</del> ':'').
                (!empty($k['i'])?'<ins>'.implode(' ',$k['i']).'</ins> ':'');
        else $ret .= $k . ' ';
    }
    return $ret;
}

I'm pretty sure I changed something in it. Other than that, it should work perfectly.

Example of use:

$a='abc defg h 12345';
$b='acb defg ikl 66 123 456';
echo htmlDiff($a,$b);

And the result:

<del>abc</del> <ins>acb</ins> defg <del>h 12345</del> <ins>ikl 66 123 456</ins> 

And visibly:

abc acb defg h 12345 ikl 66 123 456

心的憧憬 2024-10-31 04:39:04

PEAR Text_Diff 组件可能是这里很有帮助:它允许人们执行和渲染两个文本数据之间的差异。

如果您查看 渲染器示例页面中,内联应该执行您想要的操作:在给定的示例中,它:

  • 通过 包围删除文本,并且
  • 包围添加的文本(

如果您使用一些 CSS 来设置这些文本的样式) ,你应该能够得到你所要求的。

The PEAR Text_Diff component might be helpful, here : it allows one to perform, and render, diffs between two text data.

If you take a look at the Renderer examples page, the Inline one shoud do what you want : in the given example, it :

  • surrounds delete text by <del> and </del>
  • surround added text by <ins> and </ins>

If you use a bit of CSS to style those, you should be able to get what you're asking for.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文