Back to index

moin  1.9.0~rc2
diff_html.py
Go to the documentation of this file.
00001 # -*- coding: iso-8859-1 -*-
00002 """
00003     MoinMoin - Side by side diffs
00004 
00005     @copyright: 2002 Juergen Hermann <jh@web.de>,
00006                 2002 Scott Moonen <smoonen@andstuff.org>
00007     @license: GNU GPL, see COPYING for details.
00008 """
00009 
00010 from MoinMoin.support import difflib
00011 from MoinMoin.wikiutil import escape
00012 
00013 def indent(line):
00014     eol = ''
00015     while line and line[0] == '\n':
00016         eol += '\n'
00017         line = line[1:]
00018     stripped = line.lstrip()
00019     if len(line) - len(stripped):
00020         line = "&nbsp;" * (len(line) - len(stripped)) + stripped
00021     #return "%d / %d / %s" % (len(line), len(stripped), line)
00022     return eol + line
00023 
00024 
00025 # This code originally by Scott Moonen, used with permission.
00026 def diff(request, old, new):
00027     """ Find changes between old and new and return
00028         HTML markup visualising them.
00029     """
00030     _ = request.getText
00031     t_line = _("Line") + " %d"
00032 
00033     seq1 = old.splitlines()
00034     seq2 = new.splitlines()
00035 
00036     seqobj = difflib.SequenceMatcher(None, seq1, seq2)
00037     linematch = seqobj.get_matching_blocks()
00038 
00039     if len(seq1) == len(seq2) and linematch[0] == (0, 0, len(seq1)):
00040         # No differences.
00041         return " - " + _("No differences found!")
00042 
00043     lastmatch = (0, 0)
00044 
00045     result = """
00046 <table class="diff">
00047 <tr>
00048 <td class="diff-removed">
00049 <span>
00050 %s
00051 </span>
00052 </td>
00053 <td class="diff-added">
00054 <span>
00055 %s
00056 </span>
00057 </td>
00058 </tr>
00059 """ % (_('Deletions are marked like this.'), _('Additions are marked like this.'), )
00060 
00061     # Print all differences
00062     for match in linematch:
00063         # Starts of pages identical?
00064         if lastmatch == match[0:2]:
00065             lastmatch = (match[0] + match[2], match[1] + match[2])
00066             continue
00067         llineno, rlineno = lastmatch[0]+1, lastmatch[1]+1
00068         result += """
00069 <tr class="diff-title">
00070 <td>
00071 %s:
00072 </td>
00073 <td>
00074 %s:
00075 </td>
00076 </tr>
00077 """ % (request.formatter.line_anchorlink(1, llineno) + request.formatter.text(t_line % llineno) + request.formatter.line_anchorlink(0),
00078        request.formatter.line_anchorlink(1, rlineno) + request.formatter.text(t_line % rlineno) + request.formatter.line_anchorlink(0))
00079 
00080         leftpane = ''
00081         rightpane = ''
00082         linecount = max(match[0] - lastmatch[0], match[1] - lastmatch[1])
00083         for line in range(linecount):
00084             if line < match[0] - lastmatch[0]:
00085                 if line > 0:
00086                     leftpane += '\n'
00087                 leftpane += seq1[lastmatch[0] + line]
00088             if line < match[1] - lastmatch[1]:
00089                 if line > 0:
00090                     rightpane += '\n'
00091                 rightpane += seq2[lastmatch[1] + line]
00092 
00093         charobj = difflib.SequenceMatcher(None, leftpane, rightpane)
00094         charmatch = charobj.get_matching_blocks()
00095 
00096         if charobj.ratio() < 0.5:
00097             # Insufficient similarity.
00098             if leftpane:
00099                 leftresult = """<span>%s</span>""" % indent(escape(leftpane))
00100             else:
00101                 leftresult = ''
00102 
00103             if rightpane:
00104                 rightresult = """<span>%s</span>""" % indent(escape(rightpane))
00105             else:
00106                 rightresult = ''
00107         else:
00108             # Some similarities; markup changes.
00109             charlast = (0, 0)
00110 
00111             leftresult = ''
00112             rightresult = ''
00113             for thismatch in charmatch:
00114                 if thismatch[0] - charlast[0] != 0:
00115                     leftresult += """<span>%s</span>""" % indent(
00116                         escape(leftpane[charlast[0]:thismatch[0]]))
00117                 if thismatch[1] - charlast[1] != 0:
00118                     rightresult += """<span>%s</span>""" % indent(
00119                         escape(rightpane[charlast[1]:thismatch[1]]))
00120                 leftresult += escape(leftpane[thismatch[0]:thismatch[0] + thismatch[2]])
00121                 rightresult += escape(rightpane[thismatch[1]:thismatch[1] + thismatch[2]])
00122                 charlast = (thismatch[0] + thismatch[2], thismatch[1] + thismatch[2])
00123 
00124         leftpane = '<br>\n'.join([indent(x) for x in leftresult.splitlines()])
00125         rightpane = '<br>\n'.join([indent(x) for x in rightresult.splitlines()])
00126 
00127         # removed width="50%%"
00128         result += """
00129 <tr>
00130 <td class="diff-removed">
00131 %s
00132 </td>
00133 <td class="diff-added">
00134 %s
00135 </td>
00136 </tr>
00137 """ % (leftpane, rightpane)
00138 
00139         lastmatch = (match[0] + match[2], match[1] + match[2])
00140 
00141     result += '</table>\n'
00142     return result
00143