VaKeR CYBER ARMY
Logo of a company Server : Apache/2.4.41 (Ubuntu)
System : Linux absol.cf 5.4.0-198-generic #218-Ubuntu SMP Fri Sep 27 20:18:53 UTC 2024 x86_64
User : www-data ( 33)
PHP Version : 7.4.33
Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Directory :  /var/www/html/libs/absol-full/dist/js/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /var/www/html/libs/absol-full/dist/js/mdls__absol-form__js__kfeditor__KFEngine.js
/*** module: node_modules/absol-form/js/kfeditor/KFEngine.js ***/
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

var _AElement = _interopRequireDefault(require("absol/src/HTML5/AElement"));

var _FCore = require("../core/FCore");

var _CSSParser = require("absol/src/JSX/CSSParser");

var _Array = require("absol/src/DataStructure/Array");

var _utils = require("../fdeditor/utils");

var _stringUtils = require("absol/src/String/stringUtils");


var childIndexOf = child => {
  return Array.prototype.indexOf.call(child.parentElement.childNodes, child);
};
/**
 *
 * @param {KFEditor} editor
 * @constructor
 */


function KFEngine(editor) {
  this.editor = editor;
  /**
   *
   * @type {Selection}
   */

  this.sel = undefined;
  /**
   *
   * @type {null|Array<Range>}
   */

  this.ranges = null;
  /**
   *
   * @type {{ rules: KFRule[]}}
   */

  this.definitions = {
    rules: []
  };
  this.staticRules.forEach(rule => this.define(rule));
  console.log(this);
}
/*************  RANGE ***********/


KFEngine.prototype.getSelection = function () {
  if (!this.sel) this.sel = document.getSelection();
  return this.sel;
};

KFEngine.prototype.isSelectionCollapsed = function () {
  this.updateRanges();
  return this.ranges.length === 1 && this.ranges[0].collapsed;
};
/**
 *
 * @param {Range} range
 * @returns {Range}
 */


KFEngine.prototype.computeNormalizeRange = function (range) {
  console.log('normal');
  var startCtn = range.startContainer;
  var endCtn = range.endContainer;
  var startHardBlock = this.hardBlockOf(startCtn);
  var endHardBlock = this.hardBlockOf(endCtn);
  var startOffset = range.startOffset;
  var endOffset = range.endOffset;
  if (startHardBlock === endHardBlock) return range;
  var lcaNode = this.lcaOf(startCtn, endCtn);
  var sInE, eInS;

  if (this.isCavity(lcaNode) || this.isInterior(lcaNode)) {
    do {
      lcaNode = lcaNode.parentElement;
    } while (!this.isExterior(lcaNode));

    startOffset = childIndexOf(lcaNode);
    endOffset = startOffset + 1;
    range = document.createRange();
    range.setStart(lcaNode.parentElement, startOffset);
    range.setEnd(lcaNode.parentElement, endOffset);
  } else {
    eInS = _AElement.default.prototype.isDescendantOf.call(endHardBlock, startHardBlock);
    sInE = _AElement.default.prototype.isDescendantOf.call(startHardBlock, endHardBlock);

    if (eInS || !eInS && !sInE) {
      while (this.isInnerBlock(endHardBlock) || this.isCavity(endHardBlock)) {
        endHardBlock = endHardBlock.parentElement;
      }

      endOffset = childIndexOf(endHardBlock) + 1;
      endCtn = endHardBlock.parentElement;
    }

    if (sInE || !eInS && !sInE) {
      while (this.isInnerBlock(startHardBlock) || this.isCavity(startHardBlock)) {
        startHardBlock = startHardBlock.parentElement;
      }

      startOffset = childIndexOf(startHardBlock);
      startCtn = startHardBlock.parentElement;
    }

    range = document.createRange();
    range.setStart(startCtn, startOffset);
    range.setEnd(endCtn, endOffset);
  }

  return range;
};
/**
 *
 * @param {Range} range
 * @returns {boolean}
 */


KFEngine.prototype.isValidRange = function (range) {
  var ctn = range.startContainer;
  return _AElement.default.prototype.isDescendantOf.call(ctn, this.editor.$content);
};
/**
 * update ranges from DOM if ranges are in content
 */


KFEngine.prototype.updateRanges = function () {
  var sel = this.getSelection();
  var ranges = [];
  var range;

  for (var i = 0; i < sel.rangeCount; ++i) {
    range = sel.getRangeAt(i);
    if (this.isValidRange(range)) ranges.push(range);
  }

  if (ranges.length > 0) this.ranges = ranges;
  return this.ranges;
};
/**
 *
 * @returns {Array<Range>|null}
 */


KFEngine.prototype.getRanges = function () {
  if (!this.ranges) this.updateRanges();
  return this.ranges;
};
/**
 *
 * @param {Array<Range>|Range} ranges - ranges must be in content
 */


KFEngine.prototype.setRanges = function (ranges) {
  ranges = ranges || [];
  if (!Array.isArray(ranges)) ranges = [ranges];
  this.ranges = ranges;
  this.getSelection();
  this.sel.removeAllRanges();

  for (var i = 0; i < ranges.length; ++i) this.sel.addRange(ranges[i]);
};
/**
 * recover range from last focus range
 */


KFEngine.prototype.focusRanges = function () {
  if (this.ranges) this.setRanges(this.ranges);
};
/*************  DEFINITIONS ***********/

/**
 * @typedef KFRule
 * @property {string|null} selector
 * @property {"void"|"interior"|"exterior"|"container"|"cavity"|"text"} [type]
 * @property {number[]} [specificity]
 * @property {string[]} [allowChildren]
 * @property {boolean} [hard]
 * @property {string[]} [formatKeys]
 * @property {*} [empty]
 *
 */

/**
 *
 * @type {KFRule[]}
 */


KFEngine.prototype.staticRules = [{
  selector: '.kf-grid',
  type: 'exterior',
  allowChildren: ['.kf-grid-item']
}, {
  selector: '.kf-grid-item',
  type: "interior"
}, {
  selector: 'tr',
  type: "cavity"
}, {
  selector: 'thead',
  type: "cavity",
  allowChildren: ['tr']
}, {
  selector: 'tbody',
  type: "cavity",
  allowChildren: ['tr']
}, {
  selector: 'td',
  type: "interior"
}, {
  selector: 'th',
  type: "interior"
}, {
  selector: 'img',
  type: 'void'
}, {
  selector: 'input',
  type: 'void'
}, {
  selector: 'textarea',
  type: 'void'
}, {
  selector: 'br',
  type: 'void'
}, {
  selector: "table",
  type: "exterior",
  allowChildren: ['thead', 'tbody']
}, {
  selector: 'label',
  type: 'container',
  hard: true,
  empty: {
    text: _utils.CHAR_ZWS
  }
}, {
  type: 'container',
  selector: '*'
}];
/**
 *
 * @type {KFRule}
 */

