diff.js 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. "use strict";
  2. var __extends = (this && this.__extends) || (function () {
  3. var extendStatics = function (d, b) {
  4. extendStatics = Object.setPrototypeOf ||
  5. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  6. function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
  7. return extendStatics(d, b);
  8. };
  9. return function (d, b) {
  10. if (typeof b !== "function" && b !== null)
  11. throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
  12. extendStatics(d, b);
  13. function __() { this.constructor = d; }
  14. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  15. };
  16. })();
  17. Object.defineProperty(exports, "__esModule", { value: true });
  18. var PropTypes = require("prop-types");
  19. var React = require("react");
  20. var split_1 = require("./split");
  21. var DiffMatchPatch = require("diff-match-patch");
  22. var DiffComponent = /** @class */ (function (_super) {
  23. __extends(DiffComponent, _super);
  24. function DiffComponent(props) {
  25. var _this = _super.call(this, props) || this;
  26. _this.state = {
  27. value: _this.props.value
  28. };
  29. _this.onChange = _this.onChange.bind(_this);
  30. _this.diff = _this.diff.bind(_this);
  31. return _this;
  32. }
  33. DiffComponent.prototype.componentDidUpdate = function () {
  34. var value = this.props.value;
  35. if (value !== this.state.value) {
  36. this.setState({ value: value });
  37. }
  38. };
  39. DiffComponent.prototype.onChange = function (value) {
  40. this.setState({
  41. value: value
  42. });
  43. if (this.props.onChange) {
  44. this.props.onChange(value);
  45. }
  46. };
  47. DiffComponent.prototype.diff = function () {
  48. var dmp = new DiffMatchPatch();
  49. var lhString = this.state.value[0];
  50. var rhString = this.state.value[1];
  51. if (lhString.length === 0 && rhString.length === 0) {
  52. return [];
  53. }
  54. var diff = dmp.diff_main(lhString, rhString);
  55. dmp.diff_cleanupSemantic(diff);
  56. var diffedLines = this.generateDiffedLines(diff);
  57. var codeEditorSettings = this.setCodeMarkers(diffedLines);
  58. return codeEditorSettings;
  59. };
  60. DiffComponent.prototype.generateDiffedLines = function (diff) {
  61. var C = {
  62. DIFF_EQUAL: 0,
  63. DIFF_DELETE: -1,
  64. DIFF_INSERT: 1
  65. };
  66. var diffedLines = {
  67. left: [],
  68. right: []
  69. };
  70. var cursor = {
  71. left: 1,
  72. right: 1
  73. };
  74. diff.forEach(function (chunk) {
  75. var chunkType = chunk[0];
  76. var text = chunk[1];
  77. var lines = text.split("\n").length - 1;
  78. // diff-match-patch sometimes returns empty strings at random
  79. if (text.length === 0) {
  80. return;
  81. }
  82. var firstChar = text[0];
  83. var lastChar = text[text.length - 1];
  84. var linesToHighlight = 0;
  85. switch (chunkType) {
  86. case C.DIFF_EQUAL:
  87. cursor.left += lines;
  88. cursor.right += lines;
  89. break;
  90. case C.DIFF_DELETE:
  91. // If the deletion starts with a newline, push the cursor down to that line
  92. if (firstChar === "\n") {
  93. cursor.left++;
  94. lines--;
  95. }
  96. linesToHighlight = lines;
  97. // If the deletion does not include a newline, highlight the same line on the right
  98. if (linesToHighlight === 0) {
  99. diffedLines.right.push({
  100. startLine: cursor.right,
  101. endLine: cursor.right
  102. });
  103. }
  104. // If the last character is a newline, we don't want to highlight that line
  105. if (lastChar === "\n") {
  106. linesToHighlight -= 1;
  107. }
  108. diffedLines.left.push({
  109. startLine: cursor.left,
  110. endLine: cursor.left + linesToHighlight
  111. });
  112. cursor.left += lines;
  113. break;
  114. case C.DIFF_INSERT:
  115. // If the insertion starts with a newline, push the cursor down to that line
  116. if (firstChar === "\n") {
  117. cursor.right++;
  118. lines--;
  119. }
  120. linesToHighlight = lines;
  121. // If the insertion does not include a newline, highlight the same line on the left
  122. if (linesToHighlight === 0) {
  123. diffedLines.left.push({
  124. startLine: cursor.left,
  125. endLine: cursor.left
  126. });
  127. }
  128. // If the last character is a newline, we don't want to highlight that line
  129. if (lastChar === "\n") {
  130. linesToHighlight -= 1;
  131. }
  132. diffedLines.right.push({
  133. startLine: cursor.right,
  134. endLine: cursor.right + linesToHighlight
  135. });
  136. cursor.right += lines;
  137. break;
  138. default:
  139. throw new Error("Diff type was not defined.");
  140. }
  141. });
  142. return diffedLines;
  143. };
  144. // Receives a collection of line numbers and iterates through them to highlight appropriately
  145. // Returns an object that tells the render() method how to display the code editors
  146. DiffComponent.prototype.setCodeMarkers = function (diffedLines) {
  147. if (diffedLines === void 0) { diffedLines = { left: [], right: [] }; }
  148. var codeEditorSettings = [];
  149. var newMarkerSet = {
  150. left: [],
  151. right: []
  152. };
  153. for (var i = 0; i < diffedLines.left.length; i++) {
  154. var markerObj = {
  155. startRow: diffedLines.left[i].startLine - 1,
  156. endRow: diffedLines.left[i].endLine,
  157. type: "text",
  158. className: "codeMarker"
  159. };
  160. newMarkerSet.left.push(markerObj);
  161. }
  162. for (var i = 0; i < diffedLines.right.length; i++) {
  163. var markerObj = {
  164. startRow: diffedLines.right[i].startLine - 1,
  165. endRow: diffedLines.right[i].endLine,
  166. type: "text",
  167. className: "codeMarker"
  168. };
  169. newMarkerSet.right.push(markerObj);
  170. }
  171. codeEditorSettings[0] = newMarkerSet.left;
  172. codeEditorSettings[1] = newMarkerSet.right;
  173. return codeEditorSettings;
  174. };
  175. DiffComponent.prototype.render = function () {
  176. var markers = this.diff();
  177. return (React.createElement(split_1.default, { name: this.props.name, className: this.props.className, focus: this.props.focus, orientation: this.props.orientation, splits: this.props.splits, mode: this.props.mode, theme: this.props.theme, height: this.props.height, width: this.props.width, fontSize: this.props.fontSize, showGutter: this.props.showGutter, onChange: this.onChange, onPaste: this.props.onPaste, onLoad: this.props.onLoad, onScroll: this.props.onScroll, minLines: this.props.minLines, maxLines: this.props.maxLines, readOnly: this.props.readOnly, highlightActiveLine: this.props.highlightActiveLine, showPrintMargin: this.props.showPrintMargin, tabSize: this.props.tabSize, cursorStart: this.props.cursorStart, editorProps: this.props.editorProps, style: this.props.style, scrollMargin: this.props.scrollMargin, setOptions: this.props.setOptions, wrapEnabled: this.props.wrapEnabled, enableBasicAutocompletion: this.props.enableBasicAutocompletion, enableLiveAutocompletion: this.props.enableLiveAutocompletion, value: this.state.value, markers: markers }));
  178. };
  179. DiffComponent.propTypes = {
  180. cursorStart: PropTypes.number,
  181. editorProps: PropTypes.object,
  182. enableBasicAutocompletion: PropTypes.bool,
  183. enableLiveAutocompletion: PropTypes.bool,
  184. focus: PropTypes.bool,
  185. fontSize: PropTypes.number,
  186. height: PropTypes.string,
  187. highlightActiveLine: PropTypes.bool,
  188. maxLines: PropTypes.number,
  189. minLines: PropTypes.number,
  190. mode: PropTypes.string,
  191. name: PropTypes.string,
  192. className: PropTypes.string,
  193. onLoad: PropTypes.func,
  194. onPaste: PropTypes.func,
  195. onScroll: PropTypes.func,
  196. onChange: PropTypes.func,
  197. orientation: PropTypes.string,
  198. readOnly: PropTypes.bool,
  199. scrollMargin: PropTypes.array,
  200. setOptions: PropTypes.object,
  201. showGutter: PropTypes.bool,
  202. showPrintMargin: PropTypes.bool,
  203. splits: PropTypes.number,
  204. style: PropTypes.object,
  205. tabSize: PropTypes.number,
  206. theme: PropTypes.string,
  207. value: PropTypes.array,
  208. width: PropTypes.string,
  209. wrapEnabled: PropTypes.bool
  210. };
  211. DiffComponent.defaultProps = {
  212. cursorStart: 1,
  213. editorProps: {},
  214. enableBasicAutocompletion: false,
  215. enableLiveAutocompletion: false,
  216. focus: false,
  217. fontSize: 12,
  218. height: "500px",
  219. highlightActiveLine: true,
  220. maxLines: null,
  221. minLines: null,
  222. mode: "",
  223. name: "ace-editor",
  224. onLoad: null,
  225. onScroll: null,
  226. onPaste: null,
  227. onChange: null,
  228. orientation: "beside",
  229. readOnly: false,
  230. scrollMargin: [0, 0, 0, 0],
  231. setOptions: {},
  232. showGutter: true,
  233. showPrintMargin: true,
  234. splits: 2,
  235. style: {},
  236. tabSize: 4,
  237. theme: "github",
  238. value: ["", ""],
  239. width: "500px",
  240. wrapEnabled: true
  241. };
  242. return DiffComponent;
  243. }(React.Component));
  244. exports.default = DiffComponent;
  245. //# sourceMappingURL=diff.js.map