Example #1
0
        public void DiffUnambiguosAddRemoveReplace()
        {
            // NOTE (steveb): test unamibiguous addition, deletion, and replacement

            XDoc a    = XDocFactory.From("<p>the quick brown fox jumped over the lazy dog</p>", MimeType.XML);
            XDoc b    = XDocFactory.From("<p>the slow black fox jumped far over the dog</p>", MimeType.XML);
            var  diff = XDocDiff.Diff(a, b, 10000);

            Match(diff[0], ArrayDiffKind.Same, XmlNodeType.Element, "p");
            Match(diff[1], ArrayDiffKind.Same, XmlNodeType.EndElement, string.Empty);
            Match(diff[2], ArrayDiffKind.Same, XmlNodeType.Text, "the");
            Match(diff[3], ArrayDiffKind.Same, XmlNodeType.Text, " ");
            Match(diff[4], ArrayDiffKind.Removed, XmlNodeType.Text, "quick");
            Match(diff[5], ArrayDiffKind.Added, XmlNodeType.Text, "slow");
            Match(diff[6], ArrayDiffKind.Same, XmlNodeType.Text, " ");
            Match(diff[7], ArrayDiffKind.Removed, XmlNodeType.Text, "brown");
            Match(diff[8], ArrayDiffKind.Added, XmlNodeType.Text, "black");
            Match(diff[9], ArrayDiffKind.Same, XmlNodeType.Text, " ");
            Match(diff[10], ArrayDiffKind.Same, XmlNodeType.Text, "fox");
            Match(diff[11], ArrayDiffKind.Same, XmlNodeType.Text, " ");
            Match(diff[12], ArrayDiffKind.Same, XmlNodeType.Text, "jumped");
            Match(diff[13], ArrayDiffKind.Same, XmlNodeType.Text, " ");
            Match(diff[14], ArrayDiffKind.Added, XmlNodeType.Text, "far");
            Match(diff[15], ArrayDiffKind.Added, XmlNodeType.Text, " ");
            Match(diff[16], ArrayDiffKind.Same, XmlNodeType.Text, "over");
            Match(diff[17], ArrayDiffKind.Same, XmlNodeType.Text, " ");
            Match(diff[18], ArrayDiffKind.Same, XmlNodeType.Text, "the");
            Match(diff[19], ArrayDiffKind.Removed, XmlNodeType.Text, " ");
            Match(diff[20], ArrayDiffKind.Removed, XmlNodeType.Text, "lazy");
            Match(diff[21], ArrayDiffKind.Same, XmlNodeType.Text, " ");
            Match(diff[22], ArrayDiffKind.Same, XmlNodeType.Text, "dog");
            Match(diff[23], ArrayDiffKind.Same, XmlNodeType.None, "p");
        }
Example #2
0
        public void MergeConflicting()
        {
            XDoc org      = XDocFactory.From("<p>the <span>brown</span> box</p>", MimeType.XML);
            XDoc left     = XDocFactory.From("<p>the <em>brown</em> box</p>", MimeType.XML);
            XDoc right    = XDocFactory.From("<p>the <b>brown</b> fox</p>", MimeType.XML);
            var  conflict = false;
            var  result   = XDocDiff.Merge(org, left, right, 10000, ArrayMergeDiffPriority.Left, out conflict);

            Assert.AreEqual("<p>the <em>brown</em> fox</p>", result.ToString());
        }
Example #3
0
        public void DiffNumbersWithComma()
        {
            // NOTE (steveb): test if digits separated by comma are detected as one word

            XDoc a    = XDocFactory.From("<p>1,23</p>", MimeType.XML);
            XDoc b    = XDocFactory.From("<p>4,56</p>", MimeType.XML);
            var  diff = XDocDiff.Diff(a, b, 10000);

            Match(diff[0], ArrayDiffKind.Same, XmlNodeType.Element, "p");
            Match(diff[1], ArrayDiffKind.Same, XmlNodeType.EndElement, string.Empty);
            Match(diff[2], ArrayDiffKind.Removed, XmlNodeType.Text, "1,23");
            Match(diff[3], ArrayDiffKind.Added, XmlNodeType.Text, "4,56");
            Match(diff[4], ArrayDiffKind.Same, XmlNodeType.None, "p");
        }
