You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					216 lines
				
				6.1 KiB
			
		
		
			
		
	
	
					216 lines
				
				6.1 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								'use strict';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Object.defineProperty(exports, '__esModule', {
							 | 
						||
| 
								 | 
							
								  value: true
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								exports.default = void 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _cleanupSemantic = require('./cleanupSemantic');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _printDiffs = require('./printDiffs');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								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;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Encapsulate change lines until either a common newline or the end.
							 | 
						||
| 
								 | 
							
								class ChangeBuffer {
							 | 
						||
| 
								 | 
							
								  // incomplete line
							 | 
						||
| 
								 | 
							
								  // complete lines
							 | 
						||
| 
								 | 
							
								  constructor(op) {
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, 'op', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, 'line', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, 'lines', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    this.op = op;
							 | 
						||
| 
								 | 
							
								    this.line = [];
							 | 
						||
| 
								 | 
							
								    this.lines = [];
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  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.
							 | 
						||
| 
								 | 
							
								    this.lines.push(
							 | 
						||
| 
								 | 
							
								      new _cleanupSemantic.Diff(
							 | 
						||
| 
								 | 
							
								        this.op,
							 | 
						||
| 
								 | 
							
								        (0, _printDiffs.getHighlightedString)(this.op, this.line)
							 | 
						||
| 
								 | 
							
								      )
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								    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 (_printDiffs.MULTILINE_REGEXP.test(string)) {
							 | 
						||
| 
								 | 
							
								      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 (_printDiffs.MULTILINE_REGEXP.test(string)) {
							 | 
						||
| 
								 | 
							
								      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 => {
							 | 
						||
| 
								 | 
							
								  const deleteBuffer = new ChangeBuffer(_cleanupSemantic.DIFF_DELETE);
							 | 
						||
| 
								 | 
							
								  const insertBuffer = new ChangeBuffer(_cleanupSemantic.DIFF_INSERT);
							 | 
						||
| 
								 | 
							
								  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;
							 |