diff --git a/requirements.txt b/requirements.txt index ad5b2027..ffa8388a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -18,6 +18,7 @@ pygments>=1.6 django-sites==0.4 Markdown==2.4 fn==0.2.13 +diff-match-patch==20110725.1 # Comment it if you are using python >= 3.4 enum34==0.9.23 diff --git a/taiga/mdrender/service.py b/taiga/mdrender/service.py index 460a601c..fb6c9ba9 100644 --- a/taiga/mdrender/service.py +++ b/taiga/mdrender/service.py @@ -32,6 +32,9 @@ def _make_extensions_list(wikilinks_config=None): "codehilite"] +import diff_match_patch + + def cache_by_sha(func): @functools.wraps(func) def _decorator(project, text): @@ -71,5 +74,23 @@ def render(project, text): renderer = F() >> F(_preprocessors, project) >> F(_render_markdown, project) >> F(_postprocessors, project) return renderer(text) +class DiffMatchPatch(diff_match_patch.diff_match_patch): + def diff_pretty_html(self, diffs): + html = [] + for (op, data) in diffs: + text = (data.replace("&", "&").replace("<", "<") + .replace(">", ">").replace("\n", "
")) + if op == self.DIFF_INSERT: + html.append("%s" % text) + elif op == self.DIFF_DELETE: + html.append("%s" % text) + elif op == self.DIFF_EQUAL: + html.append("%s" % text) + return "".join(html) -__all__ = ['render'] +def get_diff_of_htmls(html1, html2): + diffutil = DiffMatchPatch() + diff = diffutil.diff_main(html1, html2) + return diffutil.diff_pretty_html(diff) + +__all__ = ['render', 'get_diff_of_htmls'] diff --git a/taiga/projects/history/services.py b/taiga/projects/history/services.py index c4d677a2..d1756e53 100644 --- a/taiga/projects/history/services.py +++ b/taiga/projects/history/services.py @@ -39,6 +39,7 @@ from django.contrib.contenttypes.models import ContentType from .models import HistoryType from taiga.mdrender.service import render as mdrender +from taiga.mdrender.service import get_diff_of_htmls # Type that represents a freezed object FrozenObj = namedtuple("FrozenObj", ["key", "snapshot"]) @@ -155,6 +156,13 @@ def make_diff(oldobj:FrozenObj, newobj:FrozenObj) -> FrozenDiff: if key not in first: diff[key] = (not_found_value, second[key]) + if "description" in diff: + description_diff = get_diff_of_htmls( + diff["description"][0], + diff["description"][1] + ) + diff["description_diff"] = (not_found_value, description_diff) + return FrozenDiff(newobj.key, diff, newobj.snapshot)