KFEngine.prototype.textRule = {
  type: 'text',
  selector: null
};
/**
 *
 * @param {KFRule} rule
 */

KFEngine.prototype.define = function (rule) {
  var rules = this.definitions.rules;
  rule.specificity = rule.specificity || (0, _CSSParser.getQuerySelectorSpecificity)(rule.selector);
  rule.type = rule.type || 'container';
  var i = rules.length;

  while (i > 0) {
    if ((0, _Array.arrayLexicographicalCompare)(rule.specificity, rules[i - 1].specificity) > 0) {
      --i;
    } else {
      break;
    }
  }

  rules.splice(i, 0, rule);
};
/**
 *
 * @param {Text|HTMLElement}nd
 * @returns {KFRule}
 */


KFEngine.prototype.ruleOfNode = function (nd) {
  if (this.isTextNode(nd)) return this.textRule;
  var rules = this.definitions.rules;
  var rule;

  for (var i = 0; i < rules.length; ++i) {
    rule = rules[i];
    if (nd.matches(rule.selector)) return rule;
  }

  return this.staticRules[this.staticRules.length - 1]; //never
};

KFEngine.prototype.isTextNode = function (nd) {
  return nd.nodeType === Node.TEXT_NODE;
};

KFEngine.prototype.isParagraph = function (nd) {
  if (this.isTextNode(nd)) return false;
  var displayStyle = getComputedStyle(nd).getPropertyValue('display') || '';
  return displayStyle === 'block';
};

KFEngine.prototype.isHardBlock = function (nd) {
  if (this.isTextNode(nd)) return false;
  if (nd.getAttribute('contenteditable')) return true;
  var res = false;
  var rule = this.ruleOfNode(nd);
  res = res || rule.hard || ['exterior', 'cavity', 'exterior', 'interior'].indexOf(rule.type) > 0; //other rules

  return res;
}; //inner block contain data of module/widget


KFEngine.prototype.isInnerBlock = function (nd) {
  return this.isCavity(nd) || this.isInterior(nd);
};

KFEngine.prototype.isCavity = function (nd) {
  var rule = this.ruleOfNode(nd);
  return rule.type === "cavity";
};

KFEngine.prototype.isInterior = function (nd) {
  var rule = this.ruleOfNode(nd);
  return rule.type === "interior";
};

KFEngine.prototype.isExterior = function (nd) {
  var rule = this.ruleOfNode(nd);
  return rule.type === "exterior";
};

KFEngine.prototype.isVoid = function (nd) {
  var rule = this.ruleOfNode(nd);
  return rule.type === "void";
};

KFEngine.prototype.paragraphOf = function (nd) {
  if (!nd) return null;
  if (this.isHardBlock(nd)) return null;
  if (this.isParagraph(nd)) return nd;
  return this.paragraphOf(nd.parentElement);
};

KFEngine.prototype.hardBlockOf = function (nd) {
  if (!nd) return null;
  if (this.isHardBlock(nd)) return nd;
  return this.hardBlockOf(nd.parentElement);
};

KFEngine.prototype.lcaOf = function (nd1, nd2) {
  var track1 = [];
  var track2 = [];
  var rootNode = this.editor.$content.parentElement;

  while (nd1 && nd1 !== rootNode) {
    track1.unshift(nd1);
    nd1 = nd1.parentElement;
  }

  while (nd2 && nd2 !== rootNode) {
    track2.unshift(nd2);
    nd2 = nd2.parentElement;
  }

  var res = null;

  for (var i = 0; i < track1.length && i < track2.length; ++i) {
    if (track1[i] === track2[i]) res = track1[i];else break;
  }

  return res;
};

KFEngine.prototype.breakTextNode = function (textNode, offset) {
  var parent = (0, _FCore.$)(textNode.parentElement);
  var text = textNode.data;
  var newTextNode = (0, _FCore._)({
    text: text.substring(offset)
  });
  textNode.data = text.substring(0, offset);
  parent.addChildAfter(newTextNode, textNode);
  return newTextNode;
};

KFEngine.prototype.breakElement = function (elt, offset) {
  var parent = (0, _FCore.$)(elt.parentElement);
  var newElt = elt.cloneNode(false);
  var rightChildren = Array.prototype.slice.call(elt.childNodes, offset);

  for (var i = 0; i < rightChildren.length; ++i) {
    newElt.appendChild(rightChildren[i]);
  }

  parent.addChildAfter(newElt, elt);
  return newElt;
};
/**
 *
 * @param nd
 * @param offset
 * @returns {AElement|Text} - new created node
 */


KFEngine.prototype.breakNode = function (nd, offset) {
  if (this.isTextNode(nd)) {
    return this.breakTextNode(nd, offset);
  } else {
    return this.breakElement(nd, offset);
  }
};

KFEngine.prototype.removeContentNode = function (nd) {
  if (this.isTextNode(nd)) {
    nd.remove();
  } else if (this.isInnerBlock(nd)) {
    Array.prototype.slice.call(nd.childNodes).forEach(cnd => this.removeContentNode(cnd));
  } else {
    nd.remove();
  }
};

KFEngine.prototype.trimLeftTextNode = function (textNode, offset) {
  var text = textNode.data;
  text = text.substring(offset);
  textNode.data = text;
};

KFEngine.prototype.trimLeftElement = function (elt, offset) {
  for (var i = offset - 1; i >= 0; --i) {
    if (elt.childNodes[i]) this.removeContentNode(elt.childNodes[i]);
  }
};

KFEngine.prototype.trimLeftNode = function (nd, offset) {
  if (this.isTextNode(nd)) return this.trimLeftTextNode(nd, offset);
  return this.trimLeftElement(nd, offset);
};

KFEngine.prototype.trimRightTextNode = function (textNode, offset) {
  var text = textNode.data;
  text = text.substring(0, offset);
  textNode.data = text;
};

KFEngine.prototype.trimRightElement = function (elt, offset) {
  for (var i = elt.childNodes.length - 1; i >= offset; --i) if (elt.childNodes[i]) this.removeContentNode(elt.childNodes[i]);
};

KFEngine.prototype.trimRightNode = function (nd, offset) {
  if (nd.nodeType === Node.TEXT_NODE) return this.trimRightTextNode(nd, offset);
  return this.trimRightElement(nd, offset);
};

