<commit_before>// =============================================================================
// Boost.js | Template Functions
// (c) Mathigon
// =============================================================================



export function parse(string) {
  // TODO use expressions
  // jshint evil: true

  let fn = string.replace(/"/g,'\"');
  fn = fn.replace(/\$\{([^\}]+)\}/g, (x, y) => `" + (${y}) + "`);

  try {
    return new Function('_vars', `try {
      with(_vars) { return "${fn}" }
    } catch(e) {
      if (!(e instanceof ReferenceError)) console.warn(e);
      return "";
    }`);
  } catch (e) {
    console.warn('WHILE PARSING: ', string, '\n', e);
    return function() { return ''; };
  }
}

function makeTemplate(model, property, fromObj, toObj = fromObj) {
  if (fromObj[property].indexOf('${') < 0) return;
  let fn = parse(fromObj[property]);
  model.change(function() { toObj[property] = fn(model); });
  toObj[property] = fn(model);
}

export function bind($el, model, noIterate = false) {
  for (let a of $el.attributes) {
    // NOTE: We have to convert x-path attributes, because SVG errors are thrown on load
    let to = a.name.match(/^x-/) ? document.createAttribute(a.name.replace(/^x-/, '')) : a;
    makeTemplate(model, 'value', a, to);
    if (to != a) $el._el.setAttributeNode(to);
    // TODO Update `props` property of custom elements.
  }

  if ($el.children.length) {
    for (let $c of $el.childNodes) {
      if ($c.tagName == 'TEXT') {
        makeTemplate(model, 'text', $c);<commit_msg>Allow templating functions that don't return strings<commit_after>// =============================================================================
// Boost.js | Template Functions
// (c) Mathigon
// =============================================================================



export function parse(string, expr=false) {
  // TODO use expressions
  // jshint evil: true

  let fn = string;

  if (!expr) {
    fn = fn.replace(/"/g,'\"')
           .replace(/\$\{([^\}]+)\}/g, (x, y) => `" + (${y}) + "`);
    fn = '"' + fn + '"';
  }

  try {
    return new Function('_vars', `try {
      with(_vars) { return ${fn} }
    } catch(e) {
      if (!(e instanceof ReferenceError)) console.warn(e);
      return "";
    }`);
  } catch (e) {
    console.warn('WHILE PARSING: ', string, '\n', e);
    return function() { return ''; };
  }
}

function makeTemplate(model, property, fromObj, toObj = fromObj) {
  if (fromObj[property].indexOf('${') < 0) return;
  let fn = parse(fromObj[property]);
  model.change(function() { toObj[property] = fn(model); });
  toObj[property] = fn(model);
}

export function bind($el, model, noIterate = false) {
  for (let a of $el.attributes) {
    // NOTE: We have to convert x-path attributes, because SVG errors are thrown on load
    let to = a.name.match(/^x-/) ? document.createAttribute(a.name.replace(/^x-/, '')) : a;
    makeTemplate(model, 'value', a, to);
    if (to != a) $el._el.setAttributeNode(to);
    // TODO Update `props` property of custom elements.
  }

  if ($el.children.length) {
    for (let $c of $el.childNodes) {
      if ($c.tagName == 'TEXT') {
        makeTemplate(model, 'text', $c);
{'fraction_non_alphanumeric': 0.2776381909547739, 'fraction_numerical': 0.000628140703517588, 'mean_word_length': 3.363013698630137, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, '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': '4576909', 'n_tokens_mistral': 1025, 'n_tokens_neox': 995, 'n_words': 259}