text: 'use strict';
  
  var doc = global.document;
  var body = doc.body;
  
  function rangeToTextRange (p) {
    if (p.collapsed) {
      return createBoundaryTextRange({ node: p.startContainer, offset: p.startOffset }, true);
    }
    var startRange = createBoundaryTextRange({ node: p.startContainer, offset: p.startOffset }, true);
    var endRange = createBoundaryTextRange({ node: p.endContainer, offset: p.endOffset }, false);
    var textRange = body.createTextRange();
    textRange.setEndPoint('StartToStart', startRange);
    textRange.setEndPoint('EndToEnd', endRange);
    return textRange;
  }
  
  function isCharacterDataNode (node) {
    var t = node.nodeType;
    return t === 3 || t === 4 || t === 8 ;
  }
  
  function createBoundaryTextRange (p, starting) {
    var bound;
    var parent;
    var offset = p.offset;
    var workingNode;
    var childNodes;
    var range = body.createTextRange();
    var data = isCharacterDataNode(p.node);
  
    if (data) {
      bound = p.node;
      parent = bound.parentNode;
    } else {
      childNodes = p.node.childNodes;
      bound = offset < childNodes.length ? childNodes[offset] : null;
      parent = p.node;
    }
  
    workingNode = doc.createElement('span');
    workingNode.innerHTML = '&#feff;';
  
    if (bound) {
      parent.insertBefore(workingNode, bound);
    } else {
      parent.appendChild(workingNode);
    }
  
    range.moveToElementText(workingNode);
    range.collapse(!starting);
    parent.removeChild(workingNode);
  
    if (data) {
      range[starting ? 'moveStart' : 'moveEnd']('character', offset);
    }
    return range;
  }
  
  module.exports = rangeToTextRange;
  