KFEngine.prototype.trimInTextNode = function (textNode, startOffset, endOffset) {
  var text = textNode.data;
  text = text.substring(0, startOffset) + text.substring(endOffset);
  textNode.data = text;
};

KFEngine.prototype.trimInElement = function (elt, startOffset, endOffset) {
  Array.prototype.slice.call(elt.childNodes, startOffset, endOffset).map(nd => nd.remove());
};

KFEngine.prototype.trimNode = function (nd, startOffset, endOffset) {
  if (this.isTextNode(nd)) return this.trimInTextNode(nd, startOffset, endOffset);else return this.trimInElement(nd, startOffset, endOffset);
};
/**
 * joint element and handle range
 * @param elt1
 * @param elt2
 */


KFEngine.prototype.join2Elements = function (elt1, elt2) {
  if (!elt1 || !elt2) return;
  if (this.isHardBlock(elt1) || this.isHardBlock(elt2)) return; //can not merge

  var ranges = this.getRanges();
  var range = ranges && ranges[0];
  var startCtn = range && range.startContainer;
  var endCtn = range && range.endContainer;
  var startOffset = range && range.startOffset;
  var endOffset = range && range.endOffset;
  var rangeChanged = false;
  var parent = elt1.parentElement;
  var br;
  var elt1Idx = childIndexOf(elt1);

  if (this.isParagraph(elt1)) {
    //move range
    if (range && startCtn === parent) {
      if (startOffset === elt1Idx + 1) {
        rangeChanged = true;
        startCtn = elt1;
        startOffset = elt1.childNodes.length;
      } else if (startOffset > elt1Idx + 1) {
        rangeChanged = true;
        startOffset--;
      }
    }

    if (range && endCtn === parent) {
      if (endOffset === elt1Idx + 1) {
        rangeChanged = true;
        endCtn = elt1;
        endOffset = elt1.childNodes.length;
      } else if (endOffset > elt1Idx + 1) {
        rangeChanged = true;
        endOffset--;
      }
    }

    if (this.isParagraph(elt2)) {
      (0, _FCore.$)(elt1);

      while (elt2.firstChild) {
        elt1.addChild(elt2.firstChild);
      }

      elt2.remove();
    } else {
      //span, textnode...
      (0, _FCore.$)(elt1);
      elt1.appendChild(elt2);
    }
  } else {
    if (this.isParagraph(elt2)) {
      br = (0, _FCore._)('br');
      (0, _FCore.$)(parent).addChildAfter(br, elt1);

      if (range && startCtn === parent && startOffset > elt1Idx + 1) {
        startOffset += elt2.childNodes.length; //include br - el2 removed
      }

      if (range && endCtn === parent && endOffset > elt1Idx + 1) {
        endOffset += elt2.childNodes.length;
      }

      while (elt2.firstChild) {
        parent.addChildBefore(elt2.firstChild, br);
      }

      elt2.remove();
    } else {//nothing to do
    }
  }

  if (range && rangeChanged) {
    range = document.createRange();
    range.setStart(startCtn, startOffset);
    range.setEnd(endCtn, endOffset);
    this.setRanges([range]);
  }
};

KFEngine.prototype.formatKeys = ['fontSize', 'color', 'fontWeight', 'fontStyle'];
KFEngine.prototype.fontWeightMapping = {
  100: 'thin',
  200: 'extra-light',
  300: 'light',
  400: 'normal',
  500: 'medium',
  600: 'semi-bold',
  700: 'bold',
  800: 'extra-bold',
  900: 'black'
};
/**
 *
 * @param {Text|AElement} nd
 * @param {boolean=} depth
 */

KFEngine.prototype.computeNodeFormat = function (nd, depth) {
  if (this.isTextNode(nd)) return this.computeNodeFormat(nd.parentElement); //todo: exclude some type of element

  var ndStyle = getComputedStyle(nd);
  var rule = this.ruleOfNode(nd);
  var formatKeys = rule.formatKeys || this.formatKeys;
  var res = formatKeys.reduce((ac, key) => {
    ac[key] = ndStyle[key];
    return ac;
  }, {});

  if (depth) {
    Array.prototype.filter.call(nd.childNodes, c => !this.isTextNode(c)).forEach(c => {
      var cStyle = this.computeNodeFormat(c, depth);
      var t = Object.assign({}, res, cStyle);
      Object.keys(res).forEach(key => {
        if (cStyle[key] !== res[key]) {
          if (res[key]) {
            if (cStyle[key]) res[key] = '*';
          } else {
            res[key] = cStyle[key];
          }
        }
      });
    });
  }

  if (res.fontWeight && this.fontWeightMapping[res.fontWeight]) res.fontWeight = this.fontWeightMapping[res.fontWeight];
  return res;
};
/**
 * compare 2 node can merge,..
 * @param nd1
 * @param nd2
 * @returns {boolean}
 */


KFEngine.prototype.compareFormat = function (nd1, nd2) {
  if (nd1.tagName !== nd2.tagName) return false;
  var rule1 = this.ruleOfNode(nd1);
  var rule2 = this.ruleOfNode(nd2);
  if (rule1.type !== rule2.type) return false;
  if (rule1.type === 'text') return true;
  var t1 = nd1.attributes;
  var t2 = nd2.attributes;
  if (t1.length !== t2.length) return false;
  var i;

  for (i = 0; i < t1.length; ++i) {
    if (t1[i].nodeValue !== t2[t1[i].nodeName].nodeValue) return false;
  }

  t1 = nd1.style;
  t2 = nd2.style;
  if (t1.length !== t2.length) return false;

  for (i = 0; i < t1.length; ++i) {
    if (t1[t1[i]] !== t2[t1[i]]) return false;
  }

  return true;
};
/**
 *
 * @param {AElement|Node=} nd
 */


