<commit_before>package doom.html;

import js.html.Document;
import js.html.Element;
import js.html.Node;
import doom.core.AttributeValue;
import doom.html.Component;
import doom.core.VNode;
import doom.core.VNodes;
import thx.Types;
using thx.Arrays;
using thx.Set;
using thx.Tuple;

@:access(doom.core.Component)
class Render implements doom.core.IRender<Element> {
  // namespaces
  public static var defaultNamespaces = [
    "svg" => "http://www.w3.org/2000/svg"
  ];

  public var doc(default, null) : Document;
  public var namespaces(default, null) : Map<String, String>;
  public var nodeToComponent(default, null) : Map<Node, Component<Dynamic>>;
  public var componentToNode(default, null) : Map<Component<Dynamic>, Node>;

  public function new(?doc : Document, ?namespaces : Map<String, String>) {
    if(null == doc)
      this.doc = js.Browser.document;
    else
      this.doc = doc;
    if(null == namespaces) {
      this.namespaces = new Map();
      for(key in defaultNamespaces.keys())
        this.namespaces.set(key, defaultNamespaces.get(key));
    } else
      this.namespaces = namespaces;
    nodeToComponent = new Map();
    componentToNode = new Map();
  }

  public function mount(node : VNode, parent : Element) {
    parent.innerHTML = "";
    var post = [],
        n = generate(node);
    parent.appendChild(n);
    for(f in post) f();
  }

  public function apply(node : VNode, dom : Node) {
    var post = [];
    trace("** apply");
    applyToNode(node, dom, dom.parentElement, post, false);
    for(f in post) f();
  }

  public function generate(node : VNode) : Node {
    trace("** generate");
    var post = [],
        dom = generateNode(node, post);
    for(f in post) f();
    return dom;
  }

  function applyToNode(node : Null<VNode>, dom : Null<Node>, parent : Element, post : Array<Void -> Void>, tryUnmount : Bool) : Node {
    trace("** applyToNode, has node? " + (null != node) + ", has dom? " + (null != dom) + ", tryUnmount? " + tryUnmount);
    if(null == node && null == dom) {
      return null;
    } else if(null == node) {
      // TODO remove component
      trace("REMOVE CHILD");
      if(tryUnmount)
        unmountDomComponent(dom);
      parent.removeChild(dom);
      return null;
    } else if(null == dom) {
      var el = generateNode(node, post);
      parent.appendChild(el);
      return el;
    }
    return switch node {
      case Element(name, attributes, children):
        if(tryUnmount)
          unmountDomComponent(dom);
        applyElementToNode(name, attributes, children, dom, parent, post);
      case Comment(comment):
        if(tryUnmount)
          unmountDomComponent(dom);
        applyCommentToNode(comment, dom, parent, post);
      case Raw(code):
        if(tryUnmount)
          unmountDomComponent(dom);
        dots.Html.parse(code);
      case Text(text):
        if(tryUnmount)
          unmountDomComponent(dom);
        applyTextToNode(text, dom, parent, post);
      case ComponentNode(comp):
        applyComponentToNode(cast comp, dom, parent, post); // TODO remove cast
      };
  }

  function applyNodeToNode(srcDom : Null<Node>, dstDom : Null<Node>, parent : Element) {
    trace("** applyNodeToNode");
    if(null == srcDom && null == dstDom)
      return;
    else if(null == srcDom) {
      parent.removeChild(dstDom);
      return;
    } else if(null == dstDom) {
      parent.appendChild(srcDom);
      return;
    }

    if(srcDom.nodeType == dstDom.nodeType) {
      // TODO, should we check if there is a component associated?<commit_msg>fixed application or raw content<commit_after>package doom.html;

import js.html.Document;
import js.html.Element;
import js.html.Node;
import doom.core.AttributeValue;
import doom.html.Component;
import doom.core.VNode;
import doom.core.VNodes;
import thx.Types;
using thx.Arrays;
using thx.Set;
using thx.Tuple;

@:access(doom.core.Component)
class Render implements doom.core.IRender<Element> {
  // namespaces
  public static var defaultNamespaces = [
    "svg" => "http://www.w3.org/2000/svg"
  ];

  public var doc(default, null) : Document;
  public var namespaces(default, null) : Map<String, String>;
  public var nodeToComponent(default, null) : Map<Node, Component<Dynamic>>;
  public var componentToNode(default, null) : Map<Component<Dynamic>, Node>;

  public function new(?doc : Document, ?namespaces : Map<String, String>) {
    if(null == doc)
      this.doc = js.Browser.document;
    else
      this.doc = doc;
    if(null == namespaces) {
      this.namespaces = new Map();
      for(key in defaultNamespaces.keys())
        this.namespaces.set(key, defaultNamespaces.get(key));
    } else
      this.namespaces = namespaces;
    nodeToComponent = new Map();
    componentToNode = new Map();
  }

  public function mount(node : VNode, parent : Element) {
    parent.innerHTML = "";
    var post = [],
        n = generate(node);
    parent.appendChild(n);
    for(f in post) f();
  }

  public function apply(node : VNode, dom : Node) {
    var post = [];
    trace("** apply");
    applyToNode(node, dom, dom.parentElement, post, false);
    for(f in post) f();
  }

  public function generate(node : VNode) : Node {
    trace("** generate");
    var post = [],
        dom = generateNode(node, post);
    for(f in post) f();
    return dom;
  }

  function applyToNode(node : Null<VNode>, dom : Null<Node>, parent : Element, post : Array<Void -> Void>, tryUnmount : Bool) : Node {
    trace("** applyToNode, has node? " + (null != node) + ", has dom? " + (null != dom) + ", tryUnmount? " + tryUnmount);
    if(null == node && null == dom) {
      return null;
    } else if(null == node) {
      // TODO remove component
      trace("REMOVE CHILD");
      if(tryUnmount)
        unmountDomComponent(dom);
      parent.removeChild(dom);
      return null;
    } else if(null == dom) {
      var el = generateNode(node, post);
      parent.appendChild(el);
      return el;
    }
    return switch node {
      case Element(name, attributes, children):
        if(tryUnmount)
          unmountDomComponent(dom);
        applyElementToNode(name, attributes, children, dom, parent, post);
      case Comment(comment):
        if(tryUnmount)
          unmountDomComponent(dom);
        applyCommentToNode(comment, dom, parent, post);
      case Raw(code):
        if(tryUnmount)
          unmountDomComponent(dom);
        var node = dots.Html.parse(code);
        applyNodeToNode(node, dom, parent, true);
      case Text(text):
        if(tryUnmount)
          unmountDomComponent(dom);
        applyTextToNode(text, dom, parent, post);
      case ComponentNode(comp):
        applyComponentToNode(cast comp, dom, parent, post); // TODO remove cast
      };
  }

  function applyNodeToNode(srcDom : Null<Node>, dstDom : Null<Node>, parent : Element) {
    trace("** applyNodeToNode");
    if(null == srcDom && null == dstDom)
      return;
    else if(null == srcDom) {
      parent.removeChild(dstDom);
      return;
    } else if(null == dstDom) {
      parent.appendChild(srcDom);
      return;
    }

    if(srcDom.nodeType == dstDom.nodeType) {
      // TODO, should we check if there is a component associated?
{'fraction_non_alphanumeric': 0.13477051460361614, 'fraction_numerical': 0.0013908205841446453, 'mean_word_length': 2.9166666666666665, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 31, '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': '4192033', 'n_tokens_mistral': 2245, 'n_tokens_neox': 2208, 'n_words': 571}