Example #4
0
        public void DiffBasic()
        {
            // NOTE (steveb): test a simple diff

            XDoc a    = XDocFactory.From("<p>before</p>", MimeType.XML);
            XDoc b    = XDocFactory.From("<p>after</p>", MimeType.XML);
            var  diff = XDocDiff.Diff(a, b, 10000);

            Match(diff[0], ArrayDiffKind.Same, XmlNodeType.Element, "p");
            Match(diff[1], ArrayDiffKind.Same, XmlNodeType.EndElement, string.Empty);
            Match(diff[2], ArrayDiffKind.Removed, XmlNodeType.Text, "before");
            Match(diff[3], ArrayDiffKind.Added, XmlNodeType.Text, "after");
            Match(diff[4], ArrayDiffKind.Same, XmlNodeType.None, "p");
        }
Example #5
0
        public void DiffNumbersWithPeriod()
        {
            // NOTE (steveb): test if digits separated by dot/period are detected as one word

            XDoc a = XDocFactory.From("<p>1.23</p>", MimeType.XML);
            XDoc b = XDocFactory.From("<p>4.56</p>", MimeType.XML);

            Tuplet <ArrayDiffKind, XDocDiff.Token>[] diff = XDocDiff.Diff(a, b, 10000);

            Match(diff[0], ArrayDiffKind.Same, XmlNodeType.Element, "p");
            Match(diff[1], ArrayDiffKind.Same, XmlNodeType.EndElement, string.Empty);
            Match(diff[2], ArrayDiffKind.Removed, XmlNodeType.Text, "1.23");
            Match(diff[3], ArrayDiffKind.Added, XmlNodeType.Text, "4.56");
            Match(diff[4], ArrayDiffKind.Same, XmlNodeType.None, "p");
        }
Example #6
0
        internal static DekiResource GetPageDiffSummary(PageBE page, string before, string beforeMime, string after, string afterMime, int maxDelta)
        {
            ParserResult beforeDoc = DekiXmlParser.Parse(page, beforeMime, page.Language, before, ParserMode.EDIT, false, -1, null, null);
            ParserResult afterDoc  = DekiXmlParser.Parse(page, afterMime, page.Language, after, ParserMode.EDIT, false, -1, null, null);

            Tuplet <ArrayDiffKind, XDocDiff.Token>[] diff = XDocDiff.Diff(beforeDoc.MainBody, afterDoc.MainBody, maxDelta);
            if (diff == null)
            {
                return(DekiResources.PAGE_DIFF_TOO_LARGE());
            }

            // create change summary
            int added;
            int removed;
            int attributes;
            int structural;

            return(GetChangeSummary(diff, out added, out removed, out attributes, out structural));
        }
Example #7
0
        public void HighlightAttributes()
        {
            // NOTE (steveb): test unamibiguous addition, deletion, and replacement

            XDoc a    = XDocFactory.From("<p>the <span class=\"red\">brown</span> fox</p>", MimeType.XML);
            XDoc b    = XDocFactory.From("<p>the <span class=\"blue\">brown</span> fox</p>", MimeType.XML);
            var  diff = XDocDiff.Diff(a, b, 10000);
            List <Tuple <string, string, string> > invisible;
            XDoc doc;
            XDoc before;
            XDoc after;

            XDocDiff.Highlight(diff, out doc, out invisible, out before, out after);

            Assert.AreEqual("<p>the <span class=\"blue\">brown</span> fox</p>", doc.ToString());
            Assert.AreEqual(1, invisible.Count);
            Assert.AreEqual(invisible[0].Item1, "/p/span/@class");
            Assert.AreEqual(invisible[0].Item2, "red");
            Assert.AreEqual(invisible[0].Item3, "blue");
            Assert.AreEqual(a.ToString(), before.ToString());
            Assert.AreEqual(b.ToString(), after.ToString());
        }