KFEngine.prototype.normalizeContent = function (nd) {
  var ranges = this.getRanges();
  var range = ranges && ranges[0];
  var startCtn, endCtn, startOffset, endOffset;

  if (range) {
    startCtn = range.startContainer;
    endCtn = range.endContainer;
    startOffset = range.startOffset;
    endOffset = range.endOffset;
  }

  var canMerge = (e1, e2) => {
    var t1 = e1.attributes;
    var t2 = e2.attributes;
    if (t1.length !== t2.length) return false;
    var i;

    for (i = 0; i < t1.length; ++i) {
      if (t1[i].nodeValue !== t2[t1[i].nodeName].nodeValue) return false;
    }

    t1 = e1.style;
    t2 = e2.style;
    if (t1.length !== t2.length) return false;

    for (i = 0; i < t1.length; ++i) {
      if (t1[t1[i]] !== t2[t1[i]]) return false;
    }

    return true;
  };

  nd = nd || this.editor.$content;

  var visit = cNode => {
    var cRule = this.ruleOfNode(cNode);
    if (cRule.type === 'text') return;
    var child, nextChild, allow;

    for (var i = cNode.childNodes.length - 1; i >= 0; --i) {
      child = cNode.childNodes[i];
      allow = true;

      if (cRule.allowChildren) {
        if (this.isTextNode(child)) {
          allow = cRule.allowChildren.indexOf('text') >= 0;
        } else {
          allow = cRule.allowChildren.some(selector => child.matches(selector));
        }
      }

      if (!allow) {
        child.remove();
        continue;
      }

      if (this.isTextNode(child)) {
        if (child.data.length === 0) {
          child.remove();
          continue;
        }
      }

      nextChild = cNode.childNodes[i + 1];

      if (nextChild) {
        if (this.isTextNode(child) && this.isTextNode(nextChild)) {
          child.data += nextChild.data;
          nextChild.remove();
        } else if (child.tagName === nextChild.tagName && ['SPAN', 'STRONG', 'I'].indexOf(child.tagName) >= 0) {
          if (this.compareFormat(child, nextChild)) {
            while (nextChild.firstChild) {
              child.appendChild(nextChild.firstChild);
            }

            nextChild.remove();
          }
        }
      }

      visit(child);
      if (['SPAN', 'STRONG', 'I'].indexOf(child.tagName) >= 0 && child.childNodes.length === 0) child.remove();
    }

    if (cRule.empty && cNode.childNodes.length === 0) {
      cNode.appendChild((0, _FCore._)(cRule.empty));
    }
  };

  visit(nd);
  if (!range) return;

  if (startCtn !== range.startContainer || endCtn !== range.endContainer || startOffset !== range.startOffset || endCtn !== range.endContainer) {
    range = document.createRange();
    range.setStart(startCtn, startOffset);
    range.setEnd(endCtn, endOffset);
    this.ranges = [range];
    if (document.activeElement === this.editor.$content) this.focusRanges();
  }
};
/**
 *@param  data
 * @param {Range=} range
 */


KFEngine.prototype.insert = function (data, range) {
  range = range || (this.getRanges() || [])[0];
  if (range) this.deleteContentAtCurrentSelection();
  range = range || (this.getRanges() || [])[0];
  console.log(range);

  if (Array.isArray(data)) {}
};
/**
 *@param {string} key
 *@param {string|null} value
 * @param {Range=} range
 * @returns {{}}
 */


