123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- 'use strict';
- Object.defineProperty(exports, '__esModule', {
- value: true
- });
- exports.default = void 0;
- var _cleanupSemantic = require('./cleanupSemantic');
- function _defineProperty(obj, key, value) {
- if (key in obj) {
- Object.defineProperty(obj, key, {
- value: value,
- enumerable: true,
- configurable: true,
- writable: true
- });
- } else {
- obj[key] = value;
- }
- return obj;
- }
- // Given change op and array of diffs, return concatenated string:
- // * include common strings
- // * include change strings which have argument op with changeColor
- // * exclude change strings which have opposite op
- const concatenateRelevantDiffs = (op, diffs, changeColor) =>
- diffs.reduce(
- (reduced, diff) =>
- reduced +
- (diff[0] === _cleanupSemantic.DIFF_EQUAL
- ? diff[1]
- : diff[0] === op && diff[1].length !== 0 // empty if change is newline
- ? changeColor(diff[1])
- : ''),
- ''
- ); // Encapsulate change lines until either a common newline or the end.
- class ChangeBuffer {
- // incomplete line
- // complete lines
- constructor(op, changeColor) {
- _defineProperty(this, 'op', void 0);
- _defineProperty(this, 'line', void 0);
- _defineProperty(this, 'lines', void 0);
- _defineProperty(this, 'changeColor', void 0);
- this.op = op;
- this.line = [];
- this.lines = [];
- this.changeColor = changeColor;
- }
- pushSubstring(substring) {
- this.pushDiff(new _cleanupSemantic.Diff(this.op, substring));
- }
- pushLine() {
- // Assume call only if line has at least one diff,
- // therefore an empty line must have a diff which has an empty string.
- // If line has multiple diffs, then assume it has a common diff,
- // therefore change diffs have change color;
- // otherwise then it has line color only.
- this.lines.push(
- this.line.length !== 1
- ? new _cleanupSemantic.Diff(
- this.op,
- concatenateRelevantDiffs(this.op, this.line, this.changeColor)
- )
- : this.line[0][0] === this.op
- ? this.line[0] // can use instance
- : new _cleanupSemantic.Diff(this.op, this.line[0][1]) // was common diff
- );
- this.line.length = 0;
- }
- isLineEmpty() {
- return this.line.length === 0;
- } // Minor input to buffer.
- pushDiff(diff) {
- this.line.push(diff);
- } // Main input to buffer.
- align(diff) {
- const string = diff[1];
- if (string.includes('\n')) {
- const substrings = string.split('\n');
- const iLast = substrings.length - 1;
- substrings.forEach((substring, i) => {
- if (i < iLast) {
- // The first substring completes the current change line.
- // A middle substring is a change line.
- this.pushSubstring(substring);
- this.pushLine();
- } else if (substring.length !== 0) {
- // The last substring starts a change line, if it is not empty.
- // Important: This non-empty condition also automatically omits
- // the newline appended to the end of expected and received strings.
- this.pushSubstring(substring);
- }
- });
- } else {
- // Append non-multiline string to current change line.
- this.pushDiff(diff);
- }
- } // Output from buffer.
- moveLinesTo(lines) {
- if (!this.isLineEmpty()) {
- this.pushLine();
- }
- lines.push(...this.lines);
- this.lines.length = 0;
- }
- } // Encapsulate common and change lines.
- class CommonBuffer {
- constructor(deleteBuffer, insertBuffer) {
- _defineProperty(this, 'deleteBuffer', void 0);
- _defineProperty(this, 'insertBuffer', void 0);
- _defineProperty(this, 'lines', void 0);
- this.deleteBuffer = deleteBuffer;
- this.insertBuffer = insertBuffer;
- this.lines = [];
- }
- pushDiffCommonLine(diff) {
- this.lines.push(diff);
- }
- pushDiffChangeLines(diff) {
- const isDiffEmpty = diff[1].length === 0; // An empty diff string is redundant, unless a change line is empty.
- if (!isDiffEmpty || this.deleteBuffer.isLineEmpty()) {
- this.deleteBuffer.pushDiff(diff);
- }
- if (!isDiffEmpty || this.insertBuffer.isLineEmpty()) {
- this.insertBuffer.pushDiff(diff);
- }
- }
- flushChangeLines() {
- this.deleteBuffer.moveLinesTo(this.lines);
- this.insertBuffer.moveLinesTo(this.lines);
- } // Input to buffer.
- align(diff) {
- const op = diff[0];
- const string = diff[1];
- if (string.includes('\n')) {
- const substrings = string.split('\n');
- const iLast = substrings.length - 1;
- substrings.forEach((substring, i) => {
- if (i === 0) {
- const subdiff = new _cleanupSemantic.Diff(op, substring);
- if (
- this.deleteBuffer.isLineEmpty() &&
- this.insertBuffer.isLineEmpty()
- ) {
- // If both current change lines are empty,
- // then the first substring is a common line.
- this.flushChangeLines();
- this.pushDiffCommonLine(subdiff);
- } else {
- // If either current change line is non-empty,
- // then the first substring completes the change lines.
- this.pushDiffChangeLines(subdiff);
- this.flushChangeLines();
- }
- } else if (i < iLast) {
- // A middle substring is a common line.
- this.pushDiffCommonLine(new _cleanupSemantic.Diff(op, substring));
- } else if (substring.length !== 0) {
- // The last substring starts a change line, if it is not empty.
- // Important: This non-empty condition also automatically omits
- // the newline appended to the end of expected and received strings.
- this.pushDiffChangeLines(new _cleanupSemantic.Diff(op, substring));
- }
- });
- } else {
- // Append non-multiline string to current change lines.
- // Important: It cannot be at the end following empty change lines,
- // because newline appended to the end of expected and received strings.
- this.pushDiffChangeLines(diff);
- }
- } // Output from buffer.
- getLines() {
- this.flushChangeLines();
- return this.lines;
- }
- } // Given diffs from expected and received strings,
- // return new array of diffs split or joined into lines.
- //
- // To correctly align a change line at the end, the algorithm:
- // * assumes that a newline was appended to the strings
- // * omits the last newline from the output array
- //
- // Assume the function is not called:
- // * if either expected or received is empty string
- // * if neither expected nor received is multiline string
- const getAlignedDiffs = (diffs, changeColor) => {
- const deleteBuffer = new ChangeBuffer(
- _cleanupSemantic.DIFF_DELETE,
- changeColor
- );
- const insertBuffer = new ChangeBuffer(
- _cleanupSemantic.DIFF_INSERT,
- changeColor
- );
- const commonBuffer = new CommonBuffer(deleteBuffer, insertBuffer);
- diffs.forEach(diff => {
- switch (diff[0]) {
- case _cleanupSemantic.DIFF_DELETE:
- deleteBuffer.align(diff);
- break;
- case _cleanupSemantic.DIFF_INSERT:
- insertBuffer.align(diff);
- break;
- default:
- commonBuffer.align(diff);
- }
- });
- return commonBuffer.getLines();
- };
- var _default = getAlignedDiffs;
- exports.default = _default;
|