kohutd / сторінка

Реакт, але українською

Отримати
взяти "хмарний.пак.укр/сторінка/0.0.1"
0.0.1
js "
const mavka = getMavka();
const mavkaContext = getContext();

const elementNamesMap = {
  'кнопка': 'button'
};

const elementAttributeNamesMap = {
  'клас': 'class'
};

const elementEventNamesMap = {
  'клік': 'click'
};

const init$Element = ($el) => {
  if ($el.__v) {
    return;
  }

  $el.__v = {};
  $el.__v.attrs = new Set();
  $el.__v.events = new Set();
};

const render = (vNode) => {
  if (typeof vNode !== 'object' || !vNode) {
    const $text = document.createTextNode(String(vNode));
    return $text;
  }
  
  const name = elementNamesMap[vNode['назва']] ?? vNode['назва'];
  const attrs = vNode['атрибути'];
  const children = vNode['діти'];

  const $el = document.createElement(name);

  init$Element($el);

  Object.entries(attrs).forEach(([k, v]) => {
    if (k === 'події') {
      Object.entries(v).forEach(([eK, eV]) => {
        $el.addEventListener(elementEventNamesMap[eK] ?? eK, eV);
        $el.__v.events.add(eK);
      });
    } else {
      $el.setAttribute(elementAttributeNamesMap[k] ?? k, v);
      $el.__v.attrs.add(k);
    }
  });

  children.forEach((childVNode) => {
    $el.appendChild(render(childVNode));
  });
    
  return $el;
};

const patch = ($node, newVNode) => {
  if ($node instanceof Text) {
    if ($node.textContent !== newVNode) {
      const $newNode = render(newVNode);
      $node.parentElement.replaceChild($newNode, $node);
      return $newNode;
    } else {
      return $node;
    }
  }

  init$Element($node);

  const newName = elementNamesMap[newVNode['назва']] ?? newVNode['назва'];
  
  if ($node.tagName.toLowerCase() !== newName) {
     const $newNode = render(newVNode);
     $node.parentElement.replaceChild($newNode, $node);
     $node = $newNode;
  }

  newVNode['діти'].forEach((newChildVNode, i) => {
    let $childNode = $node.childNodes[i];

    if ($childNode) {
      $childNode = patch($childNode, newChildVNode)
    } else {
      $childNode = render(newChildVNode)
      $node.appendChild($childNode);
    }
  });

  if (newVNode['діти'].length < $node.childNodes.length) {
    [...$node.childNodes].forEach(($childNode, index) => {
      if ((index + 1) > newVNode['діти'].length) {
        $childNode.remove();
      }
    });
  }

  return $node;
};

mavkaContext.set('storinka_patchApp', mavka.makePortalFunction((vNode) => {
  const $app = document.getElementById('app');
  patch($app, vNode);
}));
"

модуль сторінка
  дія створити_елемент(назва текст, атрибути словник, діти список) словник
    якщо діти не є список
      діти = [діти]
    кінець
  
    чисті_діти = діти.фільтрувати((д): д не є пусто)
    
    (назва=назва, атрибути=атрибути, діти=чисті_діти)
  кінець

  дія показати(дерево список або словник) ніщо
    storinka_patchApp(створити_елемент(
      "div", 
      (id="app"),
      дерево
    ))
  кінець

  дати створити_елемент, показати
кінець

дати сторінка
Версії