KFEngine.prototype.formatRange = function (key, value, range) {
  range = range || (this.getRanges() || [])[0];
  if (!range) return {};
  var rangeStartCtn = range.startContainer;
  var rangeEndCtn = range.endContainer;
  var rangeStartOffset = range.startOffset;
  var rangeEndOffset = range.endOffset;

  var removeInlineStyle = (nd, key, value) => {
    if (!nd) return;
    if (this.isTextNode(nd)) return;

    if (nd.style[key] === value) {
      nd.style[key] = null;
    }

    Array.prototype.forEach.call(nd.childNodes, c => removeInlineStyle(c, key, value));
  };

  var unwrapDown = (nd, selector) => {
    if (!nd.matches) return;
    var childNodes = Array.prototype.slice.call(nd.childNodes);

    if (nd.matches(selector)) {
      childNodes.forEach(c => nd.parentElement.insertBefore(c, nd));
      nd.remove();
    }

    childNodes.forEach(c => unwrapDown(c, selector));
  };

  var paragraphsIn = (elt, res) => {
    res = res || [];
    if (this.isTextNode(elt)) return res;
    var ds = getComputedStyle(elt).getPropertyValue('display');

    if (['table', 'block', 'grid'].indexOf(ds) >= 0) {
      res.push(elt);
    } else {
      Array.prototype.forEach.call(elt.childNodes, c => paragraphsIn(c, res));
    }

    return res;
  };

  var paragraphBetween = (startElt, endElt, res) => {
    res = res || [];
    var lcaElt = this.lcaOf(startElt, endElt);
    return res;
  };

  var autoMerge = cNode => {
    var nextChild, child;

    for (var i = cNode.childNodes.length - 1; i >= 0; --i) {
      nextChild = cNode.childNodes[i + 1];
      child = cNode.childNodes[i];

      if (nextChild && this.compareFormat(child, nextChild) || isInline(child)) {
        if (this.isTextNode(child)) {
          if (rangeStartCtn === nextChild) {
            rangeStartCtn = child;
            rangeStartOffset += child.data.length;
          }

          if (rangeEndCtn === nextChild) {
            rangeEndCtn = child;
            rangeEndOffset += child.data.length;
          }

          child.data += nextChild.data;
        } else {
          if (rangeStartCtn === nextChild) {
            rangeStartCtn = child;
            rangeStartOffset += child.childNodes.length;
          }

          if (rangeEndCtn === nextChild) {
            rangeEndCtn = child;
            rangeEndOffset += child.childNodes.length;
          }

          while (nextChild.firstChild) {
            child.appendChild(nextChild.firstChild);
          }
        }

        nextChild.remove();
      }

      autoMerge(child);
    }
  };

  var isInline = node => {
    if (node.nodeType === Node.TEXT_NODE) return true;
    var cStyle = getComputedStyle(node);
    var dp = cStyle.getPropertyValue('display');
    return dp.indexOf('inline') >= 0;
  };

  var wrapContent = (nodes, tag) => {
    if (!nodes.length) return;
    var parent = nodes[0].parentElement;
    var rangeEndOffsetNode;
    if (!this.isTextNode(rangeEndCtn)) rangeEndOffsetNode = rangeEndCtn.childNodes[rangeEndOffset]; //todo: modify range

    var newNode = null;
    var i, nd;

    for (i = 0; i < nodes.length; ++i) {
      nd = nodes[i];

      if (isInline(nd)) {
        if (!newNode) {
          newNode = (0, _FCore._)({
            tag: tag
          });
          parent.insertBefore(newNode, nd);
        }

        newNode.appendChild(nd);
        unwrapDown(nd, tag);
      } else {
        newNode = null;
        wrapContent(Array.prototype.slice.call(nd.childNodes), tag);
      }
    }

    if (!this.isTextNode(rangeEndCtn)) {
      if (rangeEndOffsetNode) {
        rangeEndOffset = childIndexOf(rangeEndOffsetNode);
      } else {
        rangeEndOffset = rangeEndCtn.childNodes.length;
      }
    }
  };

  var sFormat = (startNode, startOffset, endNode, endOffset, opt) => {
    var lcaNode = this.lcaOf(startNode, endNode);
    var paragraph = this.paragraphOf(lcaNode);
    var hardBlock = this.hardBlockOf(lcaNode);
    var ctn = paragraph || hardBlock;
    var ctnStyle = this.computeNodeFormat(ctn);

    if (ctnStyle[opt.key] === opt.value) {
      //normalize children only
      unwrapDown(ctn, opt.wrapTag);
      Array.prototype.forEach.call(ctn.childNodes, c => removeInlineStyle(c, opt.key, opt.value));
      return;
    }

    var startBoundElt = this.paragraphOf(startNode) || this.hardBlockOf(startNode);
    var endBoundElt = this.paragraphOf(endNode) || this.hardBlockOf(endNode);
    var curNode, curOffset, newNode, newChildren;
    var fStartCtn, fEndCtn;
    var fStartOffset, fEndOffset;
    var endOffsetNode;

    if (startBoundElt === endBoundElt) {
      endOffsetNode = endNode.childNodes[endOffset];
      curNode = startNode;
      curOffset = startOffset;

      while (curNode !== lcaNode) {
        if (curOffset === 0) {
          curOffset = childIndexOf(curNode);
        } else {
          newNode = this.breakNode(curNode, curOffset);

          if (rangeStartCtn === curNode && rangeStartOffset >= curOffset) {
            rangeStartCtn = newNode;
            rangeStartOffset -= curOffset;
          }

          curOffset = childIndexOf(newNode);

          if (endNode === newNode.parentElement && endOffset >= curOffset) {
            endOffset++;
          }
        }

        curNode = curNode.parentElement;
      }

      fStartOffset = curOffset;
      curNode = endNode;
      curOffset = endOffset;

      while (curNode !== lcaNode) {
        if (curOffset === (this.isTextNode(curNode) ? curNode.data.length : curNode.childNodes.length)) {
          curOffset = childIndexOf(curNode) + 1;
        } else {
          newNode = this.breakNode(curNode, curOffset);

          if (rangeEndCtn === curNode && rangeEndOffset > curOffset) {
            rangeEndCtn = newNode;
            rangeEndOffset -= curOffset;
          }

          curOffset = childIndexOf(newNode);
        }

        curNode = curNode.parentElement;
      }

      fEndOffset = curOffset;

      if (this.isTextNode(lcaNode)) {
        if (fEndOffset < lcaNode.data.length) {
          newNode = (0, _FCore._)({
            text: lcaNode.data.substring(fEndOffset)
          });
          lcaNode.parentElement.insertBefore(newNode, lcaNode.nextSibling);

          if (rangeEndCtn === lcaNode && rangeEndOffset > fEndOffset) {
            rangeEndOffset -= fEndOffset;
            rangeEndCtn = newNode;
          }
        }

        if (fStartOffset > 0) {
          newNode = (0, _FCore._)({
            text: lcaNode.data.substring(0, rangeStartOffset)
          });
          lcaNode.parentElement.insertBefore(newNode, lcaNode);

          if (rangeStartCtn === lcaNode) {
            if (rangeStartOffset < fStartOffset) {
              rangeStartCtn = newNode;
            } else {
              rangeStartOffset -= fStartOffset;
            }
          }

          if (rangeEndCtn === lcaNode) {
            rangeEndOffset -= fStartOffset;
          }
        }

        lcaNode.data = lcaNode.data.substring(fStartOffset, fEndOffset);
        newNode = (0, _FCore._)({
          tag: opt.wrapTag
        });
        lcaNode.parentElement.replaceChild(newNode, lcaNode);
        newNode.appendChild(lcaNode);
      } else {
        newChildren = Array.prototype.slice.call(lcaNode.childNodes, fStartOffset, fEndOffset);
        wrapContent(newChildren, opt.wrapTag);
      } // autoMerge(lcaNode);

    } else if (_AElement.default.prototype.isDescendantOf.call(startBoundElt, endBoundElt)) {
      endOffsetNode = endNode.childNodes[endOffset];
      curNode = startNode;
      curOffset = startOffset;

      while (curNode !== startBoundElt) {
        if (curOffset === 0) {
          curOffset = childIndexOf(curNode);
        } else {
          newNode = this.breakNode(curNode, curOffset);

          if (rangeStartCtn === curNode && rangeStartOffset >= curOffset) {
            rangeStartCtn = newNode;
            rangeStartOffset -= curOffset;
          }

          curOffset = childIndexOf(newNode);
        }

        curNode = curNode.parentElement;
      }

      fStartCtn = startBoundElt;
      fStartOffset = curOffset;
      newChildren = Array.prototype.slice.call(fStartCtn.childNodes, fStartOffset);
      wrapContent(newChildren, opt.wrapTag);
      curOffset = childIndexOf(startBoundElt) + 1;
      curNode = startBoundElt.parentElement;

      while (curNode !== lcaNode) {
        if (curOffset < curNode.childNodes.length) break;
        curOffset = childIndexOf(curNode);
        curNode = curNode.parentElement;
      }

      startNode = curNode;
      startOffset = curOffset;

      if (endOffsetNode) {
        endOffset = childIndexOf(endOffsetNode);
      } else {
        endOffset = endNode.childNodes.length;
      }

      if (startNode !== endNode || startOffset < endOffset) {
        sFormat(startNode, startOffset, endNode, endOffset, opt);
      }
    } else if (_AElement.default.prototype.isDescendantOf.call(endBoundElt, startBoundElt)) {
      curNode = endNode;
      curOffset = endOffset;

      while (curNode !== endBoundElt) {
        if (curOffset === (this.isTextNode(curNode) ? curNode.data.length : curNode.childNodes.length)) {
          curOffset = childIndexOf(curNode) + 1;
        } else {
          newNode = this.breakNode(curNode, curOffset);

          if (rangeEndCtn === curNode && rangeEndOffset > curOffset) {
            rangeEndCtn = newNode;
            rangeEndOffset -= curOffset;
          }

          curOffset = childIndexOf(newNode);

          if (endNode === newNode.parentElement && endOffset >= curOffset) {
            endOffset++;
          }
        }

        curNode = curNode.parentElement;
      }

      fEndOffset = curOffset;
      fEndCtn = endBoundElt;
      newChildren = Array.prototype.slice.call(fEndCtn.childNodes, 0, fEndOffset);
      wrapContent(newChildren, opt.wrapTag);
      curOffset = childIndexOf(endBoundElt);
      curNode = endBoundElt.parentElement;

      while (curNode !== lcaNode) {
        if (curOffset > 0) break;
        curOffset = childIndexOf(curNode);
        curNode = curNode.parentElement;
      }

      endNode = curNode;
      endOffset = curOffset; // console.log(startNode.cloneNode(true), startOffset,  endNode.cloneNode(true), endOffset)
      //

      if (startNode !== endNode || startOffset < endOffset) {
        sFormat(startNode, startOffset, endNode, endOffset, opt);
      }
    } else {
      curNode = startNode;
      curOffset = startOffset;

      while (curNode !== startBoundElt) {
        if (curOffset === 0) {
          curOffset = childIndexOf(curNode);
        } else {
          newNode = this.breakNode(curNode, curOffset);

          if (rangeStartCtn === curNode && rangeStartOffset >= curOffset) {
            rangeStartCtn = newNode;
            rangeStartOffset -= curOffset;
          }

          curOffset = childIndexOf(newNode);

          if (endNode === newNode.parentElement && endOffset >= curOffset) {
            endOffset++;
          }
        }

        curNode = curNode.parentElement;
      }

      fStartOffset = curOffset;
      fStartCtn = startBoundElt;
      newChildren = Array.prototype.slice.call(fStartCtn.childNodes, fStartOffset);
      wrapContent(newChildren, opt.wrapTag);
      curNode = endNode;
      curOffset = endOffset;

      while (curNode !== endBoundElt) {
        if (curOffset === (this.isTextNode(curNode) ? curNode.data.length : curNode.childNodes.length)) {
          curOffset = childIndexOf(curNode) + 1;
        } else {
          newNode = this.breakNode(curNode, curOffset);

          if (rangeEndCtn === curNode && rangeEndOffset > curOffset) {
            rangeEndCtn = newNode;
            rangeEndOffset -= curOffset;
          }

          curOffset = childIndexOf(newNode);
        }

        curNode = curNode.parentElement;
      }

      fEndOffset = curOffset;
      fEndCtn = endBoundElt;
      newChildren = Array.prototype.slice.call(fEndCtn.childNodes, 0, fEndOffset);
      newNode = (0, _FCore._)({
        tag: opt.wrapTag
      });
      fEndCtn.insertBefore(newNode, fEndCtn.firstChild);
      newChildren.forEach(c => newNode.appendChild(c));
      newChildren.forEach(c => unwrapDown(c, opt.wrapTag));
      lcaNode = this.lcaOf(startBoundElt, endBoundElt); //find between

      curOffset = childIndexOf(startBoundElt) + 1;
      curNode = startBoundElt.parentElement;

      while (curNode !== lcaNode) {
        if (curOffset < curNode.childNodes.length) break;
        curOffset = childIndexOf(curNode) + 1;
        curNode = curNode.parentElement;
      }

      startNode = curNode;
      startOffset = curOffset;
      curOffset = childIndexOf(endBoundElt);
      curNode = endBoundElt.parentElement;

      while (curNode !== lcaNode) {
        if (curOffset > 0) break;
        curOffset = childIndexOf(curNode);
        curNode = curNode.parentElement;
      }

      endNode = curNode;
      endOffset = curOffset;

      if (startNode !== endNode || startOffset < endOffset) {
        sFormat(startNode, startOffset, endNode, endOffset, opt);
      }
    }
  };

  var bold = () => {
    sFormat(rangeStartCtn, rangeStartOffset, rangeEndCtn, rangeEndOffset, {
      wrapTag: 'strong',
      key: 'fontWeight',
      value: 'bold'
    });
  };

  var italic = () => {
    sFormat(rangeStartCtn, rangeStartOffset, rangeEndCtn, rangeEndOffset, {
      wrapTag: 'i',
      key: 'fontStyle',
      value: 'italic'
    });
  };

  var alignFormat = (startNode, startOffset, endNode, endOffset, value) => {
    var lca = this.lcaOf(startNode, endNode);
    var boundElt = this.paragraphOf(lca) || this.hardBlockOf(lca);
    var rangeEndOffsetNode, rangeStartOffsetNode;
    if (!this.isTextNode(rangeStartCtn)) rangeStartOffsetNode = rangeStartCtn.childNodes[rangeStartOffset];
    if (!this.isTextNode(rangeEndCtn)) rangeEndOffsetNode = rangeEndCtn.childNodes[rangeEndOffset];
    var newChildren, child, newNode, i;

    if (boundElt === this.editor.$content) {
      while (startNode !== boundElt) {
        startOffset = childIndexOf(startNode);
        startNode = startNode.parentElement;
      }

      while (endNode !== boundElt) {
        endOffset = childIndexOf(endNode) + 1;
        endNode = endNode.parentElement;
      }

      if (isInline(boundElt.childNodes[startOffset])) {
        while (boundElt.childNodes[startOffset - 1] && boundElt.childNodes[startOffset - 1].tagName !== 'BR' && isInline(boundElt.childNodes[startOffset - 1])) startOffset--;
      }

      if (isInline(boundElt.childNodes[endOffset - 1])) {
        while (boundElt.childNodes[endOffset] && boundElt.childNodes[endOffset].tagName !== 'BR' && isInline(boundElt.childNodes[endOffset])) endOffset++;
      }

      newChildren = Array.prototype.slice.call(boundElt.childNodes, startOffset, endOffset);
      newNode = null;

      for (i = 0; i < newChildren.length; ++i) {
        child = newChildren[i];

        if (isInline(child)) {
          if (!newNode) {
            newNode = (0, _FCore._)({
              tag: 'p',
              style: {
                textAlign: value
              }
            });
            boundElt.insertBefore(newNode, child);
          }

          newNode.appendChild(child);
        } else {
          newNode = null;
          child.style.textAlign = value;
        }
      }
    } else {
      boundElt.style.textAlign = value;
    }

    if (!this.isTextNode(rangeStartCtn)) {
      if (rangeStartOffsetNode) {
        rangeStartOffset = childIndexOf(rangeStartOffsetNode);
        rangeStartCtn = rangeStartOffsetNode.parentElement;
      } else {
        rangeStartOffset = rangeStartCtn.childNodes.length;
      }
    }

    if (!this.isTextNode(rangeEndCtn)) {
      if (rangeEndOffsetNode) {
        rangeEndOffset = childIndexOf(rangeEndOffsetNode);
        rangeEndCtn = rangeEndOffsetNode.parentElement;
      } else {
        rangeEndOffset = rangeEndCtn.childNodes.length;
      }
    }
  };

  if (key === 'fontWeight') {
    if (value === 'bold') {
      bold();
    } else {}
  } else if (key === 'fontStyle') {
    if (value === 'italic') {
      italic();
    }
  } else if (key === 'textAlign') {
    alignFormat(rangeStartCtn, rangeStartOffset, rangeEndCtn, rangeEndOffset, value);
  }

  var unwrapUp = (nd, selector) => {
    if (!nd) return;
    if (nd.contenteditable) return;
    unwrapUp(nd.parentElement, selector);
    if (!nd.matches) return;
    var childNodes;

    if (nd.matches(selector)) {
      childNodes = Array.prototype.slice.call(nd.childNodes);
      childNodes.forEach(c => nd.parentElement.insertBefore(c, nd));
      nd.remove();
    }
  };

  if (rangeStartOffset !== range.startOffset || rangeEndOffset !== rangeEndOffset || rangeStartCtn !== range.startContainer || rangeEndCtn !== range.endContainer) {
    range = document.createRange();
    range.setStart(rangeStartCtn, rangeStartOffset);
    range.setEnd(rangeEndCtn, rangeEndOffset);
    this.setRanges(range);
  }
};
/**
 *
 * @param {Range} range
 * @returns {{}}
 */


