Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'rhbz756264'

Conflicts:
	server/zanata-war/src/main/java/org/zanata/webtrans/client/presenter/TransMemoryPresenter.java
	server/zanata-war/src/main/java/org/zanata/webtrans/client/view/TransMemoryView.java
	server/zanata-war/src/main/resources/org/zanata/webtrans/public/Application.css
  • Loading branch information...
commit 47fbc1d181848431064cb4f12427619faf1745d9 2 parents 9873fa5 + a72c8b5
@aeng aeng authored
Showing with 4,037 additions and 89 deletions.
  1. +3 −3 server/zanata-war/src/main/java/org/zanata/webtrans/client/presenter/TransMemoryPresenter.java
  2. +0 −71 server/zanata-war/src/main/java/org/zanata/webtrans/client/ui/CodeMirror.java
  3. +55 −0 server/zanata-war/src/main/java/org/zanata/webtrans/client/ui/DiffMatchPatchLabel.java
  4. +116 −0 server/zanata-war/src/main/java/org/zanata/webtrans/client/ui/Highlighting.java
  5. +2 −2 server/zanata-war/src/main/java/org/zanata/webtrans/client/ui/HighlightingLabel.java
  6. +4 −2 server/zanata-war/src/main/java/org/zanata/webtrans/client/view/TransMemoryView.java
  7. +25 −11 server/zanata-war/src/main/resources/org/zanata/webtrans/public/Application.css
  8. +2 −0  server/zanata-war/src/main/resources/org/zanata/webtrans/public/Application.html
  9. +177 −0 server/zanata-war/src/main/resources/org/zanata/webtrans/public/diff_match_patch/COPYING
  10. +39 −0 server/zanata-war/src/main/resources/org/zanata/webtrans/public/diff_match_patch/README.txt
  11. +87 −0 server/zanata-war/src/main/resources/org/zanata/webtrans/public/diff_match_patch/demos/demo_diff.html
  12. +92 −0 server/zanata-war/src/main/resources/org/zanata/webtrans/public/diff_match_patch/demos/demo_match.html
  13. +121 −0 server/zanata-war/src/main/resources/org/zanata/webtrans/public/diff_match_patch/demos/demo_patch.html
  14. +49 −0 ...er/zanata-war/src/main/resources/org/zanata/webtrans/public/diff_match_patch/javascript/diff_match_patch.js
  15. +146 −0 ...ta-war/src/main/resources/org/zanata/webtrans/public/diff_match_patch/javascript/diff_match_patch_test.html
  16. +932 −0 ...nata-war/src/main/resources/org/zanata/webtrans/public/diff_match_patch/javascript/diff_match_patch_test.js
  17. +2,187 −0 .../src/main/resources/org/zanata/webtrans/public/diff_match_patch/javascript/diff_match_patch_uncompressed.js
