<commit_before>import seek from 'dom-seek';


function getFirstTextNode(node) {
  if (node.nodeType === Node.TEXT_NODE) return node;
  let document = node.ownerDocument;
  let walker = document.createTreeWalker(node, NodeFilter.SHOW_TEXT);
  return walker.firstChild();
}


export default class TextPositionAnchor {
  constructor(root, start, end) {
    if (root === undefined) {
      throw new Error('missing required parameter "root"');
    }
    if (start === undefined) {
      throw new Error('missing required parameter "start"');
    }
    if (end === undefined) {
      throw new Error('missing required parameter "end"');
    }
    this.root = root;
    this.start = start;
    this.end = end;
  }

  static fromRange(root, range) {
    if (root === undefined) {
      throw new Error('missing required parameter "root"');
    }
    if (range === undefined) {
      throw new Error('missing required parameter "range"');
    }

    let startNode = range.startContainer;
    let startOffset = range.startOffset;

    // Drill down to a text node if the range starts at the container boundary.
    if (startNode.nodeType !== Node.TEXT_NODE) {
      if (startOffset === startNode.childNodes.length) {
        startNode = startNode.childNodes[startOffset - 1];
        startNode = getFirstTextNode(startNode);
        startOffset = startNode.textContent.length;
      } else {
        startNode = startNode.childNodes[startOffset];
        startNode = getFirstTextNode(startNode);
        startOffset = 0;
      }
    }

    let endNode = range.endContainer;
    let endOffset = range.endOffset;

    // Drill down to a text node if the range ends at the container boundary.
    if (endNode.nodeType !== Node.TEXT_NODE) {
      if (endOffset === endNode.childNodes.length) {
        endNode = endNode.childNodes[endOffset - 1];
        endNode = getFirstTextNode(endNode);
        endOffset = endNode.textContent.length;
      } else {
        endNode = endNode.childNodes[endOffset];
        endNode = getFirstTextNode(endNode);
        endOffset = 0;
      }
    }

    let document = root.ownerDocument;
    let iter = document.createNodeIterator(root, NodeFilter.SHOW_TEXT);
    let start = seek(iter, startNode);
    let end = start + seek(iter, endNode);

    return new TextPositionAnchor(root, start + startOffset, end + endOffset);
  }

  static fromSelector(root, selector = {}) {
    return new TextPositionAnchor(root, selector.start, selector.end);
  }

  toRange() {
    let root = this.root;
    let document = root.ownerDocument;
    let range = document.createRange();
    let iter = document.createNodeIterator(root, NodeFilter.SHOW_TEXT);<commit_msg>Use all four arguments to iterator and walker<commit_after>import seek from 'dom-seek';

const SHOW_TEXT = NodeFilter.SHOW_TEXT;


function getFirstTextNode(node) {
  if (node.nodeType === Node.TEXT_NODE) return node;
  let document = node.ownerDocument;
  let walker = document.createTreeWalker(node, SHOW_TEXT, null, false);
  return walker.firstChild();
}


export default class TextPositionAnchor {
  constructor(root, start, end) {
    if (root === undefined) {
      throw new Error('missing required parameter "root"');
    }
    if (start === undefined) {
      throw new Error('missing required parameter "start"');
    }
    if (end === undefined) {
      throw new Error('missing required parameter "end"');
    }
    this.root = root;
    this.start = start;
    this.end = end;
  }

  static fromRange(root, range) {
    if (root === undefined) {
      throw new Error('missing required parameter "root"');
    }
    if (range === undefined) {
      throw new Error('missing required parameter "range"');
    }

    let startNode = range.startContainer;
    let startOffset = range.startOffset;

    // Drill down to a text node if the range starts at the container boundary.
    if (startNode.nodeType !== Node.TEXT_NODE) {
      if (startOffset === startNode.childNodes.length) {
        startNode = startNode.childNodes[startOffset - 1];
        startNode = getFirstTextNode(startNode);
        startOffset = startNode.textContent.length;
      } else {
        startNode = startNode.childNodes[startOffset];
        startNode = getFirstTextNode(startNode);
        startOffset = 0;
      }
    }

    let endNode = range.endContainer;
    let endOffset = range.endOffset;

    // Drill down to a text node if the range ends at the container boundary.
    if (endNode.nodeType !== Node.TEXT_NODE) {
      if (endOffset === endNode.childNodes.length) {
        endNode = endNode.childNodes[endOffset - 1];
        endNode = getFirstTextNode(endNode);
        endOffset = endNode.textContent.length;
      } else {
        endNode = endNode.childNodes[endOffset];
        endNode = getFirstTextNode(endNode);
        endOffset = 0;
      }
    }

    let document = root.ownerDocument;
    let iter = document.createNodeIterator(root, SHOW_TEXT, null, false);
    let start = seek(iter, startNode);
    let end = start + seek(iter, endNode);

    return new TextPositionAnchor(root, start + startOffset, end + endOffset);
  }

  static fromSelector(root, selector = {}) {
    return new TextPositionAnchor(root, selector.start, selector.end);
  }

  toRange() {
    let root = this.root;
    let document = root.ownerDocument;
    let range = document.createRange();
    let iter = document.createNodeIterator(root, SHOW_TEXT, null, false);
{'fraction_non_alphanumeric': 0.1101491987474673, 'fraction_numerical': 0.0014735678762202984, 'mean_word_length': 3.0492170022371363, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4783903', 'n_tokens_mistral': 1584, 'n_tokens_neox': 1553, 'n_words': 427}