<commit_before>"use strict"

//---------------------------------------------------------
// MicroReact renderer
//---------------------------------------------------------

let renderer = new Renderer();
document.body.appendChild(renderer.content);

//---------------------------------------------------------
// handle dom updates
//---------------------------------------------------------

// TODO: queue updates to be applied during requestAnimationFrame

// root will get added to the dom by the program microReact element in
// drawNodeGraph
var activeElements = {"root": document.createElement("div")};
activeElements["root"].className = "program";
var activeStyles = {};
var supportedTags = {
  "div": true, "span": true, "input": true, "ul": true, "li": true, "label": true, "button": true, "header": true, "footer": true, "a": true, "strong": true,
  "svg": true, "circle": true, "line": true
};
var svgs = {"svg": true, "circle": true, "line": true};

function insertSorted(parent, child) {
  let current;
  for(let curIx = 0; curIx < parent.children.length; curIx++) {
    current = parent.children[curIx];
    if(current.sort && current.sort > child.sort) {
      break;
    } else {
      current = null;
    }
  }
  if(current) {
    parent.insertBefore(child, current);
  } else  {
    parent.appendChild(child);
  }
}

function safeEav(eav) {
  if(eav[0].type == "uuid")  {
    eav[0] = `⦑${eav[0].value}⦒`
  }
  if(eav[1].type == "uuid")  {
    eav[1] = `⦑${eav[1].value}⦒`
  }
  if(eav[2].type == "uuid")  {
    eav[2] = `⦑${eav[2].value}⦒`
  }
  return eav;
}

