symbiotic
Version:
A lightweight DOM attachment framework
7 lines (6 loc) • 6.31 kB
JavaScript
/*!
* Symbiote - A lightweight DOM attachment framework
* @version 1.0.0
* @license MIT
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Symbiote={})}(this,(function(e){"use strict";const t={id:new Map,class:new Map,tag:new Map,other:new Set};function o(e){return!/:[a-zA-Z-]/.test(e)}function s(e){const o=e.trim();if(o.startsWith("#")){const e=o.slice(1).split(/[^-_a-zA-Z0-9]/,1)[0];return t.id.has(e)||t.id.set(e,new Set),void t.id.get(e).add(o)}if(o.includes(".")){const e=o.match(/\.[a-zA-Z0-9_-]+/g);if(e){for(const s of e){const e=s.slice(1);t.class.has(e)||t.class.set(e,new Set),t.class.get(e).add(o)}return}}const s=o.split(/[\s.#[:]/,1)[0].toLowerCase();if(s&&(/^[a-z][a-z0-9-]*$/.test(s)||"*"===s))return t.tag.has(s)||t.tag.set(s,new Set),void t.tag.get(s).add(o);if(o.startsWith("[")){const e=o.match(/^([a-z][a-z0-9-]*)\[/);if(e){const s=e[1];return t.tag.has(s)||t.tag.set(s,new Set),void t.tag.get(s).add(o)}}t.other.add(o)}function n(e){const o=e.trim();let s=!1;if(o.startsWith("#")){const e=o.slice(1).split(/[^-_a-zA-Z0-9]/,1)[0],n=t.id.get(e);n&&(n.delete(o),n.size||t.id.delete(e),s=!0)}else if(o.includes(".")){const e=o.match(/\.[a-zA-Z0-9_-]+/g);if(e)for(const n of e){const e=n.slice(1),c=t.class.get(e);c&&(c.delete(o),c.size||t.class.delete(e),s=!0)}}else{const e=o.split(/[\s.#[:]/,1)[0].toLowerCase();if(e&&(/^[a-z][a-z0-9-]*$/.test(e)||"*"===e)){const n=t.tag.get(e);n&&(n.delete(o),n.size||t.tag.delete(e),s=!0)}}if(!s&&o.startsWith("[")){const e=o.match(/^([a-z][a-z0-9-]*)\[/);if(e){const n=e[1],c=t.tag.get(n);c&&(c.delete(o),c.size||t.tag.delete(n),s=!0)}}s||t.other.delete(o)}function*c(e){const o=new Set,s=e.id?.trim();if(s&&t.id.has(s))for(const e of t.id.get(s))o.add(e);if(e.classList&&e.classList.length)for(const s of e.classList){const e=t.class.get(s);if(e)for(const t of e)o.add(t)}const n=e.tagName?.toLowerCase();if(n){const e=t.tag.get(n);if(e)for(const t of e)o.add(t);const s=t.tag.get("*");if(s)for(const e of s)o.add(e)}for(const e of t.other)o.add(e);yield*o}const r=new WeakMap,i=new WeakMap,a=new WeakMap;function d(e){let t=r.get(e);return t||(t=new Set,r.set(e,t)),t}function l(e){let t=i.get(e);return t||(t=new Map,i.set(e,t)),t}function h(e,t){if("function"!=typeof t)return;let o=a.get(e);o||(o=new Set,a.set(e,o)),o.add(t)}const f=new Map,u=new Set;class m{#e=null;#t=new Set;#o=!1;#s=null;constructor(e={}){if(e&&"object"==typeof e)for(const[t,n]of Object.entries(e))o(t)&&(f.set(t,n),s(t));this.#e=new MutationObserver((e=>{for(const t of e)if("childList"===t.type)t.addedNodes.forEach((e=>this.#n(e))),t.removedNodes.forEach((e=>this.#c(e)));else if("attributes"===t.type){const e=t.target;1===e.nodeType&&this.#r(e)}}))}async attach(e=document.body){e===document.body&&await new Promise((e=>{"loading"===document.readyState?document.addEventListener("DOMContentLoaded",e):e()})),this.#s=e,this.#e.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeOldValue:!0}),this.#i(e)}batch(e){return"function"==typeof e?this.#a(e):Promise.resolve()}update(){this.#s&&this.#i(this.#s,!0)}destroy(){var e;e=this,u.delete(e),this.#e&&this.#e.disconnect(),this.#s&&this.#c(this.#s),this.#s=null}cleanup(e){(this.#s||document).querySelectorAll(e).forEach((t=>this.#d(t,e)))}checkFor(e){(this.#s||document).querySelectorAll(e).forEach((t=>{d(t).has(e)||this.#l(t,e,f.get(e))}))}#i(e,t=!1){this.#e.disconnect();const o=document.createTreeWalker(e,1,null,!1);let s=1===e.nodeType?e:null;for(s&&this.#h(s,t);s=o.nextNode();)this.#h(s,t);this.#s&&this.#e.observe(this.#s,{childList:!0,subtree:!0,attributes:!0,attributeOldValue:!0})}#n(e){if(e&&"number"==typeof e.nodeType&&(1===e.nodeType&&this.#h(e,!0),e.hasChildNodes&&e.childNodes&&e.childNodes.length)){const t=document.createTreeWalker(e,1,null,!1);let o;for(;o=t.nextNode();)this.#h(o,!0)}}#h(e,t){if(1===e.nodeType){t&&this.#r(e);for(const t of c(e)){const s=f.get(t);if(!s)continue;!d(e).has(t)&&o(t)&&e.matches(t)&&this.#l(e,t,s)}}}#r(e){const t=d(e);if(t.size)for(const o of Array.from(t))e.matches(o)||this.#d(e,o);for(const s of c(e)){const n=f.get(s);n&&!t.has(s)&&o(s)&&e.matches(s)&&this.#l(e,s,n)}}#l(e,t,o){if(!o)return;const s=d(e);if(s.has(t))return;const n="TEMPLATE"===e.tagName?[this.#f(e),this.#u()]:[e,this.#u()];try{const c=o(...n);if("function"==typeof c){l(e).set(t,c)}s.add(t)}catch(e){console.error(`Error attaching selector "${t}":`,e)}}#d(e,t){const o=d(e);if(!o.has(t))return;const s=l(e),n=s.get(t);if(n){try{n()}catch(e){console.error(e)}s.delete(t)}o.delete(t),0===o.size&&r.delete(e),0===s.size&&i.delete(e)}#m(e){const t=l(e);if(t)for(const[o]of t)this.#d(e,o);!function(e){const t=a.get(e);if(t){for(const e of t)try{e()}catch(e){console.error(e)}t.clear(),a.delete(e)}}(e)}#c(e){if(e&&"number"==typeof e.nodeType&&(1===e.nodeType&&this.#m(e),e.hasChildNodes&&e.childNodes&&e.childNodes.length)){const t=e.ownerDocument.createTreeWalker(e,1,null,!1);let o;for(;o=t.nextNode();)this.#m(o)}}#u(){return e=>this.batch(e)}#f(e){let t=[];const o=()=>{for(const e of t)this.#c(e),e.parentNode&&e.parentNode.removeChild(e);t=[]};return s=>{o();const n=document.importNode(e.content,!0);if(t=Array.from(n.children),e.after(n),"function"==typeof s)for(const e of t)if(1===e.nodeType)try{const t=s(e,this.#u());"function"==typeof t&&h(e,t)}catch(e){console.error("Error in template child setup:",e)}}}#a(e){return new Promise(((t,o)=>{this.#t.add({operations:e,resolve:t,reject:o}),this.#g()}))}#g(){if(this.#o)return;this.#o=!0;("undefined"!=typeof requestAnimationFrame?requestAnimationFrame:e=>setTimeout(e,0))((()=>{this.#t.forEach((e=>{try{e.operations(),e.resolve()}catch(t){e.reject(t)}})),this.#o=!1,this.#t.clear()}))}}function g(e){const t=new m(e);var o;return o=t,u.add(o),t}e.createSymbiote=g,e.default=g,e.defineSetup=function(e,t){return o(e)?null===t?(f.has(e)&&(u.forEach((t=>{t.cleanup(e)})),f.delete(e),n(e)),{remove(){}}):(f.has(e)&&(u.forEach((t=>{t.cleanup(e)})),n(e)),f.set(e,t),s(e),u.forEach((t=>{t.checkFor(e)})),{remove:()=>{u.forEach((t=>t.cleanup(e))),f.delete(e),n(e)}}):(console.warn(`Ignoring unstable selector: ${e}`),{remove(){}})},Object.defineProperty(e,"__esModule",{value:!0})}));