View
6 server/zanata-war/src/main/java/org/zanata/webtrans/client/presenter/TransMemoryPresenter.java
@@ -38,7 +38,7 @@
HasText getTmTextBox();
- void createTable(ArrayList<TranslationMemoryGlossaryItem> memories);
+ void createTable(String query, ArrayList<TranslationMemoryGlossaryItem> memories);
void startProcessing();
@@ -88,7 +88,7 @@ public void showResultsFor(TransUnit transUnit)
showResults(query, searchType);
}
- private void showResults(String query, GetTranslationMemory.SearchType searchType)
+ private void showResults(final String query, GetTranslationMemory.SearchType searchType)
{
display.startProcessing();
final GetTranslationMemory action = new GetTranslationMemory(query, workspaceContext.getWorkspaceId().getLocaleId(), searchType);
@@ -104,7 +104,7 @@ public void onFailure(Throwable caught)
public void onSuccess(GetTranslationMemoryResult result)
{
ArrayList<TranslationMemoryGlossaryItem> memories = result.getMemories();
- display.createTable(memories);
+ display.createTable(query, memories);
}
});
}
View
71 server/zanata-war/src/main/java/org/zanata/webtrans/client/ui/CodeMirror.java
@@ -1,71 +0,0 @@
-/*
- * Copyright 2010, Red Hat, Inc. and individual contributors as indicated by the
- * @author tags. See the copyright.txt file in the distribution for a full
- * listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation; either version 2.1 of the License, or (at your option)
- * any later version.
- *
- * This software is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this software; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
- * site: http://www.fsf.org.
- */
-package org.zanata.webtrans.client.ui;
-
-import com.google.gwt.user.client.Element;
-
-public class CodeMirror
-{
-
- public static native void doHighlight(String text, Element elem)/*-{
- elem.innerHTML = '';
- $wnd.highlightText(text, elem);
- }-*/;
-
- public static native void highlightSearch(String searchTerm, Element elem)/*-{
- // the highlightStartTag and highlightEndTag parameters are optional
- var bodyText = elem.innerHTML;
-
- var highlightStartTag = "<font style='color:blue; background-color:yellow;'>";
- var highlightEndTag = "</font>";
-
- // find all occurences of the search term in the given text,
- // and add some "highlight" tags to them (we're not using a
- // regular expression search, because we want to filter out
- // matches that occur within HTML tags and script blocks, so
- // we have to do a little extra validation)
- var newText = "";
- var i = -1;
- var lcSearchTerm = searchTerm.toLowerCase();
- var lcBodyText = bodyText.toLowerCase();
-
- while (bodyText.length > 0) {
- i = lcBodyText.indexOf(lcSearchTerm, i+1);
- if (i < 0) {
- newText += bodyText;
- bodyText = "";
- } else {
- // skip anything inside an HTML tag
- if (bodyText.lastIndexOf(">", i) >= bodyText.lastIndexOf("<", i)) {
- // skip anything inside a <script> block
- if (lcBodyText.lastIndexOf("/script>", i) >= lcBodyText.lastIndexOf("<script", i)) {
- newText += bodyText.substring(0, i) + highlightStartTag + bodyText.substr(i, searchTerm.length) + highlightEndTag;
- bodyText = bodyText.substr(i + searchTerm.length);
- lcBodyText = bodyText.toLowerCase();
- i = -1;
- }
- }
- }
- elem.innerHTML = newText;
- }
- }-*/;
-
-}
View
55 server/zanata-war/src/main/java/org/zanata/webtrans/client/ui/DiffMatchPatchLabel.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2010, Red Hat, Inc. and individual contributors as indicated by the
+ * @author tags. See the copyright.txt file in the distribution for a full
+ * listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this software; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
+ * site: http://www.fsf.org.
+ */
+package org.zanata.webtrans.client.ui;
+
+import com.google.gwt.user.client.ui.HTML;
+
+public class DiffMatchPatchLabel extends HTML
+{
+ private String original;
+ private String plainText;
+
+ public DiffMatchPatchLabel()
+ {
+ }
+
+ public DiffMatchPatchLabel(String orig, String text)
+ {
+ super();
+ this.original = orig;
+ setText(text);
+ }
+
+ @Override
+ public String getText()
+ {
+ return plainText;
+ }
+
+ @Override
+ public void setText(String text)
+ {
+ this.plainText = text;
+ String diff = Highlighting.diffAsHtml(original, plainText);
+ setHTML(diff);
+ }
+
+}
View
116 server/zanata-war/src/main/java/org/zanata/webtrans/client/ui/Highlighting.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2010, Red Hat, Inc. and individual contributors as indicated by the
+ * @author tags. See the copyright.txt file in the distribution for a full
+ * listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this software; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
+ * site: http://www.fsf.org.
+ */
+package org.zanata.webtrans.client.ui;
+
+import com.google.gwt.user.client.Element;
+
+public class Highlighting
+{
+
+ public static native void syntaxHighlight(String text, Element elem)/*-{
+ elem.innerHTML = '';
+ $wnd.highlightText(text, elem);
+ }-*/;
+
+ public static native void searchHighlight(String searchTerm, Element elem)/*-{
+ // the highlightStartTag and highlightEndTag parameters are optional
+ var bodyText = elem.innerHTML;
+
+ var highlightStartTag = "<font style='color:blue; background-color:yellow;'>";
+ var highlightEndTag = "</font>";
+
+ // find all occurences of the search term in the given text,
+ // and add some "highlight" tags to them (we're not using a
+ // regular expression search, because we want to filter out
+ // matches that occur within HTML tags and script blocks, so
+ // we have to do a little extra validation)
+ var newText = "";
+ var i = -1;
+ var lcSearchTerm = searchTerm.toLowerCase();
+ var lcBodyText = bodyText.toLowerCase();
+
+ while (bodyText.length > 0) {
+ i = lcBodyText.indexOf(lcSearchTerm, i + 1);
+ if (i < 0) {
+ newText += bodyText;
+ bodyText = "";
+ } else {
+ // skip anything inside an HTML tag
+ if (bodyText.lastIndexOf(">", i) >= bodyText
+ .lastIndexOf("<", i)) {
+ // skip anything inside a <script> block
+ if (lcBodyText.lastIndexOf("/script>", i) >= lcBodyText
+ .lastIndexOf("<script", i)) {
+ newText += bodyText.substring(0, i) + highlightStartTag
+ + bodyText.substr(i, searchTerm.length)
+ + highlightEndTag;
+ bodyText = bodyText.substr(i + searchTerm.length);
+ lcBodyText = bodyText.toLowerCase();
+ i = -1;
+ }
+ }
+ }
+ elem.innerHTML = newText;
+ }
+ }-*/;
+
+ public static native String diffAsHtml(String text1, String text2)/*-{
+ if (!$wnd.diffMatchPatch) {
+ $wnd.diffMatchPatch = new $wnd.diff_match_patch();
+ $wnd.diffMatchPatch.Diff_Timeout = 0.2;
+
+ // // modified diff_prettyHtml() from diff_match_patch.js
+ // $wnd.diffMatchPatch.prototype.diff_prettyHtml = function(diffs) {
+ // var html = [];
+ // var pattern_amp = /&/g;
+ // var pattern_lt = /</g;
+ // var pattern_gt = />/g;
+ // var pattern_para = /\n/g;
+ // for ( var x = 0; x < diffs.length; x++) {
+ // var op = diffs[x][0]; // Operation (insert, delete, equal)
+ // var data = diffs[x][1]; // Text of change.
+ // var text = data.replace(pattern_amp, '&amp;').replace(
+ // pattern_lt, '&lt;').replace(pattern_gt, '&gt;')
+ // .replace(pattern_para, '&para;<br>');
+ // switch (op) {
+ // case DIFF_INSERT:
+ // html[x] = '<ins class="diff-insert">' + text + '</ins>';
+ // break;
+ // case DIFF_DELETE:
+ // html[x] = '<del class="diff-delete">' + text + '</del>';
+ // break;
+ // case DIFF_EQUAL:
+ // html[x] = '<span class="diff-equal">' + text
+ // + '</span>';
+ // break;
+ // }
+ // }
+ // return html.join('');
+ // };
+ }
+
+ var dmp = $wnd.diffMatchPatch;
+ var d = dmp.diff_main(text1, text2);
+ dmp.diff_cleanupSemantic(d);
+ return dmp.diff_prettyHtml(d);
+ }-*/;
+
+}
View
4 server/zanata-war/src/main/java/org/zanata/webtrans/client/ui/HighlightingLabel.java
@@ -56,13 +56,13 @@ private void highlight()
{
Element element = getElement();
String text = plainText == null ? "" : plainText.replaceAll("\n", "\n");
- CodeMirror.doHighlight(text, element);
+ Highlighting.syntaxHighlight(text, element);
}
public void highlightSearch(String search)
{
Element element = getElement();
- CodeMirror.highlightSearch(search, element);
+ Highlighting.searchHighlight(search, element);
}
}
View
6 server/zanata-war/src/main/java/org/zanata/webtrans/client/view/TransMemoryView.java
@@ -5,6 +5,7 @@
import net.customware.gwt.presenter.client.EventBus;
import org.zanata.webtrans.client.events.TransMemoryCopyEvent;
+import org.zanata.webtrans.client.ui.DiffMatchPatchLabel;
import org.zanata.webtrans.client.presenter.TransMemoryDetailsPresenter;
import org.zanata.webtrans.client.presenter.TransMemoryPresenter;
import org.zanata.webtrans.client.resources.Resources;
@@ -152,7 +153,7 @@ public void stopProcessing()
}
@Override
- public void createTable(ArrayList<TranslationMemoryGlossaryItem> memories)
+ public void createTable(String query, ArrayList<TranslationMemoryGlossaryItem> memories)
{
// TODO most of this should be in TransMemoryPresenter
clearResults();
@@ -168,7 +169,7 @@ public void createTable(ArrayList<TranslationMemoryGlossaryItem> memories)
final String targetMessage = memory.getTarget();
final int similarity = memory.getSimilarityPercent();
- resultTable.setWidget(row, SOURCE_COL, new HighlightingLabel(sourceMessage));
+ resultTable.setWidget(row, SOURCE_COL, new DiffMatchPatchLabel(query, sourceMessage));
resultTable.setWidget(row, TARGET_COL, new HighlightingLabel(targetMessage));
resultTable.setText(row, SIMILARITY_COL, similarity + "%");
@@ -214,6 +215,7 @@ public void clearResults()
resultTable.removeAllRows();
}
+
@Override
public boolean isFocused()
{
View
36 server/zanata-war/src/main/resources/org/zanata/webtrans/public/Application.css
@@ -155,9 +155,9 @@ Removes some of the styling on the page-level splitters
}
.gwt-TabLayoutPanel .gwt-TabLayoutPanelTab {
- cursor:pointer;
- border-top-left-radius:5px;
- border-top-right-radius:5px;
+ cursor:pointer;
+ border-top-left-radius:5px;
+ border-top-right-radius:5px;
}
.gwt-TabLayoutPanel .gwt-TabLayoutPanelTab-selected {
@@ -167,9 +167,9 @@ Removes some of the styling on the page-level splitters
}
.gwt-TabLayoutPanel .gwt-TabLayoutPanelContent {
- border: 2px solid #e0e8ee;
- background:#FFFFFF;
- border-radius:5px;
+ border: 2px solid #e0e8ee;
+ background:#FFFFFF;
+ border-radius:5px;
}
.WebTransEditor-Outer tr.middle td.middleCenter {
@@ -304,7 +304,8 @@ td.TableEditorCell-Source {
}
td.TableEditorCell-Target {
- height:20px;
+ /*TODO: put this back on when middle colmun is removed.
+/* padding-left:20px; */
}
tr.TableEditorRow.highlighted td.TableEditorCell {
@@ -459,6 +460,21 @@ tr.ApprovedStateDecoration td.TableEditorCell-Target .TableEditorContent-Edit {
font-weight: bold
}
+.TransMemoryTableSourceColumn span {
+ background:#FF0;
+}
+
+.TransMemoryTableSourceColumn ins {
+ background:#e6ffe6;
+ text-decoration: none;
+}
+
+.TransMemoryTableSourceColumn del {
+ background:#ffe6e6;
+ text-decoration: none;
+}
+
+
.DocumentListTable {
width: 100%;
font-size:16px;
@@ -483,8 +499,7 @@ tr.ApprovedStateDecoration td.TableEditorCell-Target .TableEditorContent-Edit {
text-align: center;
border: 1px outset #999966;
height: 65px;
- -moz-border-radius:8px;
- -webkit-border-radius: 8px;
+ border-radius:8px;
}
.transUnitCountTooltipTable {
@@ -495,8 +510,7 @@ tr.ApprovedStateDecoration td.TableEditorCell-Target .TableEditorContent-Edit {
.transUnitCountTooltipTable TD {
border: 1px solid #999966;
width:75px;
- -moz-border-radius:4px;
- -webkit-border-radius: 4px;
+ border-radius:4px;
}
.pointer{
View
2  server/zanata-war/src/main/resources/org/zanata/webtrans/public/Application.html
@@ -12,6 +12,8 @@
<script src="CodeMirror-0.67/js/tokenize.js" type="text/javascript"></script>
<script src="CodeMirror-0.67/js/parsexml.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="CodeMirror-0.67/css/xmlcolors.css"/>
+
+ <script src="diff_match_patch/javascript/diff_match_patch.js" type="text/javascript"></script>
<!-- -->
<!-- This script loads your compiled module. -->
View
177 server/zanata-war/src/main/resources/org/zanata/webtrans/public/diff_match_patch/COPYING
@@ -0,0 +1,177 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
View
39 server/zanata-war/src/main/resources/org/zanata/webtrans/public/diff_match_patch/README.txt
@@ -0,0 +1,39 @@
+Diff, Match and Patch Library
+http://code.google.com/p/google-diff-match-patch/
+Neil Fraser
+
+This library is currently available in seven different ports, all using the same API.
+Every version includes a full set of unit tests.
+
+C++:
+* Ported by Mike Slemmer.
+* Currently requires the Qt library.
+
+C#:
+* Ported by Matthaeus G. Chajdas.
+
+Java:
+* Included is both the source and a Maven package.
+
+JavaScript:
+* diff_match_patch_uncompressed.js is the human-readable version.
+ Users of node.js should 'require' this uncompressed version since the
+ compressed version is not guaranteed to work outside of a web browser.
+* diff_match_patch.js has been compressed using Google's internal JavaScript compressor.
+ Non-Google hackers who wish to recompress the source can use:
+ http://dean.edwards.name/packer/
+
+Lua:
+* Ported by Duncan Cross.
+* Does not support line-mode speedup.
+
+Objective C:
+* Ported by Jan Weiss.
+* Includes speed test (this is a separate bundle for other languages).
+
+Python:
+* Two versions, one for Python 2.x, the other for Python 3.x.
+* Runs 10x faster under PyPy than CPython.
+
+Demos:
+* Separate demos for Diff, Match and Patch in JavaScript.
View
87 server/zanata-war/src/main/resources/org/zanata/webtrans/public/diff_match_patch/demos/demo_diff.html
@@ -0,0 +1,87 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<HTML>
+<HEAD>
+ <TITLE>Diff, Match and Patch: Demo of Diff</TITLE>
+ <SCRIPT TYPE="text/javascript" LANGUAGE="JavaScript" SRC="../javascript/diff_match_patch.js"></SCRIPT>
+</HEAD>
+
+<BODY>
+<H1>Diff, Match and Patch</H1>
+<H2>Demo of Diff</H2>
+
+<P>Diff takes two texts and finds the differences. This implementation works on a character by character basis.
+The result of any diff may contain 'chaff', irrelevant small commonalities which complicate the output.
+A post-diff cleanup algorithm factors out these trivial commonalities.</P>
+
+<SCRIPT TYPE="text/javascript" LANGUAGE="JavaScript">
+var dmp = new diff_match_patch();
+
+function launch() {
+ var text1 = document.getElementById('text1').value;
+ var text2 = document.getElementById('text2').value;
+ dmp.Diff_Timeout = parseFloat(document.getElementById('timeout').value);
+ dmp.Diff_EditCost = parseFloat(document.getElementById('editcost').value);
+
+ var ms_start = (new Date()).getTime();
+ var d = dmp.diff_main(text1, text2);
+ var ms_end = (new Date()).getTime();
+
+ if (document.getElementById('semantic').checked) {
+ dmp.diff_cleanupSemantic(d);
+ }
+ if (document.getElementById('efficiency').checked) {
+ dmp.diff_cleanupEfficiency(d);
+ }
+ var ds = dmp.diff_prettyHtml(d);
+ document.getElementById('outputdiv').innerHTML = ds + '<BR>Time: ' + (ms_end - ms_start) / 1000 + 's';
+}
+</SCRIPT>
+
+<FORM action="#" onsubmit="return false">
+<TABLE WIDTH="100%"><TR>
+ <TD WIDTH="50%">
+<H3>Text Version 1:</H3>
+<TEXTAREA ID="text1" STYLE="width: 100%" ROWS=10>I am the very model of a modern Major-General,
+I've information vegetable, animal, and mineral,
+I know the kings of England, and I quote the fights historical,
+From Marathon to Waterloo, in order categorical.</TEXTAREA></TD>
+ <TD WIDTH="50%">
+<H3>Text Version 2:</H3>
+<TEXTAREA ID="text2" STYLE="width: 100%" ROWS=10>I am the very model of a cartoon individual,
+My animation's comical, unusual, and whimsical,
+I'm quite adept at funny gags, comedic theory I have read,
+From wicked puns and stupid jokes to anvils that drop on your head.</TEXTAREA></TD>
+</TR></TABLE>
+
+<H3>Diff timeout:</H3>
+<P><INPUT TYPE="text" SIZE=3 MAXLENGTH=5 VALUE="1" ID="timeout"> seconds<BR>
+If the mapping phase of the diff computation takes longer than this, then the computation
+is truncated and the best solution to date is returned. While guaranteed to be correct,
+it may not be optimal. A timeout of '0' allows for unlimited computation.</P>
+
+<H3>Post-diff cleanup:</H3>
+<DL>
+<DT><INPUT TYPE="radio" NAME="cleanup" ID="semantic" CHECKED>
+<LABEL FOR="semantic">Semantic Cleanup</LABEL></DT>
+<DD>Increase human readability by factoring out commonalities which are likely to be
+coincidental.</DD>
+<DT><INPUT TYPE="radio" NAME="cleanup" ID="efficiency">
+<LABEL FOR="efficiency">Efficiency Cleanup</LABEL>,
+edit cost: <INPUT TYPE="text" SIZE=3 MAXLENGTH=5 VALUE="4" ID="editcost">
+<DD>Increase computational efficiency by factoring out short commonalities which are
+not worth the overhead. The larger the edit cost, the more agressive the cleanup.</DD>
+<DT><INPUT TYPE="radio" NAME="cleanup" ID="raw">
+<LABEL FOR="raw">No Cleanup</LABEL></DT>
+<DD>Raw output.</DD>
+</DL>
+
+<P><INPUT TYPE="button" onClick="launch()" VALUE="Compute Diff"></P>
+</FORM>
+
+<DIV ID="outputdiv"></DIV>
+
+<HR>
+Back to <A HREF="http://code.google.com/p/google-diff-match-patch/">Diff, Match and Patch</A>
+
+</BODY>
+</HTML>
View
92 server/zanata-war/src/main/resources/org/zanata/webtrans/public/diff_match_patch/demos/demo_match.html
@@ -0,0 +1,92 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<HTML>
+<HEAD>
+ <TITLE>Diff, Match and Patch: Demo of Match</TITLE>
+ <SCRIPT TYPE="text/javascript" LANGUAGE="JavaScript" SRC="../javascript/diff_match_patch.js"></SCRIPT>
+</HEAD>
+
+<BODY>
+<H1>Diff, Match and Patch</H1>
+<H2>Demo of Match</H2>
+
+<P>Match looks for a pattern within a larger text.
+This implementation of match is fuzzy, meaning it can find a match even if the
+pattern contains errors and doesn't exactly match what is found in the text.
+This implementation also accepts an expected location, near which the match should be found.
+The candidate matches are scored based on a) the number of spelling differences between the
+pattern and the text and b) the distance between the candidate match and the expected location.
+The match distance parameter sets the relative importance of these two metrics.</P>
+
+<FORM action="#" onsubmit="return false">
+<H3>Text:</H3>
+<TEXTAREA ID="text" STYLE="width: 100%" ROWS=10 onChange="textchange()">'Twas brillig, and the slithy toves
+Did gyre and gimble in the wabe.
+All mimsy were the borogroves,
+And the mome raths outgrabe.</TEXTAREA>
+
+<H3>Fuzzy pattern:</H3>
+<P><INPUT ID="pattern" SIZE=32 VALUE="slimy tools"> <SPAN ID="maxlengthspan"></SPAN><BR>
+Aproximate pattern to search for in the text. Due to limitations of the Bitap algorithm, the pattern has a limited length.</P>
+
+<H3>Fuzzy location:</H3>
+<P><INPUT ID="loc" SIZE=4 MAXLENGTH=10 VALUE="30"> <SPAN ID="maxtextspan"></SPAN><BR>
+Aproximately where in the text is the pattern expected to be found?</P>
+
+<H3>Match distance:</H3>
+<P><INPUT TYPE="text" SIZE=3 MAXLENGTH=8 VALUE="1000" ID="distance"><BR>
+Determines how close the match must be to the fuzzy location (specified above). An exact letter match which is 'distance' characters away from the fuzzy location would
+score as a complete mismatch. A distance of '0' requires the match be at the exact location specified, a threshold of '1000'
+would require a perfect match to be within 800 characters of the fuzzy location to be found using a 0.8 threshold.</P>
+
+<H3>Match threshold:</H3>
+<P><INPUT TYPE="text" SIZE=3 MAXLENGTH=5 VALUE="0.8" ID="threshold"><BR>
+At what point does the match algorithm give up. A threshold of '0.0' requires a perfect match (of both letters and location), a threshold of '1.0' would match anything.</P>
+
+<INPUT TYPE="button" onClick="launch()" VALUE="Compute Match">
+</FORM>
+
+<DIV ID="outputdiv"></DIV>
+
+<DIV ID="datediv"></DIV>
+
+<SCRIPT TYPE="text/javascript" LANGUAGE="JavaScript">
+var dmp = new diff_match_patch();
+
+function launch() {
+ var text = document.getElementById('text').value;
+ var pattern = document.getElementById('pattern').value;
+ var loc = parseInt(document.getElementById('loc').value, 10);
+
+ dmp.Match_Distance = parseFloat(document.getElementById('distance').value);
+ dmp.Match_Threshold = parseFloat(document.getElementById('threshold').value);
+
+ var ms_start = (new Date()).getTime();
+ var match = dmp.match_main(text, pattern, loc);
+ var ms_end = (new Date()).getTime();
+
+ document.getElementById('datediv').innerHTML = 'Time: ' + (ms_end - ms_start) / 1000 + 's';
+ if (match == -1) {
+ document.getElementById('outputdiv').innerHTML = 'No match found.';
+ } else {
+ var quote = text.substring(match, match + pattern.length);
+ quote = quote.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
+ quote = quote.replace(/\n/g, '&para;');
+ document.getElementById('outputdiv').innerHTML = 'Match found at character ' + match +
+ ': &nbsp; <CODE>' + quote + '</' + 'CODE>';
+ }
+}
+
+function textchange() {
+ document.getElementById('maxtextspan').innerHTML = '(text is currently ' + document.getElementById('text').value.length + ' characters long)';
+}
+
+textchange();
+document.getElementById('pattern').maxLength = dmp.Match_MaxBits;
+document.getElementById('maxlengthspan').innerHTML = '(maxlength in this browser: ' + dmp.Match_MaxBits + ')';
+</SCRIPT>
+
+<HR>
+Back to <A HREF="http://code.google.com/p/google-diff-match-patch/">Diff, Match and Patch</A>
+
+</BODY>
+</HTML>
View
121 server/zanata-war/src/main/resources/org/zanata/webtrans/public/diff_match_patch/demos/demo_patch.html
@@ -0,0 +1,121 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<HTML>
+<HEAD>
+ <TITLE>Diff, Match and Patch: Demo of Patch</TITLE>
+ <SCRIPT TYPE="text/javascript" LANGUAGE="JavaScript" SRC="../javascript/diff_match_patch.js"></SCRIPT>
+</HEAD>
+
+<BODY>
+<H1>Diff, Match and Patch</H1>
+<H2>Demo of Patch</H2>
+
+<P>Two texts can be diffed against each other, generating a list of patches.
+These patches can then be applied against a third text. If the third text has edits of its own, this version of patch
+will apply its changes on a best-effort basis, reporting which patches succeeded and which failed.</P>
+
+<P>In this scenario Shakespeare wrote Hamlet in old English, the source document. Then two derivative
+works were created. One is Hamlet updated to modern English. The other is a Star Trek parody in old English.
+This demonstrantion creates a list of patches between the source and the modern English version. Then it
+applies those patches onto the Star Trek parody, thus creating a Star Trek parody in
+modern English.</P>
+
+<SCRIPT TYPE="text/javascript" LANGUAGE="JavaScript">
+var dmp = new diff_match_patch();
+
+var patch_text = '';
+
+function diff_launch() {
+ var text1 = document.getElementById('text1a').value;
+ var text2 = document.getElementById('text2a').value;
+
+ var ms_start = (new Date).getTime();
+ var diff = dmp.diff_main(text1, text2, true);
+ var ms_end = (new Date).getTime();
+
+ if (diff.length > 2) {
+ dmp.diff_cleanupSemantic(diff);
+ }
+
+ var patch_list = dmp.patch_make(text1, text2, diff);
+ patch_text = dmp.patch_toText(patch_list);
+
+ document.getElementById('diffdatediv').innerHTML =
+ 'Time: ' + (ms_end - ms_start) / 1000 + 's';
+ document.getElementById('diffoutputdiv').innerHTML =
+ '<FIELDSET><LEGEND>Patch:</' + 'LEGEND><PRE>' + patch_text +
+ '</' + 'PRE></' + 'FIELDSET>';
+ //document.getElementById('diffoutputdiv').innerHTML = dmp.diff_prettyHtml(diff);
+ document.getElementById('patchbutton').disabled = false;
+}
+
+
+function patch_launch() {
+ var text1 = document.getElementById('text1b').value;
+ var patches = dmp.patch_fromText(patch_text);
+
+ var ms_start = (new Date).getTime();
+ var results = dmp.patch_apply(patches, text1);
+ var ms_end = (new Date).getTime();
+
+ document.getElementById('patchdatediv').innerHTML =
+ 'Time: ' + (ms_end - ms_start) / 1000 + 's';
+ document.getElementById('text2b').value = results[0];
+ results = results[1];
+ var html = '';
+ for (var x = 0; x < results.length; x++) {
+ if (results[x]) {
+ html += '<LI><FONT COLOR="#009900">Ok</' + 'FONT>';
+ } else {
+ html += '<LI><FONT COLOR="#990000">Fail</' + 'FONT>';
+ }
+ }
+ document.getElementById('passfaildiv').innerHTML = html;
+}
+</SCRIPT>
+
+<FORM action="#" onsubmit="return false">
+<H3>Shakespeare's copy:</H3>
+<TABLE WIDTH="100%"><TR>
+ <TD WIDTH="50%">Old Version:<BR><TEXTAREA ID="text1a" STYLE="width: 100%" ROWS=10>Hamlet: Do you see yonder cloud that's almost in shape of a camel?
+Polonius: By the mass, and 'tis like a camel, indeed.
+Hamlet: Methinks it is like a weasel.
+Polonius: It is backed like a weasel.
+Hamlet: Or like a whale?
+Polonius: Very like a whale.
+-- Shakespeare</TEXTAREA></TD>
+ <TD WIDTH="50%">New Version:<BR><TEXTAREA ID="text2a" STYLE="width: 100%" ROWS=10>Hamlet: Do you see the cloud over there that's almost the shape of a camel?
+Polonius: By golly, it is like a camel, indeed.
+Hamlet: I think it looks like a weasel.
+Polonius: It is shaped like a weasel.
+Hamlet: Or like a whale?
+Polonius: It's totally like a whale.
+-- Shakespeare</TEXTAREA></TD>
+</TR></TABLE>
+<P><INPUT TYPE="button" onClick="diff_launch()" VALUE="Compute Patch"></P>
+<BLOCKQUOTE><DIV ID="diffoutputdiv"></DIV></BLOCKQUOTE>
+
+<DIV ID="diffdatediv"></DIV>
+
+<H3>Trekkie's copy:</H3>
+<TABLE WIDTH="100%"><TR>
+ <TD WIDTH="50%">Old Version:<BR><TEXTAREA ID="text1b" STYLE="width: 100%" ROWS=10>Kirk: Do you see yonder cloud that's almost in shape of a Klingon?
+Spock: By the mass, and 'tis like a Klingon, indeed.
+Kirk: Methinks it is like a Vulcan.
+Spock: It is backed like a Vulcan.
+Kirk: Or like a Romulan?
+Spock: Very like a Romulan.
+-- Trekkie</TEXTAREA></TD>
+ <TD WIDTH="50%">New Version:<BR><TEXTAREA READONLY ID="text2b" STYLE="width: 100%" ROWS=10></TEXTAREA></TD>
+</TR></TABLE>
+<INPUT TYPE="button" ID="patchbutton" onClick="patch_launch()" VALUE="Apply Patch" DISABLED>
+</FORM>
+
+<OL ID="passfaildiv"></OL>
+<DIV ID="patchdatediv"></DIV>
+
+<HR>
+Back to <A HREF="http://code.google.com/p/google-diff-match-patch/">Diff, Match and Patch</A>
+
+</BODY>
+</HTML>
+
View
49 ...zanata-war/src/main/resources/org/zanata/webtrans/public/diff_match_patch/javascript/diff_match_patch.js
@@ -0,0 +1,49 @@
+(function(){function diff_match_patch(){this.Diff_Timeout=1;this.Diff_EditCost=4;this.Match_Threshold=0.5;this.Match_Distance=1E3;this.Patch_DeleteThreshold=0.5;this.Patch_Margin=4;this.Match_MaxBits=32}
+diff_match_patch.prototype.diff_main=function(a,b,c,d){typeof d=="undefined"&&(d=this.Diff_Timeout<=0?Number.MAX_VALUE:(new Date).getTime()+this.Diff_Timeout*1E3);if(a==null||b==null)throw Error("Null input. (diff_main)");if(a==b)return a?[[0,a]]:[];typeof c=="undefined"&&(c=true);var e=c,f=this.diff_commonPrefix(a,b),c=a.substring(0,f),a=a.substring(f),b=b.substring(f),f=this.diff_commonSuffix(a,b),g=a.substring(a.length-f),a=a.substring(0,a.length-f),b=b.substring(0,b.length-f),a=this.diff_compute_(a,
+b,e,d);c&&a.unshift([0,c]);g&&a.push([0,g]);this.diff_cleanupMerge(a);return a};
+diff_match_patch.prototype.diff_compute_=function(a,b,c,d){if(!a)return[[1,b]];if(!b)return[[-1,a]];var e=a.length>b.length?a:b,f=a.length>b.length?b:a,g=e.indexOf(f);if(g!=-1)return c=[[1,e.substring(0,g)],[0,f],[1,e.substring(g+f.length)]],a.length>b.length&&(c[0][0]=c[2][0]=-1),c;if(f.length==1)return[[-1,a],[1,b]];return(e=this.diff_halfMatch_(a,b))?(f=e[0],a=e[1],g=e[2],b=e[3],e=e[4],f=this.diff_main(f,g,c,d),c=this.diff_main(a,b,c,d),f.concat([[0,e]],c)):c&&a.length>100&&b.length>100?this.diff_lineMode_(a,
+b,d):this.diff_bisect_(a,b,d)};
+diff_match_patch.prototype.diff_lineMode_=function(a,b,c){var d=this.diff_linesToChars_(a,b),a=d[0],b=d[1],d=d[2],a=this.diff_bisect_(a,b,c);this.diff_charsToLines_(a,d);this.diff_cleanupSemantic(a);a.push([0,""]);for(var e=b=0,f=0,g=d="";b<a.length;){switch(a[b][0]){case 1:f++;g+=a[b][1];break;case -1:e++;d+=a[b][1];break;case 0:if(e>=1&&f>=1){d=this.diff_main(d,g,false,c);a.splice(b-e-f,e+f);b=b-e-f;for(e=d.length-1;e>=0;e--)a.splice(b,0,d[e]);b+=d.length}e=f=0;g=d=""}b++}a.pop();return a};
+diff_match_patch.prototype.diff_bisect_=function(a,b,c){for(var d=a.length,e=b.length,f=Math.ceil((d+e)/2),g=f,h=2*f,j=Array(h),i=Array(h),k=0;k<h;k++)j[k]=-1,i[k]=-1;j[g+1]=0;i[g+1]=0;for(var k=d-e,p=k%2!=0,q=0,t=0,o=0,v=0,u=0;u<f;u++){if((new Date).getTime()>c)break;for(var n=-u+q;n<=u-t;n+=2){var l=g+n,m;m=n==-u||n!=u&&j[l-1]<j[l+1]?j[l+1]:j[l-1]+1;for(var r=m-n;m<d&&r<e&&a.charAt(m)==b.charAt(r);)m++,r++;j[l]=m;if(m>d)t+=2;else if(r>e)q+=2;else if(p&&(l=g+k-n,l>=0&&l<h&&i[l]!=-1)){var s=d-i[l];
+if(m>=s)return this.diff_bisectSplit_(a,b,m,r,c)}}for(n=-u+o;n<=u-v;n+=2){l=g+n;s=n==-u||n!=u&&i[l-1]<i[l+1]?i[l+1]:i[l-1]+1;for(m=s-n;s<d&&m<e&&a.charAt(d-s-1)==b.charAt(e-m-1);)s++,m++;i[l]=s;if(s>d)v+=2;else if(m>e)o+=2;else if(!p&&(l=g+k-n,l>=0&&l<h&&j[l]!=-1&&(m=j[l],r=g+m-l,s=d-s,m>=s)))return this.diff_bisectSplit_(a,b,m,r,c)}}return[[-1,a],[1,b]]};
+diff_match_patch.prototype.diff_bisectSplit_=function(a,b,c,d,e){var f=a.substring(0,c),g=b.substring(0,d),a=a.substring(c),b=b.substring(d),f=this.diff_main(f,g,false,e),e=this.diff_main(a,b,false,e);return f.concat(e)};
+diff_match_patch.prototype.diff_linesToChars_=function(a,b){function c(a){for(var b="",c=0,f=-1,g=d.length;f<a.length-1;){f=a.indexOf("\n",c);f==-1&&(f=a.length-1);var q=a.substring(c,f+1),c=f+1;(e.hasOwnProperty?e.hasOwnProperty(q):e[q]!==void 0)?b+=String.fromCharCode(e[q]):(b+=String.fromCharCode(g),e[q]=g,d[g++]=q)}return b}var d=[],e={};d[0]="";var f=c(a),g=c(b);return[f,g,d]};
+diff_match_patch.prototype.diff_charsToLines_=function(a,b){for(var c=0;c<a.length;c++){for(var d=a[c][1],e=[],f=0;f<d.length;f++)e[f]=b[d.charCodeAt(f)];a[c][1]=e.join("")}};diff_match_patch.prototype.diff_commonPrefix=function(a,b){if(!a||!b||a.charAt(0)!=b.charAt(0))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(f,e)==b.substring(f,e)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};
+diff_match_patch.prototype.diff_commonSuffix=function(a,b){if(!a||!b||a.charAt(a.length-1)!=b.charAt(b.length-1))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(a.length-e,a.length-f)==b.substring(b.length-e,b.length-f)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};
+diff_match_patch.prototype.diff_commonOverlap_=function(a,b){var c=a.length,d=b.length;if(c==0||d==0)return 0;c>d?a=a.substring(c-d):c<d&&(b=b.substring(0,c));c=Math.min(c,d);if(a==b)return c;for(var d=0,e=1;;){var f=a.substring(c-e),f=b.indexOf(f);if(f==-1)return d;e+=f;if(f==0||a.substring(c-e)==b.substring(0,e))d=e,e++}};
+diff_match_patch.prototype.diff_halfMatch_=function(a,b){function c(a,b,c){for(var d=a.substring(c,c+Math.floor(a.length/4)),e=-1,g="",h,j,n,l;(e=b.indexOf(d,e+1))!=-1;){var m=f.diff_commonPrefix(a.substring(c),b.substring(e)),r=f.diff_commonSuffix(a.substring(0,c),b.substring(0,e));g.length<r+m&&(g=b.substring(e-r,e)+b.substring(e,e+m),h=a.substring(0,c-r),j=a.substring(c+m),n=b.substring(0,e-r),l=b.substring(e+m))}return g.length*2>=a.length?[h,j,n,l,g]:null}if(this.Diff_Timeout<=0)return null;
+var d=a.length>b.length?a:b,e=a.length>b.length?b:a;if(d.length<4||e.length*2<d.length)return null;var f=this,g=c(d,e,Math.ceil(d.length/4)),d=c(d,e,Math.ceil(d.length/2)),h;if(!g&&!d)return null;else h=d?g?g[4].length>d[4].length?g:d:d:g;var j;a.length>b.length?(g=h[0],d=h[1],e=h[2],j=h[3]):(e=h[0],j=h[1],g=h[2],d=h[3]);h=h[4];return[g,d,e,j,h]};
+diff_match_patch.prototype.diff_cleanupSemantic=function(a){for(var b=false,c=[],d=0,e=null,f=0,g=0,h=0,j=0,i=0;f<a.length;)a[f][0]==0?(c[d++]=f,g=j,h=i,i=j=0,e=a[f][1]):(a[f][0]==1?j+=a[f][1].length:i+=a[f][1].length,e!==null&&e.length<=Math.max(g,h)&&e.length<=Math.max(j,i)&&(a.splice(c[d-1],0,[-1,e]),a[c[d-1]+1][0]=1,d--,d--,f=d>0?c[d-1]:-1,i=j=h=g=0,e=null,b=true)),f++;b&&this.diff_cleanupMerge(a);this.diff_cleanupSemanticLossless(a);for(f=1;f<a.length;){if(a[f-1][0]==-1&&a[f][0]==1){b=a[f-1][1];
+c=a[f][1];d=this.diff_commonOverlap_(b,c);e=this.diff_commonOverlap_(c,b);if(d>=e){if(d>=b.length/2||d>=c.length/2)a.splice(f,0,[0,c.substring(0,d)]),a[f-1][1]=b.substring(0,b.length-d),a[f+1][1]=c.substring(d),f++}else if(e>=b.length/2||e>=c.length/2)a.splice(f,0,[0,b.substring(0,e)]),a[f-1]=[1,c.substring(0,c.length-e)],a[f+1]=[-1,b.substring(e)],f++;f++}f++}};
+diff_match_patch.prototype.diff_cleanupSemanticLossless=function(a){function b(a,b){if(!a||!b)return 6;var c=a.charAt(a.length-1),d=b.charAt(0),e=c.match(diff_match_patch.nonAlphaNumericRegex_),f=d.match(diff_match_patch.nonAlphaNumericRegex_),g=e&&c.match(diff_match_patch.whitespaceRegex_),h=f&&d.match(diff_match_patch.whitespaceRegex_),c=g&&c.match(diff_match_patch.linebreakRegex_),d=h&&d.match(diff_match_patch.linebreakRegex_),i=c&&a.match(diff_match_patch.blanklineEndRegex_),j=d&&b.match(diff_match_patch.blanklineStartRegex_);
+if(i||j)return 5;else if(c||d)return 4;else if(e&&!g&&h)return 3;else if(g||h)return 2;else if(e||f)return 1;return 0}for(var c=1;c<a.length-1;){if(a[c-1][0]==0&&a[c+1][0]==0){var d=a[c-1][1],e=a[c][1],f=a[c+1][1],g=this.diff_commonSuffix(d,e);if(g)var h=e.substring(e.length-g),d=d.substring(0,d.length-g),e=h+e.substring(0,e.length-g),f=h+f;for(var g=d,h=e,j=f,i=b(d,e)+b(e,f);e.charAt(0)===f.charAt(0);){d+=e.charAt(0);var e=e.substring(1)+f.charAt(0),f=f.substring(1),k=b(d,e)+b(e,f);k>=i&&(i=k,g=
+d,h=e,j=f)}a[c-1][1]!=g&&(g?a[c-1][1]=g:(a.splice(c-1,1),c--),a[c][1]=h,j?a[c+1][1]=j:(a.splice(c+1,1),c--))}c++}};diff_match_patch.nonAlphaNumericRegex_=/[^a-zA-Z0-9]/;diff_match_patch.whitespaceRegex_=/\s/;diff_match_patch.linebreakRegex_=/[\r\n]/;diff_match_patch.blanklineEndRegex_=/\n\r?\n$/;diff_match_patch.blanklineStartRegex_=/^\r?\n\r?\n/;
+diff_match_patch.prototype.diff_cleanupEfficiency=function(a){for(var b=false,c=[],d=0,e="",f=0,g=false,h=false,j=false,i=false;f<a.length;){if(a[f][0]==0)a[f][1].length<this.Diff_EditCost&&(j||i)?(c[d++]=f,g=j,h=i,e=a[f][1]):(d=0,e=""),j=i=false;else if(a[f][0]==-1?i=true:j=true,e&&(g&&h&&j&&i||e.length<this.Diff_EditCost/2&&g+h+j+i==3))a.splice(c[d-1],0,[-1,e]),a[c[d-1]+1][0]=1,d--,e="",g&&h?(j=i=true,d=0):(d--,f=d>0?c[d-1]:-1,j=i=false),b=true;f++}b&&this.diff_cleanupMerge(a)};
+diff_match_patch.prototype.diff_cleanupMerge=function(a){a.push([0,""]);for(var b=0,c=0,d=0,e="",f="",g;b<a.length;)switch(a[b][0]){case 1:d++;f+=a[b][1];b++;break;case -1:c++;e+=a[b][1];b++;break;case 0:c+d>1?(c!==0&&d!==0&&(g=this.diff_commonPrefix(f,e),g!==0&&(b-c-d>0&&a[b-c-d-1][0]==0?a[b-c-d-1][1]+=f.substring(0,g):(a.splice(0,0,[0,f.substring(0,g)]),b++),f=f.substring(g),e=e.substring(g)),g=this.diff_commonSuffix(f,e),g!==0&&(a[b][1]=f.substring(f.length-g)+a[b][1],f=f.substring(0,f.length-
+g),e=e.substring(0,e.length-g))),c===0?a.splice(b-c-d,c+d,[1,f]):d===0?a.splice(b-c-d,c+d,[-1,e]):a.splice(b-c-d,c+d,[-1,e],[1,f]),b=b-c-d+(c?1:0)+(d?1:0)+1):b!==0&&a[b-1][0]==0?(a[b-1][1]+=a[b][1],a.splice(b,1)):b++,c=d=0,f=e=""}a[a.length-1][1]===""&&a.pop();c=false;for(b=1;b<a.length-1;)a[b-1][0]==0&&a[b+1][0]==0&&(a[b][1].substring(a[b][1].length-a[b-1][1].length)==a[b-1][1]?(a[b][1]=a[b-1][1]+a[b][1].substring(0,a[b][1].length-a[b-1][1].length),a[b+1][1]=a[b-1][1]+a[b+1][1],a.splice(b-1,1),c=
+true):a[b][1].substring(0,a[b+1][1].length)==a[b+1][1]&&(a[b-1][1]+=a[b+1][1],a[b][1]=a[b][1].substring(a[b+1][1].length)+a[b+1][1],a.splice(b+1,1),c=true)),b++;c&&this.diff_cleanupMerge(a)};diff_match_patch.prototype.diff_xIndex=function(a,b){var c=0,d=0,e=0,f=0,g;for(g=0;g<a.length;g++){a[g][0]!==1&&(c+=a[g][1].length);a[g][0]!==-1&&(d+=a[g][1].length);if(c>b)break;e=c;f=d}return a.length!=g&&a[g][0]===-1?f:f+(b-e)};
+diff_match_patch.prototype.diff_prettyHtml=function(a){for(var b=[],c=/&/g,d=/</g,e=/>/g,f=/\n/g,g=0;g<a.length;g++){var h=a[g][0],j=a[g][1],j=j.replace(c,"&amp;").replace(d,"&lt;").replace(e,"&gt;").replace(f,"&para;<br>");switch(h){case 1:b[g]='<ins style="background:#e6ffe6;">'+j+"</ins>";break;case -1:b[g]='<del style="background:#ffe6e6;">'+j+"</del>";break;case 0:b[g]="<span>"+j+"</span>"}}return b.join("")};
+diff_match_patch.prototype.diff_text1=function(a){for(var b=[],c=0;c<a.length;c++)a[c][0]!==1&&(b[c]=a[c][1]);return b.join("")};diff_match_patch.prototype.diff_text2=function(a){for(var b=[],c=0;c<a.length;c++)a[c][0]!==-1&&(b[c]=a[c][1]);return b.join("")};diff_match_patch.prototype.diff_levenshtein=function(a){for(var b=0,c=0,d=0,e=0;e<a.length;e++){var f=a[e][0],g=a[e][1];switch(f){case 1:c+=g.length;break;case -1:d+=g.length;break;case 0:b+=Math.max(c,d),d=c=0}}b+=Math.max(c,d);return b};
+diff_match_patch.prototype.diff_toDelta=function(a){for(var b=[],c=0;c<a.length;c++)switch(a[c][0]){case 1:b[c]="+"+encodeURI(a[c][1]);break;case -1:b[c]="-"+a[c][1].length;break;case 0:b[c]="="+a[c][1].length}return b.join("\t").replace(/%20/g," ")};
+diff_match_patch.prototype.diff_fromDelta=function(a,b){for(var c=[],d=0,e=0,f=b.split(/\t/g),g=0;g<f.length;g++){var h=f[g].substring(1);switch(f[g].charAt(0)){case "+":try{c[d++]=[1,decodeURI(h)]}catch(j){throw Error("Illegal escape in diff_fromDelta: "+h);}break;case "-":case "=":var i=parseInt(h,10);if(isNaN(i)||i<0)throw Error("Invalid number in diff_fromDelta: "+h);h=a.substring(e,e+=i);f[g].charAt(0)=="="?c[d++]=[0,h]:c[d++]=[-1,h];break;default:if(f[g])throw Error("Invalid diff operation in diff_fromDelta: "+
+f[g]);}}if(e!=a.length)throw Error("Delta length ("+e+") does not equal source text length ("+a.length+").");return c};diff_match_patch.prototype.match_main=function(a,b,c){if(a==null||b==null||c==null)throw Error("Null input. (match_main)");c=Math.max(0,Math.min(c,a.length));return a==b?0:a.length?a.substring(c,c+b.length)==b?c:this.match_bitap_(a,b,c):-1};
+diff_match_patch.prototype.match_bitap_=function(a,b,c){function d(a,d){var e=a/b.length,g=Math.abs(c-d);return!f.Match_Distance?g?1:e:e+g/f.Match_Distance}if(b.length>this.Match_MaxBits)throw Error("Pattern too long for this browser.");var e=this.match_alphabet_(b),f=this,g=this.Match_Threshold,h=a.indexOf(b,c);h!=-1&&(g=Math.min(d(0,h),g),h=a.lastIndexOf(b,c+b.length),h!=-1&&(g=Math.min(d(0,h),g)));for(var j=1<<b.length-1,h=-1,i,k,p=b.length+a.length,q,t=0;t<b.length;t++){i=0;for(k=p;i<k;)d(t,c+
+k)<=g?i=k:p=k,k=Math.floor((p-i)/2+i);p=k;i=Math.max(1,c-k+1);var o=Math.min(c+k,a.length)+b.length;k=Array(o+2);for(k[o+1]=(1<<t)-1;o>=i;o--){var v=e[a.charAt(o-1)];k[o]=t===0?(k[o+1]<<1|1)&v:(k[o+1]<<1|1)&v|(q[o+1]|q[o])<<1|1|q[o+1];if(k[o]&j&&(v=d(t,o-1),v<=g))if(g=v,h=o-1,h>c)i=Math.max(1,2*c-h);else break}if(d(t+1,c)>g)break;q=k}return h};
+diff_match_patch.prototype.match_alphabet_=function(a){for(var b={},c=0;c<a.length;c++)b[a.charAt(c)]=0;for(c=0;c<a.length;c++)b[a.charAt(c)]|=1<<a.length-c-1;return b};
+diff_match_patch.prototype.patch_addContext_=function(a,b){if(b.length!=0){for(var c=b.substring(a.start2,a.start2+a.length1),d=0;b.indexOf(c)!=b.lastIndexOf(c)&&c.length<this.Match_MaxBits-this.Patch_Margin-this.Patch_Margin;)d+=this.Patch_Margin,c=b.substring(a.start2-d,a.start2+a.length1+d);d+=this.Patch_Margin;(c=b.substring(a.start2-d,a.start2))&&a.diffs.unshift([0,c]);(d=b.substring(a.start2+a.length1,a.start2+a.length1+d))&&a.diffs.push([0,d]);a.start1-=c.length;a.start2-=c.length;a.length1+=
+c.length+d.length;a.length2+=c.length+d.length}};
+diff_match_patch.prototype.patch_make=function(a,b,c){var d;if(typeof a=="string"&&typeof b=="string"&&typeof c=="undefined")d=a,b=this.diff_main(d,b,true),b.length>2&&(this.diff_cleanupSemantic(b),this.diff_cleanupEfficiency(b));else if(a&&typeof a=="object"&&typeof b=="undefined"&&typeof c=="undefined")b=a,d=this.diff_text1(b);else if(typeof a=="string"&&b&&typeof b=="object"&&typeof c=="undefined")d=a;else if(typeof a=="string"&&typeof b=="string"&&c&&typeof c=="object")d=a,b=c;else throw Error("Unknown call format to patch_make.");
+if(b.length===0)return[];for(var c=[],a=new diff_match_patch.patch_obj,e=0,f=0,g=0,h=d,j=0;j<b.length;j++){var i=b[j][0],k=b[j][1];if(!e&&i!==0)a.start1=f,a.start2=g;switch(i){case 1:a.diffs[e++]=b[j];a.length2+=k.length;d=d.substring(0,g)+k+d.substring(g);break;case -1:a.length1+=k.length;a.diffs[e++]=b[j];d=d.substring(0,g)+d.substring(g+k.length);break;case 0:k.length<=2*this.Patch_Margin&&e&&b.length!=j+1?(a.diffs[e++]=b[j],a.length1+=k.length,a.length2+=k.length):k.length>=2*this.Patch_Margin&&
+e&&(this.patch_addContext_(a,h),c.push(a),a=new diff_match_patch.patch_obj,e=0,h=d,f=g)}i!==1&&(f+=k.length);i!==-1&&(g+=k.length)}e&&(this.patch_addContext_(a,h),c.push(a));return c};diff_match_patch.prototype.patch_deepCopy=function(a){for(var b=[],c=0;c<a.length;c++){var d=a[c],e=new diff_match_patch.patch_obj;e.diffs=[];for(var f=0;f<d.diffs.length;f++)e.diffs[f]=d.diffs[f].slice();e.start1=d.start1;e.start2=d.start2;e.length1=d.length1;e.length2=d.length2;b[c]=e}return b};
+diff_match_patch.prototype.patch_apply=function(a,b){if(a.length==0)return[b,[]];var a=this.patch_deepCopy(a),c=this.patch_addPadding(a),b=c+b+c;this.patch_splitMax(a);for(var d=0,e=[],f=0;f<a.length;f++){var g=a[f].start2+d,h=this.diff_text1(a[f].diffs),j,i=-1;if(h.length>this.Match_MaxBits){if(j=this.match_main(b,h.substring(0,this.Match_MaxBits),g),j!=-1&&(i=this.match_main(b,h.substring(h.length-this.Match_MaxBits),g+h.length-this.Match_MaxBits),i==-1||j>=i))j=-1}else j=this.match_main(b,h,g);
+if(j==-1)e[f]=false,d-=a[f].length2-a[f].length1;else if(e[f]=true,d=j-g,g=i==-1?b.substring(j,j+h.length):b.substring(j,i+this.Match_MaxBits),h==g)b=b.substring(0,j)+this.diff_text2(a[f].diffs)+b.substring(j+h.length);else if(g=this.diff_main(h,g,false),h.length>this.Match_MaxBits&&this.diff_levenshtein(g)/h.length>this.Patch_DeleteThreshold)e[f]=false;else{this.diff_cleanupSemanticLossless(g);for(var h=0,k,i=0;i<a[f].diffs.length;i++){var p=a[f].diffs[i];p[0]!==0&&(k=this.diff_xIndex(g,h));p[0]===
+1?b=b.substring(0,j+k)+p[1]+b.substring(j+k):p[0]===-1&&(b=b.substring(0,j+k)+b.substring(j+this.diff_xIndex(g,h+p[1].length)));p[0]!==-1&&(h+=p[1].length)}}}b=b.substring(c.length,b.length-c.length);return[b,e]};
+diff_match_patch.prototype.patch_addPadding=function(a){for(var b=this.Patch_Margin,c="",d=1;d<=b;d++)c+=String.fromCharCode(d);for(d=0;d<a.length;d++)a[d].start1+=b,a[d].start2+=b;var d=a[0],e=d.diffs;if(e.length==0||e[0][0]!=0)e.unshift([0,c]),d.start1-=b,d.start2-=b,d.length1+=b,d.length2+=b;else if(b>e[0][1].length){var f=b-e[0][1].length;e[0][1]=c.substring(e[0][1].length)+e[0][1];d.start1-=f;d.start2-=f;d.length1+=f;d.length2+=f}d=a[a.length-1];e=d.diffs;e.length==0||e[e.length-1][0]!=0?(e.push([0,
+c]),d.length1+=b,d.length2+=b):b>e[e.length-1][1].length&&(f=b-e[e.length-1][1].length,e[e.length-1][1]+=c.substring(0,f),d.length1+=f,d.length2+=f);return c};
+diff_match_patch.prototype.patch_splitMax=function(a){for(var b=this.Match_MaxBits,c=0;c<a.length;c++)if(a[c].length1>b){var d=a[c];a.splice(c--,1);for(var e=d.start1,f=d.start2,g="";d.diffs.length!==0;){var h=new diff_match_patch.patch_obj,j=true;h.start1=e-g.length;h.start2=f-g.length;if(g!=="")h.length1=h.length2=g.length,h.diffs.push([0,g]);for(;d.diffs.length!==0&&h.length1<b-this.Patch_Margin;){var g=d.diffs[0][0],i=d.diffs[0][1];g===1?(h.length2+=i.length,f+=i.length,h.diffs.push(d.diffs.shift()),
+j=false):g===-1&&h.diffs.length==1&&h.diffs[0][0]==0&&i.length>2*b?(h.length1+=i.length,e+=i.length,j=false,h.diffs.push([g,i]),d.diffs.shift()):(i=i.substring(0,b-h.length1-this.Patch_Margin),h.length1+=i.length,e+=i.length,g===0?(h.length2+=i.length,f+=i.length):j=false,h.diffs.push([g,i]),i==d.diffs[0][1]?d.diffs.shift():d.diffs[0][1]=d.diffs[0][1].substring(i.length))}g=this.diff_text2(h.diffs);g=g.substring(g.length-this.Patch_Margin);i=this.diff_text1(d.diffs).substring(0,this.Patch_Margin);
+i!==""&&(h.length1+=i.length,h.length2+=i.length,h.diffs.length!==0&&h.diffs[h.diffs.length-1][0]===0?h.diffs[h.diffs.length-1][1]+=i:h.diffs.push([0,i]));j||a.splice(++c,0,h)}}};diff_match_patch.prototype.patch_toText=function(a){for(var b=[],c=0;c<a.length;c++)b[c]=a[c];return b.join("")};
+diff_match_patch.prototype.patch_fromText=function(a){var b=[];if(!a)return b;for(var a=a.split("\n"),c=0,d=/^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@$/;c<a.length;){var e=a[c].match(d);if(!e)throw Error("Invalid patch string: "+a[c]);var f=new diff_match_patch.patch_obj;b.push(f);f.start1=parseInt(e[1],10);e[2]===""?(f.start1--,f.length1=1):e[2]=="0"?f.length1=0:(f.start1--,f.length1=parseInt(e[2],10));f.start2=parseInt(e[3],10);e[4]===""?(f.start2--,f.length2=1):e[4]=="0"?f.length2=0:(f.start2--,f.length2=
+parseInt(e[4],10));for(c++;c<a.length;){e=a[c].charAt(0);try{var g=decodeURI(a[c].substring(1))}catch(h){throw Error("Illegal escape in patch_fromText: "+g);}if(e=="-")f.diffs.push([-1,g]);else if(e=="+")f.diffs.push([1,g]);else if(e==" ")f.diffs.push([0,g]);else if(e=="@")break;else if(e!=="")throw Error('Invalid patch mode "'+e+'" in: '+g);c++}}return b};diff_match_patch.patch_obj=function(){this.diffs=[];this.start2=this.start1=null;this.length2=this.length1=0};
+diff_match_patch.patch_obj.prototype.toString=function(){var a,b;a=this.length1===0?this.start1+",0":this.length1==1?this.start1+1:this.start1+1+","+this.length1;b=this.length2===0?this.start2+",0":this.length2==1?this.start2+1:this.start2+1+","+this.length2;a=["@@ -"+a+" +"+b+" @@\n"];var c;for(b=0;b<this.diffs.length;b++){switch(this.diffs[b][0]){case 1:c="+";break;case -1:c="-";break;case 0:c=" "}a[b+1]=c+encodeURI(this.diffs[b][1])+"\n"}return a.join("").replace(/%20/g," ")};
+this.diff_match_patch=diff_match_patch;this.DIFF_DELETE=-1;this.DIFF_INSERT=1;this.DIFF_EQUAL=0;})()
View
146 ...war/src/main/resources/org/zanata/webtrans/public/diff_match_patch/javascript/diff_match_patch_test.html
@@ -0,0 +1,146 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<!--
+ Test Harness for diff_match_patch.js and diff_match_patch_uncompressed.js
+
+ Copyright 2006 Google Inc.
+ http://code.google.com/p/google-diff-match-patch/
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<html>
+ <head>
+ <script type="text/javascript">
+ // Depending on the URL argument, test the compressed or uncompressed version.
+ var compressed = (document.location.search == '?compressed');
+ if (compressed) {
+ document.write('<TITLE>Test harness for diff_match_patch.js</TITLE>');
+ document.write('<scr'+'ipt type="text/javascript" src="diff_match_patch.js"></scr'+'ipt>');
+ } else {
+ document.write('<TITLE>Test harness for diff_match_patch_uncompressed.js</TITLE>');
+ document.write('<scr'+'ipt type="text/javascript" src="diff_match_patch_uncompressed.js"></scr'+'ipt>');
+ }
+ </script>
+
+ <script type="text/javascript" src="diff_match_patch_test.js"></script>
+
+ <script type="text/javascript">
+ // Counters for unit test results.
+ var test_good = 0;
+ var test_bad = 0;
+
+ // If expected and actual are the identical, print 'Ok', otherwise 'Fail!'
+ function assertEquals(msg, expected, actual) {
+ if (typeof actual == 'undefined') {
+ // msg is optional.
+ actual = expected;
+ expected = msg;
+ msg = 'Expected: \'' + expected + '\' Actual: \'' + actual + '\'';
+ }
+ if (expected === actual) {
+ document.write('<FONT COLOR="#009900">Ok</FONT><BR>');
+ test_good++;
+ } else {
+ document.write('<FONT COLOR="#990000"><BIG>Fail!</BIG></FONT><BR>');
+ msg = msg.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
+ document.write('<code>' + msg + '</code><BR>');
+ test_bad++;
+ }
+ }
+
+ function assertTrue(msg, actual) {
+ if (typeof actual == 'undefined') {
+ // msg is optional.
+ actual = msg;
+ assertEquals(true, actual);
+ } else {
+ assertEquals(msg, true, actual);
+ }
+ }
+
+ function assertFalse(msg, actual) {
+ if (typeof actual == 'undefined') {
+ // msg is optional.
+ actual = msg;
+ assertEquals(false, actual);
+ } else {
+ assertEquals(msg, false, actual);
+ }
+ }
+
+ function runTests() {
+ for (var x = 0; x < tests.length; x++) {
+ document.write('<H3>' + tests[x] + ':</H3>');
+ eval(tests[x] + '()');
+ }
+ }
+
+ var tests = [
+ 'testDiffCommonPrefix',
+ 'testDiffCommonSuffix',
+ 'testDiffCommonOverlap',
+ 'testDiffHalfMatch',
+ 'testDiffLinesToChars',
+ 'testDiffCharsToLines',
+ 'testDiffCleanupMerge',
+ 'testDiffCleanupSemanticLossless',
+ 'testDiffCleanupSemantic',
+ 'testDiffCleanupEfficiency',
+ 'testDiffPrettyHtml',
+ 'testDiffText',
+ 'testDiffDelta',
+ 'testDiffXIndex',
+ 'testDiffLevenshtein',
+ 'testDiffBisect',
+ 'testDiffMain',
+
+ 'testMatchAlphabet',
+ 'testMatchBitap',
+ 'testMatchMain',
+
+ 'testPatchObj',
+ 'testPatchFromText',
+ 'testPatchToText',
+ 'testPatchAddContext',
+ 'testPatchMake',
+ 'testPatchSplitMax',
+ 'testPatchAddPadding',
+ 'testPatchApply'];
+
+ </script>
+ </head>
+ <body>
+
+ <script type="text/javascript">
+ if (compressed) {
+ document.write('<H1>Test harness for diff_match_patch.js</H1>');
+ document.write('[ Switch to <A HREF="?uncompressed">Uncompressed</A>. ]');
+ } else {
+ document.write('<H1>Test harness for diff_match_patch_uncompressed.js</H1>');
+ document.write('[ Switch to <A HREF="?compressed">Compressed</A>. ]');
+ }
+ </script>
+
+ <P>If debugging errors, start with the first reported error,
+ subsequent tests often rely on earlier ones.</P>
+
+ <script type="text/javascript">
+ var startTime = (new Date()).getTime();
+ runTests();
+ var endTime = (new Date()).getTime();
+ document.write('<H3>Done.</H3>');
+ document.write('<P>Tests passed: ' + test_good + '<BR>Tests failed: ' + test_bad + '</P>');
+ document.write('<P>Total time: ' + (endTime - startTime) + ' ms</P>');
+ </script>
+ </body>
+</html>
View
932 ...a-war/src/main/resources/org/zanata/webtrans/public/diff_match_patch/javascript/diff_match_patch_test.js
@@ -0,0 +1,932 @@
+/**
+ * Test Harness for Diff Match and Patch
+ *
+ * Copyright 2006 Google Inc.
+ * http://code.google.com/p/google-diff-match-patch/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+// If expected and actual are the equivalent, pass the test.
+function assertEquivalent(msg, expected, actual) {
+ if (typeof actual == 'undefined') {
+ // msg is optional.
+ actual = expected;
+ expected = msg;
+ msg = 'Expected: \'' + expected + '\' Actual: \'' + actual + '\'';
+ }
+ if (_equivalent(expected, actual)) {
+ assertEquals(msg, String.toString(expected), String.toString(actual));
+ } else {
+ assertEquals(msg, expected, actual);
+ }
+}
+
+
+// Are a and b the equivalent? -- Recursive.
+function _equivalent(a, b) {
+ if (a == b) {
+ return true;
+ }
+ if (typeof a == 'object' && typeof b == 'object' && a !== null && b !== null) {
+ if (a.toString() != b.toString()) {
+ return false;
+ }
+ for (var p in a) {
+ if (!_equivalent(a[p], b[p])) {
+ return false;
+ }
+ }
+ for (var p in b) {
+ if (!_equivalent(a[p], b[p])) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+
+function diff_rebuildtexts(diffs) {
+ // Construct the two texts which made up the diff originally.
+ var text1 = '';
+ var text2 = '';
+ for (var x = 0; x < diffs.length; x++) {
+ if (diffs[x][0] != DIFF_INSERT) {
+ text1 += diffs[x][1];
+ }
+ if (diffs[x][0] != DIFF_DELETE) {
+ text2 += diffs[x][1];
+ }
+ }
+ return [text1, text2];
+}
+
+var dmp = new diff_match_patch();
+
+
+// DIFF TEST FUNCTIONS
+
+
+function testDiffCommonPrefix() {
+ // Detect any common prefix.
+ // Null case.
+ assertEquals(0, dmp.diff_commonPrefix('abc', 'xyz'));
+
+ // Non-null case.
+ assertEquals(4, dmp.diff_commonPrefix('1234abcdef', '1234xyz'));
+
+ // Whole case.
+ assertEquals(4, dmp.diff_commonPrefix('1234', '1234xyz'));
+}
+
+function testDiffCommonSuffix() {
+ // Detect any common suffix.
+ // Null case.
+ assertEquals(0, dmp.diff_commonSuffix('abc', 'xyz'));
+
+ // Non-null case.
+ assertEquals(4, dmp.diff_commonSuffix('abcdef1234', 'xyz1234'));
+
+ // Whole case.
+ assertEquals(4, dmp.diff_commonSuffix('1234', 'xyz1234'));
+}
+
+function testDiffCommonOverlap() {
+ // Detect any suffix/prefix overlap.
+ // Null case.
+ assertEquals(0, dmp.diff_commonOverlap_('', 'abcd'));
+
+ // Whole case.
+ assertEquals(3, dmp.diff_commonOverlap_('abc', 'abcd'));
+
+ // No overlap.
+ assertEquals(0, dmp.diff_commonOverlap_('123456', 'abcd'));
+
+ // Overlap.
+ assertEquals(3, dmp.diff_commonOverlap_('123456xxx', 'xxxabcd'));
+
+ // Unicode.
+ // Some overly clever languages (C#) may treat ligatures as equal to their
+ // component letters. E.g. U+FB01 == 'fi'
+ assertEquals(0, dmp.diff_commonOverlap_('fi', '\ufb01i'));
+}
+
+function testDiffHalfMatch() {
+ // Detect a halfmatch.
+ dmp.Diff_Timeout = 1;
+ // No match.
+ assertEquals(null, dmp.diff_halfMatch_('1234567890', 'abcdef'));
+
+ assertEquals(null, dmp.diff_halfMatch_('12345', '23'));
+
+ // Single Match.
+ assertEquivalent(['12', '90', 'a', 'z', '345678'], dmp.diff_halfMatch_('1234567890', 'a345678z'));
+
+ assertEquivalent(['a', 'z', '12', '90', '345678'], dmp.diff_halfMatch_('a345678z', '1234567890'));
+
+ assertEquivalent(['abc', 'z', '1234', '0', '56789'], dmp.diff_halfMatch_('abc56789z', '1234567890'));
+
+ assertEquivalent(['a', 'xyz', '1', '7890', '23456'], dmp.diff_halfMatch_('a23456xyz', '1234567890'));
+
+ // Multiple Matches.
+ assertEquivalent(['12123', '123121', 'a', 'z', '1234123451234'], dmp.diff_halfMatch_('121231234123451234123121', 'a1234123451234z'));
+
+ assertEquivalent(['', '-=-=-=-=-=', 'x', '', 'x-=-=-=-=-=-=-='], dmp.diff_halfMatch_('x-=-=-=-=-=-=-=-=-=-=-=-=', 'xx-=-=-=-=-=-=-='));
+
+ assertEquivalent(['-=-=-=-=-=', '', '', 'y', '-=-=-=-=-=-=-=y'], dmp.diff_halfMatch_('-=-=-=-=-=-=-=-=-=-=-=-=y', '-=-=-=-=-=-=-=yy'));
+
+ // Non-optimal halfmatch.
+ // Optimal diff would be -q+x=H-i+e=lloHe+Hu=llo-Hew+y not -qHillo+x=HelloHe-w+Hulloy
+ assertEquivalent(['qHillo', 'w', 'x', 'Hulloy', 'HelloHe'], dmp.diff_halfMatch_('qHilloHelloHew', 'xHelloHeHulloy'));
+
+ // Optimal no halfmatch.
+ dmp.Diff_Timeout = 0;
+ assertEquals(null, dmp.diff_halfMatch_('qHilloHelloHew', 'xHelloHeHulloy'));
+}
+
+function testDiffLinesToChars() {
+ // Convert lines down to characters.
+ assertEquivalent(['\x01\x02\x01', '\x02\x01\x02', ['', 'alpha\n', 'beta\n']], dmp.diff_linesToChars_('alpha\nbeta\nalpha\n', 'beta\nalpha\nbeta\n'));
+
+ assertEquivalent(['', '\x01\x02\x03\x03', ['', 'alpha\r\n', 'beta\r\n', '\r\n']], dmp.diff_linesToChars_('', 'alpha\r\nbeta\r\n\r\n\r\n'));
+
+ assertEquivalent(['\x01', '\x02', ['', 'a', 'b']], dmp.diff_linesToChars_('a', 'b'));
+
+ // More than 256 to reveal any 8-bit limitations.
+ var n = 300;
+ var lineList = [];
+ var charList = [];
+ for (var x = 1; x < n + 1; x++) {
+ lineList[x - 1] = x + '\n';
+ charList[x - 1] = String.fromCharCode(x);
+ }
+ assertEquals(n, lineList.length);
+ var lines = lineList.join('');
+ var chars = charList.join('');
+ assertEquals(n, chars.length);
+ lineList.unshift('');
+ assertEquivalent([chars, '', lineList], dmp.diff_linesToChars_(lines, ''));
+}
+
+function testDiffCharsToLines() {
+ // Convert chars up to lines.
+ var diffs = [[DIFF_EQUAL, '\x01\x02\x01'], [DIFF_INSERT, '\x02\x01\x02']];
+ dmp.diff_charsToLines_(diffs, ['', 'alpha\n', 'beta\n']);
+ assertEquivalent([[DIFF_EQUAL, 'alpha\nbeta\nalpha\n'], [DIFF_INSERT, 'beta\nalpha\nbeta\n']], diffs);
+
+ // More than 256 to reveal any 8-bit limitations.
+ var n = 300;
+ var lineList = [];
+ var charList = [];
+ for (var x = 1; x < n + 1; x++) {
+ lineList[x - 1] = x + '\n';
+ charList[x - 1] = String.fromCharCode(x);
+ }
+ assertEquals(n, lineList.length);
+ var lines = lineList.join('');
+ var chars = charList.join('');
+ assertEquals(n, chars.length);
+ lineList.unshift('');
+ var diffs = [[DIFF_DELETE, chars]];
+ dmp.diff_charsToLines_(diffs, lineList);
+ assertEquivalent([[DIFF_DELETE, lines]], diffs);
+}
+
+function testDiffCleanupMerge() {
+ // Cleanup a messy diff.
+ // Null case.
+ var diffs = [];
+ dmp.diff_cleanupMerge(diffs);
+ assertEquivalent([], diffs);
+
+ // No change case.
+ diffs = [[DIFF_EQUAL, 'a'], [DIFF_DELETE, 'b'], [DIFF_INSERT, 'c']];
+ dmp.diff_cleanupMerge(diffs);
+ assertEquivalent([[DIFF_EQUAL, 'a'], [DIFF_DELETE, 'b'], [DIFF_INSERT, 'c']], diffs);
+
+ // Merge equalities.
+ diffs = [[DIFF_EQUAL, 'a'], [DIFF_EQUAL, 'b'], [DIFF_EQUAL, 'c']];
+ dmp.diff_cleanupMerge(diffs);
+ assertEquivalent([[DIFF_EQUAL, 'abc']], diffs);
+
+ // Merge deletions.
+ diffs = [[DIFF_DELETE, 'a'], [DIFF_DELETE, 'b'], [DIFF_DELETE, 'c']];
+ dmp.diff_cleanupMerge(diffs);
+ assertEquivalent([[DIFF_DELETE, 'abc']], diffs);
+
+ // Merge insertions.
+ diffs = [[DIFF_INSERT, 'a'], [DIFF_INSERT, 'b'], [DIFF_INSERT, 'c']];
+ dmp.diff_cleanupMerge(diffs);
+ assertEquivalent([[DIFF_INSERT, 'abc']], diffs);
+
+ // Merge interweave.
+ diffs = [[DIFF_DELETE, 'a'], [DIFF_INSERT, 'b'], [DIFF_DELETE, 'c'], [DIFF_INSERT, 'd'], [DIFF_EQUAL, 'e'], [DIFF_EQUAL, 'f']];
+ dmp.diff_cleanupMerge(diffs);
+ assertEquivalent([[DIFF_DELETE, 'ac'], [DIFF_INSERT, 'bd'], [DIFF_EQUAL, 'ef']], diffs);
+
+ // Prefix and suffix detection.
+ diffs = [[DIFF_DELETE, 'a'], [DIFF_INSERT, 'abc'], [DIFF_DELETE, 'dc']];
+ dmp.diff_cleanupMerge(diffs);
+ assertEquivalent([[DIFF_EQUAL, 'a'], [DIFF_DELETE, 'd'], [DIFF_INSERT, 'b'], [DIFF_EQUAL, 'c']], diffs);
+
+ // Prefix and suffix detection with equalities.
+ diffs = [[DIFF_EQUAL, 'x'], [DIFF_DELETE, 'a'], [DIFF_INSERT, 'abc'], [DIFF_DELETE, 'dc'], [DIFF_EQUAL, 'y']];
+ dmp.diff_cleanupMerge(diffs);
+ assertEquivalent([[DIFF_EQUAL, 'xa'], [DIFF_DELETE, 'd'], [DIFF_INSERT, 'b'], [DIFF_EQUAL, 'cy']], diffs);
+
+ // Slide edit left.
+ diffs = [[DIFF_EQUAL, 'a'], [DIFF_INSERT, 'ba'], [DIFF_EQUAL, 'c']];
+ dmp.diff_cleanupMerge(diffs);
+ assertEquivalent([[DIFF_INSERT, 'ab'], [DIFF_EQUAL, 'ac']], diffs);
+
+ // Slide edit right.
+ diffs = [[DIFF_EQUAL, 'c'], [DIFF_INSERT, 'ab'], [DIFF_EQUAL, 'a']];
+ dmp.diff_cleanupMerge(diffs);
+ assertEquivalent([[DIFF_EQUAL, 'ca'], [DIFF_INSERT, 'ba']], diffs);
+
+ // Slide edit left recursive.
+ diffs = [[DIFF_EQUAL, 'a'], [DIFF_DELETE, 'b'], [DIFF_EQUAL, 'c'], [DIFF_DELETE, 'ac'], [DIFF_EQUAL, 'x']];
+ dmp.diff_cleanupMerge(diffs);
+ assertEquivalent([[DIFF_DELETE, 'abc'], [DIFF_EQUAL, 'acx']], diffs);
+
+ // Slide edit right recursive.
+ diffs = [[DIFF_EQUAL, 'x'], [DIFF_DELETE, 'ca'], [DIFF_EQUAL, 'c'], [DIFF_DELETE, 'b'], [DIFF_EQUAL, 'a']];
+ dmp.diff_cleanupMerge(diffs);
+ assertEquivalent([[DIFF_EQUAL, 'xca'], [DIFF_DELETE, 'cba']], diffs);
+}
+
+function testDiffCleanupSemanticLossless() {
+ // Slide diffs to match logical boundaries.
+ // Null case.
+ var diffs = [];
+ dmp.diff_cleanupSemanticLossless(diffs);
+ assertEquivalent([], diffs);
+
+ // Blank lines.
+ diffs = [[DIFF_EQUAL, 'AAA\r\n\r\nBBB'], [DIFF_INSERT, '\r\nDDD\r\n\r\nBBB'], [DIFF_EQUAL, '\r\nEEE']];
+ dmp.diff_cleanupSemanticLossless(diffs);
+ assertEquivalent([[DIFF_EQUAL, 'AAA\r\n\r\n'], [DIFF_INSERT, 'BBB\r\nDDD\r\n\r\n'], [DIFF_EQUAL, 'BBB\r\nEEE']], diffs);
+
+ // Line boundaries.
+ diffs = [[DIFF_EQUAL, 'AAA\r\nBBB'], [DIFF_INSERT, ' DDD\r\nBBB'], [DIFF_EQUAL, ' EEE']];
+ dmp.diff_cleanupSemanticLossless(diffs);
+ assertEquivalent([[DIFF_EQUAL, 'AAA\r\n'], [DIFF_INSERT, 'BBB DDD\r\n'], [DIFF_EQUAL, 'BBB EEE']], diffs);
+
+ // Word boundaries.
+ diffs = [[DIFF_EQUAL, 'The c'], [DIFF_INSERT, 'ow and the c'], [DIFF_EQUAL, 'at.']];
+ dmp.diff_cleanupSemanticLossless(diffs);
+ assertEquivalent([[DIFF_EQUAL, 'The '], [DIFF_INSERT, 'cow and the '], [DIFF_EQUAL, 'cat.']], diffs);
+
+ // Alphanumeric boundaries.
+ diffs = [[DIFF_EQUAL, 'The-c'], [DIFF_INSERT, 'ow-and-the-c'], [DIFF_EQUAL, 'at.']];
+ dmp.diff_cleanupSemanticLossless(diffs);
+ assertEquivalent([[DIFF_EQUAL, 'The-'], [DIFF_INSERT, 'cow-and-the-'], [DIFF_EQUAL, 'cat.']], diffs);
+
+ // Hitting the start.
+ diffs = [[DIFF_EQUAL, 'a'], [DIFF_DELETE, 'a'], [DIFF_EQUAL, 'ax']];
+ dmp.diff_cleanupSemanticLossless(diffs);
+ assertEquivalent([[DIFF_DELETE, 'a'], [DIFF_EQUAL, 'aax']], diffs);
+
+ // Hitting the end.
+ diffs = [[DIFF_EQUAL, 'xa'], [DIFF_DELETE, 'a'], [DIFF_EQUAL, 'a']];
+ dmp.diff_cleanupSemanticLossless(diffs);
+ assertEquivalent([[DIFF_EQUAL, 'xaa'], [DIFF_DELETE, 'a']], diffs);
+
+ // Sentence boundaries.
+ diffs = [[DIFF_EQUAL, 'The xxx. The '], [DIFF_INSERT, 'zzz. The '], [DIFF_EQUAL, 'yyy.']];
+ dmp.diff_cleanupSemanticLossless(diffs);
+ assertEquivalent([[DIFF_EQUAL, 'The xxx.'], [DIFF_INSERT, ' The zzz.'], [DIFF_EQUAL, ' The yyy.']], diffs);
+}
+
+function testDiffCleanupSemantic() {
+ // Cleanup semantically trivial equalities.
+ // Null case.
+ var diffs = [];
+ dmp.diff_cleanupSemantic(diffs);
+ assertEquivalent([], diffs);
+
+ // No elimination #1.
+ diffs = [[DIFF_DELETE, 'ab'], [DIFF_INSERT, 'cd'], [DIFF_EQUAL, '12'], [DIFF_DELETE, 'e']];
+ dmp.diff_cleanupSemantic(diffs);
+ assertEquivalent([[DIFF_DELETE, 'ab'], [DIFF_INSERT, 'cd'], [DIFF_EQUAL, '12'], [DIFF_DELETE, 'e']], diffs);
+
+ // No elimination #2.
+ diffs = [[DIFF_DELETE, 'abc'], [DIFF_INSERT, 'ABC'], [DIFF_EQUAL, '1234'], [DIFF_DELETE, 'wxyz']];
+ dmp.diff_cleanupSemantic(diffs);
+ assertEquivalent([[DIFF_DELETE, 'abc'], [DIFF_INSERT, 'ABC'], [DIFF_EQUAL, '1234'], [DIFF_DELETE, 'wxyz']], diffs);
+
+ // Simple elimination.
+ diffs = [[DIFF_DELETE, 'a'], [DIFF_EQUAL, 'b'], [DIFF_DELETE, 'c']];
+ dmp.diff_cleanupSemantic(diffs);
+ assertEquivalent([[DIFF_DELETE, 'abc'], [DIFF_INSERT, 'b']], diffs);
+
+ // Backpass elimination.
+ diffs = [[DIFF_DELETE, 'ab'], [DIFF_EQUAL, 'cd'], [DIFF_DELETE, 'e'], [DIFF_EQUAL, 'f'], [DIFF_INSERT, 'g']];
+ dmp.diff_cleanupSemantic(diffs);
+ assertEquivalent([[DIFF_DELETE, 'abcdef'], [DIFF_INSERT, 'cdfg']], diffs);
+
+ // Multiple eliminations.
+ diffs = [[DIFF_INSERT, '1'], [DIFF_EQUAL, 'A'], [DIFF_DELETE, 'B'], [DIFF_INSERT, '2'], [DIFF_EQUAL, '_'], [DIFF_INSERT, '1'], [DIFF_EQUAL, 'A'], [DIFF_DELETE, 'B'], [DIFF_INSERT, '2']];
+ dmp.diff_cleanupSemantic(diffs);
+ assertEquivalent([[DIFF_DELETE, 'AB_AB'], [DIFF_INSERT, '1A2_1A2']], diffs);
+
+ // Word boundaries.
+ diffs = [[DIFF_EQUAL, 'The c'], [DIFF_DELETE, 'ow and the c'], [DIFF_EQUAL, 'at.']];
+ dmp.diff_cleanupSemantic(diffs);
+ assertEquivalent([[DIFF_EQUAL, 'The '], [DIFF_DELETE, 'cow and the '], [DIFF_EQUAL, 'cat.']], diffs);
+
+ // No overlap elimination.
+ diffs = [[DIFF_DELETE, 'abcxx'], [DIFF_INSERT, 'xxdef']];
+ dmp.diff_cleanupSemantic(diffs);
+ assertEquivalent([[DIFF_DELETE, 'abcxx'], [DIFF_INSERT, 'xxdef']], diffs);
+
+ // Overlap elimination.
+ diffs = [[DIFF_DELETE, 'abcxxx'], [DIFF_INSERT, 'xxxdef']];
+ dmp.diff_cleanupSemantic(diffs);
+ assertEquivalent([[DIFF_DELETE, 'abc'], [DIFF_EQUAL, 'xxx'], [DIFF_INSERT, 'def']], diffs);
+
+ // Reverse overlap elimination.
+ diffs = [[DIFF_DELETE, 'xxxabc'], [DIFF_INSERT, 'defxxx']];
+ dmp.diff_cleanupSemantic(diffs);
+ assertEquivalent([[DIFF_INSERT, 'def'], [DIFF_EQUAL, 'xxx'], [DIFF_DELETE, 'abc']], diffs);
+
+ // Two overlap eliminations.
+ diffs = [[DIFF_DELETE, 'abcd1212'], [DIFF_INSERT, '1212efghi'], [DIFF_EQUAL, '----'], [DIFF_DELETE, 'A3'], [DIFF_INSERT, '3BC']];
+ dmp.diff_cleanupSemantic(diffs);
+ assertEquivalent([[DIFF_DELETE, 'abcd'], [DIFF_EQUAL, '1212'], [DIFF_INSERT, 'efghi'], [DIFF_EQUAL, '----'], [DIFF_DELETE, 'A'], [DIFF_EQUAL, '3'], [DIFF_INSERT, 'BC']], diffs);
+}
+
+function testDiffCleanupEfficiency() {
+ // Cleanup operationally trivial equalities.
+ dmp.Diff_EditCost = 4;
+ // Null case.
+ var diffs = [];
+ dmp.diff_cleanupEfficiency(diffs);
+ assertEquivalent([], diffs);
+
+ // No elimination.
+ diffs = [[DIFF_DELETE, 'ab'], [DIFF_INSERT, '12'], [DIFF_EQUAL, 'wxyz'], [DIFF_DELETE, 'cd'], [DIFF_INSERT, '34']];
+ dmp.diff_cleanupEfficiency(diffs);
+ assertEquivalent([[DIFF_DELETE, 'ab'], [DIFF_INSERT, '12'], [DIFF_EQUAL, 'wxyz'], [DIFF_DELETE, 'cd'], [DIFF_INSERT, '34']], diffs);
+
+ // Four-edit elimination.
+ diffs = [[DIFF_DELETE, 'ab'], [DIFF_INSERT, '12'], [DIFF_EQUAL, 'xyz'], [DIFF_DELETE, 'cd'], [DIFF_INSERT, '34']];
+ dmp.diff_cleanupEfficiency(diffs);
+ assertEquivalent([[DIFF_DELETE, 'abxyzcd'], [DIFF_INSERT, '12xyz34']], diffs);
+
+ // Three-edit elimination.
+ diffs = [[DIFF_INSERT, '12'], [DIFF_EQUAL, 'x'], [DIFF_DELETE, 'cd'], [DIFF_INSERT, '34']];
+ dmp.diff_cleanupEfficiency(diffs);
+ assertEquivalent([[DIFF_DELETE, 'xcd'], [DIFF_INSERT, '12x34']], diffs);
+
+ // Backpass elimination.
+ diffs = [[DIFF_DELETE, 'ab'], [DIFF_INSERT, '12'], [DIFF_EQUAL, 'xy'], [DIFF_INSERT, '34'], [DIFF_EQUAL, 'z'], [DIFF_DELETE, 'cd'], [DIFF_INSERT, '56']];
+ dmp.diff_cleanupEfficiency(diffs);
+ assertEquivalent([[DIFF_DELETE, 'abxyzcd'], [DIFF_INSERT, '12xy34z56']], diffs);
+
+ // High cost elimination.
+ dmp.Diff_EditCost = 5;
+ diffs = [[DIFF_DELETE, 'ab'], [DIFF_INSERT, '12'], [DIFF_EQUAL, 'wxyz'], [DIFF_DELETE, 'cd'], [DIFF_INSERT, '34']];
+ dmp.diff_cleanupEfficiency(diffs);
+ assertEquivalent([[DIFF_DELETE, 'abwxyzcd'], [DIFF_INSERT, '12wxyz34']], diffs);
+ dmp.Diff_EditCost = 4;
+}
+
+function testDiffPrettyHtml() {
+ // Pretty print.
+ var diffs = [[DIFF_EQUAL, 'a\n'], [DIFF_DELETE, '<B>b</B>'], [DIFF_INSERT, 'c&d']];
+ assertEquals('<span>a&para;<br></span><del style="background:#ffe6e6;">&lt;B&gt;b&lt;/B&gt;</del><ins style="background:#e6ffe6;">c&amp;d</ins>', dmp.diff_prettyHtml(diffs));
+}
+
+function testDiffText() {
+ // Compute the source and destination texts.
+ var diffs = [[DIFF_EQUAL, 'jump'], [DIFF_DELETE, 's'], [DIFF_INSERT, 'ed'], [DIFF_EQUAL, ' over '], [DIFF_DELETE, 'the'], [DIFF_INSERT, 'a'], [DIFF_EQUAL, ' lazy']];
+ assertEquals('jumps over the lazy', dmp.diff_text1(diffs));
+
+ assertEquals('jumped over a lazy', dmp.diff_text2(diffs));
+}
+
+function testDiffDelta() {
+ // Convert a diff into delta string.
+ var diffs = [[DIFF_EQUAL, 'jump'], [DIFF_DELETE, 's'], [DIFF_INSERT, 'ed'], [DIFF_EQUAL, ' over '], [DIFF_DELETE, 'the'], [DIFF_INSERT, 'a'], [DIFF_EQUAL, ' lazy'], [DIFF_INSERT, 'old dog']];
+ var text1 = dmp.diff_text1(diffs);
+ assertEquals('jumps over the lazy', text1);
+
+ var delta = dmp.diff_toDelta(diffs);
+ assertEquals('=4\t-1\t+ed\t=6\t-3\t+a\t=5\t+old dog', delta);
+
+ // Convert delta string into a diff.
+ assertEquivalent(diffs, dmp.diff_fromDelta(text1, delta));
+
+ // Generates error (19 != 20).
+ try {
+ dmp.diff_fromDelta(text1 + 'x', delta);
+ assertEquals(Error, null);
+ } catch (e) {
+ // Exception expected.
+ }
+
+ // Generates error (19 != 18).
+ try {
+ dmp.diff_fromDelta(text1.substring(1), delta);
+ assertEquals(Error, null);
+ } catch (e) {
+ // Exception expected.
+ }
+
+ // Generates error (%c3%xy invalid Unicode).
+ try {
+ dmp.diff_fromDelta('', '+%c3%xy');
+ assertEquals(Error, null);
+ } catch (e) {
+ // Exception expected.
+ }
+
+ // Test deltas with special characters.
+ diffs = [[DIFF_EQUAL, '\u0680 \x00 \t %'], [DIFF_DELETE, '\u0681 \x01 \n ^'], [DIFF_INSERT, '\u0682 \x02 \\ |']];
+ text1 = dmp.diff_text1(diffs);
+ assertEquals('\u0680 \x00 \t %\u0681 \x01 \n ^', text1);
+
+ delta = dmp.diff_toDelta(diffs);
+ assertEquals('=7\t-7\t+%DA%82 %02 %5C %7C', delta);
+
+ // Convert delta string into a diff.
+ assertEquivalent(diffs, dmp.diff_fromDelta(text1, delta));
+
+ // Verify pool of unchanged characters.
+ diffs = [[DIFF_INSERT, 'A-Z a-z 0-9 - _ . ! ~ * \' ( ) ; / ? : @ & = + $ , # ']];
+ var text2 = dmp.diff_text2(diffs);
+ assertEquals('A-Z a-z 0-9 - _ . ! ~ * \' ( ) ; / ? : @ & = + $ , # ', text2);
+
+ delta = dmp.diff_toDelta(diffs);
+ assertEquals('+A-Z a-z 0-9 - _ . ! ~ * \' ( ) ; / ? : @ & = + $ , # ', delta);
+
+ // Convert delta string into a diff.
+ assertEquivalent(diffs, dmp.diff_fromDelta('', delta));
+}
+
+function testDiffXIndex() {
+ // Translate a location in text1 to text2.
+ // Translation on equality.
+ assertEquals(5, dmp.diff_xIndex([[DIFF_DELETE, 'a'], [DIFF_INSERT, '1234'], [DIFF_EQUAL, 'xyz']], 2));
+
+ // Translation on deletion.
+ assertEquals(1, dmp.diff_xIndex([[DIFF_EQUAL, 'a'], [DIFF_DELETE, '1234'], [DIFF_EQUAL, 'xyz']], 3));
+}
+
+function testDiffLevenshtein() {
+ // Levenshtein with trailing equality.
+ assertEquals(4, dmp.diff_levenshtein([[DIFF_DELETE, 'abc'], [DIFF_INSERT, '1234'], [DIFF_EQUAL, 'xyz']]));
+ // Levenshtein with leading equality.
+ assertEquals(4, dmp.diff_levenshtein([[DIFF_EQUAL, 'xyz'], [DIFF_DELETE, 'abc'], [DIFF_INSERT, '1234']]));
+ // Levenshtein with middle equality.
+ assertEquals(7, dmp.diff_levenshtein([[DIFF_DELETE, 'abc'], [DIFF_EQUAL, 'xyz'], [DIFF_INSERT, '1234']]));
+}
+
+function testDiffBisect() {
+ // Normal.
+ var a = 'cat';
+ var b = 'map';
+ // Since the resulting diff hasn't been normalized, it would be ok if
+ // the insertion and deletion pairs are swapped.
+ // If the order changes, tweak this test as required.
+ assertEquivalent([[DIFF_DELETE, 'c'], [DIFF_INSERT, 'm'], [DIFF_EQUAL, 'a'], [DIFF_DELETE, 't'], [DIFF_INSERT, 'p']], dmp.diff_bisect_(a, b, Number.MAX_VALUE));
+
+ // Timeout.
+ assertEquivalent([[DIFF_DELETE, 'cat'], [DIFF_INSERT, 'map']], dmp.diff_bisect_(a, b, 0));
+}
+
+function testDiffMain() {
+ // Perform a trivial diff.
+ // Null case.
+ assertEquivalent([], dmp.diff_main('', '', false));
+
+ // Equality.
+ assertEquivalent([[DIFF_EQUAL, 'abc']], dmp.diff_main('abc', 'abc', false));
+
+ // Simple insertion.
+ assertEquivalent([[DIFF_EQUAL, 'ab'], [DIFF_INSERT, '123'], [DIFF_EQUAL, 'c']], dmp.diff_main('abc', 'ab123c', false));
+
+ // Simple deletion.
+ assertEquivalent([[DIFF_EQUAL, 'a'], [DIFF_DELETE, '123'], [DIFF_EQUAL, 'bc']], dmp.diff_main('a123bc', 'abc', false));
+
+ // Two insertions.
+ assertEquivalent([[DIFF_EQUAL, 'a'], [DIFF_INSERT, '123'], [DIFF_EQUAL, 'b'], [DIFF_INSERT, '456'], [DIFF_EQUAL, 'c']], dmp.diff_main('abc', 'a123b456c', false));
+
+ // Two deletions.
+ assertEquivalent([[DIFF_EQUAL, 'a'], [DIFF_DELETE, '123'], [DIFF_EQUAL, 'b'], [DIFF_DELETE, '456'], [DIFF_EQUAL, 'c']], dmp.diff_main('a123b456c', 'abc', false));
+
+ // Perform a real diff.
+ // Switch off the timeout.
+ dmp.Diff_Timeout = 0;
+ // Simple cases.
+ assertEquivalent([[DIFF_DELETE, 'a'], [DIFF_INSERT, 'b']], dmp.diff_main('a', 'b', false));
+
+ assertEquivalent([[DIFF_DELETE, 'Apple'], [DIFF_INSERT, 'Banana'], [DIFF_EQUAL, 's are a'], [DIFF_INSERT, 'lso'], [DIFF_EQUAL, ' fruit.']], dmp.diff_main('Apples are a fruit.', 'Bananas are also fruit.', false));
+
+ assertEquivalent([[DIFF_DELETE, 'a'], [DIFF_INSERT, '\u0680'], [DIFF_EQUAL, 'x'], [DIFF_DELETE, '\t'], [DIFF_INSERT, '\0']], dmp.diff_main('ax\t', '\u0680x\0', false));
+
+ // Overlaps.
+ assertEquivalent([[DIFF_DELETE, '1'], [DIFF_EQUAL, 'a'], [DIFF_DELETE, 'y'], [DIFF_EQUAL, 'b'], [DIFF_DELETE, '2'], [DIFF_INSERT, 'xab']], dmp.diff_main('1ayb2', 'abxab', false));
+
+ assertEquivalent([[DIFF_INSERT, 'xaxcx'], [DIFF_EQUAL, 'abc'], [DIFF_DELETE, 'y']], dmp.diff_main('abcy', 'xaxcxabc', false));
+
+ assertEquivalent([[DIFF_DELETE, 'ABCD'], [DIFF_EQUAL, 'a'], [DIFF_DELETE, '='], [DIFF_INSERT, '-'], [DIFF_EQUAL, 'bcd'], [DIFF_DELETE, '='], [DIFF_INSERT, '-'], [DIFF_EQUAL, 'efghijklmnopqrs'], [DIFF_DELETE, 'EFGHIJKLMNOefg']], dmp.diff_main('ABCDa=bcd=efghijklmnopqrsEFGHIJKLMNOefg', 'a-bcd-efghijklmnopqrs', false));
+
+ // Large equality.
+ assertEquivalent([[DIFF_INSERT, ' '], [DIFF_EQUAL, 'a'], [DIFF_INSERT, 'nd'], [DIFF_EQUAL, ' [[Pennsylvania]]'], [DIFF_DELETE, ' and [[New']], dmp.diff_main('a [[Pennsylvania]] and [[New', ' and [[Pennsylvania]]', false));
+
+ // Timeout.
+ dmp.Diff_Timeout = 0.1; // 100ms
+ var a = '`Twas brillig, and the slithy toves\nDid gyre and gimble in the wabe:\nAll mimsy were the borogoves,\nAnd the mome raths outgrabe.\n';
+ var b = 'I am the very model of a modern major general,\nI\'ve information vegetable, animal, and mineral,\nI know the kings of England, and I quote the fights historical,\nFrom Marathon to Waterloo, in order categorical.\n';
+ // Increase the text lengths by 1024 times to ensure a timeout.
+ for (var x = 0; x < 10; x++) {
+ a = a + a;
+ b = b + b;
+ }
+ var startTime = (new Date()).getTime();
+ dmp.diff_main(a, b);
+ var endTime = (new Date()).getTime();
+ // Test that we took at least the timeout period.
+ assertTrue(dmp.Diff_Timeout * 1000 <= endTime - startTime);
+ // Test that we didn't take forever (be forgiving).
+ // Theoretically this test could fail very occasionally if the
+ // OS task swaps or locks up for a second at the wrong moment.
+ // ****
+ // TODO(fraser): For unknown reasons this is taking 500 ms on Google's
+ // internal test system. Whereas browsers take 140 ms.
+ //assertTrue(dmp.Diff_Timeout * 1000 * 2 > endTime - startTime);
+ // ****
+ dmp.Diff_Timeout = 0;
+
+ // Test the linemode speedup.
+ // Must be long to pass the 100 char cutoff.
+ // Simple line-mode.
+ a = '1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n';
+ b = 'abcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\n';
+ assertEquivalent(dmp.diff_main(a, b, false), dmp.diff_main(a, b, true));
+
+ // Single line-mode.
+ a = '1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890';
+ b = 'abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij';
+ assertEquivalent(dmp.diff_main(a, b, false), dmp.diff_main(a, b, true));
+
+ // Overlap line-mode.
+ a = '1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n';
+ b = 'abcdefghij\n1234567890\n1234567890\n1234567890\nabcdefghij\n1234567890\n1234567890\n1234567890\nabcdefghij\n1234567890\n1234567890\n1234567890\nabcdefghij\n';
+ var texts_linemode = diff_rebuildtexts(dmp.diff_main(a, b, true));
+ var texts_textmode = diff_rebuildtexts(dmp.diff_main(a, b, false));
+ assertEquivalent(texts_textmode, texts_linemode);
+
+ // Test null inputs.
+ try {
+ dmp.diff_main(null, null);
+ assertEquals(Error, null);
+ } catch (e) {
+ // Exception expected.
+ }
+}
+
+
+// MATCH TEST FUNCTIONS
+
+
+function testMatchAlphabet() {
+ // Initialise the bitmasks for Bitap.
+ // Unique.
+ assertEquivalent({'a':4, 'b':2, 'c':1}, dmp.match_alphabet_('abc'));
+
+ // Duplicates.
+ assertEquivalent({'a':37, 'b':18, 'c':8}, dmp.match_alphabet_('abcaba'));
+}
+
+function testMatchBitap() {
+ // Bitap algorithm.
+ dmp.Match_Distance = 100;
+ dmp.Match_Threshold = 0.5;
+ // Exact matches.
+ assertEquals(5, dmp.match_bitap_('abcdefghijk', 'fgh', 5));
+
+ assertEquals(5, dmp.match_bitap_('abcdefghijk', 'fgh', 0));
+
+ // Fuzzy matches.
+ assertEquals(4, dmp.match_bitap_('abcdefghijk', 'efxhi', 0));
+
+ assertEquals(2, dmp.match_bitap_('abcdefghijk', 'cdefxyhijk', 5));
+
+ assertEquals(-1, dmp.match_bitap_('abcdefghijk', 'bxy', 1));
+
+ // Overflow.
+ assertEquals(2, dmp.match_bitap_('123456789xx0', '3456789x0', 2));
+
+ // Threshold test.
+ dmp.Match_Threshold = 0.4;
+ assertEquals(4, dmp.match_bitap_('abcdefghijk', 'efxyhi', 1));
+
+ dmp.Match_Threshold = 0.3;
+ assertEquals(-1, dmp.match_bitap_('abcdefghijk', 'efxyhi', 1));
+
+ dmp.Match_Threshold = 0.0;
+ assertEquals(1, dmp.match_bitap_('abcdefghijk', 'bcdef', 1));
+ dmp.Match_Threshold = 0.5;
+
+ // Multiple select.
+ assertEquals(0, dmp.match_bitap_('abcdexyzabcde', 'abccde', 3));
+
+ assertEquals(8, dmp.match_bitap_('abcdexyzabcde', 'abccde', 5));
+
+ // Distance test.
+ dmp.Match_Distance = 10; // Strict location.
+ assertEquals(-1, dmp.match_bitap_('abcdefghijklmnopqrstuvwxyz', 'abcdefg', 24));
+
+ assertEquals(0, dmp.match_bitap_('abcdefghijklmnopqrstuvwxyz', 'abcdxxefg', 1));
+
+ dmp.Match_Distance = 1000; // Loose location.
+ assertEquals(0, dmp.match_bitap_('abcdefghijklmnopqrstuvwxyz', 'abcdefg', 24));
+}
+
+function testMatchMain() {
+ // Full match.
+ // Shortcut matches.
+ assertEquals(0, dmp.match_main('abcdef', 'abcdef', 1000));
+
+ assertEquals(-1, dmp.match_main('', 'abcdef', 1));
+
+ assertEquals(3, dmp.match_main('abcdef', '', 3));
+
+ assertEquals(3, dmp.match_main('abcdef', 'de', 3));
+
+ // Beyond end match.
+ assertEquals(3, dmp.match_main("abcdef", "defy", 4));
+
+ // Oversized pattern.
+ assertEquals(0, dmp.match_main("abcdef", "abcdefy", 0));
+
+ // Complex match.
+ assertEquals(4, dmp.match_main('I am the very model of a modern major general.', ' that berry ', 5));
+
+ // Test null inputs.
+ try {
+ dmp.match_main(null, null, 0);
+ assertEquals(Error, null);
+ } catch (e) {
+ // Exception expected.
+ }
+}
+
+
+// PATCH TEST FUNCTIONS
+
+
+function testPatchObj() {
+ // Patch Object.
+ var p = new diff_match_patch.patch_obj();
+ p.start1 = 20;
+ p.start2 = 21;
+ p.length1 = 18;
+ p.length2 = 17;
+ p.diffs = [[DIFF_EQUAL, 'jump'], [DIFF_DELETE, 's'], [DIFF_INSERT, 'ed'], [DIFF_EQUAL, ' over '], [DIFF_DELETE, 'the'], [DIFF_INSERT, 'a'], [DIFF_EQUAL, '\nlaz']];
+ var strp = p.toString();
+ assertEquals('@@ -21,18 +22,17 @@\n jump\n-s\n+ed\n over \n-the\n+a\n %0Alaz\n', strp);
+}
+
+function testPatchFromText() {
+ assertEquivalent([], dmp.patch_fromText(strp));
+
+ var strp = '@@ -21,18 +22,17 @@\n jump\n-s\n+ed\n over \n-the\n+a\n %0Alaz\n';
+ assertEquals(strp, dmp.patch_fromText(strp)[0].toString());
+
+ assertEquals('@@ -1 +1 @@\n-a\n+b\n', dmp.patch_fromText('@@ -1 +1 @@\n-a\n+b\n')[0].toString());
+
+ assertEquals('@@ -1,3 +0,0 @@\n-abc\n', dmp.patch_fromText('@@ -1,3 +0,0 @@\n-abc\n')[0].toString());
+
+ assertEquals('@@ -0,0 +1,3 @@\n+abc\n', dmp.patch_fromText('@@ -0,0 +1,3 @@\n+abc\n')[0].toString());
+
+ // Generates error.
+ try {
+ dmp.patch_fromText('Bad\nPatch\n');
+ assertEquals(Error, null);
+ } catch (e) {
+ // Exception expected.
+ }
+}
+
+function testPatchToText() {
+ var strp = '@@ -21,18 +22,17 @@\n jump\n-s\n+ed\n over \n-the\n+a\n laz\n';
+ var p = dmp.patch_fromText(strp);
+ assertEquals(strp, dmp.patch_toText(p));
+
+ strp = '@@ -1,9 +1,9 @@\n-f\n+F\n oo+fooba\n@@ -7,9 +7,9 @@\n obar\n-,\n+.\n tes\n';
+ p = dmp.patch_fromText(strp);
+ assertEquals(strp, dmp.patch_toText(p));
+}
+
+function testPatchAddContext() {
+ dmp.Patch_Margin = 4;
+ var p = dmp.patch_fromText('@@ -21,4 +21,10 @@\n-jump\n+somersault\n')[0];
+ dmp.patch_addContext_(p, 'The quick brown fox jumps over the lazy dog.');
+ assertEquals('@@ -17,12 +17,18 @@\n fox \n-jump\n+somersault\n s ov\n', p.toString());
+
+ // Same, but not enough trailing context.
+ p = dmp.patch_fromText('@@ -21,4 +21,10 @@\n-jump\n+somersault\n')[0];
+ dmp.patch_addContext_(p, 'The quick brown fox jumps.');
+ assertEquals('@@ -17,10 +17,16 @@\n fox \n-jump\n+somersault\n s.\n', p.toString());
+
+ // Same, but not enough leading context.
+ p = dmp.patch_fromText('@@ -3 +3,2 @@\n-e\n+at\n')[0];
+ dmp.patch_addContext_(p, 'The quick brown fox jumps.');
+ assertEquals('@@ -1,7 +1,8 @@\n Th\n-e\n+at\n qui\n', p.toString());
+
+ // Same, but with ambiguity.
+ p = dmp.patch_fromText('@@ -3 +3,2 @@\n-e\n+at\n')[0];
+ dmp.patch_addContext_(p, 'The quick brown fox jumps. The quick brown fox crashes.');
+ assertEquals('@@ -1,27 +1,28 @@\n Th\n-e\n+at\n quick brown fox jumps. \n', p.toString());
+}
+
+function testPatchMake() {
+ // Null case.
+ var patches = dmp.patch_make('', '');
+ assertEquals('', dmp.patch_toText(patches));
+
+ var text1 = 'The quick brown fox jumps over the lazy dog.';
+ var text2 = 'That quick brown fox jumped over a lazy dog.';
+ // Text2+Text1 inputs.
+ var expectedPatch = '@@ -1,8 +1,7 @@\n Th\n-at\n+e\n qui\n@@ -21,17 +21,18 @@\n jump\n-ed\n+s\n over \n-a\n+the\n laz\n';
+ // The second patch must be "-21,17 +21,18", not "-22,17 +21,18" due to rolling context.
+ patches = dmp.patch_make(text2, text1);
+ assertEquals(expectedPatch, dmp.patch_toText(patches));
+
+ // Text1+Text2 inputs.
+ expectedPatch = '@@ -1,11 +1,12 @@\n Th\n-e\n+at\n quick b\n@@ -22,18 +22,17 @@\n jump\n-s\n+ed\n over \n-the\n+a\n laz\n';
+ patches = dmp.patch_make(text1, text2);
+ assertEquals(expectedPatch, dmp.patch_toText(patches));
+
+ // Diff input.
+ var diffs = dmp.diff_main(text1, text2, false);
+ patches = dmp.patch_make(diffs);
+ assertEquals(expectedPatch, dmp.patch_toText(patches));
+
+ // Text1+Diff inputs.
+ patches = dmp.patch_make(text1, diffs);
+ assertEquals(expectedPatch, dmp.patch_toText(patches));
+
+ // Text1+Text2+Diff inputs (deprecated).
+ patches = dmp.patch_make(text1, text2, diffs);
+ asser