<commit_before>function render(template, data) {
  var regExp = /{{\s*(\^|#)\s*(.+?)\s*}}([^]+?){{\s*\/\s*\2\s*}}/g;
  var lastIndex = regExp.lastIndex = 0;
  var result = '', match;

  while (match = regExp.exec(template)) {
    var key = match[2], flag = match[1], innerTmpl = match[3];
    var templateBetweenSections = template.substring(lastIndex, match.index);
    result += renderSingleSection(templateBetweenSections, data);
    
    var sectionData = evalProp(data, key);
    if (flag === '#' && sectionData) {
      var dataType = Object.prototype.toString.call(sectionData);
      if (dataType === '[object Array]') {
        sectionData.forEach(function (el) {
          result += render(innerTmpl, el);
        });
      } else if (dataType === '[object Object]') {
        result += render(innerTmpl, sectionData);
      } else if (dataType === '[object Function]') {
        result += sectionData.call(data, innerTmpl, function(template) {
          return renderSingleSection(template, data);
        });
      } else {
        result += render(innerTmpl, data);
      }
    } else if (flag === '^' && !sectionData) {
      result += render(innerTmpl, data);
    }
    lastIndex = regExp.lastIndex;
  }

  result += renderSingleSection(template.substring(lastIndex), data);

  return result;
}

function renderSingleSection(template, data) {
  var regExp = /{{{\s*(.+?)\s*}}}|{{&\s*(.+?)\s*}}|{{\s*(.+?)\s*}}/g;
  var lastIndex = regExp.lastIndex = 0;
  var result = '';
  var match;

  template = template;

  while (match = regExp.exec(template)) {

    result += template.substring(lastIndex, match.index);
    var matched = match[1] || match[2] || match[3];
    var escape = match[3];

    var value = evalProp(data, matched);
    if (value !== undefined && value !== null) {
      result += escape ? escapeHtml('' + value) : value;
    }

    lastIndex = regExp.lastIndex;
  }

  result += template.substring(lastIndex);

  return result;
}

function evalProp(obj, nestedProp) {
  var value = obj;
  if ((nestedProp = nestedProp.trim()) !== '.') {
    var nestedProps = nestedProp.split('.');
    for (var i = 0; i < nestedProps.length; ++i) {
      var prop = nestedProps[i].trim();
      value = value[prop];
      if (value === undefined || value === null) {
        break;
      }
    }
  }

  return (typeof(value) === 'function' ? value.call(obj) : value);
}
<commit_msg>father context and one way to implement space stripping<commit_after>function render(template, data) {
  var regExp = /(\n?[^\S\n]*){{\s*(\^|#)\s*(.+?)\s*}}([^\S\n]*)(\n?[^]+?)(\n?[^\S\n]*){{\s*\/\s*\3\s*}}([^\S\n]*)/g;
  var lastIndex = regExp.lastIndex = 0;
  var result = '', match;

  while (match = regExp.exec(template)) {
    var matchIndex = match.index, flag = match[2], key = match[3], tmplInnerSection = match[5];

    // space stripping
    if (!(match[1] && match[5] && match[1][0] === '\n' && match[5][0] === '\n')) {
      matchIndex += match[1].length;
      tmplInnerSection = match[4] + tmplInnerSection;
    }

    if (!(match[6] && match[6][0] === '\n' && template[regExp.lastIndex] === '\n')) {
      tmplInnerSection += match[6];
      regExp.lastIndex -= match[7].length;
    }

    var tmplBetweenSections = template.substring(lastIndex, matchIndex);
    result += renderSingleSection(tmplBetweenSections, data);
    
    var sectionData = evalProp(data, key);
    if (flag === '#' && sectionData) {
      var dataType = Object.prototype.toString.call(sectionData);
      if (dataType === '[object Array]') {
        sectionData.forEach(function (el) {
          result += render(tmplInnerSection, el);
        });
      } else if (dataType === '[object Object]') {
        sectionData.parent = data;
        result += render(tmplInnerSection, sectionData);
      } else if (dataType === '[object Function]') {
        result += sectionData.call(data, tmplInnerSection, function(template) {
          return renderSingleSection(template, data);
        });
      } else {
        result += render(tmplInnerSection, data);
      }
    } else if (flag === '^' && !sectionData) {
      result += render(tmplInnerSection, data);
    }
    lastIndex = regExp.lastIndex;
  }

  result += renderSingleSection(template.substring(lastIndex), data);

  return result;
}

function renderSingleSection(template, data) {
  var regExp = /{{{\s*(.+?)\s*}}}|{{&\s*(.+?)\s*}}|{{\s*(.+?)\s*}}/g;
  var lastIndex = regExp.lastIndex = 0;
  var result = '';
  var match;

  template = template;

  while (match = regExp.exec(template)) {

    result += template.substring(lastIndex, match.index);
    var matched = match[1] || match[2] || match[3];
    var escape = match[3];

    var value = evalProp(data, matched);
    if (value !== undefined && value !== null) {
      result += escape ? escapeHtml('' + value) : value;
    }

    lastIndex = regExp.lastIndex;
  }

  result += template.substring(lastIndex);

  return result;
}

function evalProp(obj, nestedProp) {
  var context = obj, lookupHit = false, value;

  while (value = context) {
    if ((nestedProp = nestedProp.trim()) !== '.') {
      var nestedProps = nestedProp.split('.');
      for (var i = 0; i < nestedProps.length; ++i) {
        var prop = nestedProps[i].trim();
        if (i === nestedProps.length - 1) {
          lookupHit = (typeof value === 'object' && (prop in value));
        }
        value = value[prop];
        if (value === undefined || value === null) {
          break;
        }
      }
    } else {
      lookupHit = true;
    }

    if (lookupHit) break;

    context = context.parent;
  }

  return (typeof(value) === 'function' ? value.call(obj) : value);
}

{'fraction_non_alphanumeric': 0.18752209261223046, 'fraction_numerical': 0.006362672322375398, 'mean_word_length': 2.913554633471646, 'pattern_counts': {'":': 0, '<': 5, '<?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': '1599073', 'n_tokens_mistral': 1855, 'n_tokens_neox': 1793, 'n_words': 405}