src/js/base/core/range.js
function textRangeToPoint(textRange, isStart) {
  let container = textRange.parentElement();
  let offset;

  const tester = document.body.createTextRange();
  let prevContainer;
  const childNodes = lists.from(container.childNodes);
  for (offset = 0; offset < childNodes.length; offset++) {
    if (dom.isText(childNodes[offset])) {
      continue;
    }
    tester.moveToElementText(childNodes[offset]);
    if (tester.compareEndPoints('StartToStart', textRange) >= 0) {
      break;
    }
    prevContainer = childNodes[offset];
  }

  if (offset !== 0 && dom.isText(childNodes[offset - 1])) {
    const textRangeStart = document.body.createTextRange();
    let curTextNode = null;
    textRangeStart.moveToElementText(prevContainer || container);
    textRangeStart.collapse(!prevContainer);
    curTextNode = prevContainer ? prevContainer.nextSibling : container.firstChild;

    const pointTester = textRange.duplicate();
    pointTester.setEndPoint('StartToStart', textRangeStart);
    let textCount = pointTester.text.replace(/[\r\n]/g, '').length;

    while (textCount > curTextNode.nodeValue.length && curTextNode.nextSibling) {
      textCount -= curTextNode.nodeValue.length;
      curTextNode = curTextNode.nextSibling;
    }

    // [workaround] enforce IE to re-reference curTextNode, hack
    const dummy = curTextNode.nodeValue; // eslint-disable-line

    if (isStart && curTextNode.nextSibling && dom.isText(curTextNode.nextSibling) &&
      textCount === curTextNode.nodeValue.length) {
      textCount -= curTextNode.nodeValue.length;
      curTextNode = curTextNode.nextSibling;
    }

    container = curTextNode;
    offset = textCount;
  }

  return {
    cont: container,
    offset: offset,
  };
}
function textRangeToPoint(textRange, isStart) {
  let container = textRange.parentElement();
  let offset;

  const tester = document.body.createTextRange();
  let prevContainer;
  const childNodes = lists.from(container.childNodes);
  for (offset = 0; offset < childNodes.length; offset++) {
    if (dom.isText(childNodes[offset])) {
      continue;
    }
    tester.moveToElementText(childNodes[offset]);
    if (tester.compareEndPoints('StartToStart', textRange) >= 0) {
      break;
    }
    prevContainer = childNodes[offset];
  }

  if (offset !== 0 && dom.isText(childNodes[offset - 1])) {
    const textRangeStart = document.body.createTextRange();
    let curTextNode = null;
    textRangeStart.moveToElementText(prevContainer || container);
    textRangeStart.collapse(!prevContainer);
    curTextNode = prevContainer ? prevContainer.nextSibling : container.firstChild;

    const pointTester = textRange.duplicate();
    pointTester.setEndPoint('StartToStart', textRangeStart);
    let textCount = pointTester.text.replace(/[\r\n]/g, '').length;

    while (textCount > curTextNode.nodeValue.length && curTextNode.nextSibling) {
      textCount -= curTextNode.nodeValue.length;
      curTextNode = curTextNode.nextSibling;
    }

    // [workaround] enforce IE to re-reference curTextNode, hack
    const dummy = curTextNode.nodeValue; // eslint-disable-line

    if (isStart && curTextNode.nextSibling && dom.isText(curTextNode.nextSibling) &&
      textCount === curTextNode.nodeValue.length) {
      textCount -= curTextNode.nodeValue.length;
      curTextNode = curTextNode.nextSibling;
    }

    container = curTextNode;
    offset = textCount;
  }

  return {
    cont: container,
    offset: offset,
  };
}
function textRangeToPoint ( textRange , isStart ) { let container = textRange . parentElement ( ) ; let offset ; const tester = document . body . createTextRange ( ) ; let prevContainer ; const childNodes = lists . from ( container . childNodes ) ; for ( offset = 0 ; offset < childNodes . length ; offset ++ ) { if ( dom . isText ( childNodes [ offset ] ) ) { continue ; } tester . moveToElementText ( childNodes [ offset ] ) ; if ( tester . compareEndPoints ( 'StartToStart' , textRange ) >= 0 ) { break ; } prevContainer = childNodes [ offset ] ; } if ( offset !== 0 && dom . isText ( childNodes [ offset - 1 ] ) ) { const textRangeStart = document . body . createTextRange ( ) ; let curTextNode = null ; textRangeStart . moveToElementText ( prevContainer || container ) ; textRangeStart . collapse ( ! prevContainer ) ; curTextNode = prevContainer ? prevContainer . nextSibling : container . firstChild ; const pointTester = textRange . duplicate ( ) ; pointTester . setEndPoint ( 'StartToStart' , textRangeStart ) ; let textCount = pointTester . text . replace ( / [\r\n] / g , '' ) . length ; while ( textCount > curTextNode . nodeValue . length && curTextNode . nextSibling ) { textCount -= curTextNode . nodeValue . length ; curTextNode = curTextNode . nextSibling ; } // [workaround] enforce IE to re-reference curTextNode, hack const dummy = curTextNode . nodeValue ; // eslint-disable-line if ( isStart && curTextNode . nextSibling && dom . isText ( curTextNode . nextSibling ) && textCount === curTextNode . nodeValue . length ) { textCount -= curTextNode . nodeValue . length ; curTextNode = curTextNode . nextSibling ; } container = curTextNode ; offset = textCount ; } return { cont : container , offset : offset , } ; }
return boundaryPoint from TextRange, inspired by Andy Na's HuskyRange.js

@param {TextRange} textRange
@param {Boolean} isStart
@return {BoundaryPoint}

@see http://msdn.microsoft.com/en-us/library/ie/ms535872(v=vs.85).aspx
return boundaryPoint from TextRange inspired by Andy Na s HuskyRange . js