KFEngine.prototype.computeRangeFormat = function (range) {
  range = range || (this.getRanges() || [])[0];
  if (!range) return {};
  if (range.collapsed) return this.computeNodeFormat(range.startContainer);
  var startCtn = range.startContainer;
  var arr = [];
  var startOffset = range.startOffset;
  var endCtn = range.endContainer;
  var endOffset = range.endOffset;
  var lcaNode = this.lcaOf(startCtn, endCtn);
  var lcaStartOffset, lcaEndOffset;
  var curNode = startCtn;
  var offset = startOffset;
  var sArr;

  while (curNode !== lcaNode) {
    // this.trimRightNode(curNode, offset);
    if (this.isTextNode(curNode)) {
      arr.push(this.computeNodeFormat(curNode));
    } else {
      sArr = Array.prototype.slice.call(curNode.childNodes, offset).filter(c => !this.isTextNode(c)).map(c => this.computeNodeFormat(c, true));
      arr = arr.concat(sArr);
    }

    offset = childIndexOf(curNode) + 1;
    curNode = curNode.parentElement;
  }

  lcaStartOffset = offset;
  curNode = endCtn;
  offset = endOffset;

  while (curNode !== lcaNode) {
    // this.trimLeftNode(curNode, offset);
    if (this.isTextNode(curNode)) {
      arr.push(this.computeNodeFormat(curNode));
    } else {
      sArr = Array.prototype.slice.call(curNode.childNodes, 0, offset).filter(c => !this.isTextNode(c)).map(c => this.computeNodeFormat(c, true));
      arr = arr.concat(sArr);
    }

    offset = childIndexOf(curNode);
    curNode = curNode.parentElement;
  }

  lcaEndOffset = offset;

  if (this.isTextNode(lcaNode) || lcaStartOffset === lcaEndOffset) {
    return this.computeNodeFormat(lcaNode);
  } else {
    sArr = Array.prototype.slice.call(lcaNode.childNodes, lcaStartOffset, lcaEndOffset).filter(c => !this.isTextNode(c)).map(c => this.computeNodeFormat(c, true));
    arr = arr.concat(sArr);
    return arr.slice(1).reduce((ac, cr) => {
      Object.keys(ac).forEach(key => {
        if (cr[key] !== ac[key]) {
          delete ac[key];
        }
      });
      return ac;
    }, arr[0]);
  }
};