function handleDOMUpdates(result) {
  let {insert, remove} = result;
  let additions = {};
  // build up a representation of the additions
  if(insert.length) {
    for(let ins of insert) {
      let [entity, attribute, value] = safeEav(ins);
      if(!additions[entity]) additions[entity] = {}
      switch(attribute) {
        case "tag":
          // we don't care about tags on this guy unless they relate
          // to dom tags
          if(!supportedTags[value]) {
            continue;
          }
          break;
        case "children":
          let children = additions[entity][attribute];
          if(!children) {
            children = [];
            additions[entity][attribute] = children;
          }
          children.push(value);
          continue;
        case "text":
          attribute = "textContent"
          break;
      }
      additions[entity][attribute] = value
    }
  }
  // do removes that aren't just going to be overwritten by
  // the adds
  if(remove && remove.length) {
    // we clean up styles after the fact so that in the case where
    // the style object is being removed, but the element is sticking
    // around, we remove any styles that may have been applied
    let stylesToMaybeGC = [];
    for(let rem of remove) {
      let [entity, attribute, value] = safeEav(rem);
      if(activeStyles[entity]) {
        // do style stuff
        for(let elem of activeStyles[entity]) {
          let style = elem.style;
          if(!additions[entity] || !additions[entity][attribute]) {
            style[attribute] = "";
          }
        }
      } else if(activeElements[entity]) {
        let elem = activeElements[entity];
        switch(attribute) {
          case "tag":
            if(supportedTags[value]) {
              //nuke the whole element
              elem.parentNode.removeChild(elem);
              activeElements[entity] = null;
              if(elem.styleId) {
                let ix = activeStyles[elem.styleId].indexOf(elem);
                activeStyles[elem.styleId].splice(ix, 1);
                stylesToMaybeGC.push(value);
              }
            }
            break;
          case "style":
            stylesToMaybeGC.push(value);
            let ix = activeStyles[value].indexOf(elem);
            if(ix > -1) {
              activeStyles[value].splice(ix, 1);
            }
            break;
          case "children":
            let child = activeElements[value];
            if(child) {
              elem.removeChild(child);
              activeElements[value] = null;
            }
            break;
          case "text":
            if(!additions[entity] || !additions[entity]["text"]) {
              elem.textContent = "";
            }
            break;
          default:
            if(!additions[entity] || !additions[entity][attribute]) {
              elem.removeAttribute(attribute);
            }
            break;
        }
      }
    }
    // clean up any styles that need to go
    for(let styleId of stylesToMaybeGC) {
      if(activeStyles[styleId] && activeStyles[styleId].length === 0) {
        activeStyles[styleId] = null;
      }
    }
  }

  let styles = [];
  let entities = Object.keys(additions)
  for(let entId of entities) {
    let ent = additions[entId];
    let elem = activeElements[entId]
    // if we don't have an element already and this one doesn't
    // have a tag, then we just skip it (e.g. a style)
    if(!elem && !ent.tag)  continue;
    if(!elem) {
      //TODO: support finding the correct tag
      if(svgs[ent.tag]) {
        elem = document.createElementNS("http://www.w3.org/2000/svg", ent.tag);
      } else {
        elem = document.createElement(ent.tag || "div")
      }
      elem.entity = entId;
      activeElements[entId] = elem;
      elem.sort = ent.sort || ent["eve-auto-index"] || "";
      insertSorted(activeElements.root, elem)
    }
    let attributes = Object.keys(ent);
    for(let attr of attributes) {
      let value = ent[attr];
      if(attr == "children") {
        for(let child of value) {
          let childElem = activeElements[child];
          if(childElem) {
            insertSorted(elem, childElem)
          } else {
            let childAddition = additions[child];
            // FIXME: if somehow you get a child id, but that child
            // has no facts provided, we'll just lose that information
            // here..
            if(childAddition) {
              childAddition._parent = entId;
            }
          }
        }
      } else if(attr == "style") {
        styles.push(value);
        if(!activeStyles[value]) {
          activeStyles[value] = [];
        }
        if(activeStyles[value].indexOf(elem) == -1) {
          elem.styleId = value;
          activeStyles[value].push(elem);
        }
      } else if(attr == "textContent") {
        elem.textContent = value;
      } else if(attr == "tag" || attr == "ix") {
        //ignore
      } else if(attr == "_parent") {
        let parent = activeElements[value];
        insertSorted(parent, elem);
      } else {
        elem.setAttribute(attr, value);
      }
    }
  }

  for(let styleId of styles) {
    let style = additions[styleId];
    if(!style) continue;
    let elems = activeStyles[styleId];
    for(let elem of elems || []) {
      if(!elem) {
        console.error("Got a style for an element that doesn't exist.");
        continue;
      }
      let elemStyle = elem.style;
      let styleAttributes = Object.keys(style);<commit_msg>Fix checked attribute handling<commit_after>"use strict"

//---------------------------------------------------------
// MicroReact renderer
//---------------------------------------------------------

let renderer = new Renderer();
document.body.appendChild(renderer.content);

//---------------------------------------------------------
// handle dom updates
//---------------------------------------------------------

// TODO: queue updates to be applied during requestAnimationFrame

// root will get added to the dom by the program microReact element in
// drawNodeGraph
var activeElements = {"root": document.createElement("div")};
activeElements["root"].className = "program";
var activeStyles = {};
var supportedTags = {
  "div": true, "span": true, "input": true, "ul": true, "li": true, "label": true, "button": true, "header": true, "footer": true, "a": true, "strong": true,
  "svg": true, "circle": true, "line": true
};
var svgs = {"svg": true, "circle": true, "line": true};

function insertSorted(parent, child) {
  let current;
  for(let curIx = 0; curIx < parent.children.length; curIx++) {
    current = parent.children[curIx];
    if(current.sort && current.sort > child.sort) {
      break;
    } else {
      current = null;
    }
  }
  if(current) {
    parent.insertBefore(child, current);
  } else  {
    parent.appendChild(child);
  }
}

function safeEav(eav) {
  if(eav[0].type == "uuid")  {
    eav[0] = `⦑${eav[0].value}⦒`
  }
  if(eav[1].type == "uuid")  {
    eav[1] = `⦑${eav[1].value}⦒`
  }
  if(eav[2].type == "uuid")  {
    eav[2] = `⦑${eav[2].value}⦒`
  }
  return eav;
}

function handleDOMUpdates(result) {
  let {insert, remove} = result;
  let additions = {};
  // build up a representation of the additions
  if(insert.length) {
    for(let ins of insert) {
      let [entity, attribute, value] = safeEav(ins);
      if(!additions[entity]) additions[entity] = {}
      switch(attribute) {
        case "tag":
          // we don't care about tags on this guy unless they relate
          // to dom tags
          if(!supportedTags[value]) {
            continue;
          }
          break;
        case "children":
          let children = additions[entity][attribute];
          if(!children) {
            children = [];
            additions[entity][attribute] = children;
          }
          children.push(value);
          continue;
        case "text":
          attribute = "textContent"
          break;
      }
      additions[entity][attribute] = value
    }
  }
  // do removes that aren't just going to be overwritten by
  // the adds
  if(remove && remove.length) {
    // we clean up styles after the fact so that in the case where
    // the style object is being removed, but the element is sticking
    // around, we remove any styles that may have been applied
    let stylesToMaybeGC = [];
    for(let rem of remove) {
      let [entity, attribute, value] = safeEav(rem);
      if(activeStyles[entity]) {
        // do style stuff
        for(let elem of activeStyles[entity]) {
          let style = elem.style;
          if(!additions[entity] || !additions[entity][attribute]) {
            style[attribute] = "";
          }
        }
      } else if(activeElements[entity]) {
        let elem = activeElements[entity];
        switch(attribute) {
          case "tag":
            if(supportedTags[value]) {
              //nuke the whole element
              elem.parentNode.removeChild(elem);
              activeElements[entity] = null;
              if(elem.styleId) {
                let ix = activeStyles[elem.styleId].indexOf(elem);
                activeStyles[elem.styleId].splice(ix, 1);
                stylesToMaybeGC.push(value);
              }
            }
            break;
          case "style":
            stylesToMaybeGC.push(value);
            let ix = activeStyles[value].indexOf(elem);
            if(ix > -1) {
              activeStyles[value].splice(ix, 1);
            }
            break;
          case "children":
            let child = activeElements[value];
            if(child) {
              elem.removeChild(child);
              activeElements[value] = null;
            }
            break;
          case "text":
            if(!additions[entity] || !additions[entity]["text"]) {
              elem.textContent = "";
            }
            break;
          default:
            if(!additions[entity] || !additions[entity][attribute]) {
              elem.removeAttribute(attribute);
            }
            break;
        }
      }
    }
    // clean up any styles that need to go
    for(let styleId of stylesToMaybeGC) {
      if(activeStyles[styleId] && activeStyles[styleId].length === 0) {
        activeStyles[styleId] = null;
      }
    }
  }

  let styles = [];
  let entities = Object.keys(additions)
  for(let entId of entities) {
    let ent = additions[entId];
    let elem = activeElements[entId]
    // if we don't have an element already and this one doesn't
    // have a tag, then we just skip it (e.g. a style)
    if(!elem && !ent.tag)  continue;
    if(!elem) {
      //TODO: support finding the correct tag
      if(svgs[ent.tag]) {
        elem = document.createElementNS("http://www.w3.org/2000/svg", ent.tag);
      } else {
        elem = document.createElement(ent.tag || "div")
      }
      elem.entity = entId;
      activeElements[entId] = elem;
      elem.sort = ent.sort || ent["eve-auto-index"] || "";
      insertSorted(activeElements.root, elem)
    }
    let attributes = Object.keys(ent);
    for(let attr of attributes) {
      let value = ent[attr];
      if(attr == "children") {
        for(let child of value) {
          let childElem = activeElements[child];
          if(childElem) {
            insertSorted(elem, childElem)
          } else {
            let childAddition = additions[child];
            // FIXME: if somehow you get a child id, but that child
            // has no facts provided, we'll just lose that information
            // here..
            if(childAddition) {
              childAddition._parent = entId;
            }
          }
        }
      } else if(attr == "style") {
        styles.push(value);
        if(!activeStyles[value]) {
          activeStyles[value] = [];
        }
        if(activeStyles[value].indexOf(elem) == -1) {
          elem.styleId = value;
          activeStyles[value].push(elem);
        }
      } else if(attr == "textContent") {
        elem.textContent = value;
      } else if(attr == "tag" || attr == "ix") {
        //ignore
      } else if(attr == "_parent") {
        let parent = activeElements[value];
        insertSorted(parent, elem);
      } else if(attr == "checked") {
        if(value) elem.setAttribute("checked", true);
        else elem.removeAttribute("checked");
      } else {
        elem.setAttribute(attr, value);
      }
    }
  }

  for(let styleId of styles) {
    let style = additions[styleId];
    if(!style) continue;
    let elems = activeStyles[styleId];
    for(let elem of elems || []) {
      if(!elem) {
        console.error("Got a style for an element that doesn't exist.");
        continue;
      }
      let elemStyle = elem.style;
      let styleAttributes = Object.keys(style);
{'fraction_non_alphanumeric': 0.16220549282029834, 'fraction_numerical': 0.0027882336539802035, 'mean_word_length': 1.8247686552470959, 'pattern_counts': {'":': 50, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '3051428', 'n_tokens_mistral': 4130, 'n_tokens_neox': 4108, 'n_words': 1034}