# -*- coding: utf-8 -*- """ sphinx.websupport.storage.differ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A differ for creating an HTML representations of proposal diffs :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ import re from difflib import Differ from sphinx.util.pycompat import htmlescape class CombinedHtmlDiff(object): """Create an HTML representation of the differences between two pieces of text. """ highlight_regex = re.compile(r'([\+\-\^]+)') def __init__(self, source, proposal): proposal = htmlescape(proposal) differ = Differ() self.diff = list(differ.compare(source.splitlines(1), proposal.splitlines(1))) def make_text(self): return '\n'.join(self.diff) def make_html(self): """Return the HTML representation of the differences between `source` and `proposal`. :param source: the original text :param proposal: the proposed text """ html = [] diff = self.diff[:] line = diff.pop(0) next = diff.pop(0) while True: html.append(self._handle_line(line, next)) line = next try: next = diff.pop(0) except IndexError: html.append(self._handle_line(line)) break return ''.join(html).rstrip() def _handle_line(self, line, next=None): """Handle an individual line in a diff.""" prefix = line[0] text = line[2:] if prefix == ' ': return text elif prefix == '?': return '' if next is not None and next[0] == '?': tag = prefix == '+' and 'ins' or 'del' text = self._highlight_text(text, next, tag) css_class = prefix == '+' and 'prop-added' or 'prop-removed' return '%s\n' % (css_class, text.rstrip()) def _highlight_text(self, text, next, tag): """Highlight the specific changes made to a line by adding and tags. """ next = next[2:] new_text = [] start = 0 for match in self.highlight_regex.finditer(next): new_text.append(text[start:match.start()]) new_text.append('<%s>' % tag) new_text.append(text[match.start():match.end()]) new_text.append('' % tag) start = match.end() new_text.append(text[start:]) return ''.join(new_text)