KFEngine.prototype.deleteContentAtCurrentSelection = function () {
  var ranges = this.getRanges();
  if (!ranges) return;
  var range = ranges[0];
  if (range.collapsed) return;
  var startCtn = range.startContainer;
  var startOffset = range.startOffset;
  var endCtn = range.endContainer;
  var endOffset = range.endOffset;
  var lcaNode = this.lcaOf(startCtn, endCtn);
  var lcaStartOffset, lcaEndOffset;
  var curNode = startCtn;
  var offset = startOffset;

  while (curNode !== lcaNode) {
    this.trimRightNode(curNode, offset);
    offset = childIndexOf(curNode) + 1;
    curNode = curNode.parentElement;
  }

  lcaStartOffset = offset;
  curNode = endCtn;
  offset = endOffset;

  while (curNode !== lcaNode) {
    this.trimLeftNode(curNode, offset);
    offset = childIndexOf(curNode);
    curNode = curNode.parentElement;
  }

  lcaEndOffset = offset;
  var inRangeNodes;

  if (this.isTextNode(lcaNode)) {
    this.trimInTextNode(lcaNode, lcaStartOffset, lcaEndOffset);
  } else {
    inRangeNodes = Array.prototype.slice.call(lcaNode.childNodes, lcaStartOffset, lcaEndOffset);
    inRangeNodes.forEach(it => this.removeContentNode(it));
  }

  endOffset = lcaStartOffset;
  startOffset = lcaStartOffset;
  startCtn = lcaNode;
  endCtn = lcaNode;
  range = document.createRange();
  range.setStart(startCtn, startOffset);
  range.setEnd(endCtn, endOffset);
  this.setRanges([range]); // /**joint**/

  var leftNode = lcaNode.childNodes[startOffset - 1];
  var rightNode = lcaNode.childNodes[endOffset];
  this.join2Elements(leftNode, rightNode);
};

