Сравнение файлов с подсветкой изменений
Для CVS необходимо показывать в документе разницу между двумя файлами. Файлы представляют собой html документы. Пользователю нужно показывать изменения в тексте, а не в коде.
Наиболее подходящий вариант это
Diff.php
< ?php /** * File: Diff.php * Description: Compare string or files class */ class Cvs_Diff { protected $python_path ='/usr/local/bin/python'; protected $diff_path ='/usr/local/www/data/dev/library/Cvs/diff.py'; function __construct() { if(!file_exists($this->python_path)) throw new Zend_Exception('python not found:'.$this->python_path); if(!file_exists($this->diff_path)) throw new Zend_Exception('diff python not found:'.$this->diff_path); } /** * Show difference between two files with HTML highlight * * @param string $file_a first file for compare * @param string $file_b second file for compare * @return string HTML out put */ public function files($file_a, $file_b) { if(!file_exists($file_a)) throw new Zend_Exception('file A not found :'.$file_a); if(!file_exists($file_b)) throw new Zend_Exception('file B not found :'.$file_b); $output = shell_exec("$this->python_path $this->diff_path $file_a $file_b"); $output .= '<style type="text/css"><!-- ins {background: #bfb} del{background: #fcc} ins,del {text-decoration: none} --></style>'; return $output; } /** * Show difference between two strings with HTML highlight * * @param string $str_a * @param string $str_b * @return string HTML out put */ public function string($str_a, $str_b) { $tmpfname_a = tempnam("/tmp", "diff_"); $tmpfname_b = tempnam("/tmp", "diff_"); if(!file_put_contents($tmpfname_a,$str_a)) throw new Zend_Exception('can\'t create temporary file :'.$tmpfname_a); if(!file_put_contents($tmpfname_b,$str_b)) throw new Zend_Exception('can\'t create temporary file :'.$tmpfname_b); $output = shell_exec("$this->python_path $this->diff_path $tmpfname_a $tmpfname_b"); unlink($tmpfname_a); unlink($tmpfname_b); $output .= '<style type="text/css"><!-- ins {background: #bfb} del{background: #fcc} ins,del {text-decoration: none} --></style>'; return $output; } }
diff.py
#!/usr/bin/python """HTML Diff: http://www.aaronsw.com/2002/diff Rough code, badly documented. Send me comments and patches.""" __author__ = 'Aaron Swartz <me @aaronsw.com>' __copyright__ = '(C) 2003 Aaron Swartz. GNU GPL 2.' __version__ = '0.22' import difflib, string def isTag(x): return x[0] == "< " and x[-1] == ">" def textDiff(a, b): """Takes in strings a and b and returns a human-readable HTML diff.""" out = [] a, b = html2list(a), html2list(b) s = difflib.SequenceMatcher(None, a, b) for e in s.get_opcodes(): if e[0] == "replace": # @@ need to do something more complicated here # call textDiff but not for html, but for some html... ugh # gonna cop-out for now out.append('<del class="diff modified">'+''.join(a[e[1]:e[2]]) + '</del><ins class="diff modified">'+''.join(b[e[3]:e[4]])+"</ins>") elif e[0] == "delete": out.append('<del class="diff">'+ ''.join(a[e[1]:e[2]]) + "</del>") elif e[0] == "insert": out.append('<ins class="diff">'+''.join(b[e[3]:e[4]]) + "</ins>") elif e[0] == "equal": out.append(''.join(b[e[3]:e[4]])) else: raise "Um, something's broken. I didn't expect a '" + `e[0]` + "'." return ''.join(out) def html2list(x, b=0): mode = 'char' cur = '' out = [] for c in x: if mode == 'tag': if c == '>': if b: cur += ']' else: cur += c out.append(cur); cur = ''; mode = 'char' else: cur += c elif mode == 'char': if c == '< ': out.append(cur) if b: cur = '[' else: cur = c mode = 'tag' elif c in string.whitespace: out.append(cur+c); cur = '' else: cur += c out.append(cur) return filter(lambda x: x is not '', out) if __name__ == '__main__': import sys try: a, b = sys.argv[1:3] except ValueError: print "htmldiff: highlight the differences between two html files" print "usage: " + sys.argv[0] + " a b" sys.exit(1) print textDiff(open(a).read(), open(b).read())