UNPKG

cthulhu-rlyeh

Version:

DOM manipulation based on cthulhu node architecture

2 lines (1 loc) 4.29 kB
import{Cthulhu as e}from"cthulhu";import{pascalOrCamelToKebab as t}from"@keltoi/naming-converting";import{Doom as o}from"cthulhu-rlyeh";class Doom extends e{#e;#t;#o=!1;#s=!1;get root(){return this.#s}set root(e=!1){this.#s=e}get isVirgin(){return!this.#t}get isDeleted(){return this.#o}constructor(e){super(Doom,e,"content","attributes","events","styleProps","hooks")}static async $(e="",t){const o=await new Doom(t).build(e);return o.root=!0,o}static async compare({oldMap:e=new Map,newMap:t=new Map,set:o=((e,t)=>{}),remove:s=((e,t)=>{})}){t.forEach(((t,s)=>{e.has(s)?(e.get(s)!=t&&o(s,t),e.delete(s)):o(s,t)})),e.forEach(((e,t)=>s(t,e)))}#n=async(e=document.createElement())=>{const o=new Map(Object.entries(this.attributes));this.#t?.has("attributes")?await Doom.compare({oldMap:this.#t,newMap:o,set:(o,s)=>e.setAttribute(t(o),s),remove:o=>{"style"!=o&&e.removeAttribute(t(o))}}):o.forEach(((o,s)=>e.setAttribute(t(s),o)))};#r=async(e=document.createElement())=>{const t=new Map(Object.entries(this.events));this.#t?.has("events")?await Doom.compare({oldMap:this.#t,newMap:t,set:(t,o)=>o.forEach((o=>e.addEventListener(t,o))),remove:(t,o)=>{try{e.removeEventListener(t,o)}finally{return}}}):t.forEach(((t,o)=>t.forEach((t=>e.addEventListener(o,t)))))};#i=async(e=document.createElement())=>{const t=new Map(Object.entries(this.styleProps));if(this.#t?.has("styleProps")){const o=new Map(Object.entries(this.#t.get("styleProps")));await Doom.compare({oldMap:o,newMap:t,set:(t,o)=>e.style[t]=o,remove:t=>e.style[t]=""})}else t.forEach(((t,o)=>e.style[o]=t))};#a=async(e=document.createElement())=>{this.#t?.has("content")?this.#t.get("content")!==this.content&&(e.innerHTML=this.content):e.innerHTML=this.content};#c=(e,t=[],o={}|[])=>{if(o instanceof Array){const s=t.map((e=>e.index??-1));o.forEach((t=>{s.includes(t.index)||t.removeFrom(e)}))}else o.removeFrom(e)};#l=e=>{const o=new Map(Object.entries(this));let s=[],n=[];return o.forEach(((o,r)=>{switch(r){case"attributes":n.push(this.#n(e));break;case"events":n.push(this.#r(e));break;case"styleProps":n.push(this.#i(e));break;case"content":n.push(this.#a(e));break;case"hooks":break;default:{const n=t(r),i=this.#t?.has(r)??!1;if(o instanceof Array){if(i){const t=this.#t.get(r);this.#c(e,o,t)}s=s.concat(o.map(((e,t)=>(e.index=t,e.isVirgin?e.build(n):e.build()))))}else o instanceof Doom&&s.push(o.isVirgin?o.root?o.build():o.build(n):o.build())}}})),{children:s,structure:n,self:o}};delete(){this.#o=!0}async build(e=0){if(this.#o)return this;const t=e?document.createElement(e):this.#e,{self:o,structure:s,children:n}=this.#l(t);return await Promise.all(s),await Promise.all(n).then((e=>{e.forEach((e=>{e.isVirgin||(e.renderOn(t),e.isDeleted&&e.removeFrom(t))}))})),this.#e=t,this.#t=o,this}removeFrom(e=document.createElement()){e.removeChild(this.#e)}renderOn(e=document.createElement()){e.appendChild(this.#e)}}class Router{#h;#u;static App(e=(()=>{}),t={}){const o=new Router({"/":t=>e(t)},t),loader=()=>{const e=o?.match(window.location.pathname,window.location.search),t=document.querySelector("#app");t.innerHTML="",e&&e.then((e=>e.renderOn(t)))};document.addEventListener("DOMContentLoaded",loader),window.onpopstate=loader}constructor(e={},t={},o=(()=>{})){this.#h=e,this.#u=t}notFound=()=>({build:()=>o.$("not-found",{h1:{content:"Page Not Found"},p:{content:"404"}})});#m=(e="")=>{for(const[t,o]of Object.entries(this.#h)){const s=/\:[a-zA-Z]+/g,n=t.replaceAll(s,"[A-Za-z0-9]+"),r=new RegExp(n);if(r.test(e))return{paramSearch:s,matcher:r,route:t,value:o}}return null};match(e="",t=""){const o=`${window.location.protocol}//${window.location.host}${e}`,s=this.#m(e);if(s){const n=e.split("/"),r=s.route.split("/").reduce(((e,t,o)=>{if(s.paramSearch.test(t)){const s=decodeURI(n[o]),r=Number.parseFloat(s);e[t.replace(":","")]=Number.isNaN(r)?s:r}return e}),{});if(""!=t){const e=t.replace("?","").split("&").reduce(((e,t)=>{const[o,s]=t.split("=");return e[o]=s,e}),{});this.#u={...this.#u,query:e}}const i={...this.#u.params,...r},a={...this.#u,params:i,link:e};return history.pushState({},"",o),s.value(a)}return this.notFound()}}const naming=(e=Doom)=>t(e.name),list=(e=[])=>e.map((e=>e instanceof Doom?e:new Doom(e))),update=(e=new Doom,t=(()=>{}))=>{t(e),e.build(null)};export{Doom,Router,list,naming,update};