KFEngine.prototype.breakParagraphAtCurrentSelection = function () {
  var ranges = this.getRanges();
  if (!ranges) return;
  var range = ranges[0];
  var curNode = range.startContainer;
  var offset = range.startOffset;
  console.log(curNode, offset);
  var newNode;

  if (curNode === this.editor.$content) {
    newNode = (0, _FCore._)('br');

    if (offset >= curNode.childNodes.length) {
      curNode.addChild(newNode);
    } else {
      curNode.addChildAfter(newNode, curNode.childNodes[offset]);
    }

    range = document.createRange();
    range.setStart(curNode, offset + 1);
    range.setEnd(curNode, offset + 1);
    this.setRanges([range]);
    return;
  }

  var parent = curNode.parentElement;
  var paragraph = this.paragraphOf(parent);
  var hardBlock = this.hardBlockOf(parent);
  var newRange;
  var newRangeCtn;
  console.log(paragraph, hardBlock);

  if (this.isInterior(curNode)) {
    newNode = (0, _FCore._)('br');
    curNode.insertBefore(newNode, curNode.childNodes[offset]);
    offset++;

    if (curNode.lastChild === newNode) {
      curNode.appendChild((0, _FCore._)('br'));
    }

    newRange = document.createRange();
    newRange.setStart(curNode, offset);
    this.setRanges(newRange);
  } else if (paragraph) {
    do {
      newNode = this.breakNode(curNode, offset);

      if (!newRangeCtn) {
        newRangeCtn = newNode;
      }

      (0, _FCore.$)(parent).addChildAfter(newNode, curNode);
      offset = childIndexOf(newNode);
      curNode = parent;
      parent = parent.parentElement;
    } while (paragraph.parentElement !== curNode);

    newRange = document.createRange();
    newRange.setStart(newRangeCtn, 0);
    this.setRanges([newRange]);
  } else if (hardBlock) {
    while (curNode !== hardBlock) {
      newNode = this.breakNode(curNode, offset);

      if (!newRangeCtn) {
        newRangeCtn = newNode;
      } // $(parent).addChildAfter(newNode, curNode);


      offset = childIndexOf(newNode);
      curNode = parent;
      parent = parent.parentElement;
    }

    if (newNode && newNode === hardBlock.lastChild) {
      hardBlock.appendChild((0, _FCore._)('br'));
    }

    newNode = (0, _FCore._)('br');
    curNode.addChildBefore(newNode, curNode.childNodes[offset]);
    newRange = document.createRange();
    newRange.setStart(newRangeCtn, 0);
    this.setRanges([newRange]);
  } else {
    console.log("TODO", "not handle this case");
  }
};

KFEngine.prototype.deleteBackAtCurrentSelection = function () {
  var ranges = this.getRanges();
  if (!ranges) return;
  var range = ranges[0];
  var startCtn = range.startContainer;
  var startOffset = range.startOffset;
  var endCtn = range.endContainer;
  var endOffset = range.endOffset;

  var moveBack = () => {
    var prevNode;

    if (this.isTextNode(startCtn)) {
      if (startOffset > 0) {
        startOffset--;
        return false;
      } else {
        startOffset = childIndexOf(startCtn);
        startCtn = startCtn.parentElement;
        return true;
      }
    } else {
      if (startOffset > 0) {
        prevNode = startCtn.childNodes[startOffset - 1];

        if (this.isVoid(prevNode)) {
          startOffset--;
          return false;
        } else if (this.isTextNode(prevNode)) {
          startCtn = prevNode;
          startOffset = prevNode.data.length;
          return true;
        } else if (this.isParagraph(prevNode)) {
          startCtn = prevNode;
          startOffset = prevNode.childNodes.length;
          return false;
        } else {
          startCtn = prevNode;
          startOffset = prevNode.childNodes.length;
          return true;
        }
      } else {
        startOffset = childIndexOf(startCtn);
        startCtn = startCtn.parentElement;
        return true;
      }
    }
  };

  while (moveBack()) {}

  var startHardBlock = this.hardBlockOf(startCtn);
  var endHardBlock = this.hardBlockOf(endCtn);
  if (startHardBlock !== endHardBlock) return;
  range = document.createRange();
  range.setStart(startCtn, startOffset);
  range.setEnd(endCtn, endOffset);
  this.ranges = [range]; //set ranges without view

  this.deleteContentAtCurrentSelection();
};

KFEngine.prototype.getData = function () {
  var data = {};
  var range = (this.getRanges() || [])[0];
  var startCtn, startOffset;
  var endCtn, endOffset;

  if (range) {
    startCtn = range.startContainer;
    startOffset = range.startOffset;
    endCtn = range.endContainer;
    endOffset = range.endOffset;
  }

  var hash = 0;

  var makeDescriptor = nd => {
    var res = {};

    if (nd === startCtn) {
      res.rangeStartOffset = startOffset;
    }

    if (nd === endCtn) {
      res.rangeEndOffset = endOffset;
    }

    var i, atrNode;

    if (nd.nodeType === Node.TEXT_NODE) {
      res.text = nd.data;
      hash = hash + (0, _stringUtils.stringHashCode)(res.text) & 0xffff;
    } else {
      res.tag = nd.tagName.toLowerCase();
      hash = hash + (0, _stringUtils.stringHashCode)(res.tag) & 0xffff;

      if (nd.style.length > 0) {
        res.style = {};

        for (i = 0; i < nd.style.length; ++i) {
          res.style[nd.style[i]] = nd.style[nd.style[i]];
          hash = hash + (0, _stringUtils.stringHashCode)(nd.style[i] + res.style[nd.style[i]]) & 0xffff;
        }
      }

      if (nd.attributes.length > 0) {
        res.attr = {};

        for (i = 0; i < nd.attributes.length; ++i) {
          atrNode = nd.attributes[i];
          res.attr[atrNode.nodeName] = atrNode.nodeValue;
        }
      }

      if (nd.childNodes.length > 0) {
        res.child = Array.prototype.map.call(nd.childNodes, e => makeDescriptor(e));
      }
    }

    return res;
  };

  data.child = Array.prototype.map.call(this.editor.$content.childNodes, e => makeDescriptor(e));
  data.hash = hash;
  return data;
};

KFEngine.prototype.setData = function (data) {
  data = data || {};
  var startCtn, startOffset;
  var endCtn, endOffset;
  var range;

  var build = data => {
    var res;

    if (typeof data.text === "string") {
      res = (0, _FCore._)({
        text: data.text
      });
    } else {
      res = (0, _FCore._)({
        tag: data.tag,
        style: data.style || {},
        attr: data.attr || {}
      });
    }

    if (typeof data.rangeStartOffset === "number") {
      startCtn = res;
      startOffset = data.rangeStartOffset;
    }

    if (typeof data.rangeEndOffset === "number") {
      endCtn = res;
      endOffset = data.rangeEndOffset;
    }

    if (Array.isArray(data.child)) {
      res.addChild(data.child.map(d => build(d)));
    }

    return res;
  };

  this.editor.$content.clearChild();

  if (Array.isArray(data.child)) {
    this.editor.$content.addChild(data.child.map(d => build(d)));
  }

  if (startCtn) {
    range = document.createRange();
    range.setStart(startCtn, startOffset);

    if (endCtn) {
      range.setEnd(endCtn, endOffset);
    }

    this.setRanges(range);
  }
};

var _default = KFEngine;
exports.default = _default;

VaKeR 2022