All files / src get-dom-diff.js

100% Statements 16/16
100% Branches 6/6
100% Functions 4/4
100% Lines 15/15

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68                                                  13x 13x   13x             74x 74x 74x                           37x 37x   37x 37x     1258x 37x   37x 24x     13x    
import { parseFragment } from '@bundled-es-modules/parse5';
import { deepDiff } from '@bundled-es-modules/deep-diff';
 
import { sanitizeHtmlString } from './sanitize-html-string';
import { normalizeAST } from './normalize-ast';
import { getDiffMessage } from './get-diff-message';
import { findDiffedObject } from './find-diffed-object';
import { getDiffPath } from './get-diff-path';
 
/**
 * @typedef {object} DiffResult
 * @param {string} message
 * @param {string} path
 */
 
/**
 * Creates the DiffResult for two AST trees.
 *
 * @param {ASTNode} leftTree the left tree AST
 * @param {ASTNode} rightTree the right tree AST
 * @param {Object} diff the semantic difference between the two trees
 *
 * @returns {DiffResult} the diff result containing the human readable semantic difference
 */
function createDiffResult(leftTree, rightTree, diff) {
  const leftDiffObject = findDiffedObject(leftTree, diff.path);
  const rightDiffObject = findDiffedObject(rightTree, diff.path);
 
  return {
    message: getDiffMessage(diff, leftDiffObject, rightDiffObject),
    path: getDiffPath(leftTree, diff.path),
  };
}
 
export function getAST(value, config = {}) {
  const ast = parseFragment(sanitizeHtmlString(value));
  normalizeAST(ast, config.ignoredTags);
  return ast;
}
 
/**
 * Parses two HTML trees, and generates the semantic difference between the two trees.
 * The HTML is diffed semantically, not literally. This means that changes in attribute
 * and class order and whitespace/newlines are ignored. Also, script and style
 * tags ignored.
 *
 * @param leftHTML the left HTML tree
 * @param rightHTML the right HTML tree
 * @returns {DiffResult | null} the diff result, or undefined if no diffs were found
 */
export function getSemanticDomDiff(leftHTML, rightHTML, config = {}) {
  const leftTree = getAST(leftHTML);
  const rightTree = getAST(rightHTML);
 
  normalizeAST(leftTree, config.ignoredTags);
  normalizeAST(rightTree, config.ignoredTags);
 
  // parentNode causes a circular reference, so ignore them.
  const ignore = (path, key) => key === 'parentNode';
  const diffs = deepDiff(leftTree, rightTree, ignore);
 
  if (!diffs || !diffs.length) {
    return null;
  }
 
  return createDiffResult(leftTree, rightTree, diffs[0]);
}