Example #8
0
        public void DiffAttributes()
        {
            // NOTE (steveb): test attribute changes

            XDoc a    = XDocFactory.From("<p>the <span class=\"red\">brown</span> fox</p>", MimeType.XML);
            XDoc b    = XDocFactory.From("<p>the <span class=\"blue\">brown</span> fox</p>", MimeType.XML);
            var  diff = XDocDiff.Diff(a, b, 10000);

            Match(diff[0], ArrayDiffKind.Same, XmlNodeType.Element, "p");
            Match(diff[1], ArrayDiffKind.Same, XmlNodeType.EndElement, string.Empty);
            Match(diff[2], ArrayDiffKind.Same, XmlNodeType.Text, "the");
            Match(diff[3], ArrayDiffKind.Same, XmlNodeType.Text, " ");
            Match(diff[4], ArrayDiffKind.Same, XmlNodeType.Element, "span");
            Match(diff[5], ArrayDiffKind.Removed, XmlNodeType.Attribute, "class=red");
            Match(diff[6], ArrayDiffKind.Added, XmlNodeType.Attribute, "class=blue");
            Match(diff[7], ArrayDiffKind.Same, XmlNodeType.EndElement, "");
            Match(diff[8], ArrayDiffKind.Same, XmlNodeType.Text, "brown");
            Match(diff[9], ArrayDiffKind.Same, XmlNodeType.None, "span");
            Match(diff[10], ArrayDiffKind.Same, XmlNodeType.Text, " ");
            Match(diff[11], ArrayDiffKind.Same, XmlNodeType.Text, "fox");
            Match(diff[12], ArrayDiffKind.Same, XmlNodeType.None, "p");
        }
Example #9
0
        internal static XDoc GetPageDiff(XDoc before, XDoc after, bool compact, int maxDelta, out XDoc invisibleDiff, out DekiResource summary, out XDoc beforeHighlightedChanges, out XDoc afterHighlightedChanges)
        {
            var  resources = DekiContext.Current.Resources;
            XDoc result    = XDoc.Empty;

            beforeHighlightedChanges = before;
            afterHighlightedChanges  = after;
            invisibleDiff            = XDoc.Empty;

            // compute diff between the two documents
            Tuplet <ArrayDiffKind, XDocDiff.Token>[] diff = XDocDiff.Diff(before, after, maxDelta);
            if (diff == null)
            {
                summary = DekiResources.PAGE_DIFF_TOO_LARGE();
                return(result);
            }

            // create change summary
            int added;
            int removed;
            int attributes;
            int structural;

            summary = GetChangeSummary(diff, out added, out removed, out attributes, out structural);

            // create document with highlighted changes
            if ((added > 0) || (removed > 0) || (attributes > 0))
            {
                try {
                    List <Tuplet <string, string, string> > invisibleChanges;
                    XDocDiff.Highlight(diff, out result, out invisibleChanges, out beforeHighlightedChanges, out afterHighlightedChanges);

                    // check if we should only keep top-level elements that contain changes to cut down on the noise
                    if (compact)
                    {
                        if ((added > 0) || (removed > 0))
                        {
                            CompactDiff(result);
                            CompactDiff(beforeHighlightedChanges);
                            CompactDiff(afterHighlightedChanges);
                        }
                        else
                        {
                            // no changes were made, remove all nodes
                            result = XDoc.Empty;
                        }
                    }

                    // add invisible changes
                    if (invisibleChanges.Count > 0)
                    {
                        invisibleDiff = new XDoc("ol");
                        foreach (Tuplet <string, string, string> change in invisibleChanges)
                        {
                            invisibleDiff.Start("li");
                            invisibleDiff.Value(string.Format("{0}: ", change.Item1));
                            if (change.Item2 != null)
                            {
                                invisibleDiff.Elem("del", change.Item2.QuoteString());
                            }
                            else
                            {
                                invisibleDiff.Value(resources.Localize(DekiResources.PAGE_DIFF_NOTHING()));
                            }
                            invisibleDiff.Value(" " + DOUBLE_ARROW + " ");
                            if (change.Item3 != null)
                            {
                                invisibleDiff.Elem("ins", change.Item3.QuoteString());
                            }
                            else
                            {
                                invisibleDiff.Value(resources.Localize(DekiResources.PAGE_DIFF_NOTHING()));
                            }
                            invisibleDiff.End();
                        }
                    }
                } catch (Exception e) {
                    summary = DekiResources.PAGE_DIFF_ERROR("MindTouch", e);
                }
            }
            return(result);
        }