lightview 2.1.0 → 2.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build-bundles.mjs +2 -6
- package/build.js +236 -46
- package/components/data-display/avatar.js +25 -1
- package/components/data-display/chart.js +22 -5
- package/components/data-display/countdown.js +3 -2
- package/components/data-input/checkbox.js +23 -1
- package/components/data-input/input.js +24 -1
- package/components/data-input/radio.js +37 -2
- package/components/data-input/select.js +24 -1
- package/components/data-input/toggle.js +21 -1
- package/components/navigation/breadcrumbs.js +42 -2
- package/docs/assets/js/examplify.js +1 -1
- package/docs/cdom-nav.html +32 -6
- package/docs/cdom.html +610 -180
- package/docs/components/avatar.html +24 -54
- package/docs/components/badge.html +14 -14
- package/docs/components/breadcrumbs.html +95 -29
- package/docs/components/chart-area.html +3 -3
- package/docs/components/chart-bar.html +4 -181
- package/docs/components/chart-column.html +4 -189
- package/docs/components/chart-line.html +3 -3
- package/docs/components/chart-pie.html +112 -166
- package/docs/components/chart.html +11 -13
- package/docs/components/checkbox.html +48 -28
- package/docs/components/collapse.html +6 -6
- package/docs/components/countdown.html +12 -12
- package/docs/components/dropdown.html +1 -1
- package/docs/components/file-input.html +4 -4
- package/docs/components/footer.html +11 -11
- package/docs/components/input.html +45 -29
- package/docs/components/join.html +4 -4
- package/docs/components/kbd.html +3 -3
- package/docs/components/loading.html +41 -53
- package/docs/components/pagination.html +4 -4
- package/docs/components/progress.html +6 -4
- package/docs/components/radio.html +42 -31
- package/docs/components/select.html +48 -59
- package/docs/components/toggle.html +44 -25
- package/docs/getting-started/index.html +4 -4
- package/jprx/LICENSE +21 -0
- package/jprx/README.md +130 -0
- package/{cdom → jprx}/helpers/array.js +9 -4
- package/{cdom → jprx}/helpers/state.js +6 -3
- package/jprx/index.js +69 -0
- package/jprx/package.json +24 -0
- package/jprx/parser.js +1517 -0
- package/lightview-all.js +3785 -1
- package/lightview-cdom.js +2128 -1
- package/lightview-router.js +179 -208
- package/lightview-x.js +1435 -1
- package/lightview.js +613 -1
- package/package.json +5 -2
- package/src/lightview-cdom.js +201 -49
- package/src/lightview-router.js +210 -0
- package/src/lightview-x.js +104 -55
- package/src/lightview.js +12 -1
- package/{watch.js → start-dev.js} +2 -1
- package/tests/cdom/parser.test.js +83 -12
- package/wrangler.toml +0 -3
- package/cdom/parser.js +0 -602
- package/test-text-tag.js +0 -6
- /package/{cdom → jprx}/helpers/compare.js +0 -0
- /package/{cdom → jprx}/helpers/conditional.js +0 -0
- /package/{cdom → jprx}/helpers/datetime.js +0 -0
- /package/{cdom → jprx}/helpers/format.js +0 -0
- /package/{cdom → jprx}/helpers/logic.js +0 -0
- /package/{cdom → jprx}/helpers/lookup.js +0 -0
- /package/{cdom → jprx}/helpers/math.js +0 -0
- /package/{cdom → jprx}/helpers/network.js +0 -0
- /package/{cdom → jprx}/helpers/stats.js +0 -0
- /package/{cdom → jprx}/helpers/string.js +0 -0
package/lightview-all.js
CHANGED
|
@@ -1 +1,3785 @@
|
|
|
1
|
-
!function(){"use strict";const e=globalThis.__LIGHTVIEW_INTERNALS__||(globalThis.__LIGHTVIEW_INTERNALS__={currentEffect:null,registry:new Map,dependencyMap:new WeakMap}),t=(t,n)=>{let r="string"==typeof n?n:null==n?void 0:n.name;const o=null==n?void 0:n.storage;if(r&&o)try{const e=o.getItem(r);null!==e&&(t=JSON.parse(e))}catch(l){}let s=t;const i=new Set,a=(...e)=>{if(0===e.length)return a.value;a.value=e[0]};if(Object.defineProperty(a,"value",{get:()=>(e.currentEffect&&(i.add(e.currentEffect),e.currentEffect.dependencies.add(i)),s),set(e){if(s!==e){if(s=e,r&&o)try{o.setItem(r,JSON.stringify(s))}catch(l){}[...i].forEach(e=>e())}}}),r)if(e.registry.has(r)){if(e.registry.get(r)!==a)throw new Error(`Lightview: A signal or state with the name "${r}" is already registered.`)}else e.registry.set(r,a);return a};t.get=(n,r)=>e.registry.has(n)||void 0===r?e.registry.get(n):t(r,n);const n=t=>{const n=()=>{if(n.active&&!n.running){n.dependencies.forEach(e=>e.delete(n)),n.dependencies.clear(),n.running=!0,e.currentEffect=n;try{t()}finally{e.currentEffect=null,n.running=!1}}};return n.active=!0,n.running=!1,n.dependencies=new Set,n.stop=()=>{n.dependencies.forEach(e=>e.delete(n)),n.dependencies.clear(),n.active=!1},n(),n},r=()=>e.registry,o=new WeakMap,s=new WeakMap,i=new WeakMap,a=(e,t)=>Object.getOwnPropertyNames(e).filter(n=>"function"==typeof e[n]&&t(n)),l=a(Date.prototype,e=>/^(to|get|valueOf)/.test(e)),c=a(Date.prototype,e=>/^set/.test(e)),u=["map","forEach","filter","find","findIndex","some","every","reduce","reduceRight","includes","indexOf","lastIndexOf","join","slice","concat","flat","flatMap","at","entries","keys","values"],d=["push","pop","shift","unshift","splice","sort","reverse","fill","copyWithin"],h=["map","forEach","filter","find","findIndex","some","every","flatMap"],f=(e,t,n)=>{let r=e.get(t);return r||(r=n(),e.set(t,r)),r},p=(e,n,r,o)=>{if("__parent__"===n)return i.get(r);o.has(n)||o.set(n,t(Reflect.get(e,n,r)));const s=o.get(n).value;if("object"==typeof s&&null!==s){const e=y(s);return i.set(e,r),e}return s},m=(e,n,r,o,s)=>{s.has(n)||s.set(n,t(Reflect.get(e,n,o)));const i=Reflect.set(e,n,r,o),a=s.get(n);return i&&a&&(a.value=r),i},g=(e,n,r=[])=>{const o=f(s,e,()=>new Map);if(!o.has(n)){const r="function"==typeof e[n]?e[n].call(e):e[n];o.set(n,t(r))}const a=e instanceof Date,g=Array.isArray(e),v=a?l:g?u:r,b=a?c:g?d:[];return new Proxy(e,{get(e,t,r){if("__parent__"===t)return i.get(r);const s=e[t];if("function"==typeof s){const a=v.includes(t),l=b.includes(t);return function(...c){if(a){const e=o.get(n);e&&e.value}const u="function"==typeof e[n]?e[n].call(e):e[n];if(g&&h.includes(t)&&"function"==typeof c[0]){const e=c[0];c[0]=function(t,n,o){const s="object"==typeof t&&null!==t?y(t):t;return s&&"object"==typeof s&&i.set(s,r),e.call(this,s,n,o)}}const d=s.apply(e,c),f="function"==typeof e[n]?e[n].call(e):e[n];if(u!==f||l){const e=o.get(n);e&&e.value!==f&&(e.value=f)}return d}}if(t===n){const s=o.get(n);return s?s.value:Reflect.get(e,t,r)}if(g&&!isNaN(parseInt(t))){const e=o.get(n);e&&e.value}return p(e,t,r,o)},set(e,t,r,s){if(t===n){const i=Reflect.set(e,t,r,s);if(i){const e=o.get(n);e&&(e.value=r)}return i}return m(e,t,r,s,o)}})},y=(e,t)=>{if("object"!=typeof e||null===e)return e;const a="string"==typeof t?t:null==t?void 0:t.name,l=null==t?void 0:t.storage;if(a&&l)try{const t=l.getItem(a);if(t){const n=JSON.parse(t);Array.isArray(e)&&Array.isArray(n)?(e.length=0,e.push(...n)):Object.assign(e,n)}}catch(u){}let c=o.get(e);if(!c){const t=Array.isArray(e),n=e instanceof Date,r=t||n;if(!r&&(e instanceof RegExp||e instanceof Map||e instanceof Set||e instanceof WeakMap||e instanceof WeakSet))return e;c=r?g(e,t?"length":n?"getTime":null):new Proxy(e,{get:(e,t,n)=>"__parent__"===t?i.get(n):p(e,t,n,f(s,e,()=>new Map)),set:(e,t,n,r)=>m(e,t,n,r,f(s,e,()=>new Map))}),o.set(e,c)}if(a&&l&&n(()=>{try{l.setItem(a,JSON.stringify(c))}catch(u){}}),a){const e=r();if(e.has(a)){if(e.get(a)!==c)throw new Error(`Lightview: A signal or state with the name "${a}" is already registered.`)}else e.set(a,c)}return c};y.get=(e,t)=>{const n=r();return n.has(e)||void 0===t?n.get(e):y(t,e)};const v={get currentEffect(){return(globalThis.__LIGHTVIEW_INTERNALS__||(globalThis.__LIGHTVIEW_INTERNALS__={})).currentEffect}},b=new WeakMap,w=()=>({effects:[],onmount:null,onunmount:null}),E=r(),S=(e,t)=>{const n=f(b,e,w);n.effects||(n.effects=[]),n.effects.push(t)},A=Symbol("lightview.shadowDOM"),T=e=>e&&"object"==typeof e&&!0===e[A],C=(e,t)=>{if(t.shadowRoot)return void console.warn("Lightview: Element already has a shadowRoot, skipping shadowDOM directive");const n=t.attachShadow({mode:e.mode}),r=[],o=[...e.styles||[]];if(e.adoptedStyleSheets&&e.adoptedStyleSheets.length>0&&e.adoptedStyleSheets.forEach(e=>{e instanceof CSSStyleSheet?r.push(e):"string"==typeof e&&o.push(e)}),r.length>0)try{n.adoptedStyleSheets=r}catch(s){console.warn("Lightview: adoptedStyleSheets not supported")}for(const i of o){const e=document.createElement("link");e.rel="stylesheet",e.href=i,n.appendChild(e)}e.children&&e.children.length>0&&D(e.children,n)};let L=!1;const N=new WeakMap,O=(e,t,n={},r=[])=>{const o=_({tag:t,attributes:n,children:r,get domEl(){return e}});return N.set(e,o),o},M=(e,t={},r=[])=>{if(R[e]&&(e=R[e]),"function"==typeof e){const n=e({...t},r);return k(n)}if("shadowDOM"===e)return((e,t)=>({[A]:!0,mode:e.mode||"open",styles:e.styles||[],adoptedStyleSheets:e.adoptedStyleSheets||[],children:t}))(t,r);if("text"===e&&!L){const o=document.createTextNode(""),s={tag:e,attributes:t,children:r,get domEl(){return o}},i=()=>{const e=(Array.isArray(s.children)?s.children:[s.children]).flat(1/0).map(e=>{const t="function"==typeof e?e():e;return t&&"object"==typeof t&&t.domEl?t.domEl.textContent:null==t?"":String(t)});o.textContent=e.join(" ")},a=new Proxy(s,{set:(e,t,n)=>(e[t]=n,"children"===t&&i(),!0)});if(r.flat(1/0).some(e=>"function"==typeof e)){const e=n(i);S(o,e)}return i(),a}const o="svg"===e.toLowerCase(),s=L;o&&(L=!0);const i=L?document.createElementNS("http://www.w3.org/2000/svg",e):document.createElement(e),a=O(i,e,t,r);return a.attributes=t,a.children=r,o&&(L=s),a},k=e=>{if(!e)return null;if(F.hooks.processChild&&(e=F.hooks.processChild(e)??e),e.domEl)return e;const t=typeof e;if("object"===t&&e instanceof HTMLElement)return O(e,e.tagName.toLowerCase(),{},[]);if("object"===t&&e instanceof String){const t=document.createElement("span");return t.textContent=e.toString(),O(t,"span",{},[])}if("string"===t){const t=document.createElement("template");t.innerHTML=e.trim();const n=t.content;if(1===n.childNodes.length&&n.firstChild instanceof HTMLElement){const e=n.firstChild;return O(e,e.tagName.toLowerCase(),{},[])}{const e=document.createElement("span");return e.style.display="contents",e.appendChild(n),O(e,"span",{},[])}}return"object"==typeof e&&e.tag?M(e.tag,e.attributes||{},e.children||[]):null},_=e=>{const t=e.domEl;return new Proxy(e,{set:(e,n,r)=>(e[n]="attributes"===n?j(r,t):"children"===n?I(r,t):r,!0)})},W=new Set(["value","checked","selected","selectedIndex","className","innerHTML","innerText"]),x=(e,t,n)=>{const r="boolean"==typeof e[t];"href"!==t&&"src"!==t||"string"!=typeof n||!/^(javascript|vbscript|data:text\/html|data:application\/javascript)/i.test(n)||(console.warn(`[Lightview] Blocked dangerous protocol in ${t}: ${n}`),n="javascript:void(0)"),W.has(t)||r?e[t]=r?null!=n&&!1!==n&&"false"!==n:n:null==n?e.removeAttribute(t):e.setAttribute(t,n)},j=(e,t)=>{const r={};for(let[o,s]of Object.entries(e))if("onmount"===o||"onunmount"===o){f(b,t,w)[o]=s,"onmount"===o&&t.isConnected&&s(t)}else if(o.startsWith("on")){if("function"==typeof s){const e=o.slice(2).toLowerCase();t.addEventListener(e,s)}else"string"==typeof s&&t.setAttribute(o,s);r[o]=s}else if("function"==typeof s){const e=n(()=>{const e=s();"style"===o&&"object"==typeof e?Object.assign(t.style,e):x(t,o,e)});S(t,e),r[o]=s}else"style"===o&&"object"==typeof s?(Object.entries(s).forEach(([e,r])=>{if("function"==typeof r){const o=n(()=>{t.style[e]=r()});S(t,o)}else t.style[e]=r}),r[o]=s):(x(t,o,s),r[o]=s);return r},$=(e,t,r=!0)=>{r&&void 0!==t.innerHTML&&(t.innerHTML="");const o=[],s=t.tagName&&("script"===t.tagName.toLowerCase()||"style"===t.tagName.toLowerCase()),i=e.flat(1/0);for(let a of i){if(F.hooks.processChild&&!s&&(a=F.hooks.processChild(a)??a),T(a)){if(t instanceof ShadowRoot){console.warn("Lightview: Cannot nest shadowDOM inside another shadowDOM");continue}C(a,t);continue}const e=typeof a;if("function"===e){const e=document.createComment("lv:s"),r=document.createComment("lv:e");let s;t.appendChild(e),t.appendChild(r);const i=()=>{for(;e.nextSibling&&e.nextSibling!==r;)e.nextSibling.remove();const t=a();if(null!=t)if(!s||e.isConnected)if("object"==typeof t&&t instanceof String){const e=document.createTextNode(t);r.parentNode.insertBefore(e,r)}else{const e=document.createDocumentFragment(),n=Array.isArray(t)?t:[t];$(n,e,!1),r.parentNode.insertBefore(e,r)}else s.stop()};s=n(i),S(e,s),o.push(a)}else if(["string","number","boolean","symbol"].includes(e)||a&&"object"===e&&a instanceof String)t.appendChild(document.createTextNode(a)),o.push(a);else if(a&&"object"===e&&a.tag){const e=a.domEl?a:M(a.tag,a.attributes||{},a.children||[]);t.appendChild(e.domEl),o.push(e)}}return o},D=(e,t)=>$(e,t,!1),I=(e,t)=>$(e,t,!0),R={},P=new Proxy({},{get(e,t){if("_customTags"===t)return{...R};const n=(...e)=>{let n={},r=e;const o=e[0];return e.length>0&&o&&"object"==typeof o&&!o.tag&&!o.domEl&&!Array.isArray(o)&&(n=o,r=e.slice(1)),M(R[t]||t,n,r)};return R[t]&&Object.assign(n,R[t]),n},set:(e,t,n)=>(R[t]=n,!0)}),F={signal:t,get:t.get,computed:e=>{const r=t(void 0);return n(()=>{r.value=e()}),r},effect:n,registry:E,element:M,enhance:(e,t={})=>{const r="string"==typeof e?document.querySelector(e):e,o=r.domEl||r;if(!(o instanceof HTMLElement))return null;const s=o.tagName.toLowerCase();let i=N.get(o);i||(i=O(o,s));const{innerText:a,innerHTML:l,...c}=t;return void 0!==a&&("function"==typeof a?n(()=>{o.innerText=a()}):o.innerText=a),void 0!==l&&("function"==typeof l?n(()=>{o.innerHTML=l()}):o.innerHTML=l),Object.keys(c).length>0&&(i.attributes=c),i},tags:P,$:(e,t=document.body)=>{const n="string"==typeof e?t.querySelector(e):e;return n?(Object.defineProperty(n,"content",{value(e,t="inner"){t=t.toLowerCase(),F.tags;const r=n.tagName&&("script"===n.tagName.toLowerCase()||"style"===n.tagName.toLowerCase()),o=(Array.isArray(e)?e:[e]).map(e=>(F.hooks.processChild&&!r&&(e=F.hooks.processChild(e)??e),e.tag&&!e.domEl?M(e.tag,e.attributes||{},e.children||[]).domEl:e.domEl||e)),s="shadow"===t?n.shadowRoot||n.attachShadow({mode:"open"}):n;return"inner"===t||"shadow"===t?s.replaceChildren(...o):"outer"===t?s.replaceWith(...o):"afterbegin"===t?s.prepend(...o):"beforeend"===t?s.append(...o):o.forEach(e=>n.insertAdjacentElement(t,e)),n},configurable:!0,writable:!0}),n):null},hooks:{onNonStandardHref:null,processChild:null,validateUrl:null},internals:{core:v,domToElement:N,wrapDomElement:O,setupChildren:I}};if("undefined"!=typeof module&&module.exports&&(module.exports=F),"undefined"!=typeof window&&(globalThis.Lightview=F,globalThis.addEventListener("click",e=>{const t=e.composedPath().find(e=>{var t,n;return"A"===e.tagName&&(null==(n=null==(t=e.getAttribute)?void 0:t.call(e,"href"))?void 0:n.startsWith("#"))});if(t&&!e.defaultPrevented){const n=t.getAttribute("href");if(n.length>1){const r=n.slice(1),o=t.getRootNode(),s=(o.getElementById?o.getElementById(r):null)||(o.querySelector?o.querySelector(`#${r}`):null);s&&(e.preventDefault(),requestAnimationFrame(()=>{requestAnimationFrame(()=>{s.style.scrollMarginTop="calc(var(--site-nav-height, 0px) + 2rem)",s.scrollIntoView({behavior:"smooth",block:"start",inline:"start"})})}))}}F.hooks.onNonStandardHref&&F.hooks.onNonStandardHref(e)}),"undefined"!=typeof MutationObserver)){const e=(t,n)=>{var r;n(t),null==(r=t.childNodes)||r.forEach(t=>e(t,n)),t.shadowRoot&&e(t.shadowRoot,n)},t=t=>e(t,e=>{var t,n;const r=b.get(e);r&&(null==(t=r.effects)||t.forEach(e=>e.stop()),null==(n=r.onunmount)||n.call(r,e),b.delete(e))}),n=t=>e(t,e=>{var t,n;null==(n=null==(t=b.get(e))?void 0:t.onmount)||n.call(t,e)}),r=new MutationObserver(e=>{e.forEach(e=>{e.removedNodes.forEach(t),e.addedNodes.forEach(n)})}),o=()=>{document.body&&r.observe(document.body,{childList:!0,subtree:!0})};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",o):o()}const H=["img","script","iframe","video","audio","source","track","embed","input"],q=["a","area","base","link"],U=e=>{if(!e||"string"!=typeof e)return!1;const t=e.trim().toLowerCase();return t.startsWith("javascript:")||t.startsWith("vbscript:")||t.startsWith("data:text/html")||t.startsWith("data:application/javascript")},B=e=>{if(!e)return!1;if(!/^[a-z][a-z0-9+.-]*:/i.test(e))return!0;try{const t="undefined"!=typeof document?document.baseURI:globalThis.location.origin,n=new URL(e,"null"===t?void 0:t),r=globalThis.location;return n.origin===r.origin&&"null"!==n.origin||(!(!n.hostname||n.hostname!==r.hostname)||(!!(n.hostname&&r.hostname&&n.hostname.endsWith("."+r.hostname))||"file:"===r.protocol&&"file:"===n.protocol))}catch(t){return!1}},z=e=>{var t,n;if("object"!=typeof e||null===e)return e;if(Array.isArray(e))return e.map(z);if(e.tag)return{...e,children:e.children?z(e.children):[]};if(e.domEl||!(e=>{if("object"!=typeof e||null===e||Array.isArray(e)||e.tag||e.domEl)return!1;const t=Object.keys(e);return 1===t.length&&"string"==typeof(n=t[0])&&n.length>0&&"children"!==n&&"object"==typeof e[t[0]];var n})(e))return e;const r=Object.keys(e)[0],o=e[r],s="undefined"!=typeof window||"undefined"!=typeof globalThis?globalThis.Lightview:null,i=(null==(n=null==(t=null==s?void 0:s.tags)?void 0:t._customTags)?void 0:n[r])||r,{children:a,...l}=o;return{tag:i,attributes:l,children:a?z(a):[]}},X="https://cdn.jsdelivr.net/npm/daisyui@3.9.4/dist/full.min.css",J={initialized:!1,shadowDefault:!0,daisyStyleSheet:null,themeStyleSheet:null,componentStyleSheets:new Map,customStyleSheets:new Map},V=async(e,t)=>{if(!J.customStyleSheets.has(e))try{let n=t;if(void 0===n)if(e.startsWith("#")){const t=document.querySelector(e);if(!t)throw new Error(`Style block '${e}' not found`);n=t.textContent}else{const t=await fetch(e);if(!t.ok)throw new Error(`Fetch failed: ${t.status}`);n=await t.text()}if(void 0!==n){const t=new CSSStyleSheet;t.replaceSync(n),J.customStyleSheets.set(e,t)}}catch(n){console.error(`LightviewX: Failed to register stylesheet '${e}':`,n)}},Y=()=>{try{if("undefined"!=typeof localStorage)return localStorage.getItem("lightview-theme")}catch(e){return null}},G=t("undefined"!=typeof document&&document.documentElement.getAttribute("data-theme")||Y()||"light"),Z=e=>{if(e){"undefined"!=typeof document&&document.documentElement.setAttribute("data-theme",e),G&&G.value!==e&&(G.value=e);try{"undefined"!=typeof localStorage&&localStorage.setItem("lightview-theme",e)}catch(t){}}},K=async(e={})=>{const{shadowDefault:t=!0}=e;if(J.shadowDefault=t,t)try{const e=await fetch(X);if(!e.ok)throw new Error(`Failed to fetch DaisyUI CSS: ${e.status}`);const t=await e.text(),n=new CSSStyleSheet;n.replaceSync(t),J.daisyStyleSheet=n}catch(n){console.error("LightviewX: Failed to preload DaisyUI stylesheet:",n)}J.initialized=!0};(async()=>{await K()})();const Q=(e,t=[])=>{const n=[];if(J.daisyStyleSheet?n.push(J.daisyStyleSheet):n.push(X),J.themeStyleSheet&&n.push(J.themeStyleSheet),e){const t=J.componentStyleSheets.get(e);t&&n.push(t)}return Array.isArray(t)&&t.forEach(e=>{const t=J.customStyleSheets.get(e);t?n.push(t):(V(e),n.push(e))}),n},ee=e=>{try{const t=e.trim().startsWith("${")&&e.trim().endsWith("}")&&!e.trim().includes("${",2)?"return "+e.trim().slice(2,-1):"return `"+e.replace(/\\/g,"\\\\").replace(/`/g,"\\`")+"`";return new Function("state","signal",t)}catch(t){return()=>""}},te=(e,t,n=null)=>{const r="script"===n||"style"===n,o=globalThis.Lightview;return e.map(e=>e.nodeType===Node.TEXT_NODE?((e,t,n)=>{const r=e.textContent;if(t)return r;if(!r.trim()&&!r.includes("${"))return null;if(r.includes("${")){const e=ee(r);return()=>e(n.state,n.signal)}return r})(e,r,o):e.nodeType===Node.ELEMENT_NODE?((e,t,n)=>{const r=e.tagName.toLowerCase(),o={},s="script"===r||"style"===r,i="undefined"!=typeof window||"undefined"!=typeof globalThis?globalThis.Lightview:null;for(let a of e.attributes){const e=a.value;o[a.name]=!s&&e.includes("${")?(()=>{const t=ee(e);return()=>t(i.state,i.signal)})():e}return t(r,o,n(Array.from(e.childNodes),t,r))})(e,t,te):null).filter(e=>null!==e)},ne=new WeakMap,re=(e,t=!1)=>document.createComment(`lv-src-${t?"end":"start"}:${e}`),oe=e=>{if(!e)return;e.querySelectorAll("script").forEach(e=>{const t=document.createElement("script");Array.from(e.attributes).forEach(e=>{t.setAttribute(e.name,e.value)}),e.src?t.src=e.src:t.textContent=e.textContent,e.parentNode.replaceChild(t,e)})},se=(e,t,n,r,o,s=!1,i="")=>{var a;if(t)return Array.isArray(e)?e:[e];if(s&&"cdomc"===i){const t=null==(a=globalThis.LightviewCDOM)?void 0:a.parseCDOMC;if(!t)return console.warn("LightviewX: CDOMC parser not found. Ensure lightview-cdom.js is loaded."),[];try{const n=t(e);return Array.isArray(n)?n:[n]}catch(l){return console.warn("LightviewX: Failed to parse .cdomc:",l),[]}}if(n){if("true"===r.domEl.getAttribute("escape"))return[e];const t=(new DOMParser).parseFromString(e.replace(/<head[^>]*>[\s\S]*?<\/head>/i,""),"text/html");return te([...Array.from(t.head.childNodes),...Array.from(t.body.childNodes)],o)}return[e]},ie=(e,t,n,r,o,{element:s,setupChildren:i},a=null)=>{const l=`${r}-${o.slice(0,8)}`;let c=f(ne,e.domEl,()=>({}));c[r]&&((e,t)=>{const n=`lv-src-start:${t}`,r=`lv-src-end:${t}`;let o=!1;const s=[],i=document.createTreeWalker(e.parentElement||e,NodeFilter.SHOW_COMMENT|NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT,null,!1);for(;i.nextNode();){const e=i.currentNode;if(e.nodeType===Node.COMMENT_NODE){if(e.textContent===n){o=!0,s.push(e);continue}if(e.textContent===r){s.push(e);break}}o&&s.push(e)}s.forEach(e=>e.remove()),s.length})(e.domEl,`${r}-${c[r].slice(0,8)}`),c[r]=o;const u=e=>{a&&requestAnimationFrame(()=>{requestAnimationFrame(()=>{const t=a.startsWith("#")?a.slice(1):a,n=e.getElementById?e.getElementById(t):e.querySelector(`#${t}`);n&&(n.style.scrollMarginTop="calc(var(--site-nav-height, 0px) + 2rem)",n.scrollIntoView({behavior:"smooth",block:"start",inline:"start"}))})})};"shadow"===r?(e.domEl.shadowRoot||e.domEl.attachShadow({mode:"open"}),i(t,e.domEl.shadowRoot),oe(e.domEl.shadowRoot),u(e.domEl.shadowRoot)):"innerhtml"===r?(e.children=t,oe(e.domEl),u(document)):(((e,t,n,r,{element:o,setupChildren:s})=>{const i="outerhtml"===n,a="beforebegin"===n||"afterend"===n||i?t.parentElement:t;if(!a)return console.warn(`LightviewX: No parent for ${n}`);const l=document.createDocumentFragment();l.appendChild(re(r,!1)),e.forEach(e=>{var t,n,r;if("string"==typeof e)l.appendChild(document.createTextNode(e));else if(e.domEl)l.appendChild(e.domEl);else if(e instanceof Node)l.appendChild(e);else{const s=(null==(r=null==(t=globalThis.Lightview)?void 0:(n=t.hooks).processChild)?void 0:r.call(n,e))||e;if(s.tag){const e=o(s.tag,s.attributes||{},s.children||[]);(null==e?void 0:e.domEl)&&l.appendChild(e.domEl)}}}),l.appendChild(re(r,!0)),i?a.replaceChild(l,t):"beforebegin"===n?a.insertBefore(l,t):"afterend"===n?a.insertBefore(l,t.nextSibling):"afterbegin"===n?t.insertBefore(l,t.firstChild):"beforeend"===n&&t.appendChild(l),oe(a)})(t,e.domEl,r,l,{element:s,setupChildren:i}),u(document))},ae=async(e,t,n,{element:r,setupChildren:o})=>{if(H.includes(n))return;let s=[],i="",a=null;if("string"==typeof(l=t)&&!U(l)&&/^(https?:|\.|\/|[\w])|(\.(html|json|[vo]dom|cdomc?))$/i.test(l)){t.includes("#")&&([t,a]=t.split("#"));const n=await(async e=>{var t;try{const n=globalThis.Lightview;if((null==(t=null==n?void 0:n.hooks)?void 0:t.validateUrl)&&!n.hooks.validateUrl(e))return console.warn(`[LightviewX] Fetch blocked by validateUrl hook: ${e}`),null;const r=new URL(e,document.baseURI),o=await fetch(r);if(!o.ok)return null;const s=r.pathname.split(".").pop().toLowerCase(),i="vdom"===s||"odom"===s||"cdom"===s,a="html"===s,l="cdom"===s||"cdomc"===s,c=i?await o.json():await o.text();return{content:c,isJson:i,isHtml:a,isCdom:l,ext:s,raw:i?JSON.stringify(c):c}}catch(n){return null}})(t);n&&(s=se(n.content,n.isJson,n.isHtml,e,r,n.isCdom,n.ext),i=n.raw)}var l;if(!s.length){const e=((e,t)=>{try{const n=document.querySelectorAll(e);return n.length?{elements:te(Array.from(n),t),raw:Array.from(n).map(e=>e.outerHTML||e.textContent).join("")}:null}catch(n){return null}})(t,r);e&&(s=e.elements,i=e.raw)}if(!s.length)return;const c=(e.domEl.getAttribute("location")||"innerhtml").toLowerCase(),u=(e=>{let t=0;for(let n=0;n<e.length;n++)t=(t<<5)-t+e.charCodeAt(n),t&=t;return t.toString(36)})(i);if(f(ne,e.domEl,()=>({}))[c]!==u)ie(e,s,0,c,u,{element:r,setupChildren:o},a);else if(a){const t="shadow"===c?e.domEl.shadowRoot:document;t&&requestAnimationFrame(()=>{requestAnimationFrame(()=>{var e;const n=a.startsWith("#")?a.slice(1):a,r=t.getElementById?t.getElementById(n):null==(e=t.querySelector)?void 0:e.call(t,`#${n}`);r&&(r.style.scrollMarginTop="calc(var(--site-nav-height, 0px) + 2rem)",r.scrollIntoView({behavior:"smooth",block:"start",inline:"start"}))})})}},le=["beforebegin","afterbegin","beforeend","afterend","innerhtml","outerhtml","shadow"],ce=(e,{domToElement:t,wrapDomElement:n})=>{var r;const o=e.target.closest("[href]");if(!o)return;const s=o.tagName.toLowerCase();if(q.includes(s))return;e.preventDefault();const i=o.getAttribute("href"),a=globalThis.Lightview;if(i&&(U(i)||(null==(r=null==a?void 0:a.hooks)?void 0:r.validateUrl)&&!a.hooks.validateUrl(i)))return void console.warn(`[LightviewX] Navigation or fetch blocked by security policy: ${i}`);const l=o.getAttribute("target");if(!l){let e=t.get(o);if(!e){const t={};for(let e of o.attributes)t[e.name]=e.value;e=n(o,s,t)}const r={...e.attributes,src:i};return void(e.attributes=r)}if(l.startsWith("_")){switch(l){case"_self":globalThis.location.href=i;break;case"_parent":globalThis.parent.location.href=i;break;case"_top":globalThis.top.location.href=i;break;default:globalThis.open(i,l)}return}const{selector:c,location:u}=(e=>{for(const t of le){const n=":"+t;if(e.toLowerCase().endsWith(n))return{selector:e.slice(0,-n.length),location:t}}return{selector:e,location:null}})(l);try{document.querySelectorAll(c).forEach(e=>{let r=t.get(e);if(!r){const t={};for(let n of e.attributes)t[n.name]=n.value;r=n(e,e.tagName.toLowerCase(),t)}const o={...r.attributes,src:i};u&&(o.location=u),r.attributes=o})}catch(d){console.warn("Invalid target selector:",c,d)}},ue=new WeakMap,de="__lv_passed",he="__lv_resume",fe=["click","dblclick","mousedown","mouseup","contextmenu","submit","reset","change","input","invalid","keydown","keyup","keypress","touchstart","touchend"],pe=["focus","blur"],me=(e,t)=>{let n=ue.get(e);n||(n=new Map,ue.set(e,n));let r=n.get(t);return r||(r={},n.set(t,r)),r},ge=function(e){const t=arguments[arguments.length-1];if(null==t?void 0:t[he])return!0;const n=`throttle-${(null==t?void 0:t.type)||"all"}-${e}`,r=me(this,n),o=Date.now();return o-(r.last||0)>=e&&(r.last=o,!0)},ye=function(e){const t=arguments[arguments.length-1],n=`debounce-${(null==t?void 0:t.type)||"all"}-${e}`,r=me(this,n);return r.timer&&clearTimeout(r.timer),(null==t?void 0:t[he])&&r.passed?(r.passed=!1,!0):(r.timer=setTimeout(()=>{r.passed=!0;const e=new t.constructor(t.type,t);e[he]=!0,this.dispatchEvent(e)},e),!1)},ve=async e=>{var t,n;if(e[de])return;const r=null==(n=(t=e.target).closest)?void 0:n.call(t,"[lv-before]");if(!r)return;const{events:o,exclusions:s,calls:i}=(e=>{const t=[];let n="",r=0,o=null;for(let c=0;c<e.length;c++){const s=e[c];o?(n+=s,s===o&&"\\"!==e[c-1]&&(o=null)):"'"===s||'"'===s?(o=s,n+=s):"("===s?(r++,n+=s):")"===s?(r--,n+=s):/\s/.test(s)&&0===r?(n&&t.push(n),n=""):n+=s}n&&t.push(n);const s=[],i=[],a=[];let l=0;for(;l<t.length;){const e=t[l];if(!e||e.includes("("))break;e.startsWith("!")?i.push(e.slice(1)):s.push(e),l++}for(;l<t.length;)t[l]&&a.push(t[l]),l++;return{events:s,exclusions:i,calls:a}})(r.getAttribute("lv-before")),a=s.includes(e.type),l=o.includes("*")||o.includes(e.type);if(a||!l)return;e.stopImmediatePropagation(),e.preventDefault();for(const d of i)try{const t=d.match(/^([\w\.]+)\((.*)\)$/);if(!t)continue;const n=t[1],o=t[2],s=globalThis.Lightview,i=globalThis.LightviewX;let a=n.split(".").reduce((e,t)=>null==e?void 0:e[t],globalThis);if(a||"throttle"!==n||(a=ge),a||"debounce"!==n||(a=ye),!a&&i&&i[n]&&(a=i[n]),"function"!=typeof a){console.warn(`LightviewX: lv-before function '${n}' not found`);continue}const l=new Function("event","state","signal",`return [${o}]`).call(r,e,(null==s?void 0:s.state)||{},(null==s?void 0:s.signal)||{});l.push(e);let c=a.apply(r,l);if(c instanceof Promise&&(c=await c),!1===c||null==c)return}catch(u){return void console.error(`LightviewX: Error executing lv-before gate '${d}':`,u)}const c=new e.constructor(e.type,e);c[de]=!0,r.dispatchEvent(c)},be=(e,t)=>{if(e.nodeType!==Node.ELEMENT_NODE)return;const n=e.tagName.toLowerCase();if((e=>H.includes(e)||e.startsWith("lv-"))(n))return;const r=e.getAttribute("src");if(!r)return;let o=t.internals.domToElement.get(e);if(!o){const r={};for(let t of e.attributes)r[t.name]=t.value;o=t.internals.wrapDomElement(e,n,r,[])}ae(o,r,n,{element:t.element,setupChildren:t.internals.setupChildren})},we=new WeakSet,Ee=(e,t)=>{if(!e||!t)return;const n=(e,n,r=!1,o=null)=>{if(we.has(e)&&!r)return;r||we.add(e);const s=ee(n);t.effect(()=>{try{const n=s(t.state,t.signal);r?null==n||!1===n?e.removeAttribute(o):e.setAttribute(o,n):e.textContent=void 0!==n?n:""}catch(n){}})},r=document.evaluate(".//text()[contains(., '${')]",e,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null);for(let s=0;s<r.snapshotLength;s++){const e=r.snapshotItem(s);e.parentElement&&e.parentElement.closest("SCRIPT, STYLE, CODE, PRE, TEMPLATE, NOSCRIPT")||n(e,e.textContent)}const o=document.evaluate(".//*[@*[contains(., '${')]]",e,null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,null);for(let s=0;s<o.snapshotLength;s++){const e=o.snapshotItem(s);["SCRIPT","STYLE","CODE","PRE","TEMPLATE","NOSCRIPT"].includes(e.tagName)||Array.from(e.attributes).forEach(t=>{t.value.includes("${")&&n(e,t.value,!0,t.name)})}e.nodeType!==Node.ELEMENT_NODE||["SCRIPT","STYLE","CODE","PRE","TEMPLATE","NOSCRIPT"].includes(e.tagName)||Array.from(e.attributes).forEach(t=>{t.value.includes("${")&&n(e,t.value,!0,t.name)})},Se=(e,t,n)=>{if(e.nodeType!==Node.ELEMENT_NODE&&e.nodeType!==Node.TEXT_NODE||n.push(e),e.nodeType!==Node.ELEMENT_NODE)return;t.push(e);const r="[src]:not("+H.join("):not(")+")",o=e.querySelectorAll(r);for(const s of o)s.tagName.toLowerCase().startsWith("lv-")||t.push(s)},Ae=e=>{const t=new MutationObserver(t=>{const{nodesToProcess:n,nodesToActivate:r}=(e=>{const t=[],n=[];for(const r of e)"childList"===r.type?r.addedNodes.forEach(e=>Se(e,t,n)):"attributes"===r.type&&"src"===r.attributeName&&t.push(r.target);return{nodesToProcess:t,nodesToActivate:n}})(t);(n.length>0||r.length>0)&&requestAnimationFrame(()=>{r.forEach(t=>Ee(t,e)),n.forEach(t=>be(t,e))})});return t.observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["src"]}),t};if("undefined"!=typeof window&&globalThis.Lightview){const e=globalThis.Lightview;"loading"===document.readyState?document.addEventListener("DOMContentLoaded",()=>Ae(e)):Ae(e);const t=()=>{requestAnimationFrame(()=>{Ee(document.body,e);const t="[src]:not("+H.join("):not(")+")";document.querySelectorAll(t).forEach(t=>{t.tagName.toLowerCase().startsWith("lv-")||be(t,e)})})};document.body?t():document.addEventListener("DOMContentLoaded",t),e.hooks.onNonStandardHref=t=>{ce(t,{domToElement:e.internals.domToElement,wrapDomElement:e.internals.wrapDomElement})},fe.forEach(e=>window.addEventListener(e,ve,!0)),pe.forEach(e=>window.addEventListener(e,ve,!0)),e.hooks.processChild=t=>{if(!t)return t;if("object"!=typeof t||Array.isArray(t)||t.tag||t.domEl||(t=z(t)),"string"==typeof t&&t.startsWith("$")&&isNaN(parseInt(t[1]))){const e=globalThis.LightviewCDOM;if(e)return e.parseExpression(t)}if("string"==typeof t&&(t.trim().startsWith("{")||t.trim().startsWith("[")))try{const e=new Function("return ("+t+")")();if("object"==typeof e&&null!==e)return Array.isArray(e)||e.tag||e.domEl?e:z(e)}catch(n){}return((e,t)=>{if("string"==typeof e&&e.includes("${")){const n=ee(e);return()=>n(t.state,t.signal)}return e})(t,{state:y,signal:e.signal})}}const Te={state:y,themeSignal:G,setTheme:Z,registerStyleSheet:V,registerThemeSheet:async e=>{try{const t=await fetch(e);if(!t.ok)throw new Error(`Failed to fetch theme CSS: ${t.status}`);const n=await t.text(),r=new CSSStyleSheet;r.replaceSync(n),J.themeStyleSheet=r}catch(t){console.error(`LightviewX: Failed to register theme stylesheet '${e}':`,t)}},throttle:ge,debounce:ye,initComponents:K,componentConfig:J,shouldUseShadow:e=>void 0!==e?e:J.shadowDefault,getAdoptedStyleSheets:Q,preloadComponentCSS:async e=>{J.componentStyleSheets.has(e)||await(async e=>{if(J.componentStyleSheets.has(e))return J.componentStyleSheets.get(e);try{const t=await fetch(e);if(!t.ok)throw new Error(`Failed to fetch component CSS: ${t.status}`);const n=await t.text(),r=new CSSStyleSheet;return r.replaceSync(n),J.componentStyleSheets.set(e,r),r}catch(t){return console.error(`LightviewX: Failed to create stylesheet for ${e}:`,t),null}})(e)},createCustomElement:(e,t={})=>class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}async connectedCallback(){const{cssUrl:n,styles:r}=t;this.themeWrapper=document.createElement("div"),this.themeWrapper.style.display="contents";const o=()=>{const e=document.documentElement.getAttribute("data-theme")||"light";this.themeWrapper.setAttribute("data-theme",e)};o(),this.themeObserver=new MutationObserver(o),this.themeObserver.observe(document.documentElement,{attributes:!0,attributeFilter:["data-theme"]}),this.shadowRoot.appendChild(this.themeWrapper);const s=Q(n,r);try{const e=s.filter(e=>e instanceof CSSStyleSheet);this.shadowRoot.adoptedStyleSheets=e}catch(i){}if(!J.daisyStyleSheet){const e=document.createElement("link");e.rel="stylesheet",e.href=X,this.shadowRoot.appendChild(e)}s.forEach(e=>{if("string"==typeof e){const t=document.createElement("link");t.rel="stylesheet",t.href=e,this.shadowRoot.appendChild(t)}}),this.render=()=>{const t={};for(const e of this.attributes){const n=e.name.replace(/-([a-z])/g,e=>e[1].toUpperCase());""===e.value?t[n]=!0:t[n]=e.value}t.useShadow=!1;const n=globalThis.Lightview.tags.slot(),r=e(t,n);globalThis.Lightview.internals.setupChildren([r],this.themeWrapper)},"undefined"!=typeof MutationObserver&&"undefined"!=typeof HTMLElement&&(this.attrObserver=new MutationObserver(e=>{this.render()}),this.attrObserver.observe(this,{attributes:!0})),this.render()}disconnectedCallback(){this.themeObserver&&this.themeObserver.disconnect(),this.attrObserver&&this.attrObserver.disconnect()}},customElementWrapper:(e,t={})=>{const{attributeMap:n={},childElements:r={}}=t;return class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){const e=document.createElement("link");e.rel="stylesheet",e.href="https://cdn.jsdelivr.net/npm/daisyui@5.5.14/daisyui.min.css",this.shadowRoot.appendChild(e);const t=document.createElement("div");t.setAttribute("data-theme",document.documentElement.getAttribute("data-theme")||"light"),t.style.display="contents",this.shadowRoot.appendChild(t),this.themeWrapper=t,this.themeObserver=new MutationObserver(()=>{const e=document.documentElement.getAttribute("data-theme")||"light";this.themeWrapper.setAttribute("data-theme",e)}),this.themeObserver.observe(document.documentElement,{attributes:!0,attributeFilter:["data-theme"]}),this.render();const o=Object.keys(n);o.length>0&&(this.attrObserver=new MutationObserver(()=>this.render()),this.attrObserver.observe(this,{attributes:!0,attributeFilter:o})),Object.keys(r).length>0&&(this.childObserver=new MutationObserver(()=>this.render()),this.childObserver.observe(this,{childList:!0,subtree:!0,attributes:!0}))}disconnectedCallback(){this.themeObserver&&this.themeObserver.disconnect(),this.attrObserver&&this.attrObserver.disconnect(),this.childObserver&&this.childObserver.disconnect()}parseChildrenToVDOM(){return Array.from(this.children).map(e=>{const t=e.tagName.toLowerCase(),n=r[t];if(!n)return null;const{component:o,attributeMap:s={},innerHTML:i=!1}=n,a={};return Object.entries(s).forEach(([t,n])=>{const r=e.getAttribute(t);null!==r&&(n===Boolean?a[t]="true"===r||""===r:a[t]=n===Number?Number(r):r)}),e.onclick&&(a.onclick=e.onclick.bind(e)),{tag:o,attributes:a,children:i?[e.innerHTML]:[e.textContent]}}).filter(Boolean)}render(){var t,o;const s={useShadow:!1};Object.entries(n).forEach(([e,t])=>{const n=this.getAttribute(e);null!==n&&(t===Boolean?s[e]="true"===n||""===n:s[e]=t===Number?Number(n):n)});const i=this.parseChildrenToVDOM(),a=Object.keys(r).length>0?i:[{tag:globalThis.Lightview.tags.slot}],l=e(s,...a);(null==(o=null==(t=globalThis.Lightview)?void 0:t.internals)?void 0:o.setupChildren)&&this.themeWrapper&&(this.themeWrapper.innerHTML="",globalThis.Lightview.internals.setupChildren([l],this.themeWrapper))}static get observedAttributes(){return Object.keys(n)}attributeChangedCallback(){this.render()}}},internals:{handleSrcAttribute:ae,parseElements:se}};if("undefined"!=typeof module&&module.exports&&(module.exports=Te),"undefined"!=typeof window&&(globalThis.LightviewX=Te),"undefined"!=typeof window){try{const e=Y();e&&Z(e)}catch(Mn){}"undefined"!=typeof window&&globalThis.Lightview&&(globalThis.Lightview.hooks.validateUrl||(globalThis.Lightview.hooks.validateUrl=B))}"undefined"!=typeof globalThis&&globalThis.Lightview&&(globalThis.Lightview.hooks.validateUrl||(globalThis.Lightview.hooks.validateUrl=B));const Ce=new Map,Le=new Map,Ne=(e,t,n={})=>{Ce.set(e,t),n&&Le.set(e,n)},Oe=()=>globalThis.Lightview||null,Me=()=>{var e;return(null==(e=Oe())?void 0:e.registry)||null};class ke{constructor(e,t){this.parent=e,this.key=t,this.isBindingTarget=!0}get value(){return this.parent[this.key]}set value(e){this.parent[this.key]=e}get __parent__(){return this.parent}}const _e=e=>e&&"function"==typeof e&&"value"in e?e.value:!e||"object"!=typeof e||globalThis.Node&&e instanceof globalThis.Node||!("value"in e)?e:e.value,We=(e,t)=>{let n=e;for(const r of t){if(!r)continue;if(n=_e(n),null==n)return;n=n[r.startsWith("[")?r.slice(1,-1):r]}return _e(n)},xe=(e,t)=>{let n=e;for(let r=0;r<t.length;r++){const e=t[r];if(!e)continue;const o=e.startsWith("[")?e.slice(1,-1):e,s=_e(n);if(null==s)return;if(r===t.length-1)return new ke(s,o);n=s[o]}return n},je=(e,t)=>{if("string"!=typeof e)return e;const n=Me();if("."===e)return _e(t);if(e.startsWith("$/")){const[t,...r]=e.slice(2).split("/"),o=null==n?void 0:n.get(t);if(!o)return;return We(o,r)}if(e.startsWith("./"))return We(t,e.slice(2).split("/"));if(e.startsWith("../"))return We(null==t?void 0:t.__parent__,e.slice(3).split("/"));if(e.includes("/")||e.includes("."))return We(t,e.split(/[\/.]/));const r=_e(t);return r&&"object"==typeof r&&(e in r||void 0!==r[e])?We(r,[e]):e},$e=(e,t)=>{if("string"!=typeof e)return e;const n=Me();if("."===e)return t;if(e.startsWith("$/")){const t=e.slice(2).split(/[\/.]/),r=t.shift(),o=null==n?void 0:n.get(r);if(!o)return;return xe(o,t)}if(e.startsWith("./"))return xe(t,e.slice(2).split(/[\/.]/));if(e.startsWith("../"))return xe(null==t?void 0:t.__parent__,e.slice(3).split(/[\/.]/));if(e.includes("/")||e.includes("."))return xe(t,e.split(/[\/.]/));const r=_e(t);return r&&"object"==typeof r&&/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(e)?new ke(r,e):e};class De{constructor(e){this.fn=e,this.isLazy=!0}resolve(e){return this.fn(e)}}const Ie=(e,t,n=!1)=>{if(e.startsWith("'")&&e.endsWith("'")||e.startsWith('"')&&e.endsWith('"'))return{value:e.slice(1,-1),isLiteral:!0};if(""!==e&&!isNaN(Number(e)))return{value:Number(e),isLiteral:!0};if("true"===e)return{value:!0,isLiteral:!0};if("false"===e)return{value:!1,isLiteral:!0};if("null"===e)return{value:null,isLiteral:!0};if("_"===e||e.startsWith("_/")||e.startsWith("_."))return{value:new De(t=>{if("_"===e)return t;const n=(e.startsWith("_."),e.slice(2));return je(n,t)}),isLazy:!0};if("$event"===e||e.startsWith("$event/")||e.startsWith("$event."))return{value:new De(t=>{if("$event"===e)return t;const n=(e.startsWith("$event."),e.slice(7));return je(n,t)}),isLazy:!0};if(e.includes("(")){let r=e;e.startsWith("/")?r="$"+e:!n||e.startsWith("$")||e.startsWith("./")||(r=`$/${e}`);const o=Re(r,t);return o instanceof De?{value:o,isLazy:!0}:{value:o,isSignal:!1}}const r=e.endsWith("..."),o=r?e.slice(0,-3):e;let s;if(s=o.startsWith("/")?"$"+o:o.startsWith("$")||o.startsWith("./")||o.startsWith("../")?o:n?`$/${o}`:`./${o}`,r){const e=s.split("/"),n=e.pop(),r=e.join("/"),o=r?je(r,t):t,i=_e(o);if(Array.isArray(i)){return{value:i.map(e=>{const t=_e(e);return t&&t[n]}),isExplosion:!0}}if(i&&"object"==typeof i){const e=i[n];return{value:_e(e),isExplosion:!0}}return{value:void 0,isExplosion:!0}}return{value:$e(s,t),isExplosion:!1}},Re=(e,t)=>{var n;if("string"!=typeof e)return e;const r=e.indexOf("(");if(-1!==r&&e.endsWith(")")){const o=e.slice(0,r).trim(),s=e.slice(r+1,-1),i=o.split("/");let a=i.pop().replace(/^\$/,"");""===a&&(i.length>0||"/"===o)&&(a="/");const l=i.join("/"),c=e.startsWith("$/")||e.startsWith("$");let u=t;l&&"$"!==l&&(u=$e(l,t));const d=Ce.get(a);if(!d)return null==(n=globalThis.console)||n.warn(`LightviewCDOM: Helper "${a}" not found.`),e;const h=Le.get(a)||{},f=[];let p="",m=0,g=null;for(let e=0;e<s.length;e++){const t=s[e];if(t===g)g=null;else if(g||"'"!==t&&'"'!==t)if(g||"("!==t)if(g||")"!==t){if(!g&&","===t&&0===m){f.push(p.trim()),p="";continue}}else m--;else m++;else g=t;p+=t}p&&f.push(p.trim());const y=[];let v=!1;for(let e=0;e<f.length;e++){const t=f[e],n=Ie(t,u,c&&("$"===l||!l));n.isLazy&&(v=!0);const r=!(h.pathAware&&0===e);let o=r?_e(n.value):n.value;n.isExplosion&&Array.isArray(o)?y.push(...o.map(e=>r?_e(e):e)):y.push(o)}if(v)return new De(e=>{const t=y.map((t,n)=>{const r=!(h.pathAware&&0===n),o=t instanceof De?t.resolve(e):t;return r?_e(o):o});return d(...t)});const b=d(...y);return _e(b)}return _e(je(e,t))},Pe=(e,t)=>{const n=Oe();return n&&"string"==typeof e?n.computed(()=>Re(e,t)):e},Fe=(...e)=>e.reduce((e,t)=>Number(e)+Number(t),0),He=(e,t)=>Number(e)-Number(t),qe=(...e)=>e.reduce((e,t)=>Number(e)*Number(t),1),Ue=(e,t)=>Number(e)/Number(t),Be=(e,t=0)=>Number(Math.round(e+"e"+t)+"e-"+t),ze=e=>Math.ceil(e),Xe=e=>Math.floor(e),Je=e=>Math.abs(e),Ve=(e,t)=>e%t,Ye=(e,t)=>Math.pow(e,t),Ge=e=>Math.sqrt(e),Ze=(e,t,n)=>e?t:n,Ke=(...e)=>e.every(Boolean),Qe=(...e)=>e.some(Boolean),et=e=>!e,tt=(e,t)=>e===t,nt=(e,t)=>e!==t,rt=(...e)=>{const t=e[e.length-1];return e.slice(0,-1).join(t)},ot=(...e)=>e.join(""),st=e=>String(e).toUpperCase(),it=e=>String(e).toLowerCase(),at=e=>String(e).trim(),lt=e=>String(e).length,ct=(e,t,n)=>String(e).replace(t,n),ut=(e,t)=>String(e).split(t),dt=e=>{const t=String(e);return t.charAt(0).toUpperCase()+t.slice(1)},ht=e=>String(e).toLowerCase().split(" ").map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" "),ft=(e,t)=>String(e).includes(t),pt=(e,t)=>String(e).startsWith(t),mt=(e,t)=>String(e).endsWith(t),gt=(e,t)=>null!=e?e:t,yt=(...e)=>e.length,vt=(e,t)=>Array.isArray(e)?"function"==typeof t&&t.isLazy?e.filter(e=>t.resolve(e)):e.filter(e=>!!e):[],bt=(e,t)=>Array.isArray(e)?"string"==typeof t?e.map(e=>e&&"object"==typeof e?e[t]:e):t&&t.isLazy?e.map(e=>t.resolve(e)):e:[],wt=(e,t)=>{if(Array.isArray(e))return t&&t.isLazy?e.find(e=>t.resolve(e)):e.find(e=>!!e)},Et=e=>Array.isArray(e)?[...new Set(e)]:[],St=(e,t="asc")=>{if(!Array.isArray(e))return[];const n=[...e];return n.sort((e,n)=>e<n?"asc"===t?-1:1:e>n?"asc"===t?1:-1:0),n},At=e=>Array.isArray(e)?[...e].reverse():[],Tt=e=>Array.isArray(e)?e[0]:void 0,Ct=e=>Array.isArray(e)?e[e.length-1]:void 0,Lt=(e,t,n)=>Array.isArray(e)?e.slice(t,n):[],Nt=e=>Array.isArray(e)?e.flat(1/0):[],Ot=(e,t=",")=>Array.isArray(e)?e.join(String(t)):"",Mt=e=>Array.isArray(e)?e.length:e?String(e).length:0,kt=(e,t)=>e>t,_t=(e,t)=>e<t,Wt=(e,t)=>e>=t,xt=(e,t)=>e<=t,jt=(e,t)=>e!==t,$t=(e,t,n)=>e>=t&&e<=n,Dt=(e,t)=>Array.isArray(e)&&e.includes(t),It=(e,t)=>{if(!Array.isArray(e))return 0;return(t&&t.isLazy?e.filter(e=>t.resolve(e)):e).reduce((e,t)=>e+(Number(t)||0),0)},Rt=(e,t)=>Array.isArray(e)?t&&t.isLazy?e.filter(e=>t.resolve(e)).length:e.filter(e=>!!e).length:0,Pt=(e,t)=>{if(!Array.isArray(e))return 0;const n=t&&t.isLazy?e.filter(e=>t.resolve(e)):e;return 0===n.length?0:n.reduce((e,t)=>e+(Number(t)||0),0)/n.length},Ft=()=>(new Date).getTime(),Ht=()=>{const e=new Date;return e.setHours(0,0,0,0),e.getTime()},qt=e=>new Date(e).getTime(),Ut=(e,t)=>{const n=new Date(e);if(isNaN(n.getTime()))return"";const r={year:"numeric",month:"2-digit",day:"2-digit"};return"long"===t&&(r.month="long"),n.toLocaleDateString(void 0,r)},Bt=e=>new Date(e).getFullYear(),zt=e=>new Date(e).getMonth()+1,Xt=e=>new Date(e).getDate(),Jt=e=>new Date(e).getDay(),Vt=(e,t)=>{const n=new Date(e);return n.setDate(n.getDate()+Number(t)),n.getTime()},Yt=(e,t,n="days")=>{const r=Math.abs(new Date(e)-new Date(t));return"seconds"===n?r/1e3:"minutes"===n?r/6e4:"hours"===n?r/36e5:r/864e5},Gt=(e,t=2)=>Number(e).toFixed(t),Zt=(e,t="$",n=2)=>t+Number(e).toFixed(n).replace(/\B(?=(\d{3})+(?!\d))/g,","),Kt=(e,t=0)=>(100*Number(e)).toFixed(t)+"%",Qt=e=>String(e).replace(/\B(?=(\d{3})+(?!\d))/g,","),en=(e,t,n)=>{if(!Array.isArray(t))return;const r=t.indexOf(e);return-1!==r&&Array.isArray(n)?n[r]:void 0},tn=(e,t,n)=>{if(!Array.isArray(t))return;const r=t.find(t=>Array.isArray(t)&&t[0]===e);return r?r[n-1]:void 0},nn=(e,t)=>Array.isArray(e)?e[t]:void 0,rn=(e,t)=>Array.isArray(t)?t.indexOf(e):-1,on=(...e)=>e.reduce((e,t)=>e+(Number(t)||0),0),sn=(...e)=>0===e.length?0:on(...e)/e.length,an=(...e)=>Math.min(...e),ln=(...e)=>Math.max(...e),cn=(...e)=>{if(0===e.length)return 0;const t=[...e].sort((e,t)=>e-t),n=Math.floor(t.length/2);return t.length%2!=0?t[n]:(t[n-1]+t[n])/2},un=(...e)=>{if(0===e.length)return 0;const t=sn(...e),n=e.map(e=>Math.pow(e-t,2));return Math.sqrt(sn(...n))},dn=(...e)=>{if(0===e.length)return 0;const t=sn(...e),n=e.map(e=>Math.pow(e-t,2));return sn(...n)},hn=(e,t)=>(e&&"object"==typeof e&&"value"in e||e&&"function"==typeof e&&"value"in e?e.value=t:e&&"object"==typeof e&&t&&"object"==typeof t&&Object.assign(e,t),t),fn=(e,t=1)=>{const n=e&&"object"==typeof e&&"value"in e?e.value:0,r=Number(n)+Number(t);return hn(e,r)},pn=(e,t=1)=>{const n=e&&"object"==typeof e&&"value"in e?e.value:0,r=Number(n)-Number(t);return hn(e,r)},mn=e=>{const t=!(!e||"object"!=typeof e||!("value"in e))&&e.value;return hn(e,!t)},gn=(e,t)=>{const n=e&&"object"==typeof e&&"value"in e?e.value:[];if(Array.isArray(n)){const r=[...n,t];return hn(e,r)}return n},yn=e=>{const t=e&&"object"==typeof e&&"value"in e?e.value:[];if(Array.isArray(t)&&t.length>0){const n=t.slice(0,-1);hn(e,n)}return t},vn=(e,t)=>{const n={...e&&"object"==typeof e&&"value"in e?e.value:{},...t};return hn(e,n)},bn=e=>{const t=e&&"object"==typeof e&&"value"in e?e.value:null;return Array.isArray(t)?hn(e,[]):hn(e,"object"==typeof t&&null!==t?{}:null)},wn=(e,t={})=>{const n={...t},r={...n.headers};let o=n.body;return void 0!==o&&(null!==o&&"object"==typeof o?(o=JSON.stringify(o),r["Content-Type"]||(r["Content-Type"]="application/json")):(o=String(o),r["Content-Type"]||(r["Content-Type"]="text/plain"))),n.body=o,n.headers=r,globalThis.fetch(e,n)};var En;(En=Ne)("+",Fe),En("add",Fe),En("-",He),En("sub",He),En("*",qe),En("mul",qe),En("/",Ue),En("div",Ue),En("round",Be),En("ceil",ze),En("floor",Xe),En("abs",Je),En("mod",Ve),En("pow",Ye),En("sqrt",Ge),(e=>{e("if",Ze),e("and",Ke),e("&&",Ke),e("or",Qe),e("||",Qe),e("not",et),e("!",et),e("eq",tt),e("==",tt),e("===",tt),e("neq",nt)})(Ne),(e=>{e("join",rt),e("concat",ot),e("upper",st),e("lower",it),e("trim",at),e("len",lt),e("replace",ct),e("split",ut),e("capitalize",dt),e("titleCase",ht),e("contains",ft),e("startsWith",pt),e("endsWith",mt),e("default",gt)})(Ne),(e=>{e("count",yt),e("filter",vt),e("map",bt),e("find",wt),e("unique",Et),e("sort",St),e("reverse",At),e("first",Tt),e("last",Ct),e("slice",Lt),e("flatten",Nt),e("join",Ot),e("len",Mt),e("length",Mt)})(Ne),(e=>{e("gt",kt),e(">",kt),e("lt",_t),e("<",_t),e("gte",Wt),e(">=",Wt),e("lte",xt),e("<=",xt),e("neq",jt),e("!=",jt),e("between",$t),e("in",Dt)})(Ne),(e=>{e("sumIf",It),e("countIf",Rt),e("avgIf",Pt)})(Ne),(e=>{e("now",Ft),e("today",Ht),e("date",qt),e("formatDate",Ut),e("year",Bt),e("month",zt),e("day",Xt),e("weekday",Jt),e("addDays",Vt),e("dateDiff",Yt)})(Ne),(e=>{e("number",Gt),e("currency",Zt),e("percent",Kt),e("thousands",Qt)})(Ne),(e=>{e("lookup",en),e("vlookup",tn),e("index",nn),e("match",rn)})(Ne),(e=>{e("sum",on),e("avg",sn),e("min",an),e("max",ln),e("median",cn),e("stdev",un),e("var",dn)})(Ne),(e=>{const t={pathAware:!0};e("set",hn,t),e("increment",fn,t),e("++",fn,t),e("decrement",pn,t),e("--",pn,t),e("toggle",mn,t),e("!!",mn,t),e("push",gn,t),e("pop",yn,t),e("assign",vn,t),e("clear",bn,t)})((e,t)=>Ne(e,t,{pathAware:!0})),(e=>{e("fetch",wn)})(Ne);const Sn=new WeakMap,An=(e,t=null)=>{const n=[];let o=e;const s=globalThis.ShadowRoot;for(;o;){const e=Sn.get(o);e&&n.unshift(e),o=o.parentElement||(s&&o.parentNode instanceof s?o.parentNode.host:null)}const i=r();return new Proxy({},{get(e,r,o){var s;if("$event"===r||"event"===r)return t;if("__parent__"===r)return;for(let t=n.length-1;t>=0;t--){const e=n[t];if(r in e)return e[r]}if(i&&i.has(r))return i.get(r);const a=null==(s=globalThis.Lightview)?void 0:s.state;return a&&r in a?a[r]:void 0},set(e,t,r,o){var s;for(let a=n.length-1;a>=0;a--){const e=n[a];if(t in e)return e[t]=r,!0}if(n.length>0)return n[n.length-1][t]=r,!0;const i=null==(s=globalThis.Lightview)?void 0:s.state;return!!i&&(i[t]=r,!0)},has(e,r){var o;if("$event"===r||"event"===r)return!!t;for(const t of n)if(r in t)return!0;const s=null==(o=globalThis.Lightview)?void 0:o.state;return!(!s||!(r in s))},ownKeys(e){var r;const o=new Set;t&&(o.add("$event"),o.add("event"));for(const t of n)for(const e in t)o.add(e);const s=null==(r=globalThis.Lightview)?void 0:r.state;if(s)for(const t in s)o.add(t);return Array.from(o)},getOwnPropertyDescriptor:(e,t)=>({enumerable:!0,configurable:!0})})},Tn=e=>{var t;const n=e.getAttribute("cdom-state");if(n&&!Sn.has(e))try{const t=JSON.parse(n),r=y(t);Sn.set(e,r)}catch(Mn){null==(t=globalThis.console)||t.error("LightviewCDOM: Failed to parse cdom-state",Mn)}},Cn=e=>{const t=e.getAttribute("cdom-bind");if(!t)return;const r=e.type||"",o=e.tagName.toLowerCase();let s="value",i="input";"checkbox"===r||"radio"===r?(s="checked",i="change"):"select"===o&&(i="change");const a=An(e);let l=$e(t,a);if(l&&l.isBindingTarget&&void 0===l.value){const n=e[s];void 0!==n&&""!==n&&(hn(a,{[l.key]:n}),l=$e(t,a))}n(()=>{const t=_e(l);e[s]!==t&&(e[s]=void 0===t?"":t)}),e.addEventListener(i,()=>{const n=e[s];l&&l.isBindingTarget?l.value=n:hn(a,{[t]:n})})},Ln=e=>{Array.from(e.attributes).forEach(t=>{if(t.name.startsWith("cdom-on:")){const n=t.name.slice(8),r=t.value;e.addEventListener(n,t=>{const n=An(e,t),o=Re(r,n);o&&"object"==typeof o&&o.isLazy&&"function"==typeof o.resolve&&o.resolve(t)})}})},Nn=(e,t=null)=>{if(!e)return e;if("string"==typeof e&&e.startsWith("$"))return Pe(e,t);if(Array.isArray(e))return e.map(e=>Nn(e,t));if(e instanceof String)return e.toString();if("object"==typeof e&&null!==e){t&&!("__parent__"in e)&&Object.defineProperty(e,"__parent__",{value:t,enumerable:!1,writable:!0,configurable:!0});for(const t in e)e[t]=Nn(e[t],e);return e}return e},On={registerHelper:Ne,parseExpression:Pe,resolvePath:je,resolvePathAsContext:$e,resolveExpression:Re,parseCDOMC:e=>{let t=0;const n=e.length,r=()=>{for(;t<n;){const r=e[t];if(!/\s/.test(r)){if("/"===r){const r=e[t+1];if("/"===r){for(t+=2;t<n&&"\n"!==e[t]&&"\r"!==e[t];)t++;continue}if("*"===r){for(t+=2;t<n;){if("*"===e[t]&&"/"===e[t+1]){t+=2;break}t++}continue}}break}t++}},o=()=>{const r=e[t++];let o="";for(;t<n;){const n=e[t++];if(n===r)return new String(o);if("\\"===n){const n=e[t++];o+="n"===n?"\n":"t"===n?"\t":'"'===n?'"':"'"===n?"'":"\\"===n?"\\":n}else o+=n}throw new Error("Unterminated string")},s=()=>{const r=t;let o=0;for(;t<n;){const n=e[t];if(o>0)")"===n?o--:"("===n&&o++,t++;else{if(/[\s:,{}\[\]"'`()]/.test(n)){if("("===n){o++,t++;continue}break}t++}}const s=e.slice(r,t);return"true"===s||"false"!==s&&("null"===s?null:""===s.trim()||isNaN(Number(s))?s:Number(s))},i=()=>{if(r(),t>=n)return;const i=e[t];return"{"===i?a():"["===i?l():'"'===i||"'"===i?o():s()},a=()=>{t++;const a={};if(r(),t<n&&"}"===e[t])return t++,a;for(;t<n;){let n;if(r(),n='"'===e[t]||"'"===e[t]?o():s(),r(),":"!==e[t])throw new Error(`Expected ':' at position ${t}, found '${e[t]}'`);t++;const l=i();if(a[String(n)]=l,r(),"}"===e[t])return t++,a;if(","!==e[t])throw new Error(`Expected '}' or ',' at position ${t}, found '${e[t]}'`);if(t++,r(),"}"===e[t])return t++,a}},l=()=>{t++;const o=[];if(r(),t<n&&"]"===e[t])return t++,o;for(;t<n;){const n=i();if(o.push(n),r(),"]"===e[t])return t++,o;if(","!==e[t])throw new Error(`Expected ']' or ',' at position ${t}, found '${e[t]}'`);if(t++,r(),"]"===e[t])return t++,o}};r();return i()},unwrapSignal:_e,getContext:An,handleCDOMState:Tn,handleCDOMBind:Cn,handleCDOMOn:Ln,activate:(e=document.body)=>{const t=e=>{1===e.nodeType&&(e.hasAttribute("cdom-state")&&Tn(e),e.hasAttribute("cdom-bind")&&Cn(e),Ln(e));let n=e.firstChild;for(;n;)t(n),n=n.nextSibling};t(e)},hydrate:Nn,version:"1.0.0"};"undefined"!=typeof window&&(globalThis.LightviewCDOM=On),console.log("Lightview Full Bundle Loaded")}();
|
|
1
|
+
(function() {
|
|
2
|
+
"use strict";
|
|
3
|
+
const _LV = globalThis.__LIGHTVIEW_INTERNALS__ || (globalThis.__LIGHTVIEW_INTERNALS__ = {
|
|
4
|
+
currentEffect: null,
|
|
5
|
+
registry: /* @__PURE__ */ new Map(),
|
|
6
|
+
dependencyMap: /* @__PURE__ */ new WeakMap()
|
|
7
|
+
// Tracking signals -> subscribers
|
|
8
|
+
});
|
|
9
|
+
const signal = (initialValue, optionsOrName) => {
|
|
10
|
+
let name = typeof optionsOrName === "string" ? optionsOrName : optionsOrName == null ? void 0 : optionsOrName.name;
|
|
11
|
+
const storage = optionsOrName == null ? void 0 : optionsOrName.storage;
|
|
12
|
+
if (name && storage) {
|
|
13
|
+
try {
|
|
14
|
+
const stored = storage.getItem(name);
|
|
15
|
+
if (stored !== null) {
|
|
16
|
+
initialValue = JSON.parse(stored);
|
|
17
|
+
}
|
|
18
|
+
} catch (e) {
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
let value = initialValue;
|
|
22
|
+
const subscribers = /* @__PURE__ */ new Set();
|
|
23
|
+
const f = (...args) => {
|
|
24
|
+
if (args.length === 0) return f.value;
|
|
25
|
+
f.value = args[0];
|
|
26
|
+
};
|
|
27
|
+
Object.defineProperty(f, "value", {
|
|
28
|
+
get() {
|
|
29
|
+
if (_LV.currentEffect) {
|
|
30
|
+
subscribers.add(_LV.currentEffect);
|
|
31
|
+
_LV.currentEffect.dependencies.add(subscribers);
|
|
32
|
+
}
|
|
33
|
+
return value;
|
|
34
|
+
},
|
|
35
|
+
set(newValue) {
|
|
36
|
+
if (value !== newValue) {
|
|
37
|
+
value = newValue;
|
|
38
|
+
if (name && storage) {
|
|
39
|
+
try {
|
|
40
|
+
storage.setItem(name, JSON.stringify(value));
|
|
41
|
+
} catch (e) {
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
[...subscribers].forEach((effect2) => effect2());
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
if (name) {
|
|
49
|
+
if (_LV.registry.has(name)) {
|
|
50
|
+
if (_LV.registry.get(name) !== f) {
|
|
51
|
+
throw new Error(`Lightview: A signal or state with the name "${name}" is already registered.`);
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
_LV.registry.set(name, f);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return f;
|
|
58
|
+
};
|
|
59
|
+
const getSignal = (name, defaultValue) => {
|
|
60
|
+
if (!_LV.registry.has(name) && defaultValue !== void 0) {
|
|
61
|
+
return signal(defaultValue, name);
|
|
62
|
+
}
|
|
63
|
+
return _LV.registry.get(name);
|
|
64
|
+
};
|
|
65
|
+
signal.get = getSignal;
|
|
66
|
+
const effect = (fn) => {
|
|
67
|
+
const execute = () => {
|
|
68
|
+
if (!execute.active || execute.running) return;
|
|
69
|
+
execute.dependencies.forEach((dep) => dep.delete(execute));
|
|
70
|
+
execute.dependencies.clear();
|
|
71
|
+
execute.running = true;
|
|
72
|
+
_LV.currentEffect = execute;
|
|
73
|
+
try {
|
|
74
|
+
fn();
|
|
75
|
+
} finally {
|
|
76
|
+
_LV.currentEffect = null;
|
|
77
|
+
execute.running = false;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
execute.active = true;
|
|
81
|
+
execute.running = false;
|
|
82
|
+
execute.dependencies = /* @__PURE__ */ new Set();
|
|
83
|
+
execute.stop = () => {
|
|
84
|
+
execute.dependencies.forEach((dep) => dep.delete(execute));
|
|
85
|
+
execute.dependencies.clear();
|
|
86
|
+
execute.active = false;
|
|
87
|
+
};
|
|
88
|
+
execute();
|
|
89
|
+
return execute;
|
|
90
|
+
};
|
|
91
|
+
const computed = (fn) => {
|
|
92
|
+
const sig = signal(void 0);
|
|
93
|
+
effect(() => {
|
|
94
|
+
sig.value = fn();
|
|
95
|
+
});
|
|
96
|
+
return sig;
|
|
97
|
+
};
|
|
98
|
+
const getRegistry$1 = () => _LV.registry;
|
|
99
|
+
const stateCache = /* @__PURE__ */ new WeakMap();
|
|
100
|
+
const stateSignals = /* @__PURE__ */ new WeakMap();
|
|
101
|
+
const parents = /* @__PURE__ */ new WeakMap();
|
|
102
|
+
const protoMethods = (proto, test) => Object.getOwnPropertyNames(proto).filter((k) => typeof proto[k] === "function" && test(k));
|
|
103
|
+
const DATE_TRACKING = protoMethods(Date.prototype, (k) => /^(to|get|valueOf)/.test(k));
|
|
104
|
+
const DATE_MUTATING = protoMethods(Date.prototype, (k) => /^set/.test(k));
|
|
105
|
+
const ARRAY_TRACKING = [
|
|
106
|
+
"map",
|
|
107
|
+
"forEach",
|
|
108
|
+
"filter",
|
|
109
|
+
"find",
|
|
110
|
+
"findIndex",
|
|
111
|
+
"some",
|
|
112
|
+
"every",
|
|
113
|
+
"reduce",
|
|
114
|
+
"reduceRight",
|
|
115
|
+
"includes",
|
|
116
|
+
"indexOf",
|
|
117
|
+
"lastIndexOf",
|
|
118
|
+
"join",
|
|
119
|
+
"slice",
|
|
120
|
+
"concat",
|
|
121
|
+
"flat",
|
|
122
|
+
"flatMap",
|
|
123
|
+
"at",
|
|
124
|
+
"entries",
|
|
125
|
+
"keys",
|
|
126
|
+
"values"
|
|
127
|
+
];
|
|
128
|
+
const ARRAY_MUTATING = ["push", "pop", "shift", "unshift", "splice", "sort", "reverse", "fill", "copyWithin"];
|
|
129
|
+
const ARRAY_ITERATION = ["map", "forEach", "filter", "find", "findIndex", "some", "every", "flatMap"];
|
|
130
|
+
const getOrSet = (map2, key, factory) => {
|
|
131
|
+
let v = map2.get(key);
|
|
132
|
+
if (!v) {
|
|
133
|
+
v = factory();
|
|
134
|
+
map2.set(key, v);
|
|
135
|
+
}
|
|
136
|
+
return v;
|
|
137
|
+
};
|
|
138
|
+
const proxyGet = (target, prop, receiver, signals) => {
|
|
139
|
+
if (prop === "__parent__") return parents.get(receiver);
|
|
140
|
+
if (!signals.has(prop)) {
|
|
141
|
+
signals.set(prop, signal(Reflect.get(target, prop, receiver)));
|
|
142
|
+
}
|
|
143
|
+
const signal$1 = signals.get(prop);
|
|
144
|
+
const val = signal$1.value;
|
|
145
|
+
if (typeof val === "object" && val !== null) {
|
|
146
|
+
const childProxy = state(val);
|
|
147
|
+
parents.set(childProxy, receiver);
|
|
148
|
+
return childProxy;
|
|
149
|
+
}
|
|
150
|
+
return val;
|
|
151
|
+
};
|
|
152
|
+
const proxySet = (target, prop, value, receiver, signals) => {
|
|
153
|
+
if (!signals.has(prop)) {
|
|
154
|
+
signals.set(prop, signal(Reflect.get(target, prop, receiver)));
|
|
155
|
+
}
|
|
156
|
+
const success = Reflect.set(target, prop, value, receiver);
|
|
157
|
+
const signal$1 = signals.get(prop);
|
|
158
|
+
if (success && signal$1) signal$1.value = value;
|
|
159
|
+
return success;
|
|
160
|
+
};
|
|
161
|
+
const createSpecialProxy = (obj, monitor, trackingProps = []) => {
|
|
162
|
+
const signals = getOrSet(stateSignals, obj, () => /* @__PURE__ */ new Map());
|
|
163
|
+
if (!signals.has(monitor)) {
|
|
164
|
+
const initialValue = typeof obj[monitor] === "function" ? obj[monitor].call(obj) : obj[monitor];
|
|
165
|
+
signals.set(monitor, signal(initialValue));
|
|
166
|
+
}
|
|
167
|
+
const isDate = obj instanceof Date;
|
|
168
|
+
const isArray = Array.isArray(obj);
|
|
169
|
+
const trackingMethods = isDate ? DATE_TRACKING : isArray ? ARRAY_TRACKING : trackingProps;
|
|
170
|
+
const mutatingMethods = isDate ? DATE_MUTATING : isArray ? ARRAY_MUTATING : [];
|
|
171
|
+
return new Proxy(obj, {
|
|
172
|
+
get(target, prop, receiver) {
|
|
173
|
+
if (prop === "__parent__") return parents.get(receiver);
|
|
174
|
+
const value = target[prop];
|
|
175
|
+
if (typeof value === "function") {
|
|
176
|
+
const isTracking = trackingMethods.includes(prop);
|
|
177
|
+
const isMutating = mutatingMethods.includes(prop);
|
|
178
|
+
return function(...args) {
|
|
179
|
+
if (isTracking) {
|
|
180
|
+
const sig = signals.get(monitor);
|
|
181
|
+
if (sig) void sig.value;
|
|
182
|
+
}
|
|
183
|
+
const startValue = typeof target[monitor] === "function" ? target[monitor].call(target) : target[monitor];
|
|
184
|
+
if (isArray && ARRAY_ITERATION.includes(prop) && typeof args[0] === "function") {
|
|
185
|
+
const originalCallback = args[0];
|
|
186
|
+
args[0] = function(element2, index2, array) {
|
|
187
|
+
const wrappedElement = typeof element2 === "object" && element2 !== null ? state(element2) : element2;
|
|
188
|
+
if (wrappedElement && typeof wrappedElement === "object") {
|
|
189
|
+
parents.set(wrappedElement, receiver);
|
|
190
|
+
}
|
|
191
|
+
return originalCallback.call(this, wrappedElement, index2, array);
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
const result = value.apply(target, args);
|
|
195
|
+
const endValue = typeof target[monitor] === "function" ? target[monitor].call(target) : target[monitor];
|
|
196
|
+
if (startValue !== endValue || isMutating) {
|
|
197
|
+
const sig = signals.get(monitor);
|
|
198
|
+
if (sig && sig.value !== endValue) {
|
|
199
|
+
sig.value = endValue;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return result;
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
if (prop === monitor) {
|
|
206
|
+
const sig = signals.get(monitor);
|
|
207
|
+
return sig ? sig.value : Reflect.get(target, prop, receiver);
|
|
208
|
+
}
|
|
209
|
+
if (isArray && !isNaN(parseInt(prop))) {
|
|
210
|
+
const monitorSig = signals.get(monitor);
|
|
211
|
+
if (monitorSig) void monitorSig.value;
|
|
212
|
+
}
|
|
213
|
+
return proxyGet(target, prop, receiver, signals);
|
|
214
|
+
},
|
|
215
|
+
set(target, prop, value, receiver) {
|
|
216
|
+
if (prop === monitor) {
|
|
217
|
+
const success = Reflect.set(target, prop, value, receiver);
|
|
218
|
+
if (success) {
|
|
219
|
+
const sig = signals.get(monitor);
|
|
220
|
+
if (sig) sig.value = value;
|
|
221
|
+
}
|
|
222
|
+
return success;
|
|
223
|
+
}
|
|
224
|
+
return proxySet(target, prop, value, receiver, signals);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
};
|
|
228
|
+
const state = (obj, optionsOrName) => {
|
|
229
|
+
if (typeof obj !== "object" || obj === null) return obj;
|
|
230
|
+
const name = typeof optionsOrName === "string" ? optionsOrName : optionsOrName == null ? void 0 : optionsOrName.name;
|
|
231
|
+
const storage = optionsOrName == null ? void 0 : optionsOrName.storage;
|
|
232
|
+
if (name && storage) {
|
|
233
|
+
try {
|
|
234
|
+
const item = storage.getItem(name);
|
|
235
|
+
if (item) {
|
|
236
|
+
const loaded = JSON.parse(item);
|
|
237
|
+
Array.isArray(obj) && Array.isArray(loaded) ? (obj.length = 0, obj.push(...loaded)) : Object.assign(obj, loaded);
|
|
238
|
+
}
|
|
239
|
+
} catch (e) {
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
let proxy = stateCache.get(obj);
|
|
243
|
+
if (!proxy) {
|
|
244
|
+
const isArray = Array.isArray(obj), isDate = obj instanceof Date;
|
|
245
|
+
const isSpecial = isArray || isDate;
|
|
246
|
+
const monitor = isArray ? "length" : isDate ? "getTime" : null;
|
|
247
|
+
if (isSpecial || !(obj instanceof RegExp || obj instanceof Map || obj instanceof Set || obj instanceof WeakMap || obj instanceof WeakSet)) {
|
|
248
|
+
proxy = isSpecial ? createSpecialProxy(obj, monitor) : new Proxy(obj, {
|
|
249
|
+
get(t, p, r) {
|
|
250
|
+
if (p === "__parent__") return parents.get(r);
|
|
251
|
+
return proxyGet(t, p, r, getOrSet(stateSignals, t, () => /* @__PURE__ */ new Map()));
|
|
252
|
+
},
|
|
253
|
+
set(t, p, v, r) {
|
|
254
|
+
return proxySet(t, p, v, r, getOrSet(stateSignals, t, () => /* @__PURE__ */ new Map()));
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
stateCache.set(obj, proxy);
|
|
258
|
+
} else return obj;
|
|
259
|
+
}
|
|
260
|
+
if (name && storage) {
|
|
261
|
+
effect(() => {
|
|
262
|
+
try {
|
|
263
|
+
storage.setItem(name, JSON.stringify(proxy));
|
|
264
|
+
} catch (e) {
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
if (name) {
|
|
269
|
+
const registry2 = getRegistry$1();
|
|
270
|
+
if (registry2.has(name)) {
|
|
271
|
+
if (registry2.get(name) !== proxy) {
|
|
272
|
+
throw new Error(`Lightview: A signal or state with the name "${name}" is already registered.`);
|
|
273
|
+
}
|
|
274
|
+
} else {
|
|
275
|
+
registry2.set(name, proxy);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return proxy;
|
|
279
|
+
};
|
|
280
|
+
const getState = (name, defaultValue) => {
|
|
281
|
+
const registry2 = getRegistry$1();
|
|
282
|
+
if (!registry2.has(name) && defaultValue !== void 0) {
|
|
283
|
+
return state(defaultValue, name);
|
|
284
|
+
}
|
|
285
|
+
return registry2.get(name);
|
|
286
|
+
};
|
|
287
|
+
state.get = getState;
|
|
288
|
+
const core = {
|
|
289
|
+
get currentEffect() {
|
|
290
|
+
return (globalThis.__LIGHTVIEW_INTERNALS__ || (globalThis.__LIGHTVIEW_INTERNALS__ = {})).currentEffect;
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
const nodeState = /* @__PURE__ */ new WeakMap();
|
|
294
|
+
const nodeStateFactory = () => ({ effects: [], onmount: null, onunmount: null });
|
|
295
|
+
const registry = getRegistry$1();
|
|
296
|
+
const trackEffect = (node, effectFn) => {
|
|
297
|
+
const state2 = getOrSet(nodeState, node, nodeStateFactory);
|
|
298
|
+
if (!state2.effects) state2.effects = [];
|
|
299
|
+
state2.effects.push(effectFn);
|
|
300
|
+
};
|
|
301
|
+
const SHADOW_DOM_MARKER = Symbol("lightview.shadowDOM");
|
|
302
|
+
const createShadowDOMMarker = (attributes, children) => ({
|
|
303
|
+
[SHADOW_DOM_MARKER]: true,
|
|
304
|
+
mode: attributes.mode || "open",
|
|
305
|
+
styles: attributes.styles || [],
|
|
306
|
+
adoptedStyleSheets: attributes.adoptedStyleSheets || [],
|
|
307
|
+
children
|
|
308
|
+
});
|
|
309
|
+
const isShadowDOMMarker = (obj) => obj && typeof obj === "object" && obj[SHADOW_DOM_MARKER] === true;
|
|
310
|
+
const processShadowDOM = (marker, parentNode) => {
|
|
311
|
+
if (parentNode.shadowRoot) {
|
|
312
|
+
console.warn("Lightview: Element already has a shadowRoot, skipping shadowDOM directive");
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
const shadowRoot = parentNode.attachShadow({ mode: marker.mode });
|
|
316
|
+
const sheets = [];
|
|
317
|
+
const linkUrls = [...marker.styles || []];
|
|
318
|
+
if (marker.adoptedStyleSheets && marker.adoptedStyleSheets.length > 0) {
|
|
319
|
+
marker.adoptedStyleSheets.forEach((item) => {
|
|
320
|
+
if (item instanceof CSSStyleSheet) {
|
|
321
|
+
sheets.push(item);
|
|
322
|
+
} else if (typeof item === "string") {
|
|
323
|
+
linkUrls.push(item);
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
if (sheets.length > 0) {
|
|
328
|
+
try {
|
|
329
|
+
shadowRoot.adoptedStyleSheets = sheets;
|
|
330
|
+
} catch (e) {
|
|
331
|
+
console.warn("Lightview: adoptedStyleSheets not supported");
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
for (const styleUrl of linkUrls) {
|
|
335
|
+
const link = document.createElement("link");
|
|
336
|
+
link.rel = "stylesheet";
|
|
337
|
+
link.href = styleUrl;
|
|
338
|
+
shadowRoot.appendChild(link);
|
|
339
|
+
}
|
|
340
|
+
if (marker.children && marker.children.length > 0) {
|
|
341
|
+
setupChildrenInTarget(marker.children, shadowRoot);
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
let inSVG = false;
|
|
345
|
+
const domToElement = /* @__PURE__ */ new WeakMap();
|
|
346
|
+
const wrapDomElement = (domNode, tag, attributes = {}, children = []) => {
|
|
347
|
+
const el = {
|
|
348
|
+
tag,
|
|
349
|
+
attributes,
|
|
350
|
+
children,
|
|
351
|
+
get domEl() {
|
|
352
|
+
return domNode;
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
const proxy = makeReactive(el);
|
|
356
|
+
domToElement.set(domNode, proxy);
|
|
357
|
+
return proxy;
|
|
358
|
+
};
|
|
359
|
+
const element = (tag, attributes = {}, children = []) => {
|
|
360
|
+
if (customTags[tag]) tag = customTags[tag];
|
|
361
|
+
if (typeof tag === "function") {
|
|
362
|
+
const result = tag({ ...attributes }, children);
|
|
363
|
+
return processComponentResult(result);
|
|
364
|
+
}
|
|
365
|
+
if (tag === "shadowDOM") {
|
|
366
|
+
return createShadowDOMMarker(attributes, children);
|
|
367
|
+
}
|
|
368
|
+
if (tag === "text" && !inSVG) {
|
|
369
|
+
const domNode2 = document.createTextNode("");
|
|
370
|
+
const el = {
|
|
371
|
+
tag,
|
|
372
|
+
attributes,
|
|
373
|
+
children,
|
|
374
|
+
get domEl() {
|
|
375
|
+
return domNode2;
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
const update = () => {
|
|
379
|
+
const flat = (Array.isArray(el.children) ? el.children : [el.children]).flat(Infinity);
|
|
380
|
+
const bits = flat.map((c) => {
|
|
381
|
+
const val = typeof c === "function" ? c() : c;
|
|
382
|
+
if (val && typeof val === "object" && val.domEl) return val.domEl.textContent;
|
|
383
|
+
return val === null || val === void 0 ? "" : String(val);
|
|
384
|
+
});
|
|
385
|
+
domNode2.textContent = bits.join(" ");
|
|
386
|
+
};
|
|
387
|
+
const proxy2 = new Proxy(el, {
|
|
388
|
+
set(target, prop, value) {
|
|
389
|
+
target[prop] = value;
|
|
390
|
+
if (prop === "children") update();
|
|
391
|
+
return true;
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
const hasReactive = children.flat(Infinity).some((c) => typeof c === "function");
|
|
395
|
+
if (hasReactive) {
|
|
396
|
+
const runner = effect(update);
|
|
397
|
+
trackEffect(domNode2, runner);
|
|
398
|
+
}
|
|
399
|
+
update();
|
|
400
|
+
return proxy2;
|
|
401
|
+
}
|
|
402
|
+
const isSVG = tag.toLowerCase() === "svg";
|
|
403
|
+
const wasInSVG = inSVG;
|
|
404
|
+
if (isSVG) inSVG = true;
|
|
405
|
+
const domNode = inSVG ? document.createElementNS("http://www.w3.org/2000/svg", tag) : document.createElement(tag);
|
|
406
|
+
const proxy = wrapDomElement(domNode, tag, attributes, children);
|
|
407
|
+
proxy.attributes = attributes;
|
|
408
|
+
proxy.children = children;
|
|
409
|
+
if (isSVG) inSVG = wasInSVG;
|
|
410
|
+
return proxy;
|
|
411
|
+
};
|
|
412
|
+
const processComponentResult = (result) => {
|
|
413
|
+
if (!result) return null;
|
|
414
|
+
if (Lightview.hooks.processChild) {
|
|
415
|
+
result = Lightview.hooks.processChild(result) ?? result;
|
|
416
|
+
}
|
|
417
|
+
if (result.domEl) return result;
|
|
418
|
+
const type = typeof result;
|
|
419
|
+
if (type === "object" && result instanceof HTMLElement) {
|
|
420
|
+
return wrapDomElement(result, result.tagName.toLowerCase(), {}, []);
|
|
421
|
+
}
|
|
422
|
+
if (type === "object" && result instanceof String) {
|
|
423
|
+
const span = document.createElement("span");
|
|
424
|
+
span.textContent = result.toString();
|
|
425
|
+
return wrapDomElement(span, "span", {}, []);
|
|
426
|
+
}
|
|
427
|
+
if (type === "string") {
|
|
428
|
+
const template = document.createElement("template");
|
|
429
|
+
template.innerHTML = result.trim();
|
|
430
|
+
const content = template.content;
|
|
431
|
+
if (content.childNodes.length === 1 && content.firstChild instanceof HTMLElement) {
|
|
432
|
+
const el = content.firstChild;
|
|
433
|
+
return wrapDomElement(el, el.tagName.toLowerCase(), {}, []);
|
|
434
|
+
} else {
|
|
435
|
+
const wrapper = document.createElement("span");
|
|
436
|
+
wrapper.style.display = "contents";
|
|
437
|
+
wrapper.appendChild(content);
|
|
438
|
+
return wrapDomElement(wrapper, "span", {}, []);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
if (typeof result === "object" && result.tag) {
|
|
442
|
+
return element(result.tag, result.attributes || {}, result.children || []);
|
|
443
|
+
}
|
|
444
|
+
return null;
|
|
445
|
+
};
|
|
446
|
+
const makeReactive = (el) => {
|
|
447
|
+
const domNode = el.domEl;
|
|
448
|
+
return new Proxy(el, {
|
|
449
|
+
set(target, prop, value) {
|
|
450
|
+
if (prop === "attributes") {
|
|
451
|
+
target[prop] = makeReactiveAttributes(value, domNode);
|
|
452
|
+
} else if (prop === "children") {
|
|
453
|
+
target[prop] = setupChildren(value, domNode);
|
|
454
|
+
} else {
|
|
455
|
+
target[prop] = value;
|
|
456
|
+
}
|
|
457
|
+
return true;
|
|
458
|
+
}
|
|
459
|
+
});
|
|
460
|
+
};
|
|
461
|
+
const NODE_PROPERTIES = /* @__PURE__ */ new Set(["value", "checked", "selected", "selectedIndex", "className", "innerHTML", "innerText"]);
|
|
462
|
+
const setAttributeValue = (domNode, key, value) => {
|
|
463
|
+
const isBool = typeof domNode[key] === "boolean";
|
|
464
|
+
if ((key === "href" || key === "src") && typeof value === "string" && /^(javascript|vbscript|data:text\/html|data:application\/javascript)/i.test(value)) {
|
|
465
|
+
console.warn(`[Lightview] Blocked dangerous protocol in ${key}: ${value}`);
|
|
466
|
+
value = "javascript:void(0)";
|
|
467
|
+
}
|
|
468
|
+
if (NODE_PROPERTIES.has(key) || isBool || key.startsWith("cdom-")) {
|
|
469
|
+
domNode[key] = isBool ? value !== null && value !== void 0 && value !== false && value !== "false" : value;
|
|
470
|
+
} else if (value === null || value === void 0) {
|
|
471
|
+
domNode.removeAttribute(key);
|
|
472
|
+
} else {
|
|
473
|
+
domNode.setAttribute(key, value);
|
|
474
|
+
}
|
|
475
|
+
};
|
|
476
|
+
const makeReactiveAttributes = (attributes, domNode) => {
|
|
477
|
+
const reactiveAttrs = {};
|
|
478
|
+
for (let [key, value] of Object.entries(attributes)) {
|
|
479
|
+
if (key === "onmount" || key === "onunmount") {
|
|
480
|
+
const state2 = getOrSet(nodeState, domNode, nodeStateFactory);
|
|
481
|
+
state2[key] = value;
|
|
482
|
+
if (key === "onmount" && domNode.isConnected) {
|
|
483
|
+
value(domNode);
|
|
484
|
+
}
|
|
485
|
+
} else if (key.startsWith("on")) {
|
|
486
|
+
if (typeof value === "function") {
|
|
487
|
+
const eventName = key.slice(2).toLowerCase();
|
|
488
|
+
domNode.addEventListener(eventName, value);
|
|
489
|
+
} else if (typeof value === "string") {
|
|
490
|
+
domNode.setAttribute(key, value);
|
|
491
|
+
}
|
|
492
|
+
reactiveAttrs[key] = value;
|
|
493
|
+
} else if (typeof value === "function") {
|
|
494
|
+
const runner = effect(() => {
|
|
495
|
+
const result = value();
|
|
496
|
+
if (key === "style" && typeof result === "object") {
|
|
497
|
+
Object.assign(domNode.style, result);
|
|
498
|
+
} else {
|
|
499
|
+
setAttributeValue(domNode, key, result);
|
|
500
|
+
}
|
|
501
|
+
});
|
|
502
|
+
trackEffect(domNode, runner);
|
|
503
|
+
reactiveAttrs[key] = value;
|
|
504
|
+
} else if (key === "style" && typeof value === "object") {
|
|
505
|
+
Object.entries(value).forEach(([styleKey, styleValue]) => {
|
|
506
|
+
if (typeof styleValue === "function") {
|
|
507
|
+
const runner = effect(() => {
|
|
508
|
+
domNode.style[styleKey] = styleValue();
|
|
509
|
+
});
|
|
510
|
+
trackEffect(domNode, runner);
|
|
511
|
+
} else {
|
|
512
|
+
domNode.style[styleKey] = styleValue;
|
|
513
|
+
}
|
|
514
|
+
});
|
|
515
|
+
reactiveAttrs[key] = value;
|
|
516
|
+
} else {
|
|
517
|
+
setAttributeValue(domNode, key, value);
|
|
518
|
+
reactiveAttrs[key] = value;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
return reactiveAttrs;
|
|
522
|
+
};
|
|
523
|
+
const processChildren = (children, targetNode, clearExisting = true) => {
|
|
524
|
+
if (clearExisting && targetNode.innerHTML !== void 0) {
|
|
525
|
+
targetNode.innerHTML = "";
|
|
526
|
+
}
|
|
527
|
+
const childElements = [];
|
|
528
|
+
const isSpecialElement = targetNode.tagName && (targetNode.tagName.toLowerCase() === "script" || targetNode.tagName.toLowerCase() === "style");
|
|
529
|
+
const flatChildren = children.flat(Infinity);
|
|
530
|
+
for (let child of flatChildren) {
|
|
531
|
+
if (Lightview.hooks.processChild && !isSpecialElement) {
|
|
532
|
+
child = Lightview.hooks.processChild(child) ?? child;
|
|
533
|
+
}
|
|
534
|
+
if (isShadowDOMMarker(child)) {
|
|
535
|
+
if (targetNode instanceof ShadowRoot) {
|
|
536
|
+
console.warn("Lightview: Cannot nest shadowDOM inside another shadowDOM");
|
|
537
|
+
continue;
|
|
538
|
+
}
|
|
539
|
+
processShadowDOM(child, targetNode);
|
|
540
|
+
continue;
|
|
541
|
+
}
|
|
542
|
+
const type = typeof child;
|
|
543
|
+
if (type === "function") {
|
|
544
|
+
const startMarker = document.createComment("lv:s");
|
|
545
|
+
const endMarker = document.createComment("lv:e");
|
|
546
|
+
targetNode.appendChild(startMarker);
|
|
547
|
+
targetNode.appendChild(endMarker);
|
|
548
|
+
let runner;
|
|
549
|
+
const update = () => {
|
|
550
|
+
while (startMarker.nextSibling && startMarker.nextSibling !== endMarker) {
|
|
551
|
+
startMarker.nextSibling.remove();
|
|
552
|
+
}
|
|
553
|
+
const val = child();
|
|
554
|
+
if (val === void 0 || val === null) return;
|
|
555
|
+
if (runner && !startMarker.isConnected) {
|
|
556
|
+
runner.stop();
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
if (typeof val === "object" && val instanceof String) {
|
|
560
|
+
const textNode = document.createTextNode(val);
|
|
561
|
+
endMarker.parentNode.insertBefore(textNode, endMarker);
|
|
562
|
+
} else {
|
|
563
|
+
const fragment = document.createDocumentFragment();
|
|
564
|
+
const childrenToProcess = Array.isArray(val) ? val : [val];
|
|
565
|
+
processChildren(childrenToProcess, fragment, false);
|
|
566
|
+
endMarker.parentNode.insertBefore(fragment, endMarker);
|
|
567
|
+
}
|
|
568
|
+
};
|
|
569
|
+
runner = effect(update);
|
|
570
|
+
trackEffect(startMarker, runner);
|
|
571
|
+
childElements.push(child);
|
|
572
|
+
} else if (["string", "number", "boolean", "symbol"].includes(type) || child && type === "object" && child instanceof String) {
|
|
573
|
+
targetNode.appendChild(document.createTextNode(child));
|
|
574
|
+
childElements.push(child);
|
|
575
|
+
} else if (child instanceof Node) {
|
|
576
|
+
const node = child.domEl || child;
|
|
577
|
+
if (node instanceof HTMLElement || node instanceof SVGElement) {
|
|
578
|
+
const wrapped = wrapDomElement(node, node.tagName.toLowerCase());
|
|
579
|
+
targetNode.appendChild(node);
|
|
580
|
+
childElements.push(wrapped);
|
|
581
|
+
} else {
|
|
582
|
+
targetNode.appendChild(node);
|
|
583
|
+
childElements.push(child);
|
|
584
|
+
}
|
|
585
|
+
} else if (child && type === "object" && child.tag) {
|
|
586
|
+
const childEl = child.domEl ? child : element(child.tag, child.attributes || {}, child.children || []);
|
|
587
|
+
targetNode.appendChild(childEl.domEl);
|
|
588
|
+
childElements.push(childEl);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
return childElements;
|
|
592
|
+
};
|
|
593
|
+
const setupChildrenInTarget = (children, targetNode) => {
|
|
594
|
+
return processChildren(children, targetNode, false);
|
|
595
|
+
};
|
|
596
|
+
const setupChildren = (children, domNode) => {
|
|
597
|
+
return processChildren(children, domNode, true);
|
|
598
|
+
};
|
|
599
|
+
const enhance = (selectorOrNode, options = {}) => {
|
|
600
|
+
const domNode = typeof selectorOrNode === "string" ? document.querySelector(selectorOrNode) : selectorOrNode;
|
|
601
|
+
const node = domNode.domEl || domNode;
|
|
602
|
+
if (!(node instanceof HTMLElement)) return null;
|
|
603
|
+
const tagName = node.tagName.toLowerCase();
|
|
604
|
+
let el = domToElement.get(node);
|
|
605
|
+
if (!el) {
|
|
606
|
+
el = wrapDomElement(node, tagName);
|
|
607
|
+
}
|
|
608
|
+
const { innerText, innerHTML, ...attrs } = options;
|
|
609
|
+
if (innerText !== void 0) {
|
|
610
|
+
if (typeof innerText === "function") {
|
|
611
|
+
effect(() => {
|
|
612
|
+
node.innerText = innerText();
|
|
613
|
+
});
|
|
614
|
+
} else {
|
|
615
|
+
node.innerText = innerText;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
if (innerHTML !== void 0) {
|
|
619
|
+
if (typeof innerHTML === "function") {
|
|
620
|
+
effect(() => {
|
|
621
|
+
node.innerHTML = innerHTML();
|
|
622
|
+
});
|
|
623
|
+
} else {
|
|
624
|
+
node.innerHTML = innerHTML;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
if (Object.keys(attrs).length > 0) {
|
|
628
|
+
el.attributes = attrs;
|
|
629
|
+
}
|
|
630
|
+
return el;
|
|
631
|
+
};
|
|
632
|
+
const $ = (cssSelectorOrElement, startingDomEl = document.body) => {
|
|
633
|
+
const el = typeof cssSelectorOrElement === "string" ? startingDomEl.querySelector(cssSelectorOrElement) : cssSelectorOrElement;
|
|
634
|
+
if (!el) return null;
|
|
635
|
+
Object.defineProperty(el, "content", {
|
|
636
|
+
value(child, location = "inner") {
|
|
637
|
+
location = location.toLowerCase();
|
|
638
|
+
Lightview.tags;
|
|
639
|
+
const isSpecialElement = el.tagName && (el.tagName.toLowerCase() === "script" || el.tagName.toLowerCase() === "style");
|
|
640
|
+
const array = (Array.isArray(child) ? child : [child]).map((item) => {
|
|
641
|
+
if (Lightview.hooks.processChild && !isSpecialElement) {
|
|
642
|
+
item = Lightview.hooks.processChild(item) ?? item;
|
|
643
|
+
}
|
|
644
|
+
if (item.tag && !item.domEl) {
|
|
645
|
+
return element(item.tag, item.attributes || {}, item.children || []).domEl;
|
|
646
|
+
} else {
|
|
647
|
+
return item.domEl || item;
|
|
648
|
+
}
|
|
649
|
+
});
|
|
650
|
+
const target = location === "shadow" ? el.shadowRoot || el.attachShadow({ mode: "open" }) : el;
|
|
651
|
+
if (location === "inner" || location === "shadow") {
|
|
652
|
+
target.replaceChildren(...array);
|
|
653
|
+
} else if (location === "outer") {
|
|
654
|
+
target.replaceWith(...array);
|
|
655
|
+
} else if (location === "afterbegin") {
|
|
656
|
+
target.prepend(...array);
|
|
657
|
+
} else if (location === "beforeend") {
|
|
658
|
+
target.append(...array);
|
|
659
|
+
} else {
|
|
660
|
+
array.forEach((item) => el.insertAdjacentElement(location, item));
|
|
661
|
+
}
|
|
662
|
+
return el;
|
|
663
|
+
},
|
|
664
|
+
configurable: true,
|
|
665
|
+
writable: true
|
|
666
|
+
});
|
|
667
|
+
return el;
|
|
668
|
+
};
|
|
669
|
+
const customTags = {};
|
|
670
|
+
const tags = new Proxy({}, {
|
|
671
|
+
get(_, tag) {
|
|
672
|
+
if (tag === "_customTags") return { ...customTags };
|
|
673
|
+
const wrapper = (...args) => {
|
|
674
|
+
let attributes = {};
|
|
675
|
+
let children = args;
|
|
676
|
+
const arg0 = args[0];
|
|
677
|
+
if (args.length > 0 && arg0 && typeof arg0 === "object" && !arg0.tag && !arg0.domEl && !Array.isArray(arg0)) {
|
|
678
|
+
attributes = arg0;
|
|
679
|
+
children = args.slice(1);
|
|
680
|
+
}
|
|
681
|
+
return element(customTags[tag] || tag, attributes, children);
|
|
682
|
+
};
|
|
683
|
+
if (customTags[tag]) {
|
|
684
|
+
Object.assign(wrapper, customTags[tag]);
|
|
685
|
+
}
|
|
686
|
+
return wrapper;
|
|
687
|
+
},
|
|
688
|
+
set(_, tag, value) {
|
|
689
|
+
customTags[tag] = value;
|
|
690
|
+
return true;
|
|
691
|
+
}
|
|
692
|
+
});
|
|
693
|
+
const Lightview = {
|
|
694
|
+
signal,
|
|
695
|
+
get: signal.get,
|
|
696
|
+
computed,
|
|
697
|
+
effect,
|
|
698
|
+
registry,
|
|
699
|
+
element,
|
|
700
|
+
// do not document this
|
|
701
|
+
enhance,
|
|
702
|
+
tags,
|
|
703
|
+
$,
|
|
704
|
+
// Extension hooks
|
|
705
|
+
hooks: {
|
|
706
|
+
onNonStandardHref: null,
|
|
707
|
+
processChild: null,
|
|
708
|
+
validateUrl: null
|
|
709
|
+
},
|
|
710
|
+
// Internals exposed for extensions
|
|
711
|
+
internals: {
|
|
712
|
+
core,
|
|
713
|
+
domToElement,
|
|
714
|
+
wrapDomElement,
|
|
715
|
+
setupChildren
|
|
716
|
+
}
|
|
717
|
+
};
|
|
718
|
+
if (typeof module !== "undefined" && module.exports) {
|
|
719
|
+
module.exports = Lightview;
|
|
720
|
+
}
|
|
721
|
+
if (typeof window !== "undefined") {
|
|
722
|
+
globalThis.Lightview = Lightview;
|
|
723
|
+
globalThis.addEventListener("click", (e) => {
|
|
724
|
+
const path = e.composedPath();
|
|
725
|
+
const link = path.find((el) => {
|
|
726
|
+
var _a, _b;
|
|
727
|
+
return el.tagName === "A" && ((_b = (_a = el.getAttribute) == null ? void 0 : _a.call(el, "href")) == null ? void 0 : _b.startsWith("#"));
|
|
728
|
+
});
|
|
729
|
+
if (link && !e.defaultPrevented) {
|
|
730
|
+
const href = link.getAttribute("href");
|
|
731
|
+
if (href.length > 1) {
|
|
732
|
+
const id = href.slice(1);
|
|
733
|
+
const root = link.getRootNode();
|
|
734
|
+
const target = (root.getElementById ? root.getElementById(id) : null) || (root.querySelector ? root.querySelector(`#${id}`) : null);
|
|
735
|
+
if (target) {
|
|
736
|
+
e.preventDefault();
|
|
737
|
+
requestAnimationFrame(() => {
|
|
738
|
+
requestAnimationFrame(() => {
|
|
739
|
+
target.style.scrollMarginTop = "calc(var(--site-nav-height, 0px) + 2rem)";
|
|
740
|
+
target.scrollIntoView({ behavior: "smooth", block: "start", inline: "start" });
|
|
741
|
+
});
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
if (Lightview.hooks.onNonStandardHref) {
|
|
747
|
+
Lightview.hooks.onNonStandardHref(e);
|
|
748
|
+
}
|
|
749
|
+
});
|
|
750
|
+
if (typeof MutationObserver !== "undefined") {
|
|
751
|
+
const walkNodes = (node, fn) => {
|
|
752
|
+
var _a;
|
|
753
|
+
fn(node);
|
|
754
|
+
(_a = node.childNodes) == null ? void 0 : _a.forEach((n) => walkNodes(n, fn));
|
|
755
|
+
if (node.shadowRoot) walkNodes(node.shadowRoot, fn);
|
|
756
|
+
};
|
|
757
|
+
const cleanupNode = (node) => walkNodes(node, (n) => {
|
|
758
|
+
var _a, _b;
|
|
759
|
+
const s = nodeState.get(n);
|
|
760
|
+
if (s) {
|
|
761
|
+
(_a = s.effects) == null ? void 0 : _a.forEach((e) => e.stop());
|
|
762
|
+
(_b = s.onunmount) == null ? void 0 : _b.call(s, n);
|
|
763
|
+
nodeState.delete(n);
|
|
764
|
+
}
|
|
765
|
+
});
|
|
766
|
+
const mountNode = (node) => walkNodes(node, (n) => {
|
|
767
|
+
var _a, _b;
|
|
768
|
+
(_b = (_a = nodeState.get(n)) == null ? void 0 : _a.onmount) == null ? void 0 : _b.call(_a, n);
|
|
769
|
+
});
|
|
770
|
+
const observer = new MutationObserver((mutations) => {
|
|
771
|
+
mutations.forEach((mutation) => {
|
|
772
|
+
mutation.removedNodes.forEach(cleanupNode);
|
|
773
|
+
mutation.addedNodes.forEach(mountNode);
|
|
774
|
+
});
|
|
775
|
+
});
|
|
776
|
+
const startObserving = () => {
|
|
777
|
+
if (document.body) {
|
|
778
|
+
observer.observe(document.body, {
|
|
779
|
+
childList: true,
|
|
780
|
+
subtree: true
|
|
781
|
+
});
|
|
782
|
+
}
|
|
783
|
+
};
|
|
784
|
+
if (document.readyState === "loading") {
|
|
785
|
+
document.addEventListener("DOMContentLoaded", startObserving);
|
|
786
|
+
} else {
|
|
787
|
+
startObserving();
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
const STANDARD_SRC_TAGS = ["img", "script", "iframe", "video", "audio", "source", "track", "embed", "input"];
|
|
792
|
+
const isStandardSrcTag = (tagName) => STANDARD_SRC_TAGS.includes(tagName) || tagName.startsWith("lv-");
|
|
793
|
+
const STANDARD_HREF_TAGS = ["a", "area", "base", "link"];
|
|
794
|
+
const isValidTagName = (name) => typeof name === "string" && name.length > 0 && name !== "children";
|
|
795
|
+
const isDangerousProtocol = (url) => {
|
|
796
|
+
if (!url || typeof url !== "string") return false;
|
|
797
|
+
const normalized = url.trim().toLowerCase();
|
|
798
|
+
return normalized.startsWith("javascript:") || normalized.startsWith("vbscript:") || normalized.startsWith("data:text/html") || normalized.startsWith("data:application/javascript");
|
|
799
|
+
};
|
|
800
|
+
const validateUrl = (url) => {
|
|
801
|
+
if (!url) return false;
|
|
802
|
+
if (!/^[a-z][a-z0-9+.-]*:/i.test(url)) return true;
|
|
803
|
+
try {
|
|
804
|
+
const base = typeof document !== "undefined" ? document.baseURI : globalThis.location.origin;
|
|
805
|
+
const target = new URL(url, base === "null" ? void 0 : base);
|
|
806
|
+
const current = globalThis.location;
|
|
807
|
+
if (target.origin === current.origin && target.origin !== "null") return true;
|
|
808
|
+
if (target.hostname && target.hostname === current.hostname) return true;
|
|
809
|
+
if (target.hostname && current.hostname && target.hostname.endsWith("." + current.hostname)) return true;
|
|
810
|
+
if (current.protocol === "file:" && target.protocol === "file:") return true;
|
|
811
|
+
return false;
|
|
812
|
+
} catch (e) {
|
|
813
|
+
return false;
|
|
814
|
+
}
|
|
815
|
+
};
|
|
816
|
+
const isObjectDOM = (obj) => {
|
|
817
|
+
if (typeof obj !== "object" || obj === null || Array.isArray(obj) || obj.tag || obj.domEl) return false;
|
|
818
|
+
const keys = Object.keys(obj);
|
|
819
|
+
return keys.length === 1 && isValidTagName(keys[0]) && typeof obj[keys[0]] === "object";
|
|
820
|
+
};
|
|
821
|
+
const convertObjectDOM = (obj) => {
|
|
822
|
+
var _a, _b;
|
|
823
|
+
if (typeof obj !== "object" || obj === null) return obj;
|
|
824
|
+
if (Array.isArray(obj)) return obj.map(convertObjectDOM);
|
|
825
|
+
if (obj.tag) return { ...obj, children: obj.children ? convertObjectDOM(obj.children) : [] };
|
|
826
|
+
if (obj.domEl || !isObjectDOM(obj)) return obj;
|
|
827
|
+
const tagKey = Object.keys(obj)[0];
|
|
828
|
+
const content = obj[tagKey];
|
|
829
|
+
const LV = typeof window !== "undefined" ? globalThis.Lightview : typeof globalThis !== "undefined" ? globalThis.Lightview : null;
|
|
830
|
+
const tag = ((_b = (_a = LV == null ? void 0 : LV.tags) == null ? void 0 : _a._customTags) == null ? void 0 : _b[tagKey]) || tagKey;
|
|
831
|
+
const { children, ...attributes } = content;
|
|
832
|
+
return { tag, attributes, children: children ? convertObjectDOM(children) : [] };
|
|
833
|
+
};
|
|
834
|
+
const DAISYUI_CDN = "https://cdn.jsdelivr.net/npm/daisyui@4.12.23/dist/full.min.css";
|
|
835
|
+
const componentConfig = {
|
|
836
|
+
initialized: false,
|
|
837
|
+
shadowDefault: true,
|
|
838
|
+
// Default: components use shadow DOM
|
|
839
|
+
daisyStyleSheet: null,
|
|
840
|
+
themeStyleSheet: null,
|
|
841
|
+
// Global theme stylesheet
|
|
842
|
+
componentStyleSheets: /* @__PURE__ */ new Map(),
|
|
843
|
+
customStyleSheets: /* @__PURE__ */ new Map(),
|
|
844
|
+
// Registry for named custom stylesheets
|
|
845
|
+
customStyleSheetPromises: /* @__PURE__ */ new Map()
|
|
846
|
+
// Cache for pending stylesheet fetches
|
|
847
|
+
};
|
|
848
|
+
const registerStyleSheet = async (nameOrIdOrUrl, cssText) => {
|
|
849
|
+
if (componentConfig.customStyleSheets.has(nameOrIdOrUrl)) return componentConfig.customStyleSheets.get(nameOrIdOrUrl);
|
|
850
|
+
if (componentConfig.customStyleSheetPromises.has(nameOrIdOrUrl)) return componentConfig.customStyleSheetPromises.get(nameOrIdOrUrl);
|
|
851
|
+
const promise = (async () => {
|
|
852
|
+
try {
|
|
853
|
+
let finalCss = cssText;
|
|
854
|
+
if (finalCss === void 0) {
|
|
855
|
+
if (nameOrIdOrUrl.startsWith("#")) {
|
|
856
|
+
const el = document.querySelector(nameOrIdOrUrl);
|
|
857
|
+
if (el) {
|
|
858
|
+
finalCss = el.textContent;
|
|
859
|
+
} else {
|
|
860
|
+
throw new Error(`Style block '${nameOrIdOrUrl}' not found`);
|
|
861
|
+
}
|
|
862
|
+
} else {
|
|
863
|
+
const response = await fetch(nameOrIdOrUrl);
|
|
864
|
+
if (!response.ok) throw new Error(`Fetch failed: ${response.status}`);
|
|
865
|
+
finalCss = await response.text();
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
if (finalCss !== void 0) {
|
|
869
|
+
const sheet = new CSSStyleSheet();
|
|
870
|
+
sheet.replaceSync(finalCss);
|
|
871
|
+
componentConfig.customStyleSheets.set(nameOrIdOrUrl, sheet);
|
|
872
|
+
return sheet;
|
|
873
|
+
}
|
|
874
|
+
} catch (e) {
|
|
875
|
+
console.error(`LightviewX: Failed to register stylesheet '${nameOrIdOrUrl}':`, e);
|
|
876
|
+
} finally {
|
|
877
|
+
componentConfig.customStyleSheetPromises.delete(nameOrIdOrUrl);
|
|
878
|
+
}
|
|
879
|
+
})();
|
|
880
|
+
componentConfig.customStyleSheetPromises.set(nameOrIdOrUrl, promise);
|
|
881
|
+
return promise;
|
|
882
|
+
};
|
|
883
|
+
const getSavedTheme = () => {
|
|
884
|
+
try {
|
|
885
|
+
if (typeof localStorage !== "undefined") {
|
|
886
|
+
return localStorage.getItem("lightview-theme");
|
|
887
|
+
}
|
|
888
|
+
} catch (e) {
|
|
889
|
+
return null;
|
|
890
|
+
}
|
|
891
|
+
};
|
|
892
|
+
const themeSignal = signal(
|
|
893
|
+
typeof document !== "undefined" && document.documentElement.getAttribute("data-theme") || getSavedTheme() || "light"
|
|
894
|
+
);
|
|
895
|
+
const setTheme = (themeName) => {
|
|
896
|
+
if (!themeName) return;
|
|
897
|
+
if (typeof document !== "undefined") {
|
|
898
|
+
document.documentElement.setAttribute("data-theme", themeName);
|
|
899
|
+
}
|
|
900
|
+
if (themeSignal && themeSignal.value !== themeName) {
|
|
901
|
+
themeSignal.value = themeName;
|
|
902
|
+
}
|
|
903
|
+
try {
|
|
904
|
+
if (typeof localStorage !== "undefined") {
|
|
905
|
+
localStorage.setItem("lightview-theme", themeName);
|
|
906
|
+
}
|
|
907
|
+
} catch (e) {
|
|
908
|
+
}
|
|
909
|
+
};
|
|
910
|
+
const registerThemeSheet = async (url) => {
|
|
911
|
+
try {
|
|
912
|
+
const response = await fetch(url);
|
|
913
|
+
if (!response.ok) throw new Error(`Failed to fetch theme CSS: ${response.status}`);
|
|
914
|
+
const cssText = await response.text();
|
|
915
|
+
const sheet = new CSSStyleSheet();
|
|
916
|
+
sheet.replaceSync(cssText);
|
|
917
|
+
componentConfig.themeStyleSheet = sheet;
|
|
918
|
+
} catch (e) {
|
|
919
|
+
console.error(`LightviewX: Failed to register theme stylesheet '${url}':`, e);
|
|
920
|
+
}
|
|
921
|
+
};
|
|
922
|
+
const initComponents = async (options = {}) => {
|
|
923
|
+
const { shadowDefault = true } = options;
|
|
924
|
+
componentConfig.shadowDefault = shadowDefault;
|
|
925
|
+
if (shadowDefault) {
|
|
926
|
+
try {
|
|
927
|
+
const response = await fetch(DAISYUI_CDN);
|
|
928
|
+
if (!response.ok) {
|
|
929
|
+
throw new Error(`Failed to fetch DaisyUI CSS: ${response.status}`);
|
|
930
|
+
}
|
|
931
|
+
const cssText = await response.text();
|
|
932
|
+
const sheet = new CSSStyleSheet();
|
|
933
|
+
sheet.replaceSync(cssText);
|
|
934
|
+
componentConfig.daisyStyleSheet = sheet;
|
|
935
|
+
} catch (e) {
|
|
936
|
+
console.error("LightviewX: Failed to preload DaisyUI stylesheet:", e);
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
componentConfig.initialized = true;
|
|
940
|
+
};
|
|
941
|
+
(async () => await initComponents())();
|
|
942
|
+
const getComponentStyleSheet = async (cssUrl) => {
|
|
943
|
+
if (componentConfig.componentStyleSheets.has(cssUrl)) {
|
|
944
|
+
return componentConfig.componentStyleSheets.get(cssUrl);
|
|
945
|
+
}
|
|
946
|
+
try {
|
|
947
|
+
const response = await fetch(cssUrl);
|
|
948
|
+
if (!response.ok) {
|
|
949
|
+
throw new Error(`Failed to fetch component CSS: ${response.status}`);
|
|
950
|
+
}
|
|
951
|
+
const cssText = await response.text();
|
|
952
|
+
const sheet = new CSSStyleSheet();
|
|
953
|
+
sheet.replaceSync(cssText);
|
|
954
|
+
componentConfig.componentStyleSheets.set(cssUrl, sheet);
|
|
955
|
+
return sheet;
|
|
956
|
+
} catch (e) {
|
|
957
|
+
console.error(`LightviewX: Failed to create stylesheet for ${cssUrl}:`, e);
|
|
958
|
+
return null;
|
|
959
|
+
}
|
|
960
|
+
};
|
|
961
|
+
const shouldUseShadow = (useShadowProp) => {
|
|
962
|
+
if (useShadowProp !== void 0) {
|
|
963
|
+
return useShadowProp;
|
|
964
|
+
}
|
|
965
|
+
return componentConfig.shadowDefault;
|
|
966
|
+
};
|
|
967
|
+
const getAdoptedStyleSheets = (componentCssUrl, requestedSheets = []) => {
|
|
968
|
+
const result = [];
|
|
969
|
+
if (componentConfig.daisyStyleSheet) {
|
|
970
|
+
result.push(componentConfig.daisyStyleSheet);
|
|
971
|
+
} else {
|
|
972
|
+
result.push(DAISYUI_CDN);
|
|
973
|
+
}
|
|
974
|
+
if (componentConfig.themeStyleSheet) {
|
|
975
|
+
result.push(componentConfig.themeStyleSheet);
|
|
976
|
+
}
|
|
977
|
+
if (componentCssUrl) {
|
|
978
|
+
const componentSheet = componentConfig.componentStyleSheets.get(componentCssUrl);
|
|
979
|
+
if (componentSheet) {
|
|
980
|
+
result.push(componentSheet);
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
if (Array.isArray(requestedSheets)) {
|
|
984
|
+
requestedSheets.forEach((url) => {
|
|
985
|
+
const sheet = componentConfig.customStyleSheets.get(url);
|
|
986
|
+
if (sheet) {
|
|
987
|
+
result.push(sheet);
|
|
988
|
+
} else {
|
|
989
|
+
registerStyleSheet(url);
|
|
990
|
+
result.push(url);
|
|
991
|
+
}
|
|
992
|
+
});
|
|
993
|
+
}
|
|
994
|
+
return result;
|
|
995
|
+
};
|
|
996
|
+
const preloadComponentCSS = async (cssUrl) => {
|
|
997
|
+
if (!componentConfig.componentStyleSheets.has(cssUrl)) {
|
|
998
|
+
await getComponentStyleSheet(cssUrl);
|
|
999
|
+
}
|
|
1000
|
+
};
|
|
1001
|
+
const compileTemplate = (code) => {
|
|
1002
|
+
try {
|
|
1003
|
+
const isSingle = code.trim().startsWith("${") && code.trim().endsWith("}") && !code.trim().includes("${", 2);
|
|
1004
|
+
const body = isSingle ? "return " + code.trim().slice(2, -1) : "return `" + code.replace(/\\/g, "\\\\").replace(/`/g, "\\`") + "`";
|
|
1005
|
+
return new Function("state", "signal", body);
|
|
1006
|
+
} catch (e) {
|
|
1007
|
+
return () => "";
|
|
1008
|
+
}
|
|
1009
|
+
};
|
|
1010
|
+
const processTemplateChild = (child, LV) => {
|
|
1011
|
+
if (typeof child === "string" && child.includes("${")) {
|
|
1012
|
+
const fn = compileTemplate(child);
|
|
1013
|
+
return () => fn(LV.state, LV.signal);
|
|
1014
|
+
}
|
|
1015
|
+
return child;
|
|
1016
|
+
};
|
|
1017
|
+
const transformTextNode = (node, isRaw, LV) => {
|
|
1018
|
+
const text = node.textContent;
|
|
1019
|
+
if (isRaw) return text;
|
|
1020
|
+
if (!text.trim() && !text.includes("${")) return null;
|
|
1021
|
+
if (text.includes("${")) {
|
|
1022
|
+
const fn = compileTemplate(text);
|
|
1023
|
+
return () => fn(LV.state, LV.signal);
|
|
1024
|
+
}
|
|
1025
|
+
return text;
|
|
1026
|
+
};
|
|
1027
|
+
const transformElementNode = (node, element2, domToElements2) => {
|
|
1028
|
+
const tagName = node.tagName.toLowerCase();
|
|
1029
|
+
const attributes = {};
|
|
1030
|
+
const skip = tagName === "script" || tagName === "style";
|
|
1031
|
+
const LV = typeof window !== "undefined" ? globalThis.Lightview : typeof globalThis !== "undefined" ? globalThis.Lightview : null;
|
|
1032
|
+
for (let attr of node.attributes) {
|
|
1033
|
+
const val = attr.value;
|
|
1034
|
+
attributes[attr.name] = !skip && val.includes("${") ? (() => {
|
|
1035
|
+
const fn = compileTemplate(val);
|
|
1036
|
+
return () => fn(LV.state, LV.signal);
|
|
1037
|
+
})() : val;
|
|
1038
|
+
}
|
|
1039
|
+
return element2(tagName, attributes, domToElements2(Array.from(node.childNodes), element2, tagName));
|
|
1040
|
+
};
|
|
1041
|
+
const domToElements = (domNodes, element2, parentTagName = null) => {
|
|
1042
|
+
const isRaw = parentTagName === "script" || parentTagName === "style";
|
|
1043
|
+
const LV = globalThis.Lightview;
|
|
1044
|
+
return domNodes.map((node) => {
|
|
1045
|
+
if (node.nodeType === Node.TEXT_NODE) return transformTextNode(node, isRaw, LV);
|
|
1046
|
+
if (node.nodeType === Node.ELEMENT_NODE) return transformElementNode(node, element2, domToElements);
|
|
1047
|
+
return null;
|
|
1048
|
+
}).filter((n) => n !== null);
|
|
1049
|
+
};
|
|
1050
|
+
const insertedContentMap = /* @__PURE__ */ new WeakMap();
|
|
1051
|
+
const hashContent = (str) => {
|
|
1052
|
+
let hash = 0;
|
|
1053
|
+
for (let i = 0; i < str.length; i++) {
|
|
1054
|
+
const char = str.charCodeAt(i);
|
|
1055
|
+
hash = (hash << 5) - hash + char;
|
|
1056
|
+
hash = hash & hash;
|
|
1057
|
+
}
|
|
1058
|
+
return hash.toString(36);
|
|
1059
|
+
};
|
|
1060
|
+
const createMarker = (id, isEnd = false) => {
|
|
1061
|
+
return document.createComment(`lv-src-${isEnd ? "end" : "start"}:${id}`);
|
|
1062
|
+
};
|
|
1063
|
+
const executeScripts = (container) => {
|
|
1064
|
+
if (!container) return;
|
|
1065
|
+
const scripts = container.querySelectorAll("script");
|
|
1066
|
+
scripts.forEach((oldScript) => {
|
|
1067
|
+
const newScript = document.createElement("script");
|
|
1068
|
+
Array.from(oldScript.attributes).forEach((attr) => {
|
|
1069
|
+
newScript.setAttribute(attr.name, attr.value);
|
|
1070
|
+
});
|
|
1071
|
+
if (oldScript.src) {
|
|
1072
|
+
newScript.src = oldScript.src;
|
|
1073
|
+
} else {
|
|
1074
|
+
newScript.textContent = oldScript.textContent;
|
|
1075
|
+
}
|
|
1076
|
+
oldScript.parentNode.replaceChild(newScript, oldScript);
|
|
1077
|
+
});
|
|
1078
|
+
};
|
|
1079
|
+
const removeInsertedContent = (parentEl, markerId) => {
|
|
1080
|
+
const startMarker = `lv-src-start:${markerId}`;
|
|
1081
|
+
const endMarker = `lv-src-end:${markerId}`;
|
|
1082
|
+
let inRange = false;
|
|
1083
|
+
const nodesToRemove = [];
|
|
1084
|
+
const walker = document.createTreeWalker(
|
|
1085
|
+
parentEl.parentElement || parentEl,
|
|
1086
|
+
NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT,
|
|
1087
|
+
null,
|
|
1088
|
+
false
|
|
1089
|
+
);
|
|
1090
|
+
while (walker.nextNode()) {
|
|
1091
|
+
const node = walker.currentNode;
|
|
1092
|
+
if (node.nodeType === Node.COMMENT_NODE) {
|
|
1093
|
+
if (node.textContent === startMarker) {
|
|
1094
|
+
inRange = true;
|
|
1095
|
+
nodesToRemove.push(node);
|
|
1096
|
+
continue;
|
|
1097
|
+
}
|
|
1098
|
+
if (node.textContent === endMarker) {
|
|
1099
|
+
nodesToRemove.push(node);
|
|
1100
|
+
break;
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
if (inRange) {
|
|
1104
|
+
nodesToRemove.push(node);
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
nodesToRemove.forEach((node) => node.remove());
|
|
1108
|
+
return nodesToRemove.length > 0;
|
|
1109
|
+
};
|
|
1110
|
+
const insert = (elements, parent, location, markerId, { element: element2, setupChildren: setupChildren2 }) => {
|
|
1111
|
+
const isSibling = location === "beforebegin" || location === "afterend";
|
|
1112
|
+
const isOuter = location === "outerhtml";
|
|
1113
|
+
const target = isSibling || isOuter ? parent.parentElement : parent;
|
|
1114
|
+
if (!target) return console.warn(`LightviewX: No parent for ${location}`);
|
|
1115
|
+
const frag = document.createDocumentFragment();
|
|
1116
|
+
frag.appendChild(createMarker(markerId, false));
|
|
1117
|
+
elements.forEach((c) => {
|
|
1118
|
+
var _a, _b, _c;
|
|
1119
|
+
if (typeof c === "string") frag.appendChild(document.createTextNode(c));
|
|
1120
|
+
else if (c.domEl) frag.appendChild(c.domEl);
|
|
1121
|
+
else if (c instanceof Node) frag.appendChild(c);
|
|
1122
|
+
else {
|
|
1123
|
+
const v = ((_c = (_a = globalThis.Lightview) == null ? void 0 : (_b = _a.hooks).processChild) == null ? void 0 : _c.call(_b, c)) || c;
|
|
1124
|
+
if (v.tag) {
|
|
1125
|
+
const n = element2(v.tag, v.attributes || {}, v.children || []);
|
|
1126
|
+
if (n == null ? void 0 : n.domEl) frag.appendChild(n.domEl);
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
});
|
|
1130
|
+
frag.appendChild(createMarker(markerId, true));
|
|
1131
|
+
if (isOuter) target.replaceChild(frag, parent);
|
|
1132
|
+
else if (location === "beforebegin") target.insertBefore(frag, parent);
|
|
1133
|
+
else if (location === "afterend") target.insertBefore(frag, parent.nextSibling);
|
|
1134
|
+
else if (location === "afterbegin") parent.insertBefore(frag, parent.firstChild);
|
|
1135
|
+
else if (location === "beforeend") parent.appendChild(frag);
|
|
1136
|
+
executeScripts(target);
|
|
1137
|
+
};
|
|
1138
|
+
const isPath = (s) => typeof s === "string" && !isDangerousProtocol(s) && /^(https?:|\.|\/|[\w])|(\.(html|json|[vo]dom|cdomc?))$/i.test(s);
|
|
1139
|
+
const fetchContent = async (src) => {
|
|
1140
|
+
var _a;
|
|
1141
|
+
try {
|
|
1142
|
+
const LV = globalThis.Lightview;
|
|
1143
|
+
if (((_a = LV == null ? void 0 : LV.hooks) == null ? void 0 : _a.validateUrl) && !LV.hooks.validateUrl(src)) {
|
|
1144
|
+
console.warn(`[LightviewX] Fetch blocked by validateUrl hook: ${src}`);
|
|
1145
|
+
return null;
|
|
1146
|
+
}
|
|
1147
|
+
const url = new URL(src, document.baseURI);
|
|
1148
|
+
const res = await fetch(url);
|
|
1149
|
+
if (!res.ok) return null;
|
|
1150
|
+
const ext = url.pathname.split(".").pop().toLowerCase();
|
|
1151
|
+
const isJson = ext === "vdom" || ext === "odom" || ext === "cdom";
|
|
1152
|
+
const isHtml = ext === "html";
|
|
1153
|
+
const isCdom = ext === "cdom" || ext === "cdomc";
|
|
1154
|
+
const content = isJson ? await res.json() : await res.text();
|
|
1155
|
+
return {
|
|
1156
|
+
content,
|
|
1157
|
+
isJson,
|
|
1158
|
+
isHtml,
|
|
1159
|
+
isCdom,
|
|
1160
|
+
ext,
|
|
1161
|
+
raw: isJson ? JSON.stringify(content) : content
|
|
1162
|
+
};
|
|
1163
|
+
} catch (e) {
|
|
1164
|
+
return null;
|
|
1165
|
+
}
|
|
1166
|
+
};
|
|
1167
|
+
const parseElements = (content, isJson, isHtml, el, element2, isCdom = false, ext = "") => {
|
|
1168
|
+
var _a;
|
|
1169
|
+
if (isJson) return Array.isArray(content) ? content : [content];
|
|
1170
|
+
if (isCdom && ext === "cdomc") {
|
|
1171
|
+
const parser = (_a = globalThis.LightviewCDOM) == null ? void 0 : _a.parseCDOMC;
|
|
1172
|
+
if (parser) {
|
|
1173
|
+
try {
|
|
1174
|
+
const obj = parser(content);
|
|
1175
|
+
return Array.isArray(obj) ? obj : [obj];
|
|
1176
|
+
} catch (e) {
|
|
1177
|
+
console.warn("LightviewX: Failed to parse .cdomc:", e);
|
|
1178
|
+
return [];
|
|
1179
|
+
}
|
|
1180
|
+
} else {
|
|
1181
|
+
console.warn("LightviewX: CDOMC parser not found. Ensure lightview-cdom.js is loaded.");
|
|
1182
|
+
return [];
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
if (isHtml) {
|
|
1186
|
+
if (el.domEl.getAttribute("escape") === "true") return [content];
|
|
1187
|
+
const doc = new DOMParser().parseFromString(content.replace(/<head[^>]*>[\s\S]*?<\/head>/i, ""), "text/html");
|
|
1188
|
+
return domToElements([...Array.from(doc.head.childNodes), ...Array.from(doc.body.childNodes)], element2);
|
|
1189
|
+
}
|
|
1190
|
+
return [content];
|
|
1191
|
+
};
|
|
1192
|
+
const elementsFromSelector = (selector, element2) => {
|
|
1193
|
+
try {
|
|
1194
|
+
const sel = document.querySelectorAll(selector);
|
|
1195
|
+
if (!sel.length) return null;
|
|
1196
|
+
return {
|
|
1197
|
+
elements: domToElements(Array.from(sel), element2),
|
|
1198
|
+
raw: Array.from(sel).map((n) => n.outerHTML || n.textContent).join("")
|
|
1199
|
+
};
|
|
1200
|
+
} catch (e) {
|
|
1201
|
+
return null;
|
|
1202
|
+
}
|
|
1203
|
+
};
|
|
1204
|
+
const updateTargetContent = (el, elements, raw, loc, contentHash, { element: element2, setupChildren: setupChildren2 }, targetHash = null) => {
|
|
1205
|
+
const markerId = `${loc}-${contentHash.slice(0, 8)}`;
|
|
1206
|
+
let track = getOrSet(insertedContentMap, el.domEl, () => ({}));
|
|
1207
|
+
if (track[loc]) removeInsertedContent(el.domEl, `${loc}-${track[loc].slice(0, 8)}`);
|
|
1208
|
+
track[loc] = contentHash;
|
|
1209
|
+
const performScroll = (root) => {
|
|
1210
|
+
if (!targetHash) return;
|
|
1211
|
+
requestAnimationFrame(() => {
|
|
1212
|
+
requestAnimationFrame(() => {
|
|
1213
|
+
const id = targetHash.startsWith("#") ? targetHash.slice(1) : targetHash;
|
|
1214
|
+
const target = root.getElementById ? root.getElementById(id) : root.querySelector(`#${id}`);
|
|
1215
|
+
if (target) {
|
|
1216
|
+
target.style.scrollMarginTop = "calc(var(--site-nav-height, 0px) + 2rem)";
|
|
1217
|
+
target.scrollIntoView({ behavior: "smooth", block: "start", inline: "start" });
|
|
1218
|
+
}
|
|
1219
|
+
});
|
|
1220
|
+
});
|
|
1221
|
+
};
|
|
1222
|
+
if (loc === "shadow") {
|
|
1223
|
+
if (!el.domEl.shadowRoot) el.domEl.attachShadow({ mode: "open" });
|
|
1224
|
+
setupChildren2(elements, el.domEl.shadowRoot);
|
|
1225
|
+
executeScripts(el.domEl.shadowRoot);
|
|
1226
|
+
performScroll(el.domEl.shadowRoot);
|
|
1227
|
+
} else if (loc === "innerhtml") {
|
|
1228
|
+
el.children = elements;
|
|
1229
|
+
executeScripts(el.domEl);
|
|
1230
|
+
performScroll(document);
|
|
1231
|
+
} else {
|
|
1232
|
+
insert(elements, el.domEl, loc, markerId, { element: element2, setupChildren: setupChildren2 });
|
|
1233
|
+
performScroll(document);
|
|
1234
|
+
}
|
|
1235
|
+
};
|
|
1236
|
+
const handleSrcAttribute = async (el, src, tagName, { element: element2, setupChildren: setupChildren2 }) => {
|
|
1237
|
+
if (STANDARD_SRC_TAGS.includes(tagName)) return;
|
|
1238
|
+
let elements = [], raw = "", targetHash = null;
|
|
1239
|
+
if (isPath(src)) {
|
|
1240
|
+
if (src.includes("#")) {
|
|
1241
|
+
[src, targetHash] = src.split("#");
|
|
1242
|
+
}
|
|
1243
|
+
const result = await fetchContent(src);
|
|
1244
|
+
if (result) {
|
|
1245
|
+
elements = parseElements(result.content, result.isJson, result.isHtml, el, element2, result.isCdom, result.ext);
|
|
1246
|
+
raw = result.raw;
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
if (!elements.length) {
|
|
1250
|
+
const result = elementsFromSelector(src, element2);
|
|
1251
|
+
if (result) {
|
|
1252
|
+
elements = result.elements;
|
|
1253
|
+
raw = result.raw;
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
if (!elements.length) return;
|
|
1257
|
+
const loc = (el.domEl.getAttribute("location") || "innerhtml").toLowerCase();
|
|
1258
|
+
const contentHash = hashContent(raw);
|
|
1259
|
+
const track = getOrSet(insertedContentMap, el.domEl, () => ({}));
|
|
1260
|
+
if (track[loc] === contentHash) {
|
|
1261
|
+
if (targetHash) {
|
|
1262
|
+
const root = loc === "shadow" ? el.domEl.shadowRoot : document;
|
|
1263
|
+
if (root) {
|
|
1264
|
+
requestAnimationFrame(() => {
|
|
1265
|
+
requestAnimationFrame(() => {
|
|
1266
|
+
var _a;
|
|
1267
|
+
const id = targetHash.startsWith("#") ? targetHash.slice(1) : targetHash;
|
|
1268
|
+
const target = root.getElementById ? root.getElementById(id) : (_a = root.querySelector) == null ? void 0 : _a.call(root, `#${id}`);
|
|
1269
|
+
if (target) {
|
|
1270
|
+
target.style.scrollMarginTop = "calc(var(--site-nav-height, 0px) + 2rem)";
|
|
1271
|
+
target.scrollIntoView({ behavior: "smooth", block: "start", inline: "start" });
|
|
1272
|
+
}
|
|
1273
|
+
});
|
|
1274
|
+
});
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
return;
|
|
1278
|
+
}
|
|
1279
|
+
updateTargetContent(el, elements, raw, loc, contentHash, { element: element2, setupChildren: setupChildren2 }, targetHash);
|
|
1280
|
+
};
|
|
1281
|
+
const VALID_LOCATIONS = ["beforebegin", "afterbegin", "beforeend", "afterend", "innerhtml", "outerhtml", "shadow"];
|
|
1282
|
+
const parseTargetWithLocation = (targetStr) => {
|
|
1283
|
+
for (const loc of VALID_LOCATIONS) {
|
|
1284
|
+
const suffix = ":" + loc;
|
|
1285
|
+
if (targetStr.toLowerCase().endsWith(suffix)) {
|
|
1286
|
+
return {
|
|
1287
|
+
selector: targetStr.slice(0, -suffix.length),
|
|
1288
|
+
location: loc
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
return { selector: targetStr, location: null };
|
|
1293
|
+
};
|
|
1294
|
+
const handleNonStandardHref = (e, { domToElement: domToElement2, wrapDomElement: wrapDomElement2 }) => {
|
|
1295
|
+
var _a;
|
|
1296
|
+
const clickedEl = e.target.closest("[href]");
|
|
1297
|
+
if (!clickedEl) return;
|
|
1298
|
+
const tagName = clickedEl.tagName.toLowerCase();
|
|
1299
|
+
if (STANDARD_HREF_TAGS.includes(tagName)) return;
|
|
1300
|
+
e.preventDefault();
|
|
1301
|
+
const href = clickedEl.getAttribute("href");
|
|
1302
|
+
const LV = globalThis.Lightview;
|
|
1303
|
+
if (href && (isDangerousProtocol(href) || ((_a = LV == null ? void 0 : LV.hooks) == null ? void 0 : _a.validateUrl) && !LV.hooks.validateUrl(href))) {
|
|
1304
|
+
console.warn(`[LightviewX] Navigation or fetch blocked by security policy: ${href}`);
|
|
1305
|
+
return;
|
|
1306
|
+
}
|
|
1307
|
+
const targetAttr = clickedEl.getAttribute("target");
|
|
1308
|
+
if (!targetAttr) {
|
|
1309
|
+
let el = domToElement2.get(clickedEl);
|
|
1310
|
+
if (!el) {
|
|
1311
|
+
const attrs = {};
|
|
1312
|
+
for (let attr of clickedEl.attributes) attrs[attr.name] = attr.value;
|
|
1313
|
+
el = wrapDomElement2(clickedEl, tagName, attrs);
|
|
1314
|
+
}
|
|
1315
|
+
const newAttrs = { ...el.attributes, src: href };
|
|
1316
|
+
el.attributes = newAttrs;
|
|
1317
|
+
return;
|
|
1318
|
+
}
|
|
1319
|
+
if (targetAttr.startsWith("_")) {
|
|
1320
|
+
switch (targetAttr) {
|
|
1321
|
+
case "_self":
|
|
1322
|
+
globalThis.location.href = href;
|
|
1323
|
+
break;
|
|
1324
|
+
case "_parent":
|
|
1325
|
+
globalThis.parent.location.href = href;
|
|
1326
|
+
break;
|
|
1327
|
+
case "_top":
|
|
1328
|
+
globalThis.top.location.href = href;
|
|
1329
|
+
break;
|
|
1330
|
+
case "_blank":
|
|
1331
|
+
default:
|
|
1332
|
+
globalThis.open(href, targetAttr);
|
|
1333
|
+
break;
|
|
1334
|
+
}
|
|
1335
|
+
return;
|
|
1336
|
+
}
|
|
1337
|
+
const { selector, location } = parseTargetWithLocation(targetAttr);
|
|
1338
|
+
try {
|
|
1339
|
+
const targetElements = document.querySelectorAll(selector);
|
|
1340
|
+
targetElements.forEach((targetEl) => {
|
|
1341
|
+
let el = domToElement2.get(targetEl);
|
|
1342
|
+
if (!el) {
|
|
1343
|
+
const attrs = {};
|
|
1344
|
+
for (let attr of targetEl.attributes) attrs[attr.name] = attr.value;
|
|
1345
|
+
el = wrapDomElement2(targetEl, targetEl.tagName.toLowerCase(), attrs);
|
|
1346
|
+
}
|
|
1347
|
+
const newAttrs = { ...el.attributes, src: href };
|
|
1348
|
+
if (location) {
|
|
1349
|
+
newAttrs.location = location;
|
|
1350
|
+
}
|
|
1351
|
+
el.attributes = newAttrs;
|
|
1352
|
+
});
|
|
1353
|
+
} catch (err) {
|
|
1354
|
+
console.warn("Invalid target selector:", selector, err);
|
|
1355
|
+
}
|
|
1356
|
+
};
|
|
1357
|
+
const gateStates = /* @__PURE__ */ new WeakMap();
|
|
1358
|
+
const BYPASS_FLAG = "__lv_passed";
|
|
1359
|
+
const RESUME_FLAG = "__lv_resume";
|
|
1360
|
+
const SENSIBLE_EVENTS = [
|
|
1361
|
+
"click",
|
|
1362
|
+
"dblclick",
|
|
1363
|
+
"mousedown",
|
|
1364
|
+
"mouseup",
|
|
1365
|
+
"contextmenu",
|
|
1366
|
+
"submit",
|
|
1367
|
+
"reset",
|
|
1368
|
+
"change",
|
|
1369
|
+
"input",
|
|
1370
|
+
"invalid",
|
|
1371
|
+
"keydown",
|
|
1372
|
+
"keyup",
|
|
1373
|
+
"keypress",
|
|
1374
|
+
"touchstart",
|
|
1375
|
+
"touchend"
|
|
1376
|
+
];
|
|
1377
|
+
const CAPTURE_EVENTS = ["focus", "blur"];
|
|
1378
|
+
const getGateState = (el, key) => {
|
|
1379
|
+
let elState = gateStates.get(el);
|
|
1380
|
+
if (!elState) {
|
|
1381
|
+
elState = /* @__PURE__ */ new Map();
|
|
1382
|
+
gateStates.set(el, elState);
|
|
1383
|
+
}
|
|
1384
|
+
let state2 = elState.get(key);
|
|
1385
|
+
if (!state2) {
|
|
1386
|
+
state2 = {};
|
|
1387
|
+
elState.set(key, state2);
|
|
1388
|
+
}
|
|
1389
|
+
return state2;
|
|
1390
|
+
};
|
|
1391
|
+
const gateThrottle = function(ms) {
|
|
1392
|
+
const event = arguments[arguments.length - 1];
|
|
1393
|
+
if (event == null ? void 0 : event[RESUME_FLAG]) return true;
|
|
1394
|
+
const key = `throttle-${(event == null ? void 0 : event.type) || "all"}-${ms}`;
|
|
1395
|
+
const state2 = getGateState(this, key);
|
|
1396
|
+
const now2 = Date.now();
|
|
1397
|
+
if (now2 - (state2.last || 0) >= ms) {
|
|
1398
|
+
state2.last = now2;
|
|
1399
|
+
return true;
|
|
1400
|
+
}
|
|
1401
|
+
return false;
|
|
1402
|
+
};
|
|
1403
|
+
const gateDebounce = function(ms) {
|
|
1404
|
+
const event = arguments[arguments.length - 1];
|
|
1405
|
+
const key = `debounce-${(event == null ? void 0 : event.type) || "all"}-${ms}`;
|
|
1406
|
+
const state2 = getGateState(this, key);
|
|
1407
|
+
if (state2.timer) clearTimeout(state2.timer);
|
|
1408
|
+
if ((event == null ? void 0 : event[RESUME_FLAG]) && state2.passed) {
|
|
1409
|
+
state2.passed = false;
|
|
1410
|
+
return true;
|
|
1411
|
+
}
|
|
1412
|
+
state2.timer = setTimeout(() => {
|
|
1413
|
+
state2.passed = true;
|
|
1414
|
+
const newEvent = new event.constructor(event.type, event);
|
|
1415
|
+
newEvent[RESUME_FLAG] = true;
|
|
1416
|
+
this.dispatchEvent(newEvent);
|
|
1417
|
+
}, ms);
|
|
1418
|
+
return false;
|
|
1419
|
+
};
|
|
1420
|
+
const parseBeforeAttribute = (attrValue) => {
|
|
1421
|
+
const tokens = [];
|
|
1422
|
+
let current = "", depth = 0, inQuote = null;
|
|
1423
|
+
for (let i2 = 0; i2 < attrValue.length; i2++) {
|
|
1424
|
+
const char = attrValue[i2];
|
|
1425
|
+
if (inQuote) {
|
|
1426
|
+
current += char;
|
|
1427
|
+
if (char === inQuote && attrValue[i2 - 1] !== "\\") inQuote = null;
|
|
1428
|
+
} else if (char === "'" || char === '"') {
|
|
1429
|
+
inQuote = char;
|
|
1430
|
+
current += char;
|
|
1431
|
+
} else if (char === "(") {
|
|
1432
|
+
depth++;
|
|
1433
|
+
current += char;
|
|
1434
|
+
} else if (char === ")") {
|
|
1435
|
+
depth--;
|
|
1436
|
+
current += char;
|
|
1437
|
+
} else if (/\s/.test(char) && depth === 0) {
|
|
1438
|
+
if (current) tokens.push(current);
|
|
1439
|
+
current = "";
|
|
1440
|
+
} else {
|
|
1441
|
+
current += char;
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
if (current) tokens.push(current);
|
|
1445
|
+
const events = [];
|
|
1446
|
+
const exclusions = [];
|
|
1447
|
+
const calls = [];
|
|
1448
|
+
let i = 0;
|
|
1449
|
+
while (i < tokens.length) {
|
|
1450
|
+
const token = tokens[i];
|
|
1451
|
+
if (!token || token.includes("(")) break;
|
|
1452
|
+
if (token.startsWith("!")) exclusions.push(token.slice(1));
|
|
1453
|
+
else events.push(token);
|
|
1454
|
+
i++;
|
|
1455
|
+
}
|
|
1456
|
+
while (i < tokens.length) {
|
|
1457
|
+
if (tokens[i]) calls.push(tokens[i]);
|
|
1458
|
+
i++;
|
|
1459
|
+
}
|
|
1460
|
+
return { events, exclusions, calls };
|
|
1461
|
+
};
|
|
1462
|
+
const globalBeforeInterceptor = async (e) => {
|
|
1463
|
+
var _a, _b;
|
|
1464
|
+
if (e[BYPASS_FLAG]) return;
|
|
1465
|
+
const target = (_b = (_a = e.target).closest) == null ? void 0 : _b.call(_a, "[lv-before]");
|
|
1466
|
+
if (!target) return;
|
|
1467
|
+
const { events, exclusions, calls } = parseBeforeAttribute(target.getAttribute("lv-before"));
|
|
1468
|
+
const isExcluded = exclusions.includes(e.type);
|
|
1469
|
+
const isIncluded = events.includes("*") || events.includes(e.type);
|
|
1470
|
+
if (isExcluded || !isIncluded) return;
|
|
1471
|
+
e.stopImmediatePropagation();
|
|
1472
|
+
e.preventDefault();
|
|
1473
|
+
for (const callStr of calls) {
|
|
1474
|
+
try {
|
|
1475
|
+
const match2 = callStr.match(/^([\w\.]+)\((.*)\)$/);
|
|
1476
|
+
if (!match2) continue;
|
|
1477
|
+
const funcName = match2[1];
|
|
1478
|
+
const argsStr = match2[2];
|
|
1479
|
+
const LV = globalThis.Lightview;
|
|
1480
|
+
const LVX = globalThis.LightviewX;
|
|
1481
|
+
let fn = funcName.split(".").reduce((obj, key) => obj == null ? void 0 : obj[key], globalThis);
|
|
1482
|
+
if (!fn && funcName === "throttle") fn = gateThrottle;
|
|
1483
|
+
if (!fn && funcName === "debounce") fn = gateDebounce;
|
|
1484
|
+
if (!fn && LVX && LVX[funcName]) fn = LVX[funcName];
|
|
1485
|
+
if (typeof fn !== "function") {
|
|
1486
|
+
console.warn(`LightviewX: lv-before function '${funcName}' not found`);
|
|
1487
|
+
continue;
|
|
1488
|
+
}
|
|
1489
|
+
const evalArgs = new Function("event", "state", "signal", `return [${argsStr}]`);
|
|
1490
|
+
const args = evalArgs.call(target, e, (LV == null ? void 0 : LV.state) || {}, (LV == null ? void 0 : LV.signal) || {});
|
|
1491
|
+
args.push(e);
|
|
1492
|
+
let result = fn.apply(target, args);
|
|
1493
|
+
if (result instanceof Promise) result = await result;
|
|
1494
|
+
if (result === false || result === null || result === void 0) return;
|
|
1495
|
+
} catch (err) {
|
|
1496
|
+
console.error(`LightviewX: Error executing lv-before gate '${callStr}':`, err);
|
|
1497
|
+
return;
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
const finalEvent = new e.constructor(e.type, e);
|
|
1501
|
+
finalEvent[BYPASS_FLAG] = true;
|
|
1502
|
+
target.dispatchEvent(finalEvent);
|
|
1503
|
+
};
|
|
1504
|
+
const processSrcOnNode = (node, LV) => {
|
|
1505
|
+
if (node.nodeType !== Node.ELEMENT_NODE) return;
|
|
1506
|
+
const tagName = node.tagName.toLowerCase();
|
|
1507
|
+
if (isStandardSrcTag(tagName)) return;
|
|
1508
|
+
const src = node.getAttribute("src");
|
|
1509
|
+
if (!src) return;
|
|
1510
|
+
let el = LV.internals.domToElement.get(node);
|
|
1511
|
+
if (!el) {
|
|
1512
|
+
const attrs = {};
|
|
1513
|
+
for (let attr of node.attributes) attrs[attr.name] = attr.value;
|
|
1514
|
+
el = LV.internals.wrapDomElement(node, tagName, attrs, []);
|
|
1515
|
+
}
|
|
1516
|
+
handleSrcAttribute(el, src, tagName, {
|
|
1517
|
+
element: LV.element,
|
|
1518
|
+
setupChildren: LV.internals.setupChildren
|
|
1519
|
+
});
|
|
1520
|
+
};
|
|
1521
|
+
const processedNodes = /* @__PURE__ */ new WeakSet();
|
|
1522
|
+
const activateReactiveSyntax = (root, LV) => {
|
|
1523
|
+
if (!root || !LV) return;
|
|
1524
|
+
const bindEffect = (node, codeStr, isAttr = false, attrName = null) => {
|
|
1525
|
+
if (processedNodes.has(node) && !isAttr) return;
|
|
1526
|
+
if (!isAttr) processedNodes.add(node);
|
|
1527
|
+
const fn = compileTemplate(codeStr);
|
|
1528
|
+
LV.effect(() => {
|
|
1529
|
+
try {
|
|
1530
|
+
const val = fn(LV.state, LV.signal);
|
|
1531
|
+
if (isAttr) {
|
|
1532
|
+
if (attrName.startsWith("cdom-")) {
|
|
1533
|
+
node[attrName] = val;
|
|
1534
|
+
} else {
|
|
1535
|
+
val === null || val === void 0 || val === false ? node.removeAttribute(attrName) : node.setAttribute(attrName, val);
|
|
1536
|
+
}
|
|
1537
|
+
} else node.textContent = val !== void 0 ? val : "";
|
|
1538
|
+
} catch (e) {
|
|
1539
|
+
}
|
|
1540
|
+
});
|
|
1541
|
+
};
|
|
1542
|
+
const textXPath = ".//text()[contains(., '${')]";
|
|
1543
|
+
const textResult = document.evaluate(
|
|
1544
|
+
textXPath,
|
|
1545
|
+
root,
|
|
1546
|
+
null,
|
|
1547
|
+
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
|
|
1548
|
+
null
|
|
1549
|
+
);
|
|
1550
|
+
for (let i = 0; i < textResult.snapshotLength; i++) {
|
|
1551
|
+
const node = textResult.snapshotItem(i);
|
|
1552
|
+
if (node.parentElement && node.parentElement.closest("SCRIPT, STYLE, CODE, PRE, TEMPLATE, NOSCRIPT")) continue;
|
|
1553
|
+
bindEffect(node, node.textContent);
|
|
1554
|
+
}
|
|
1555
|
+
const attrXPath = ".//*[@*[contains(., '${')]]";
|
|
1556
|
+
const attrResult = document.evaluate(
|
|
1557
|
+
attrXPath,
|
|
1558
|
+
root,
|
|
1559
|
+
null,
|
|
1560
|
+
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
|
|
1561
|
+
null
|
|
1562
|
+
);
|
|
1563
|
+
for (let i = 0; i < attrResult.snapshotLength; i++) {
|
|
1564
|
+
const element2 = attrResult.snapshotItem(i);
|
|
1565
|
+
if (["SCRIPT", "STYLE", "CODE", "PRE", "TEMPLATE", "NOSCRIPT"].includes(element2.tagName)) continue;
|
|
1566
|
+
Array.from(element2.attributes).forEach((attr) => {
|
|
1567
|
+
if (attr.value.includes("${")) {
|
|
1568
|
+
bindEffect(element2, attr.value, true, attr.name);
|
|
1569
|
+
}
|
|
1570
|
+
});
|
|
1571
|
+
}
|
|
1572
|
+
if (root.nodeType === Node.ELEMENT_NODE && !["SCRIPT", "STYLE", "CODE", "PRE", "TEMPLATE", "NOSCRIPT"].includes(root.tagName)) {
|
|
1573
|
+
Array.from(root.attributes).forEach((attr) => {
|
|
1574
|
+
if (attr.value.includes("${")) {
|
|
1575
|
+
bindEffect(root, attr.value, true, attr.name);
|
|
1576
|
+
}
|
|
1577
|
+
});
|
|
1578
|
+
}
|
|
1579
|
+
};
|
|
1580
|
+
const processAddedNode = (node, nodesToProcess, nodesToActivate) => {
|
|
1581
|
+
if (node.nodeType === Node.ELEMENT_NODE || node.nodeType === Node.TEXT_NODE) {
|
|
1582
|
+
nodesToActivate.push(node);
|
|
1583
|
+
}
|
|
1584
|
+
if (node.nodeType !== Node.ELEMENT_NODE) return;
|
|
1585
|
+
nodesToProcess.push(node);
|
|
1586
|
+
const selector = "[src]:not(" + STANDARD_SRC_TAGS.join("):not(") + ")";
|
|
1587
|
+
const descendants = node.querySelectorAll(selector);
|
|
1588
|
+
for (const desc of descendants) {
|
|
1589
|
+
if (!desc.tagName.toLowerCase().startsWith("lv-")) {
|
|
1590
|
+
nodesToProcess.push(desc);
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
};
|
|
1594
|
+
const collectNodesFromMutations = (mutations) => {
|
|
1595
|
+
const nodesToProcess = [];
|
|
1596
|
+
const nodesToActivate = [];
|
|
1597
|
+
for (const mutation of mutations) {
|
|
1598
|
+
if (mutation.type === "childList") {
|
|
1599
|
+
mutation.addedNodes.forEach((node) => processAddedNode(node, nodesToProcess, nodesToActivate));
|
|
1600
|
+
} else if (mutation.type === "attributes" && mutation.attributeName === "src") {
|
|
1601
|
+
nodesToProcess.push(mutation.target);
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
return { nodesToProcess, nodesToActivate };
|
|
1605
|
+
};
|
|
1606
|
+
const setupSrcObserver = (LV) => {
|
|
1607
|
+
const observer = new MutationObserver((mutations) => {
|
|
1608
|
+
const { nodesToProcess, nodesToActivate } = collectNodesFromMutations(mutations);
|
|
1609
|
+
if (nodesToProcess.length > 0 || nodesToActivate.length > 0) {
|
|
1610
|
+
requestAnimationFrame(() => {
|
|
1611
|
+
nodesToActivate.forEach((node) => activateReactiveSyntax(node, LV));
|
|
1612
|
+
nodesToProcess.forEach((node) => processSrcOnNode(node, LV));
|
|
1613
|
+
});
|
|
1614
|
+
}
|
|
1615
|
+
});
|
|
1616
|
+
observer.observe(document.body, {
|
|
1617
|
+
childList: true,
|
|
1618
|
+
subtree: true,
|
|
1619
|
+
attributes: true,
|
|
1620
|
+
attributeFilter: ["src"]
|
|
1621
|
+
});
|
|
1622
|
+
return observer;
|
|
1623
|
+
};
|
|
1624
|
+
if (typeof window !== "undefined" && globalThis.Lightview) {
|
|
1625
|
+
const LV = globalThis.Lightview;
|
|
1626
|
+
if (document.readyState === "loading") {
|
|
1627
|
+
document.addEventListener("DOMContentLoaded", () => setupSrcObserver(LV));
|
|
1628
|
+
} else {
|
|
1629
|
+
setupSrcObserver(LV);
|
|
1630
|
+
}
|
|
1631
|
+
const initialScan = () => {
|
|
1632
|
+
requestAnimationFrame(() => {
|
|
1633
|
+
activateReactiveSyntax(document.body, LV);
|
|
1634
|
+
const selector = "[src]:not(" + STANDARD_SRC_TAGS.join("):not(") + ")";
|
|
1635
|
+
const nodes = document.querySelectorAll(selector);
|
|
1636
|
+
nodes.forEach((node) => {
|
|
1637
|
+
if (node.tagName.toLowerCase().startsWith("lv-")) return;
|
|
1638
|
+
processSrcOnNode(node, LV);
|
|
1639
|
+
});
|
|
1640
|
+
});
|
|
1641
|
+
};
|
|
1642
|
+
if (document.body) {
|
|
1643
|
+
initialScan();
|
|
1644
|
+
} else {
|
|
1645
|
+
document.addEventListener("DOMContentLoaded", initialScan);
|
|
1646
|
+
}
|
|
1647
|
+
LV.hooks.onNonStandardHref = (e) => {
|
|
1648
|
+
handleNonStandardHref(e, {
|
|
1649
|
+
domToElement: LV.internals.domToElement,
|
|
1650
|
+
wrapDomElement: LV.internals.wrapDomElement
|
|
1651
|
+
});
|
|
1652
|
+
};
|
|
1653
|
+
SENSIBLE_EVENTS.forEach((ev) => window.addEventListener(ev, globalBeforeInterceptor, true));
|
|
1654
|
+
CAPTURE_EVENTS.forEach((ev) => window.addEventListener(ev, globalBeforeInterceptor, true));
|
|
1655
|
+
LV.hooks.processChild = (child) => {
|
|
1656
|
+
if (!child) return child;
|
|
1657
|
+
if (typeof child === "object" && !Array.isArray(child) && !child.tag && !child.domEl) {
|
|
1658
|
+
child = convertObjectDOM(child);
|
|
1659
|
+
}
|
|
1660
|
+
if (typeof child === "string" && child.startsWith("$") && isNaN(parseInt(child[1]))) {
|
|
1661
|
+
const CDOM = globalThis.LightviewCDOM;
|
|
1662
|
+
if (CDOM) return CDOM.parseExpression(child);
|
|
1663
|
+
}
|
|
1664
|
+
if (typeof child === "string" && (child.trim().startsWith("{") || child.trim().startsWith("["))) {
|
|
1665
|
+
try {
|
|
1666
|
+
const parsed = new Function("return (" + child + ")")();
|
|
1667
|
+
if (typeof parsed === "object" && parsed !== null) {
|
|
1668
|
+
if (Array.isArray(parsed)) {
|
|
1669
|
+
return parsed;
|
|
1670
|
+
}
|
|
1671
|
+
if (parsed.tag || parsed.domEl) {
|
|
1672
|
+
return parsed;
|
|
1673
|
+
}
|
|
1674
|
+
return convertObjectDOM(parsed);
|
|
1675
|
+
}
|
|
1676
|
+
} catch (e) {
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
return processTemplateChild(child, {
|
|
1680
|
+
state,
|
|
1681
|
+
signal: LV.signal
|
|
1682
|
+
});
|
|
1683
|
+
};
|
|
1684
|
+
}
|
|
1685
|
+
const createCustomElement = (Component, options = {}) => {
|
|
1686
|
+
return class extends HTMLElement {
|
|
1687
|
+
constructor() {
|
|
1688
|
+
super();
|
|
1689
|
+
this.attachShadow({ mode: "open" });
|
|
1690
|
+
}
|
|
1691
|
+
async connectedCallback() {
|
|
1692
|
+
const { cssUrl, styles } = options;
|
|
1693
|
+
this.themeWrapper = document.createElement("div");
|
|
1694
|
+
this.themeWrapper.style.display = "contents";
|
|
1695
|
+
const syncTheme = () => {
|
|
1696
|
+
const theme = document.documentElement.getAttribute("data-theme") || "light";
|
|
1697
|
+
this.themeWrapper.setAttribute("data-theme", theme);
|
|
1698
|
+
};
|
|
1699
|
+
syncTheme();
|
|
1700
|
+
this.themeObserver = new MutationObserver(syncTheme);
|
|
1701
|
+
this.themeObserver.observe(document.documentElement, {
|
|
1702
|
+
attributes: true,
|
|
1703
|
+
attributeFilter: ["data-theme"]
|
|
1704
|
+
});
|
|
1705
|
+
this.shadowRoot.appendChild(this.themeWrapper);
|
|
1706
|
+
const adoptedStyleSheets = getAdoptedStyleSheets(cssUrl, styles);
|
|
1707
|
+
try {
|
|
1708
|
+
const sheets = adoptedStyleSheets.filter((s) => s instanceof CSSStyleSheet);
|
|
1709
|
+
this.shadowRoot.adoptedStyleSheets = sheets;
|
|
1710
|
+
} catch (e) {
|
|
1711
|
+
}
|
|
1712
|
+
if (!componentConfig.daisyStyleSheet) {
|
|
1713
|
+
const link = document.createElement("link");
|
|
1714
|
+
link.rel = "stylesheet";
|
|
1715
|
+
link.href = DAISYUI_CDN;
|
|
1716
|
+
this.shadowRoot.appendChild(link);
|
|
1717
|
+
}
|
|
1718
|
+
adoptedStyleSheets.forEach((s) => {
|
|
1719
|
+
if (typeof s === "string") {
|
|
1720
|
+
const link = document.createElement("link");
|
|
1721
|
+
link.rel = "stylesheet";
|
|
1722
|
+
link.href = s;
|
|
1723
|
+
this.shadowRoot.appendChild(link);
|
|
1724
|
+
}
|
|
1725
|
+
});
|
|
1726
|
+
this.render = () => {
|
|
1727
|
+
const props = {};
|
|
1728
|
+
for (const attr of this.attributes) {
|
|
1729
|
+
const name = attr.name.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
|
|
1730
|
+
if (attr.value === "") {
|
|
1731
|
+
props[name] = true;
|
|
1732
|
+
} else {
|
|
1733
|
+
props[name] = attr.value;
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
props.useShadow = false;
|
|
1737
|
+
const slot = globalThis.Lightview.tags.slot();
|
|
1738
|
+
const result = Component(props, slot);
|
|
1739
|
+
globalThis.Lightview.internals.setupChildren([result], this.themeWrapper);
|
|
1740
|
+
};
|
|
1741
|
+
if (typeof MutationObserver !== "undefined" && typeof HTMLElement !== "undefined") {
|
|
1742
|
+
this.attrObserver = new MutationObserver((mutations) => {
|
|
1743
|
+
this.render();
|
|
1744
|
+
});
|
|
1745
|
+
this.attrObserver.observe(this, {
|
|
1746
|
+
attributes: true
|
|
1747
|
+
});
|
|
1748
|
+
}
|
|
1749
|
+
this.render();
|
|
1750
|
+
}
|
|
1751
|
+
disconnectedCallback() {
|
|
1752
|
+
if (this.themeObserver) {
|
|
1753
|
+
this.themeObserver.disconnect();
|
|
1754
|
+
}
|
|
1755
|
+
if (this.attrObserver) {
|
|
1756
|
+
this.attrObserver.disconnect();
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
};
|
|
1760
|
+
};
|
|
1761
|
+
const customElementWrapper = (Component, config = {}) => {
|
|
1762
|
+
const {
|
|
1763
|
+
attributeMap = {},
|
|
1764
|
+
childElements = {}
|
|
1765
|
+
} = config;
|
|
1766
|
+
return class extends HTMLElement {
|
|
1767
|
+
constructor() {
|
|
1768
|
+
super();
|
|
1769
|
+
this.attachShadow({ mode: "open" });
|
|
1770
|
+
}
|
|
1771
|
+
connectedCallback() {
|
|
1772
|
+
let adopted = false;
|
|
1773
|
+
if (componentConfig.daisyStyleSheet) {
|
|
1774
|
+
try {
|
|
1775
|
+
const sheets = [componentConfig.daisyStyleSheet];
|
|
1776
|
+
if (componentConfig.themeStyleSheet) {
|
|
1777
|
+
sheets.push(componentConfig.themeStyleSheet);
|
|
1778
|
+
}
|
|
1779
|
+
this.shadowRoot.adoptedStyleSheets = sheets;
|
|
1780
|
+
adopted = true;
|
|
1781
|
+
} catch (e) {
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
if (!adopted) {
|
|
1785
|
+
const link = document.createElement("link");
|
|
1786
|
+
link.rel = "stylesheet";
|
|
1787
|
+
link.href = DAISYUI_CDN;
|
|
1788
|
+
this.shadowRoot.appendChild(link);
|
|
1789
|
+
}
|
|
1790
|
+
const themeWrapper = document.createElement("div");
|
|
1791
|
+
themeWrapper.setAttribute("data-theme", document.documentElement.getAttribute("data-theme") || "light");
|
|
1792
|
+
themeWrapper.style.display = "contents";
|
|
1793
|
+
this.shadowRoot.appendChild(themeWrapper);
|
|
1794
|
+
this.themeWrapper = themeWrapper;
|
|
1795
|
+
this.themeObserver = new MutationObserver(() => {
|
|
1796
|
+
const theme = document.documentElement.getAttribute("data-theme") || "light";
|
|
1797
|
+
this.themeWrapper.setAttribute("data-theme", theme);
|
|
1798
|
+
});
|
|
1799
|
+
this.themeObserver.observe(document.documentElement, {
|
|
1800
|
+
attributes: true,
|
|
1801
|
+
attributeFilter: ["data-theme"]
|
|
1802
|
+
});
|
|
1803
|
+
this.render();
|
|
1804
|
+
const attrs = Object.keys(attributeMap);
|
|
1805
|
+
if (attrs.length > 0) {
|
|
1806
|
+
this.attrObserver = new MutationObserver(() => this.render());
|
|
1807
|
+
this.attrObserver.observe(this, {
|
|
1808
|
+
attributes: true,
|
|
1809
|
+
attributeFilter: attrs
|
|
1810
|
+
});
|
|
1811
|
+
}
|
|
1812
|
+
if (Object.keys(childElements).length > 0) {
|
|
1813
|
+
this.childObserver = new MutationObserver(() => this.render());
|
|
1814
|
+
this.childObserver.observe(this, {
|
|
1815
|
+
childList: true,
|
|
1816
|
+
subtree: true,
|
|
1817
|
+
attributes: true
|
|
1818
|
+
});
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
disconnectedCallback() {
|
|
1822
|
+
if (this.themeObserver) this.themeObserver.disconnect();
|
|
1823
|
+
if (this.attrObserver) this.attrObserver.disconnect();
|
|
1824
|
+
if (this.childObserver) this.childObserver.disconnect();
|
|
1825
|
+
}
|
|
1826
|
+
parseChildrenToVDOM() {
|
|
1827
|
+
return Array.from(this.children).map((child) => {
|
|
1828
|
+
const tagName = child.tagName.toLowerCase();
|
|
1829
|
+
const componentInfo = childElements[tagName];
|
|
1830
|
+
if (!componentInfo) return null;
|
|
1831
|
+
const { component, attributeMap: attributeMap2 = {} } = componentInfo;
|
|
1832
|
+
const attributes = {};
|
|
1833
|
+
for (const attr of child.attributes) {
|
|
1834
|
+
const name = attr.name.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
|
|
1835
|
+
const type = attributeMap2[name];
|
|
1836
|
+
const value = attr.value;
|
|
1837
|
+
if (type === Boolean) {
|
|
1838
|
+
attributes[name] = value === "true" || value === "";
|
|
1839
|
+
} else if (type === Number) {
|
|
1840
|
+
attributes[name] = Number(value);
|
|
1841
|
+
} else if (type === Array || type === Object) {
|
|
1842
|
+
try {
|
|
1843
|
+
attributes[name] = JSON.parse(value);
|
|
1844
|
+
} catch (e) {
|
|
1845
|
+
console.warn(`[Lightview] Failed to parse child attribute ${name} as JSON:`, value);
|
|
1846
|
+
attributes[name] = value;
|
|
1847
|
+
}
|
|
1848
|
+
} else {
|
|
1849
|
+
attributes[name] = value;
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1852
|
+
if (child.onclick) attributes.onclick = child.onclick.bind(child);
|
|
1853
|
+
return {
|
|
1854
|
+
tag: component,
|
|
1855
|
+
attributes,
|
|
1856
|
+
children: Array.from(child.childNodes)
|
|
1857
|
+
};
|
|
1858
|
+
}).filter(Boolean);
|
|
1859
|
+
}
|
|
1860
|
+
render() {
|
|
1861
|
+
var _a, _b;
|
|
1862
|
+
const props = { useShadow: false };
|
|
1863
|
+
for (const attr of this.attributes) {
|
|
1864
|
+
const name = attr.name.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
|
|
1865
|
+
const type = attributeMap[name];
|
|
1866
|
+
const value = attr.value;
|
|
1867
|
+
if (type === Boolean) {
|
|
1868
|
+
props[name] = value === "true" || value === "";
|
|
1869
|
+
} else if (type === Number) {
|
|
1870
|
+
props[name] = Number(value);
|
|
1871
|
+
} else if (type === Array || type === Object) {
|
|
1872
|
+
try {
|
|
1873
|
+
props[name] = JSON.parse(value);
|
|
1874
|
+
} catch (e) {
|
|
1875
|
+
console.warn(`[Lightview] Failed to parse ${name} as JSON:`, value);
|
|
1876
|
+
props[name] = value;
|
|
1877
|
+
}
|
|
1878
|
+
} else {
|
|
1879
|
+
props[name] = value;
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
const vdomChildren = this.parseChildrenToVDOM();
|
|
1883
|
+
const children = Object.keys(childElements).length > 0 ? vdomChildren : [{ tag: globalThis.Lightview.tags.slot }];
|
|
1884
|
+
const result = Component(props, ...children);
|
|
1885
|
+
if (((_b = (_a = globalThis.Lightview) == null ? void 0 : _a.internals) == null ? void 0 : _b.setupChildren) && this.themeWrapper) {
|
|
1886
|
+
this.themeWrapper.innerHTML = "";
|
|
1887
|
+
globalThis.Lightview.internals.setupChildren([result], this.themeWrapper);
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
static get observedAttributes() {
|
|
1891
|
+
return Object.keys(attributeMap);
|
|
1892
|
+
}
|
|
1893
|
+
attributeChangedCallback() {
|
|
1894
|
+
this.render();
|
|
1895
|
+
}
|
|
1896
|
+
};
|
|
1897
|
+
};
|
|
1898
|
+
const LightviewX = {
|
|
1899
|
+
state,
|
|
1900
|
+
themeSignal,
|
|
1901
|
+
setTheme,
|
|
1902
|
+
registerStyleSheet,
|
|
1903
|
+
registerThemeSheet,
|
|
1904
|
+
// Gate modifiers
|
|
1905
|
+
throttle: gateThrottle,
|
|
1906
|
+
debounce: gateDebounce,
|
|
1907
|
+
// Component initialization
|
|
1908
|
+
initComponents,
|
|
1909
|
+
componentConfig,
|
|
1910
|
+
shouldUseShadow,
|
|
1911
|
+
getAdoptedStyleSheets,
|
|
1912
|
+
preloadComponentCSS,
|
|
1913
|
+
createCustomElement,
|
|
1914
|
+
customElementWrapper,
|
|
1915
|
+
internals: {
|
|
1916
|
+
handleSrcAttribute,
|
|
1917
|
+
parseElements
|
|
1918
|
+
}
|
|
1919
|
+
};
|
|
1920
|
+
if (typeof module !== "undefined" && module.exports) {
|
|
1921
|
+
module.exports = LightviewX;
|
|
1922
|
+
}
|
|
1923
|
+
if (typeof window !== "undefined") {
|
|
1924
|
+
globalThis.LightviewX = LightviewX;
|
|
1925
|
+
}
|
|
1926
|
+
if (typeof window !== "undefined") {
|
|
1927
|
+
try {
|
|
1928
|
+
const savedTheme = getSavedTheme();
|
|
1929
|
+
if (savedTheme) {
|
|
1930
|
+
setTheme(savedTheme);
|
|
1931
|
+
}
|
|
1932
|
+
} catch (e) {
|
|
1933
|
+
}
|
|
1934
|
+
if (typeof window !== "undefined" && globalThis.Lightview) {
|
|
1935
|
+
if (!globalThis.Lightview.hooks.validateUrl) {
|
|
1936
|
+
globalThis.Lightview.hooks.validateUrl = validateUrl;
|
|
1937
|
+
}
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1940
|
+
if (typeof globalThis !== "undefined" && globalThis.Lightview) {
|
|
1941
|
+
if (!globalThis.Lightview.hooks.validateUrl) {
|
|
1942
|
+
globalThis.Lightview.hooks.validateUrl = validateUrl;
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
const helpers = /* @__PURE__ */ new Map();
|
|
1946
|
+
const helperOptions = /* @__PURE__ */ new Map();
|
|
1947
|
+
const operators = {
|
|
1948
|
+
prefix: /* @__PURE__ */ new Map(),
|
|
1949
|
+
// e.g., '++' -> { helper: 'increment', precedence: 70 }
|
|
1950
|
+
postfix: /* @__PURE__ */ new Map(),
|
|
1951
|
+
// e.g., '++' -> { helper: 'increment', precedence: 70 }
|
|
1952
|
+
infix: /* @__PURE__ */ new Map()
|
|
1953
|
+
// e.g., '+' -> { helper: 'add', precedence: 50 }
|
|
1954
|
+
};
|
|
1955
|
+
const DEFAULT_PRECEDENCE = {
|
|
1956
|
+
prefix: 80,
|
|
1957
|
+
postfix: 80,
|
|
1958
|
+
infix: 50
|
|
1959
|
+
};
|
|
1960
|
+
const registerHelper = (name, fn, options = {}) => {
|
|
1961
|
+
helpers.set(name, fn);
|
|
1962
|
+
if (options) helperOptions.set(name, options);
|
|
1963
|
+
};
|
|
1964
|
+
const registerOperator = (helperName, symbol, position, precedence) => {
|
|
1965
|
+
var _a;
|
|
1966
|
+
if (!["prefix", "postfix", "infix"].includes(position)) {
|
|
1967
|
+
throw new Error(`Invalid operator position: ${position}. Must be 'prefix', 'postfix', or 'infix'.`);
|
|
1968
|
+
}
|
|
1969
|
+
if (!helpers.has(helperName)) {
|
|
1970
|
+
(_a = globalThis.console) == null ? void 0 : _a.warn(`LightviewCDOM: Operator "${symbol}" registered for helper "${helperName}" which is not yet registered.`);
|
|
1971
|
+
}
|
|
1972
|
+
const prec = precedence ?? DEFAULT_PRECEDENCE[position];
|
|
1973
|
+
operators[position].set(symbol, { helper: helperName, precedence: prec });
|
|
1974
|
+
};
|
|
1975
|
+
const getLV = () => globalThis.Lightview || null;
|
|
1976
|
+
const getRegistry = () => {
|
|
1977
|
+
var _a;
|
|
1978
|
+
return ((_a = getLV()) == null ? void 0 : _a.registry) || null;
|
|
1979
|
+
};
|
|
1980
|
+
class BindingTarget {
|
|
1981
|
+
constructor(parent, key) {
|
|
1982
|
+
this.parent = parent;
|
|
1983
|
+
this.key = key;
|
|
1984
|
+
this.isBindingTarget = true;
|
|
1985
|
+
}
|
|
1986
|
+
get value() {
|
|
1987
|
+
return this.parent[this.key];
|
|
1988
|
+
}
|
|
1989
|
+
set value(v) {
|
|
1990
|
+
this.parent[this.key] = v;
|
|
1991
|
+
}
|
|
1992
|
+
get __parent__() {
|
|
1993
|
+
return this.parent;
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
const unwrapSignal = (val) => {
|
|
1997
|
+
if (val && typeof val === "function" && "value" in val) {
|
|
1998
|
+
return val.value;
|
|
1999
|
+
}
|
|
2000
|
+
if (val && typeof val === "object" && !(globalThis.Node && val instanceof globalThis.Node) && "value" in val) {
|
|
2001
|
+
return val.value;
|
|
2002
|
+
}
|
|
2003
|
+
return val;
|
|
2004
|
+
};
|
|
2005
|
+
const traverse = (root, segments) => {
|
|
2006
|
+
let current = root;
|
|
2007
|
+
for (const segment of segments) {
|
|
2008
|
+
if (!segment) continue;
|
|
2009
|
+
current = unwrapSignal(current);
|
|
2010
|
+
if (current == null) return void 0;
|
|
2011
|
+
const key = segment.startsWith("[") ? segment.slice(1, -1) : segment;
|
|
2012
|
+
current = current[key];
|
|
2013
|
+
}
|
|
2014
|
+
return unwrapSignal(current);
|
|
2015
|
+
};
|
|
2016
|
+
const traverseAsContext = (root, segments) => {
|
|
2017
|
+
let current = root;
|
|
2018
|
+
for (let i = 0; i < segments.length; i++) {
|
|
2019
|
+
const segment = segments[i];
|
|
2020
|
+
if (!segment) continue;
|
|
2021
|
+
const key = segment.startsWith("[") ? segment.slice(1, -1) : segment;
|
|
2022
|
+
const unwrapped = unwrapSignal(current);
|
|
2023
|
+
if (unwrapped == null) return void 0;
|
|
2024
|
+
if (i === segments.length - 1) {
|
|
2025
|
+
return new BindingTarget(unwrapped, key);
|
|
2026
|
+
}
|
|
2027
|
+
current = unwrapped[key];
|
|
2028
|
+
}
|
|
2029
|
+
return current;
|
|
2030
|
+
};
|
|
2031
|
+
const resolvePath = (path, context) => {
|
|
2032
|
+
if (typeof path !== "string") return path;
|
|
2033
|
+
const registry2 = getRegistry();
|
|
2034
|
+
if (path === ".") return unwrapSignal(context);
|
|
2035
|
+
if (path.startsWith("$/")) {
|
|
2036
|
+
const [rootName, ...rest] = path.slice(2).split("/");
|
|
2037
|
+
let cur = context;
|
|
2038
|
+
while (cur) {
|
|
2039
|
+
const localState = cur.__state__;
|
|
2040
|
+
if (localState && rootName in localState) {
|
|
2041
|
+
return traverse(localState[rootName], rest);
|
|
2042
|
+
}
|
|
2043
|
+
cur = cur.__parent__;
|
|
2044
|
+
}
|
|
2045
|
+
const rootSignal = registry2 == null ? void 0 : registry2.get(rootName);
|
|
2046
|
+
if (!rootSignal) return void 0;
|
|
2047
|
+
return traverse(rootSignal, rest);
|
|
2048
|
+
}
|
|
2049
|
+
if (path.startsWith("./")) {
|
|
2050
|
+
return traverse(context, path.slice(2).split("/"));
|
|
2051
|
+
}
|
|
2052
|
+
if (path.startsWith("../")) {
|
|
2053
|
+
return traverse(context == null ? void 0 : context.__parent__, path.slice(3).split("/"));
|
|
2054
|
+
}
|
|
2055
|
+
if (path.includes("/") || path.includes(".")) {
|
|
2056
|
+
return traverse(context, path.split(/[\/.]/));
|
|
2057
|
+
}
|
|
2058
|
+
const unwrappedContext = unwrapSignal(context);
|
|
2059
|
+
if (unwrappedContext && typeof unwrappedContext === "object") {
|
|
2060
|
+
if (path in unwrappedContext || unwrappedContext[path] !== void 0) {
|
|
2061
|
+
return traverse(unwrappedContext, [path]);
|
|
2062
|
+
}
|
|
2063
|
+
}
|
|
2064
|
+
return path;
|
|
2065
|
+
};
|
|
2066
|
+
const resolvePathAsContext = (path, context) => {
|
|
2067
|
+
if (typeof path !== "string") return path;
|
|
2068
|
+
const registry2 = getRegistry();
|
|
2069
|
+
if (path === ".") return context;
|
|
2070
|
+
if (path.startsWith("$/")) {
|
|
2071
|
+
const segments = path.slice(2).split(/[/.]/);
|
|
2072
|
+
const rootName = segments.shift();
|
|
2073
|
+
let cur = context;
|
|
2074
|
+
while (cur) {
|
|
2075
|
+
const localState = cur.__state__;
|
|
2076
|
+
if (localState && rootName in localState) {
|
|
2077
|
+
return traverseAsContext(localState[rootName], segments);
|
|
2078
|
+
}
|
|
2079
|
+
cur = cur.__parent__;
|
|
2080
|
+
}
|
|
2081
|
+
const rootSignal = registry2 == null ? void 0 : registry2.get(rootName);
|
|
2082
|
+
if (!rootSignal) return void 0;
|
|
2083
|
+
return traverseAsContext(rootSignal, segments);
|
|
2084
|
+
}
|
|
2085
|
+
if (path.startsWith("./")) {
|
|
2086
|
+
return traverseAsContext(context, path.slice(2).split(/[\/.]/));
|
|
2087
|
+
}
|
|
2088
|
+
if (path.startsWith("../")) {
|
|
2089
|
+
return traverseAsContext(context == null ? void 0 : context.__parent__, path.slice(3).split(/[\/.]/));
|
|
2090
|
+
}
|
|
2091
|
+
if (path.includes("/") || path.includes(".")) {
|
|
2092
|
+
return traverseAsContext(context, path.split(/[\/.]/));
|
|
2093
|
+
}
|
|
2094
|
+
const unwrappedContext = unwrapSignal(context);
|
|
2095
|
+
if (unwrappedContext && typeof unwrappedContext === "object") {
|
|
2096
|
+
if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(path)) {
|
|
2097
|
+
return new BindingTarget(unwrappedContext, path);
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2100
|
+
return path;
|
|
2101
|
+
};
|
|
2102
|
+
class LazyValue {
|
|
2103
|
+
constructor(fn) {
|
|
2104
|
+
this.fn = fn;
|
|
2105
|
+
this.isLazy = true;
|
|
2106
|
+
}
|
|
2107
|
+
resolve(context) {
|
|
2108
|
+
return this.fn(context);
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2111
|
+
const resolveArgument = (arg, context, globalMode = false) => {
|
|
2112
|
+
if (arg.startsWith("'") && arg.endsWith("'") || arg.startsWith('"') && arg.endsWith('"')) {
|
|
2113
|
+
return { value: arg.slice(1, -1), isLiteral: true };
|
|
2114
|
+
}
|
|
2115
|
+
if (arg !== "" && !isNaN(Number(arg))) {
|
|
2116
|
+
return { value: Number(arg), isLiteral: true };
|
|
2117
|
+
}
|
|
2118
|
+
if (arg === "true") return { value: true, isLiteral: true };
|
|
2119
|
+
if (arg === "false") return { value: false, isLiteral: true };
|
|
2120
|
+
if (arg === "null") return { value: null, isLiteral: true };
|
|
2121
|
+
if (arg === "_" || arg.startsWith("_/") || arg.startsWith("_.")) {
|
|
2122
|
+
return {
|
|
2123
|
+
value: new LazyValue((item) => {
|
|
2124
|
+
if (arg === "_") return item;
|
|
2125
|
+
const path = arg.startsWith("_.") ? arg.slice(2) : arg.slice(2);
|
|
2126
|
+
return resolvePath(path, item);
|
|
2127
|
+
}),
|
|
2128
|
+
isLazy: true
|
|
2129
|
+
};
|
|
2130
|
+
}
|
|
2131
|
+
if (arg === "$event" || arg.startsWith("$event/") || arg.startsWith("$event.")) {
|
|
2132
|
+
return {
|
|
2133
|
+
value: new LazyValue((event) => {
|
|
2134
|
+
if (arg === "$event") return event;
|
|
2135
|
+
const path = arg.startsWith("$event.") ? arg.slice(7) : arg.slice(7);
|
|
2136
|
+
return resolvePath(path, event);
|
|
2137
|
+
}),
|
|
2138
|
+
isLazy: true
|
|
2139
|
+
};
|
|
2140
|
+
}
|
|
2141
|
+
if (arg.startsWith("{") || arg.startsWith("[")) {
|
|
2142
|
+
try {
|
|
2143
|
+
const data = parseJPRX(arg);
|
|
2144
|
+
const resolveTemplate = (node, context2) => {
|
|
2145
|
+
if (typeof node === "string") {
|
|
2146
|
+
if (node.startsWith("$")) {
|
|
2147
|
+
const res = resolveExpression(node, context2);
|
|
2148
|
+
const final = res instanceof LazyValue ? res.resolve(context2) : res;
|
|
2149
|
+
return unwrapSignal(final);
|
|
2150
|
+
}
|
|
2151
|
+
if (node === "_" || node.startsWith("_/") || node.startsWith("_.")) {
|
|
2152
|
+
const path = node.startsWith("_.") || node.startsWith("_/") ? node.slice(2) : node.slice(2);
|
|
2153
|
+
const res = node === "_" ? context2 : resolvePath(path, context2);
|
|
2154
|
+
return unwrapSignal(res);
|
|
2155
|
+
}
|
|
2156
|
+
if (node.startsWith("../")) return unwrapSignal(resolvePath(node, context2));
|
|
2157
|
+
}
|
|
2158
|
+
if (Array.isArray(node)) return node.map((n) => resolveTemplate(n, context2));
|
|
2159
|
+
if (node && typeof node === "object") {
|
|
2160
|
+
const res = {};
|
|
2161
|
+
for (const k in node) res[k] = resolveTemplate(node[k], context2);
|
|
2162
|
+
return res;
|
|
2163
|
+
}
|
|
2164
|
+
return node;
|
|
2165
|
+
};
|
|
2166
|
+
const hasReactive = (obj) => {
|
|
2167
|
+
if (typeof obj === "string") {
|
|
2168
|
+
return obj.startsWith("$") || obj.startsWith("_") || obj.startsWith("../");
|
|
2169
|
+
}
|
|
2170
|
+
if (Array.isArray(obj)) return obj.some(hasReactive);
|
|
2171
|
+
if (obj && typeof obj === "object") return Object.values(obj).some(hasReactive);
|
|
2172
|
+
return false;
|
|
2173
|
+
};
|
|
2174
|
+
if (hasReactive(data)) {
|
|
2175
|
+
return {
|
|
2176
|
+
value: new LazyValue((context2) => resolveTemplate(data, context2)),
|
|
2177
|
+
isLazy: true
|
|
2178
|
+
};
|
|
2179
|
+
}
|
|
2180
|
+
return { value: data, isLiteral: true };
|
|
2181
|
+
} catch (e) {
|
|
2182
|
+
}
|
|
2183
|
+
}
|
|
2184
|
+
if (arg.includes("(")) {
|
|
2185
|
+
let nestedExpr = arg;
|
|
2186
|
+
if (arg.startsWith("/")) {
|
|
2187
|
+
nestedExpr = "$" + arg;
|
|
2188
|
+
} else if (globalMode && !arg.startsWith("$") && !arg.startsWith("./")) {
|
|
2189
|
+
nestedExpr = `$/${arg}`;
|
|
2190
|
+
}
|
|
2191
|
+
const val = resolveExpression(nestedExpr, context);
|
|
2192
|
+
if (val instanceof LazyValue) {
|
|
2193
|
+
return { value: val, isLazy: true };
|
|
2194
|
+
}
|
|
2195
|
+
return { value: val, isSignal: false };
|
|
2196
|
+
}
|
|
2197
|
+
let normalizedPath;
|
|
2198
|
+
if (arg.startsWith("/")) {
|
|
2199
|
+
normalizedPath = "$" + arg;
|
|
2200
|
+
} else if (arg.startsWith("$") || arg.startsWith("./") || arg.startsWith("../")) {
|
|
2201
|
+
normalizedPath = arg;
|
|
2202
|
+
} else if (globalMode) {
|
|
2203
|
+
normalizedPath = `$/${arg}`;
|
|
2204
|
+
} else {
|
|
2205
|
+
normalizedPath = `./${arg}`;
|
|
2206
|
+
}
|
|
2207
|
+
const explosionIdx = arg.indexOf("...");
|
|
2208
|
+
if (explosionIdx !== -1) {
|
|
2209
|
+
const normExplosionIdx = normalizedPath.indexOf("...");
|
|
2210
|
+
const pathPart = normalizedPath.slice(0, normExplosionIdx);
|
|
2211
|
+
const propName = arg.slice(explosionIdx + 3);
|
|
2212
|
+
const parent = resolvePath(pathPart, context);
|
|
2213
|
+
const unwrappedParent = unwrapSignal(parent);
|
|
2214
|
+
if (Array.isArray(unwrappedParent)) {
|
|
2215
|
+
const values = unwrappedParent.map((item) => {
|
|
2216
|
+
const unwrappedItem = unwrapSignal(item);
|
|
2217
|
+
if (!propName) return unwrappedItem;
|
|
2218
|
+
return unwrappedItem && typeof unwrappedItem === "object" ? unwrapSignal(unwrappedItem[propName]) : void 0;
|
|
2219
|
+
});
|
|
2220
|
+
return { value: values, isExplosion: true };
|
|
2221
|
+
} else if (unwrappedParent && typeof unwrappedParent === "object") {
|
|
2222
|
+
if (!propName) return { value: unwrappedParent, isExplosion: true };
|
|
2223
|
+
const val = unwrappedParent[propName];
|
|
2224
|
+
return { value: unwrapSignal(val), isExplosion: true };
|
|
2225
|
+
}
|
|
2226
|
+
return { value: void 0, isExplosion: true };
|
|
2227
|
+
}
|
|
2228
|
+
const value = resolvePathAsContext(normalizedPath, context);
|
|
2229
|
+
return { value, isExplosion: false };
|
|
2230
|
+
};
|
|
2231
|
+
const TokenType = {
|
|
2232
|
+
PATH: "PATH",
|
|
2233
|
+
// $/user/age, ./name, ../parent
|
|
2234
|
+
LITERAL: "LITERAL",
|
|
2235
|
+
// 123, "hello", true, false, null
|
|
2236
|
+
OPERATOR: "OPERATOR",
|
|
2237
|
+
// +, -, *, /, ++, --, etc.
|
|
2238
|
+
LPAREN: "LPAREN",
|
|
2239
|
+
// (
|
|
2240
|
+
RPAREN: "RPAREN",
|
|
2241
|
+
// )
|
|
2242
|
+
COMMA: "COMMA",
|
|
2243
|
+
// ,
|
|
2244
|
+
EXPLOSION: "EXPLOSION",
|
|
2245
|
+
// ... suffix
|
|
2246
|
+
PLACEHOLDER: "PLACEHOLDER",
|
|
2247
|
+
// _, _/path
|
|
2248
|
+
EVENT: "EVENT",
|
|
2249
|
+
// $event, $event.target
|
|
2250
|
+
EOF: "EOF"
|
|
2251
|
+
};
|
|
2252
|
+
const getOperatorSymbols = () => {
|
|
2253
|
+
const allOps = /* @__PURE__ */ new Set([
|
|
2254
|
+
...operators.prefix.keys(),
|
|
2255
|
+
...operators.postfix.keys(),
|
|
2256
|
+
...operators.infix.keys()
|
|
2257
|
+
]);
|
|
2258
|
+
return [...allOps].sort((a, b) => b.length - a.length);
|
|
2259
|
+
};
|
|
2260
|
+
const tokenize = (expr) => {
|
|
2261
|
+
const tokens = [];
|
|
2262
|
+
let i = 0;
|
|
2263
|
+
const len2 = expr.length;
|
|
2264
|
+
const opSymbols = getOperatorSymbols();
|
|
2265
|
+
while (i < len2) {
|
|
2266
|
+
if (/\s/.test(expr[i])) {
|
|
2267
|
+
i++;
|
|
2268
|
+
continue;
|
|
2269
|
+
}
|
|
2270
|
+
if (expr[i] === "$" && i + 1 < len2) {
|
|
2271
|
+
let isOpAfter = false;
|
|
2272
|
+
for (const op of opSymbols) {
|
|
2273
|
+
if (expr.slice(i + 1, i + 1 + op.length) === op) {
|
|
2274
|
+
isOpAfter = true;
|
|
2275
|
+
break;
|
|
2276
|
+
}
|
|
2277
|
+
}
|
|
2278
|
+
if (isOpAfter) {
|
|
2279
|
+
i++;
|
|
2280
|
+
continue;
|
|
2281
|
+
}
|
|
2282
|
+
}
|
|
2283
|
+
if (expr[i] === "(") {
|
|
2284
|
+
tokens.push({ type: TokenType.LPAREN, value: "(" });
|
|
2285
|
+
i++;
|
|
2286
|
+
continue;
|
|
2287
|
+
}
|
|
2288
|
+
if (expr[i] === ")") {
|
|
2289
|
+
tokens.push({ type: TokenType.RPAREN, value: ")" });
|
|
2290
|
+
i++;
|
|
2291
|
+
continue;
|
|
2292
|
+
}
|
|
2293
|
+
if (expr[i] === ",") {
|
|
2294
|
+
tokens.push({ type: TokenType.COMMA, value: "," });
|
|
2295
|
+
i++;
|
|
2296
|
+
continue;
|
|
2297
|
+
}
|
|
2298
|
+
let matchedOp = null;
|
|
2299
|
+
for (const op of opSymbols) {
|
|
2300
|
+
if (expr.slice(i, i + op.length) === op) {
|
|
2301
|
+
const before = i > 0 ? expr[i - 1] : " ";
|
|
2302
|
+
const after = i + op.length < len2 ? expr[i + op.length] : " ";
|
|
2303
|
+
const isInfix = operators.infix.has(op);
|
|
2304
|
+
const isPrefix = operators.prefix.has(op);
|
|
2305
|
+
const isPostfix = operators.postfix.has(op);
|
|
2306
|
+
if (isInfix && !isPrefix && !isPostfix) {
|
|
2307
|
+
if (/\s/.test(before) && /\s/.test(after)) {
|
|
2308
|
+
matchedOp = op;
|
|
2309
|
+
break;
|
|
2310
|
+
}
|
|
2311
|
+
continue;
|
|
2312
|
+
}
|
|
2313
|
+
const validBefore = /[\s)]/.test(before) || i === 0 || tokens.length === 0 || tokens[tokens.length - 1].type === TokenType.LPAREN || tokens[tokens.length - 1].type === TokenType.COMMA || tokens[tokens.length - 1].type === TokenType.OPERATOR;
|
|
2314
|
+
const validAfter = /[\s($./'"0-9_]/.test(after) || i + op.length >= len2 || opSymbols.some((o) => expr.slice(i + op.length).startsWith(o));
|
|
2315
|
+
if (validBefore || validAfter) {
|
|
2316
|
+
matchedOp = op;
|
|
2317
|
+
break;
|
|
2318
|
+
}
|
|
2319
|
+
}
|
|
2320
|
+
}
|
|
2321
|
+
if (matchedOp) {
|
|
2322
|
+
tokens.push({ type: TokenType.OPERATOR, value: matchedOp });
|
|
2323
|
+
i += matchedOp.length;
|
|
2324
|
+
continue;
|
|
2325
|
+
}
|
|
2326
|
+
if (expr[i] === '"' || expr[i] === "'") {
|
|
2327
|
+
const quote = expr[i];
|
|
2328
|
+
let str = "";
|
|
2329
|
+
i++;
|
|
2330
|
+
while (i < len2 && expr[i] !== quote) {
|
|
2331
|
+
if (expr[i] === "\\" && i + 1 < len2) {
|
|
2332
|
+
i++;
|
|
2333
|
+
if (expr[i] === "n") str += "\n";
|
|
2334
|
+
else if (expr[i] === "t") str += " ";
|
|
2335
|
+
else str += expr[i];
|
|
2336
|
+
} else {
|
|
2337
|
+
str += expr[i];
|
|
2338
|
+
}
|
|
2339
|
+
i++;
|
|
2340
|
+
}
|
|
2341
|
+
i++;
|
|
2342
|
+
tokens.push({ type: TokenType.LITERAL, value: str });
|
|
2343
|
+
continue;
|
|
2344
|
+
}
|
|
2345
|
+
if (/\d/.test(expr[i]) || expr[i] === "-" && /\d/.test(expr[i + 1]) && (tokens.length === 0 || tokens[tokens.length - 1].type === TokenType.OPERATOR || tokens[tokens.length - 1].type === TokenType.LPAREN || tokens[tokens.length - 1].type === TokenType.COMMA)) {
|
|
2346
|
+
let num = "";
|
|
2347
|
+
if (expr[i] === "-") {
|
|
2348
|
+
num = "-";
|
|
2349
|
+
i++;
|
|
2350
|
+
}
|
|
2351
|
+
while (i < len2 && /[\d.]/.test(expr[i])) {
|
|
2352
|
+
num += expr[i];
|
|
2353
|
+
i++;
|
|
2354
|
+
}
|
|
2355
|
+
tokens.push({ type: TokenType.LITERAL, value: parseFloat(num) });
|
|
2356
|
+
continue;
|
|
2357
|
+
}
|
|
2358
|
+
if (expr[i] === "_" && (i + 1 >= len2 || !/[a-zA-Z0-9]/.test(expr[i + 1]) || expr[i + 1] === "/" || expr[i + 1] === ".")) {
|
|
2359
|
+
let placeholder = "_";
|
|
2360
|
+
i++;
|
|
2361
|
+
if (i < len2 && (expr[i] === "/" || expr[i] === ".")) {
|
|
2362
|
+
while (i < len2 && !/[\s,)(]/.test(expr[i])) {
|
|
2363
|
+
placeholder += expr[i];
|
|
2364
|
+
i++;
|
|
2365
|
+
}
|
|
2366
|
+
}
|
|
2367
|
+
tokens.push({ type: TokenType.PLACEHOLDER, value: placeholder });
|
|
2368
|
+
continue;
|
|
2369
|
+
}
|
|
2370
|
+
if (expr.slice(i, i + 6) === "$event") {
|
|
2371
|
+
let eventPath = "$event";
|
|
2372
|
+
i += 6;
|
|
2373
|
+
while (i < len2 && /[a-zA-Z0-9_./]/.test(expr[i])) {
|
|
2374
|
+
eventPath += expr[i];
|
|
2375
|
+
i++;
|
|
2376
|
+
}
|
|
2377
|
+
tokens.push({ type: TokenType.EVENT, value: eventPath });
|
|
2378
|
+
continue;
|
|
2379
|
+
}
|
|
2380
|
+
if (expr[i] === "$" || expr[i] === "." || expr[i] === "/") {
|
|
2381
|
+
let path = "";
|
|
2382
|
+
while (i < len2) {
|
|
2383
|
+
let isOp = false;
|
|
2384
|
+
for (const op of opSymbols) {
|
|
2385
|
+
if (expr.slice(i, i + op.length) === op) {
|
|
2386
|
+
const isInfix = operators.infix.has(op);
|
|
2387
|
+
const isPrefix = operators.prefix.has(op);
|
|
2388
|
+
const isPostfix = operators.postfix.has(op);
|
|
2389
|
+
if (isInfix && !isPrefix && !isPostfix) {
|
|
2390
|
+
const after = i + op.length < len2 ? expr[i + op.length] : " ";
|
|
2391
|
+
if (/\s/.test(expr[i - 1]) && /\s/.test(after)) {
|
|
2392
|
+
isOp = true;
|
|
2393
|
+
break;
|
|
2394
|
+
}
|
|
2395
|
+
continue;
|
|
2396
|
+
}
|
|
2397
|
+
if (path.length > 0 && path[path.length - 1] !== "/") {
|
|
2398
|
+
isOp = true;
|
|
2399
|
+
break;
|
|
2400
|
+
}
|
|
2401
|
+
}
|
|
2402
|
+
}
|
|
2403
|
+
if (isOp) break;
|
|
2404
|
+
if (/[\s,()]/.test(expr[i])) break;
|
|
2405
|
+
if (expr.slice(i, i + 3) === "...") {
|
|
2406
|
+
break;
|
|
2407
|
+
}
|
|
2408
|
+
path += expr[i];
|
|
2409
|
+
i++;
|
|
2410
|
+
}
|
|
2411
|
+
if (expr.slice(i, i + 3) === "...") {
|
|
2412
|
+
tokens.push({ type: TokenType.PATH, value: path });
|
|
2413
|
+
tokens.push({ type: TokenType.EXPLOSION, value: "..." });
|
|
2414
|
+
i += 3;
|
|
2415
|
+
} else {
|
|
2416
|
+
tokens.push({ type: TokenType.PATH, value: path });
|
|
2417
|
+
}
|
|
2418
|
+
continue;
|
|
2419
|
+
}
|
|
2420
|
+
if (/[a-zA-Z]/.test(expr[i])) {
|
|
2421
|
+
let ident = "";
|
|
2422
|
+
while (i < len2 && /[a-zA-Z0-9_]/.test(expr[i])) {
|
|
2423
|
+
ident += expr[i];
|
|
2424
|
+
i++;
|
|
2425
|
+
}
|
|
2426
|
+
if (ident === "true") tokens.push({ type: TokenType.LITERAL, value: true });
|
|
2427
|
+
else if (ident === "false") tokens.push({ type: TokenType.LITERAL, value: false });
|
|
2428
|
+
else if (ident === "null") tokens.push({ type: TokenType.LITERAL, value: null });
|
|
2429
|
+
else tokens.push({ type: TokenType.PATH, value: ident });
|
|
2430
|
+
continue;
|
|
2431
|
+
}
|
|
2432
|
+
i++;
|
|
2433
|
+
}
|
|
2434
|
+
tokens.push({ type: TokenType.EOF, value: null });
|
|
2435
|
+
return tokens;
|
|
2436
|
+
};
|
|
2437
|
+
const hasOperatorSyntax = (expr) => {
|
|
2438
|
+
if (!expr || typeof expr !== "string") return false;
|
|
2439
|
+
if (expr.includes("(")) return false;
|
|
2440
|
+
if (/^\$(\+\+|--|!!)\/?/.test(expr)) {
|
|
2441
|
+
return true;
|
|
2442
|
+
}
|
|
2443
|
+
if (/(\+\+|--)$/.test(expr)) {
|
|
2444
|
+
return true;
|
|
2445
|
+
}
|
|
2446
|
+
if (/\s+([+\-*/]|>|<|>=|<=|!=)\s+/.test(expr)) {
|
|
2447
|
+
return true;
|
|
2448
|
+
}
|
|
2449
|
+
return false;
|
|
2450
|
+
};
|
|
2451
|
+
class PrattParser {
|
|
2452
|
+
constructor(tokens, context, isGlobalMode = false) {
|
|
2453
|
+
this.tokens = tokens;
|
|
2454
|
+
this.pos = 0;
|
|
2455
|
+
this.context = context;
|
|
2456
|
+
this.isGlobalMode = isGlobalMode;
|
|
2457
|
+
}
|
|
2458
|
+
peek() {
|
|
2459
|
+
return this.tokens[this.pos] || { type: TokenType.EOF, value: null };
|
|
2460
|
+
}
|
|
2461
|
+
consume() {
|
|
2462
|
+
return this.tokens[this.pos++];
|
|
2463
|
+
}
|
|
2464
|
+
expect(type) {
|
|
2465
|
+
const tok = this.consume();
|
|
2466
|
+
if (tok.type !== type) {
|
|
2467
|
+
throw new Error(`JPRX: Expected ${type} but got ${tok.type}`);
|
|
2468
|
+
}
|
|
2469
|
+
return tok;
|
|
2470
|
+
}
|
|
2471
|
+
/**
|
|
2472
|
+
* Get binding power (precedence) for an infix or postfix operator.
|
|
2473
|
+
*/
|
|
2474
|
+
getInfixPrecedence(op) {
|
|
2475
|
+
const infixInfo = operators.infix.get(op);
|
|
2476
|
+
if (infixInfo) return infixInfo.precedence;
|
|
2477
|
+
const postfixInfo = operators.postfix.get(op);
|
|
2478
|
+
if (postfixInfo) return postfixInfo.precedence;
|
|
2479
|
+
return 0;
|
|
2480
|
+
}
|
|
2481
|
+
/**
|
|
2482
|
+
* Parse an expression with given minimum precedence.
|
|
2483
|
+
*/
|
|
2484
|
+
parseExpression(minPrecedence = 0) {
|
|
2485
|
+
let left = this.parsePrefix();
|
|
2486
|
+
let tok = this.peek();
|
|
2487
|
+
while (tok.type === TokenType.OPERATOR) {
|
|
2488
|
+
const prec = this.getInfixPrecedence(tok.value);
|
|
2489
|
+
if (prec < minPrecedence) break;
|
|
2490
|
+
if (operators.postfix.has(tok.value) && !operators.infix.has(tok.value)) {
|
|
2491
|
+
this.consume();
|
|
2492
|
+
left = { type: "Postfix", operator: tok.value, operand: left };
|
|
2493
|
+
tok = this.peek();
|
|
2494
|
+
continue;
|
|
2495
|
+
}
|
|
2496
|
+
if (operators.infix.has(tok.value)) {
|
|
2497
|
+
this.consume();
|
|
2498
|
+
const right = this.parseExpression(prec + 1);
|
|
2499
|
+
left = { type: "Infix", operator: tok.value, left, right };
|
|
2500
|
+
tok = this.peek();
|
|
2501
|
+
continue;
|
|
2502
|
+
}
|
|
2503
|
+
this.consume();
|
|
2504
|
+
const nextTok = this.peek();
|
|
2505
|
+
if (nextTok.type === TokenType.PATH || nextTok.type === TokenType.LITERAL || nextTok.type === TokenType.LPAREN || nextTok.type === TokenType.PLACEHOLDER || nextTok.type === TokenType.EVENT || nextTok.type === TokenType.OPERATOR && operators.prefix.has(nextTok.value)) {
|
|
2506
|
+
const right = this.parseExpression(prec + 1);
|
|
2507
|
+
left = { type: "Infix", operator: tok.value, left, right };
|
|
2508
|
+
} else {
|
|
2509
|
+
left = { type: "Postfix", operator: tok.value, operand: left };
|
|
2510
|
+
}
|
|
2511
|
+
tok = this.peek();
|
|
2512
|
+
}
|
|
2513
|
+
return left;
|
|
2514
|
+
}
|
|
2515
|
+
/**
|
|
2516
|
+
* Parse a prefix expression (literals, paths, prefix operators, groups).
|
|
2517
|
+
*/
|
|
2518
|
+
parsePrefix() {
|
|
2519
|
+
const tok = this.peek();
|
|
2520
|
+
if (tok.type === TokenType.OPERATOR && operators.prefix.has(tok.value)) {
|
|
2521
|
+
this.consume();
|
|
2522
|
+
const prefixInfo = operators.prefix.get(tok.value);
|
|
2523
|
+
const operand = this.parseExpression(prefixInfo.precedence);
|
|
2524
|
+
return { type: "Prefix", operator: tok.value, operand };
|
|
2525
|
+
}
|
|
2526
|
+
if (tok.type === TokenType.LPAREN) {
|
|
2527
|
+
this.consume();
|
|
2528
|
+
const inner = this.parseExpression(0);
|
|
2529
|
+
this.expect(TokenType.RPAREN);
|
|
2530
|
+
return inner;
|
|
2531
|
+
}
|
|
2532
|
+
if (tok.type === TokenType.LITERAL) {
|
|
2533
|
+
this.consume();
|
|
2534
|
+
return { type: "Literal", value: tok.value };
|
|
2535
|
+
}
|
|
2536
|
+
if (tok.type === TokenType.PLACEHOLDER) {
|
|
2537
|
+
this.consume();
|
|
2538
|
+
return { type: "Placeholder", value: tok.value };
|
|
2539
|
+
}
|
|
2540
|
+
if (tok.type === TokenType.EVENT) {
|
|
2541
|
+
this.consume();
|
|
2542
|
+
return { type: "Event", value: tok.value };
|
|
2543
|
+
}
|
|
2544
|
+
if (tok.type === TokenType.PATH) {
|
|
2545
|
+
this.consume();
|
|
2546
|
+
const nextTok = this.peek();
|
|
2547
|
+
if (nextTok.type === TokenType.EXPLOSION) {
|
|
2548
|
+
this.consume();
|
|
2549
|
+
return { type: "Explosion", path: tok.value };
|
|
2550
|
+
}
|
|
2551
|
+
return { type: "Path", value: tok.value };
|
|
2552
|
+
}
|
|
2553
|
+
if (tok.type === TokenType.EOF) {
|
|
2554
|
+
return { type: "Literal", value: void 0 };
|
|
2555
|
+
}
|
|
2556
|
+
throw new Error(`JPRX: Unexpected token ${tok.type}: ${tok.value}`);
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
const evaluateAST = (ast, context, forMutation = false) => {
|
|
2560
|
+
if (!ast) return void 0;
|
|
2561
|
+
switch (ast.type) {
|
|
2562
|
+
case "Literal":
|
|
2563
|
+
return ast.value;
|
|
2564
|
+
case "Path": {
|
|
2565
|
+
const resolved = forMutation ? resolvePathAsContext(ast.value, context) : resolvePath(ast.value, context);
|
|
2566
|
+
return forMutation ? resolved : unwrapSignal(resolved);
|
|
2567
|
+
}
|
|
2568
|
+
case "Placeholder": {
|
|
2569
|
+
return new LazyValue((item) => {
|
|
2570
|
+
if (ast.value === "_") return item;
|
|
2571
|
+
const path = ast.value.startsWith("_.") ? ast.value.slice(2) : ast.value.slice(2);
|
|
2572
|
+
return resolvePath(path, item);
|
|
2573
|
+
});
|
|
2574
|
+
}
|
|
2575
|
+
case "Event": {
|
|
2576
|
+
return new LazyValue((event) => {
|
|
2577
|
+
if (ast.value === "$event") return event;
|
|
2578
|
+
const path = ast.value.startsWith("$event.") ? ast.value.slice(7) : ast.value.slice(7);
|
|
2579
|
+
return resolvePath(path, event);
|
|
2580
|
+
});
|
|
2581
|
+
}
|
|
2582
|
+
case "Explosion": {
|
|
2583
|
+
const result = resolveArgument(ast.path + "...", context, false);
|
|
2584
|
+
return result.value;
|
|
2585
|
+
}
|
|
2586
|
+
case "Prefix": {
|
|
2587
|
+
const opInfo = operators.prefix.get(ast.operator);
|
|
2588
|
+
if (!opInfo) {
|
|
2589
|
+
throw new Error(`JPRX: Unknown prefix operator: ${ast.operator}`);
|
|
2590
|
+
}
|
|
2591
|
+
const helper = helpers.get(opInfo.helper);
|
|
2592
|
+
if (!helper) {
|
|
2593
|
+
throw new Error(`JPRX: Helper "${opInfo.helper}" for operator "${ast.operator}" not found.`);
|
|
2594
|
+
}
|
|
2595
|
+
const opts = helperOptions.get(opInfo.helper) || {};
|
|
2596
|
+
const operand = evaluateAST(ast.operand, context, opts.pathAware);
|
|
2597
|
+
return helper(operand);
|
|
2598
|
+
}
|
|
2599
|
+
case "Postfix": {
|
|
2600
|
+
const opInfo = operators.postfix.get(ast.operator);
|
|
2601
|
+
if (!opInfo) {
|
|
2602
|
+
throw new Error(`JPRX: Unknown postfix operator: ${ast.operator}`);
|
|
2603
|
+
}
|
|
2604
|
+
const helper = helpers.get(opInfo.helper);
|
|
2605
|
+
if (!helper) {
|
|
2606
|
+
throw new Error(`JPRX: Helper "${opInfo.helper}" for operator "${ast.operator}" not found.`);
|
|
2607
|
+
}
|
|
2608
|
+
const opts = helperOptions.get(opInfo.helper) || {};
|
|
2609
|
+
const operand = evaluateAST(ast.operand, context, opts.pathAware);
|
|
2610
|
+
return helper(operand);
|
|
2611
|
+
}
|
|
2612
|
+
case "Infix": {
|
|
2613
|
+
const opInfo = operators.infix.get(ast.operator);
|
|
2614
|
+
if (!opInfo) {
|
|
2615
|
+
throw new Error(`JPRX: Unknown infix operator: ${ast.operator}`);
|
|
2616
|
+
}
|
|
2617
|
+
const helper = helpers.get(opInfo.helper);
|
|
2618
|
+
if (!helper) {
|
|
2619
|
+
throw new Error(`JPRX: Helper "${opInfo.helper}" for operator "${ast.operator}" not found.`);
|
|
2620
|
+
}
|
|
2621
|
+
const opts = helperOptions.get(opInfo.helper) || {};
|
|
2622
|
+
const left = evaluateAST(ast.left, context, opts.pathAware);
|
|
2623
|
+
const right = evaluateAST(ast.right, context, false);
|
|
2624
|
+
return helper(unwrapSignal(left), unwrapSignal(right));
|
|
2625
|
+
}
|
|
2626
|
+
default:
|
|
2627
|
+
throw new Error(`JPRX: Unknown AST node type: ${ast.type}`);
|
|
2628
|
+
}
|
|
2629
|
+
};
|
|
2630
|
+
const parseWithPratt = (expr, context) => {
|
|
2631
|
+
const tokens = tokenize(expr);
|
|
2632
|
+
const parser = new PrattParser(tokens, context);
|
|
2633
|
+
const ast = parser.parseExpression(0);
|
|
2634
|
+
return evaluateAST(ast, context);
|
|
2635
|
+
};
|
|
2636
|
+
const resolveExpression = (expr, context) => {
|
|
2637
|
+
var _a, _b;
|
|
2638
|
+
if (typeof expr !== "string") return expr;
|
|
2639
|
+
if (hasOperatorSyntax(expr)) {
|
|
2640
|
+
try {
|
|
2641
|
+
return parseWithPratt(expr, context);
|
|
2642
|
+
} catch (e) {
|
|
2643
|
+
(_a = globalThis.console) == null ? void 0 : _a.warn("JPRX: Pratt parser failed, falling back to legacy:", e.message);
|
|
2644
|
+
}
|
|
2645
|
+
}
|
|
2646
|
+
const funcStart = expr.indexOf("(");
|
|
2647
|
+
if (funcStart !== -1 && expr.endsWith(")")) {
|
|
2648
|
+
const fullPath = expr.slice(0, funcStart).trim();
|
|
2649
|
+
const argsStr = expr.slice(funcStart + 1, -1);
|
|
2650
|
+
const segments = fullPath.split("/");
|
|
2651
|
+
let funcName = segments.pop().replace(/^\$/, "");
|
|
2652
|
+
if (funcName === "" && (segments.length > 0 || fullPath === "/")) {
|
|
2653
|
+
funcName = "/";
|
|
2654
|
+
}
|
|
2655
|
+
const navPath = segments.join("/");
|
|
2656
|
+
const isGlobalExpr = expr.startsWith("$/") || expr.startsWith("$");
|
|
2657
|
+
let baseContext = context;
|
|
2658
|
+
if (navPath && navPath !== "$") {
|
|
2659
|
+
baseContext = resolvePathAsContext(navPath, context);
|
|
2660
|
+
}
|
|
2661
|
+
const helper = helpers.get(funcName);
|
|
2662
|
+
if (!helper) {
|
|
2663
|
+
(_b = globalThis.console) == null ? void 0 : _b.warn(`LightviewCDOM: Helper "${funcName}" not found.`);
|
|
2664
|
+
return expr;
|
|
2665
|
+
}
|
|
2666
|
+
const options = helperOptions.get(funcName) || {};
|
|
2667
|
+
const argsList = [];
|
|
2668
|
+
let current = "", parenDepth = 0, braceDepth = 0, bracketDepth = 0, quote = null;
|
|
2669
|
+
for (let i = 0; i < argsStr.length; i++) {
|
|
2670
|
+
const char = argsStr[i];
|
|
2671
|
+
if (char === quote) quote = null;
|
|
2672
|
+
else if (!quote && (char === "'" || char === '"')) quote = char;
|
|
2673
|
+
else if (!quote && char === "(") parenDepth++;
|
|
2674
|
+
else if (!quote && char === ")") parenDepth--;
|
|
2675
|
+
else if (!quote && char === "{") braceDepth++;
|
|
2676
|
+
else if (!quote && char === "}") braceDepth--;
|
|
2677
|
+
else if (!quote && char === "[") bracketDepth++;
|
|
2678
|
+
else if (!quote && char === "]") bracketDepth--;
|
|
2679
|
+
else if (!quote && char === "," && parenDepth === 0 && braceDepth === 0 && bracketDepth === 0) {
|
|
2680
|
+
argsList.push(current.trim());
|
|
2681
|
+
current = "";
|
|
2682
|
+
continue;
|
|
2683
|
+
}
|
|
2684
|
+
current += char;
|
|
2685
|
+
}
|
|
2686
|
+
if (current) argsList.push(current.trim());
|
|
2687
|
+
const resolvedArgs = [];
|
|
2688
|
+
let hasLazy = false;
|
|
2689
|
+
for (let i = 0; i < argsList.length; i++) {
|
|
2690
|
+
const arg = argsList[i];
|
|
2691
|
+
const useGlobalMode = isGlobalExpr && (navPath === "$" || !navPath);
|
|
2692
|
+
const res = resolveArgument(arg, baseContext, useGlobalMode);
|
|
2693
|
+
if (res.isLazy) hasLazy = true;
|
|
2694
|
+
const shouldUnwrap = !(options.pathAware && i === 0);
|
|
2695
|
+
let val = res.value;
|
|
2696
|
+
if (shouldUnwrap && !(val && val.isLazy)) {
|
|
2697
|
+
val = unwrapSignal(val);
|
|
2698
|
+
}
|
|
2699
|
+
if (res.isExplosion && Array.isArray(val)) {
|
|
2700
|
+
resolvedArgs.push(...val.map((v) => shouldUnwrap && !(v && v.isLazy) ? unwrapSignal(v) : v));
|
|
2701
|
+
} else {
|
|
2702
|
+
resolvedArgs.push(val);
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2705
|
+
if (hasLazy && !options.lazyAware) {
|
|
2706
|
+
return new LazyValue((contextOverride) => {
|
|
2707
|
+
const finalArgs = resolvedArgs.map((arg, i) => {
|
|
2708
|
+
const shouldUnwrap = !(options.pathAware && i === 0);
|
|
2709
|
+
const resolved = arg instanceof LazyValue ? arg.resolve(contextOverride) : arg;
|
|
2710
|
+
return shouldUnwrap ? unwrapSignal(resolved) : resolved;
|
|
2711
|
+
});
|
|
2712
|
+
return helper(...finalArgs);
|
|
2713
|
+
});
|
|
2714
|
+
}
|
|
2715
|
+
const result = helper(...resolvedArgs);
|
|
2716
|
+
return unwrapSignal(result);
|
|
2717
|
+
}
|
|
2718
|
+
return unwrapSignal(resolvePath(expr, context));
|
|
2719
|
+
};
|
|
2720
|
+
const parseExpression = (expr, context) => {
|
|
2721
|
+
const LV = getLV();
|
|
2722
|
+
if (!LV || typeof expr !== "string") return expr;
|
|
2723
|
+
return LV.computed(() => resolveExpression(expr, context));
|
|
2724
|
+
};
|
|
2725
|
+
const parseCDOMC = (input) => {
|
|
2726
|
+
let i = 0;
|
|
2727
|
+
const len2 = input.length;
|
|
2728
|
+
const skipWhitespace = () => {
|
|
2729
|
+
while (i < len2) {
|
|
2730
|
+
const char = input[i];
|
|
2731
|
+
if (/\s/.test(char)) {
|
|
2732
|
+
i++;
|
|
2733
|
+
continue;
|
|
2734
|
+
}
|
|
2735
|
+
if (char === "/") {
|
|
2736
|
+
const next = input[i + 1];
|
|
2737
|
+
if (next === "/") {
|
|
2738
|
+
i += 2;
|
|
2739
|
+
while (i < len2 && input[i] !== "\n" && input[i] !== "\r") i++;
|
|
2740
|
+
continue;
|
|
2741
|
+
} else if (next === "*") {
|
|
2742
|
+
i += 2;
|
|
2743
|
+
while (i < len2) {
|
|
2744
|
+
if (input[i] === "*" && input[i + 1] === "/") {
|
|
2745
|
+
i += 2;
|
|
2746
|
+
break;
|
|
2747
|
+
}
|
|
2748
|
+
i++;
|
|
2749
|
+
}
|
|
2750
|
+
continue;
|
|
2751
|
+
}
|
|
2752
|
+
}
|
|
2753
|
+
break;
|
|
2754
|
+
}
|
|
2755
|
+
};
|
|
2756
|
+
const parseString = () => {
|
|
2757
|
+
const quote = input[i++];
|
|
2758
|
+
let res2 = "";
|
|
2759
|
+
while (i < len2) {
|
|
2760
|
+
const char = input[i++];
|
|
2761
|
+
if (char === quote) return res2;
|
|
2762
|
+
if (char === "\\") {
|
|
2763
|
+
const next = input[i++];
|
|
2764
|
+
if (next === "n") res2 += "\n";
|
|
2765
|
+
else if (next === "t") res2 += " ";
|
|
2766
|
+
else if (next === '"') res2 += '"';
|
|
2767
|
+
else if (next === "'") res2 += "'";
|
|
2768
|
+
else if (next === "\\") res2 += "\\";
|
|
2769
|
+
else res2 += next;
|
|
2770
|
+
} else {
|
|
2771
|
+
res2 += char;
|
|
2772
|
+
}
|
|
2773
|
+
}
|
|
2774
|
+
throw new Error("Unterminated string");
|
|
2775
|
+
};
|
|
2776
|
+
const parseWord = () => {
|
|
2777
|
+
const start = i;
|
|
2778
|
+
let pDepth = 0;
|
|
2779
|
+
let bDepth = 0;
|
|
2780
|
+
let brDepth = 0;
|
|
2781
|
+
let quote = null;
|
|
2782
|
+
while (i < len2) {
|
|
2783
|
+
const char = input[i];
|
|
2784
|
+
if (quote) {
|
|
2785
|
+
if (char === quote) quote = null;
|
|
2786
|
+
i++;
|
|
2787
|
+
continue;
|
|
2788
|
+
} else if (char === '"' || char === "'" || char === "`") {
|
|
2789
|
+
quote = char;
|
|
2790
|
+
i++;
|
|
2791
|
+
continue;
|
|
2792
|
+
}
|
|
2793
|
+
if (char === "(") {
|
|
2794
|
+
pDepth++;
|
|
2795
|
+
i++;
|
|
2796
|
+
continue;
|
|
2797
|
+
}
|
|
2798
|
+
if (char === "{") {
|
|
2799
|
+
bDepth++;
|
|
2800
|
+
i++;
|
|
2801
|
+
continue;
|
|
2802
|
+
}
|
|
2803
|
+
if (char === "[") {
|
|
2804
|
+
brDepth++;
|
|
2805
|
+
i++;
|
|
2806
|
+
continue;
|
|
2807
|
+
}
|
|
2808
|
+
if (char === ")") {
|
|
2809
|
+
if (pDepth > 0) {
|
|
2810
|
+
pDepth--;
|
|
2811
|
+
i++;
|
|
2812
|
+
continue;
|
|
2813
|
+
}
|
|
2814
|
+
}
|
|
2815
|
+
if (char === "}") {
|
|
2816
|
+
if (bDepth > 0) {
|
|
2817
|
+
bDepth--;
|
|
2818
|
+
i++;
|
|
2819
|
+
continue;
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2822
|
+
if (char === "]") {
|
|
2823
|
+
if (brDepth > 0) {
|
|
2824
|
+
brDepth--;
|
|
2825
|
+
i++;
|
|
2826
|
+
continue;
|
|
2827
|
+
}
|
|
2828
|
+
}
|
|
2829
|
+
if (pDepth === 0 && bDepth === 0 && brDepth === 0) {
|
|
2830
|
+
if (/[\s:,{}\[\]"'`()]/.test(char)) {
|
|
2831
|
+
break;
|
|
2832
|
+
}
|
|
2833
|
+
}
|
|
2834
|
+
i++;
|
|
2835
|
+
}
|
|
2836
|
+
const word = input.slice(start, i);
|
|
2837
|
+
if (word.startsWith("$")) {
|
|
2838
|
+
return word;
|
|
2839
|
+
}
|
|
2840
|
+
if (word === "true") return true;
|
|
2841
|
+
if (word === "false") return false;
|
|
2842
|
+
if (word === "null") return null;
|
|
2843
|
+
if (word.trim() !== "" && !isNaN(Number(word))) return Number(word);
|
|
2844
|
+
return word;
|
|
2845
|
+
};
|
|
2846
|
+
const parseValue = () => {
|
|
2847
|
+
skipWhitespace();
|
|
2848
|
+
if (i >= len2) return void 0;
|
|
2849
|
+
const char = input[i];
|
|
2850
|
+
if (char === "{") return parseObject();
|
|
2851
|
+
if (char === "[") return parseArray();
|
|
2852
|
+
if (char === '"' || char === "'") return parseString();
|
|
2853
|
+
return parseWord();
|
|
2854
|
+
};
|
|
2855
|
+
const parseObject = () => {
|
|
2856
|
+
i++;
|
|
2857
|
+
const obj = {};
|
|
2858
|
+
skipWhitespace();
|
|
2859
|
+
if (i < len2 && input[i] === "}") {
|
|
2860
|
+
i++;
|
|
2861
|
+
return obj;
|
|
2862
|
+
}
|
|
2863
|
+
while (i < len2) {
|
|
2864
|
+
skipWhitespace();
|
|
2865
|
+
let key;
|
|
2866
|
+
if (input[i] === '"' || input[i] === "'") key = parseString();
|
|
2867
|
+
else key = parseWord();
|
|
2868
|
+
skipWhitespace();
|
|
2869
|
+
if (input[i] !== ":") throw new Error(`Expected ':' at position ${i}, found '${input[i]}'`);
|
|
2870
|
+
i++;
|
|
2871
|
+
const value = parseValue();
|
|
2872
|
+
obj[String(key)] = value;
|
|
2873
|
+
skipWhitespace();
|
|
2874
|
+
if (input[i] === "}") {
|
|
2875
|
+
i++;
|
|
2876
|
+
return obj;
|
|
2877
|
+
}
|
|
2878
|
+
if (input[i] === ",") {
|
|
2879
|
+
i++;
|
|
2880
|
+
skipWhitespace();
|
|
2881
|
+
if (input[i] === "}") {
|
|
2882
|
+
i++;
|
|
2883
|
+
return obj;
|
|
2884
|
+
}
|
|
2885
|
+
continue;
|
|
2886
|
+
}
|
|
2887
|
+
throw new Error(`Expected '}' or ',' at position ${i}, found '${input[i]}'`);
|
|
2888
|
+
}
|
|
2889
|
+
};
|
|
2890
|
+
const parseArray = () => {
|
|
2891
|
+
i++;
|
|
2892
|
+
const arr = [];
|
|
2893
|
+
skipWhitespace();
|
|
2894
|
+
if (i < len2 && input[i] === "]") {
|
|
2895
|
+
i++;
|
|
2896
|
+
return arr;
|
|
2897
|
+
}
|
|
2898
|
+
while (i < len2) {
|
|
2899
|
+
const val = parseValue();
|
|
2900
|
+
arr.push(val);
|
|
2901
|
+
skipWhitespace();
|
|
2902
|
+
if (input[i] === "]") {
|
|
2903
|
+
i++;
|
|
2904
|
+
return arr;
|
|
2905
|
+
}
|
|
2906
|
+
if (input[i] === ",") {
|
|
2907
|
+
i++;
|
|
2908
|
+
skipWhitespace();
|
|
2909
|
+
if (input[i] === "]") {
|
|
2910
|
+
i++;
|
|
2911
|
+
return arr;
|
|
2912
|
+
}
|
|
2913
|
+
continue;
|
|
2914
|
+
}
|
|
2915
|
+
throw new Error(`Expected ']' or ',' at position ${i}, found '${input[i]}'`);
|
|
2916
|
+
}
|
|
2917
|
+
};
|
|
2918
|
+
skipWhitespace();
|
|
2919
|
+
const res = parseValue();
|
|
2920
|
+
return res;
|
|
2921
|
+
};
|
|
2922
|
+
const parseJPRX = (input) => {
|
|
2923
|
+
var _a, _b;
|
|
2924
|
+
let result = "";
|
|
2925
|
+
let i = 0;
|
|
2926
|
+
const len2 = input.length;
|
|
2927
|
+
while (i < len2) {
|
|
2928
|
+
const char = input[i];
|
|
2929
|
+
if (char === "/" && input[i + 1] === "/") {
|
|
2930
|
+
while (i < len2 && input[i] !== "\n") i++;
|
|
2931
|
+
continue;
|
|
2932
|
+
}
|
|
2933
|
+
if (char === "/" && input[i + 1] === "*") {
|
|
2934
|
+
i += 2;
|
|
2935
|
+
while (i < len2 && !(input[i] === "*" && input[i + 1] === "/")) i++;
|
|
2936
|
+
i += 2;
|
|
2937
|
+
continue;
|
|
2938
|
+
}
|
|
2939
|
+
if (char === '"' || char === "'") {
|
|
2940
|
+
const quote = char;
|
|
2941
|
+
result += '"';
|
|
2942
|
+
i++;
|
|
2943
|
+
while (i < len2 && input[i] !== quote) {
|
|
2944
|
+
const c = input[i];
|
|
2945
|
+
if (c === "\\") {
|
|
2946
|
+
result += "\\";
|
|
2947
|
+
i++;
|
|
2948
|
+
if (i < len2) {
|
|
2949
|
+
const next = input[i];
|
|
2950
|
+
if (next === '"') result += '\\"';
|
|
2951
|
+
else result += next;
|
|
2952
|
+
i++;
|
|
2953
|
+
}
|
|
2954
|
+
} else if (c === '"') {
|
|
2955
|
+
result += '\\"';
|
|
2956
|
+
i++;
|
|
2957
|
+
} else if (c === "\n") {
|
|
2958
|
+
result += "\\n";
|
|
2959
|
+
i++;
|
|
2960
|
+
} else if (c === "\r") {
|
|
2961
|
+
result += "\\r";
|
|
2962
|
+
i++;
|
|
2963
|
+
} else if (c === " ") {
|
|
2964
|
+
result += "\\t";
|
|
2965
|
+
i++;
|
|
2966
|
+
} else {
|
|
2967
|
+
result += c;
|
|
2968
|
+
i++;
|
|
2969
|
+
}
|
|
2970
|
+
}
|
|
2971
|
+
result += '"';
|
|
2972
|
+
i++;
|
|
2973
|
+
continue;
|
|
2974
|
+
}
|
|
2975
|
+
if (char === "$") {
|
|
2976
|
+
let expr = "";
|
|
2977
|
+
let parenDepth = 0;
|
|
2978
|
+
let braceDepth = 0;
|
|
2979
|
+
let bracketDepth = 0;
|
|
2980
|
+
let inExprQuote = null;
|
|
2981
|
+
while (i < len2) {
|
|
2982
|
+
const c = input[i];
|
|
2983
|
+
if (inExprQuote) {
|
|
2984
|
+
if (c === inExprQuote && input[i - 1] !== "\\") inExprQuote = null;
|
|
2985
|
+
} else if (c === '"' || c === "'") {
|
|
2986
|
+
inExprQuote = c;
|
|
2987
|
+
} else {
|
|
2988
|
+
if (parenDepth === 0 && braceDepth === 0 && bracketDepth === 0) {
|
|
2989
|
+
if (/[\s,}\]:]/.test(c) && expr.length > 1) break;
|
|
2990
|
+
}
|
|
2991
|
+
if (c === "(") parenDepth++;
|
|
2992
|
+
else if (c === ")") parenDepth--;
|
|
2993
|
+
else if (c === "{") braceDepth++;
|
|
2994
|
+
else if (c === "}") braceDepth--;
|
|
2995
|
+
else if (c === "[") bracketDepth++;
|
|
2996
|
+
else if (c === "]") bracketDepth--;
|
|
2997
|
+
}
|
|
2998
|
+
expr += c;
|
|
2999
|
+
i++;
|
|
3000
|
+
}
|
|
3001
|
+
result += JSON.stringify(expr);
|
|
3002
|
+
continue;
|
|
3003
|
+
}
|
|
3004
|
+
if (/[a-zA-Z_./]/.test(char)) {
|
|
3005
|
+
let word = "";
|
|
3006
|
+
while (i < len2 && /[a-zA-Z0-9_$/.-]/.test(input[i])) {
|
|
3007
|
+
word += input[i];
|
|
3008
|
+
i++;
|
|
3009
|
+
}
|
|
3010
|
+
let j = i;
|
|
3011
|
+
while (j < len2 && /\s/.test(input[j])) j++;
|
|
3012
|
+
if (input[j] === ":") {
|
|
3013
|
+
result += `"${word}"`;
|
|
3014
|
+
} else {
|
|
3015
|
+
if (word === "true" || word === "false" || word === "null") {
|
|
3016
|
+
result += word;
|
|
3017
|
+
} else if (!isNaN(Number(word))) {
|
|
3018
|
+
result += word;
|
|
3019
|
+
} else {
|
|
3020
|
+
result += `"${word}"`;
|
|
3021
|
+
}
|
|
3022
|
+
}
|
|
3023
|
+
continue;
|
|
3024
|
+
}
|
|
3025
|
+
if (/[\d]/.test(char) || char === "-" && /\d/.test(input[i + 1])) {
|
|
3026
|
+
let num = "";
|
|
3027
|
+
while (i < len2 && /[\d.\-eE]/.test(input[i])) {
|
|
3028
|
+
num += input[i];
|
|
3029
|
+
i++;
|
|
3030
|
+
}
|
|
3031
|
+
result += num;
|
|
3032
|
+
continue;
|
|
3033
|
+
}
|
|
3034
|
+
result += char;
|
|
3035
|
+
i++;
|
|
3036
|
+
}
|
|
3037
|
+
try {
|
|
3038
|
+
return JSON.parse(result);
|
|
3039
|
+
} catch (e) {
|
|
3040
|
+
(_a = globalThis.console) == null ? void 0 : _a.error("parseJPRX: JSON parse failed", e);
|
|
3041
|
+
(_b = globalThis.console) == null ? void 0 : _b.error("Transformed input:", result);
|
|
3042
|
+
throw e;
|
|
3043
|
+
}
|
|
3044
|
+
};
|
|
3045
|
+
const add = (...args) => args.reduce((a, b) => Number(a) + Number(b), 0);
|
|
3046
|
+
const subtract = (a, b) => Number(a) - Number(b);
|
|
3047
|
+
const multiply = (...args) => args.reduce((a, b) => Number(a) * Number(b), 1);
|
|
3048
|
+
const divide = (a, b) => Number(a) / Number(b);
|
|
3049
|
+
const round = (val, decimals = 0) => Number(Math.round(val + "e" + decimals) + "e-" + decimals);
|
|
3050
|
+
const ceil = (val) => Math.ceil(val);
|
|
3051
|
+
const floor = (val) => Math.floor(val);
|
|
3052
|
+
const abs = (val) => Math.abs(val);
|
|
3053
|
+
const mod = (a, b) => a % b;
|
|
3054
|
+
const pow = (a, b) => Math.pow(a, b);
|
|
3055
|
+
const sqrt = (val) => Math.sqrt(val);
|
|
3056
|
+
const registerMathHelpers = (register) => {
|
|
3057
|
+
register("+", add);
|
|
3058
|
+
register("add", add);
|
|
3059
|
+
register("-", subtract);
|
|
3060
|
+
register("sub", subtract);
|
|
3061
|
+
register("*", multiply);
|
|
3062
|
+
register("mul", multiply);
|
|
3063
|
+
register("/", divide);
|
|
3064
|
+
register("div", divide);
|
|
3065
|
+
register("round", round);
|
|
3066
|
+
register("ceil", ceil);
|
|
3067
|
+
register("floor", floor);
|
|
3068
|
+
register("abs", abs);
|
|
3069
|
+
register("mod", mod);
|
|
3070
|
+
register("pow", pow);
|
|
3071
|
+
register("sqrt", sqrt);
|
|
3072
|
+
};
|
|
3073
|
+
const ifHelper = (condition, thenVal, elseVal) => condition ? thenVal : elseVal;
|
|
3074
|
+
const andHelper = (...args) => args.every(Boolean);
|
|
3075
|
+
const orHelper = (...args) => args.some(Boolean);
|
|
3076
|
+
const notHelper = (val) => !val;
|
|
3077
|
+
const eqHelper = (a, b) => a === b;
|
|
3078
|
+
const neqHelper = (a, b) => a !== b;
|
|
3079
|
+
const registerLogicHelpers = (register) => {
|
|
3080
|
+
register("if", ifHelper);
|
|
3081
|
+
register("and", andHelper);
|
|
3082
|
+
register("&&", andHelper);
|
|
3083
|
+
register("or", orHelper);
|
|
3084
|
+
register("||", orHelper);
|
|
3085
|
+
register("not", notHelper);
|
|
3086
|
+
register("!", notHelper);
|
|
3087
|
+
register("eq", eqHelper);
|
|
3088
|
+
register("==", eqHelper);
|
|
3089
|
+
register("===", eqHelper);
|
|
3090
|
+
register("neq", neqHelper);
|
|
3091
|
+
};
|
|
3092
|
+
const join$1 = (...args) => {
|
|
3093
|
+
const separator = args[args.length - 1];
|
|
3094
|
+
const items = args.slice(0, -1);
|
|
3095
|
+
return items.join(separator);
|
|
3096
|
+
};
|
|
3097
|
+
const concat = (...args) => args.join("");
|
|
3098
|
+
const upper = (s) => String(s).toUpperCase();
|
|
3099
|
+
const lower = (s) => String(s).toLowerCase();
|
|
3100
|
+
const trim = (s) => String(s).trim();
|
|
3101
|
+
const len = (s) => String(s).length;
|
|
3102
|
+
const replace = (s, search, replacement) => String(s).replace(search, replacement);
|
|
3103
|
+
const split = (s, separator) => String(s).split(separator);
|
|
3104
|
+
const capitalize = (s) => {
|
|
3105
|
+
const str = String(s);
|
|
3106
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
3107
|
+
};
|
|
3108
|
+
const titleCase = (s) => {
|
|
3109
|
+
return String(s).toLowerCase().split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
3110
|
+
};
|
|
3111
|
+
const contains$1 = (s, search) => String(s).includes(search);
|
|
3112
|
+
const startsWith = (s, prefix) => String(s).startsWith(prefix);
|
|
3113
|
+
const endsWith = (s, suffix) => String(s).endsWith(suffix);
|
|
3114
|
+
const defaultHelper = (val, fallback) => val !== void 0 && val !== null ? val : fallback;
|
|
3115
|
+
const registerStringHelpers = (register) => {
|
|
3116
|
+
register("join", join$1);
|
|
3117
|
+
register("concat", concat);
|
|
3118
|
+
register("upper", upper);
|
|
3119
|
+
register("lower", lower);
|
|
3120
|
+
register("trim", trim);
|
|
3121
|
+
register("len", len);
|
|
3122
|
+
register("replace", replace);
|
|
3123
|
+
register("split", split);
|
|
3124
|
+
register("capitalize", capitalize);
|
|
3125
|
+
register("titleCase", titleCase);
|
|
3126
|
+
register("contains", contains$1);
|
|
3127
|
+
register("startsWith", startsWith);
|
|
3128
|
+
register("endsWith", endsWith);
|
|
3129
|
+
register("default", defaultHelper);
|
|
3130
|
+
};
|
|
3131
|
+
const count = (...args) => args.length;
|
|
3132
|
+
const filter = (arr, predicate) => {
|
|
3133
|
+
if (!Array.isArray(arr)) return [];
|
|
3134
|
+
if (typeof predicate === "function" && predicate.isLazy) {
|
|
3135
|
+
return arr.filter((item) => predicate.resolve(item));
|
|
3136
|
+
}
|
|
3137
|
+
return arr.filter((item) => !!item);
|
|
3138
|
+
};
|
|
3139
|
+
const map = (arr, transform) => {
|
|
3140
|
+
if (!Array.isArray(arr)) return [];
|
|
3141
|
+
if (typeof transform === "string") {
|
|
3142
|
+
return arr.map((item) => item && typeof item === "object" ? item[transform] : item);
|
|
3143
|
+
}
|
|
3144
|
+
if (transform && transform.isLazy && typeof transform.resolve === "function") {
|
|
3145
|
+
return arr.map((item) => transform.resolve(item));
|
|
3146
|
+
}
|
|
3147
|
+
if (typeof transform === "function") {
|
|
3148
|
+
return arr.map(transform);
|
|
3149
|
+
}
|
|
3150
|
+
return arr;
|
|
3151
|
+
};
|
|
3152
|
+
const find = (arr, predicate) => {
|
|
3153
|
+
if (!Array.isArray(arr)) return void 0;
|
|
3154
|
+
if (predicate && predicate.isLazy) {
|
|
3155
|
+
return arr.find((item) => predicate.resolve(item));
|
|
3156
|
+
}
|
|
3157
|
+
return arr.find((item) => !!item);
|
|
3158
|
+
};
|
|
3159
|
+
const unique = (arr) => Array.isArray(arr) ? [...new Set(arr)] : [];
|
|
3160
|
+
const sort = (arr, order = "asc") => {
|
|
3161
|
+
if (!Array.isArray(arr)) return [];
|
|
3162
|
+
const sorted = [...arr];
|
|
3163
|
+
sorted.sort((a, b) => {
|
|
3164
|
+
if (a < b) return order === "asc" ? -1 : 1;
|
|
3165
|
+
if (a > b) return order === "asc" ? 1 : -1;
|
|
3166
|
+
return 0;
|
|
3167
|
+
});
|
|
3168
|
+
return sorted;
|
|
3169
|
+
};
|
|
3170
|
+
const reverse = (arr) => Array.isArray(arr) ? [...arr].reverse() : [];
|
|
3171
|
+
const first = (arr) => Array.isArray(arr) ? arr[0] : void 0;
|
|
3172
|
+
const last = (arr) => Array.isArray(arr) ? arr[arr.length - 1] : void 0;
|
|
3173
|
+
const slice = (arr, start, end) => Array.isArray(arr) ? arr.slice(start, end) : [];
|
|
3174
|
+
const flatten = (arr) => Array.isArray(arr) ? arr.flat(Infinity) : [];
|
|
3175
|
+
const join = (arr, sep = ",") => Array.isArray(arr) ? arr.join(String(sep)) : "";
|
|
3176
|
+
const length = (arg) => Array.isArray(arg) ? arg.length : arg ? String(arg).length : 0;
|
|
3177
|
+
const registerArrayHelpers = (register) => {
|
|
3178
|
+
register("count", count);
|
|
3179
|
+
register("filter", filter, { lazyAware: true });
|
|
3180
|
+
register("map", map, { lazyAware: true });
|
|
3181
|
+
register("find", find, { lazyAware: true });
|
|
3182
|
+
register("unique", unique);
|
|
3183
|
+
register("sort", sort);
|
|
3184
|
+
register("reverse", reverse);
|
|
3185
|
+
register("first", first);
|
|
3186
|
+
register("last", last);
|
|
3187
|
+
register("slice", slice);
|
|
3188
|
+
register("flatten", flatten);
|
|
3189
|
+
register("join", join);
|
|
3190
|
+
register("len", length);
|
|
3191
|
+
register("length", length);
|
|
3192
|
+
};
|
|
3193
|
+
const gt = (a, b) => a > b;
|
|
3194
|
+
const lt = (a, b) => a < b;
|
|
3195
|
+
const gte = (a, b) => a >= b;
|
|
3196
|
+
const lte = (a, b) => a <= b;
|
|
3197
|
+
const neq = (a, b) => a !== b;
|
|
3198
|
+
const between = (val, min2, max2) => val >= min2 && val <= max2;
|
|
3199
|
+
const contains = (arr, val) => Array.isArray(arr) && arr.includes(val);
|
|
3200
|
+
const registerCompareHelpers = (register) => {
|
|
3201
|
+
register("gt", gt);
|
|
3202
|
+
register(">", gt);
|
|
3203
|
+
register("lt", lt);
|
|
3204
|
+
register("<", lt);
|
|
3205
|
+
register("gte", gte);
|
|
3206
|
+
register(">=", gte);
|
|
3207
|
+
register("lte", lte);
|
|
3208
|
+
register("<=", lte);
|
|
3209
|
+
register("neq", neq);
|
|
3210
|
+
register("!=", neq);
|
|
3211
|
+
register("between", between);
|
|
3212
|
+
register("in", contains);
|
|
3213
|
+
};
|
|
3214
|
+
const sumIf = (arr, predicate) => {
|
|
3215
|
+
if (!Array.isArray(arr)) return 0;
|
|
3216
|
+
const filtered = predicate && predicate.isLazy ? arr.filter((item) => predicate.resolve(item)) : arr;
|
|
3217
|
+
return filtered.reduce((a, b) => a + (Number(b) || 0), 0);
|
|
3218
|
+
};
|
|
3219
|
+
const countIf = (arr, predicate) => {
|
|
3220
|
+
if (!Array.isArray(arr)) return 0;
|
|
3221
|
+
if (predicate && predicate.isLazy) {
|
|
3222
|
+
return arr.filter((item) => predicate.resolve(item)).length;
|
|
3223
|
+
}
|
|
3224
|
+
return arr.filter((item) => !!item).length;
|
|
3225
|
+
};
|
|
3226
|
+
const avgIf = (arr, predicate) => {
|
|
3227
|
+
if (!Array.isArray(arr)) return 0;
|
|
3228
|
+
const filtered = predicate && predicate.isLazy ? arr.filter((item) => predicate.resolve(item)) : arr;
|
|
3229
|
+
if (filtered.length === 0) return 0;
|
|
3230
|
+
return filtered.reduce((a, b) => a + (Number(b) || 0), 0) / filtered.length;
|
|
3231
|
+
};
|
|
3232
|
+
const registerConditionalHelpers = (register) => {
|
|
3233
|
+
register("sumIf", sumIf);
|
|
3234
|
+
register("countIf", countIf);
|
|
3235
|
+
register("avgIf", avgIf);
|
|
3236
|
+
};
|
|
3237
|
+
const now = () => (/* @__PURE__ */ new Date()).getTime();
|
|
3238
|
+
const today = () => {
|
|
3239
|
+
const d = /* @__PURE__ */ new Date();
|
|
3240
|
+
d.setHours(0, 0, 0, 0);
|
|
3241
|
+
return d.getTime();
|
|
3242
|
+
};
|
|
3243
|
+
const date = (val) => new Date(val).getTime();
|
|
3244
|
+
const formatDate = (val, format) => {
|
|
3245
|
+
const d = new Date(val);
|
|
3246
|
+
if (isNaN(d.getTime())) return "";
|
|
3247
|
+
const options = { year: "numeric", month: "2-digit", day: "2-digit" };
|
|
3248
|
+
if (format === "long") options.month = "long";
|
|
3249
|
+
return d.toLocaleDateString(void 0, options);
|
|
3250
|
+
};
|
|
3251
|
+
const year = (val) => new Date(val).getFullYear();
|
|
3252
|
+
const month = (val) => new Date(val).getMonth() + 1;
|
|
3253
|
+
const day = (val) => new Date(val).getDate();
|
|
3254
|
+
const weekday = (val) => new Date(val).getDay();
|
|
3255
|
+
const addDays = (val, days) => {
|
|
3256
|
+
const d = new Date(val);
|
|
3257
|
+
d.setDate(d.getDate() + Number(days));
|
|
3258
|
+
return d.getTime();
|
|
3259
|
+
};
|
|
3260
|
+
const dateDiff = (d1, d2, unit = "days") => {
|
|
3261
|
+
const diff = Math.abs(new Date(d1) - new Date(d2));
|
|
3262
|
+
if (unit === "seconds") return diff / 1e3;
|
|
3263
|
+
if (unit === "minutes") return diff / (1e3 * 60);
|
|
3264
|
+
if (unit === "hours") return diff / (1e3 * 60 * 60);
|
|
3265
|
+
return diff / (1e3 * 60 * 60 * 24);
|
|
3266
|
+
};
|
|
3267
|
+
const registerDateTimeHelpers = (register) => {
|
|
3268
|
+
register("now", now);
|
|
3269
|
+
register("today", today);
|
|
3270
|
+
register("date", date);
|
|
3271
|
+
register("formatDate", formatDate);
|
|
3272
|
+
register("year", year);
|
|
3273
|
+
register("month", month);
|
|
3274
|
+
register("day", day);
|
|
3275
|
+
register("weekday", weekday);
|
|
3276
|
+
register("addDays", addDays);
|
|
3277
|
+
register("dateDiff", dateDiff);
|
|
3278
|
+
};
|
|
3279
|
+
const number = (val, decimals = 2) => Number(val).toFixed(decimals);
|
|
3280
|
+
const currency = (val, symbol = "$", decimals = 2) => {
|
|
3281
|
+
return symbol + Number(val).toFixed(decimals).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
3282
|
+
};
|
|
3283
|
+
const percent = (val, decimals = 0) => (Number(val) * 100).toFixed(decimals) + "%";
|
|
3284
|
+
const thousands = (val) => String(val).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
3285
|
+
const registerFormatHelpers = (register) => {
|
|
3286
|
+
register("number", number);
|
|
3287
|
+
register("currency", currency);
|
|
3288
|
+
register("percent", percent);
|
|
3289
|
+
register("thousands", thousands);
|
|
3290
|
+
};
|
|
3291
|
+
const lookup = (val, searchArr, resultArr) => {
|
|
3292
|
+
if (!Array.isArray(searchArr)) return void 0;
|
|
3293
|
+
const idx = searchArr.indexOf(val);
|
|
3294
|
+
return idx !== -1 && Array.isArray(resultArr) ? resultArr[idx] : void 0;
|
|
3295
|
+
};
|
|
3296
|
+
const vlookup = (val, table, colIdx) => {
|
|
3297
|
+
if (!Array.isArray(table)) return void 0;
|
|
3298
|
+
const row = table.find((r) => Array.isArray(r) && r[0] === val);
|
|
3299
|
+
return row ? row[colIdx - 1] : void 0;
|
|
3300
|
+
};
|
|
3301
|
+
const index = (arr, idx) => Array.isArray(arr) ? arr[idx] : void 0;
|
|
3302
|
+
const match = (val, arr) => Array.isArray(arr) ? arr.indexOf(val) : -1;
|
|
3303
|
+
const registerLookupHelpers = (register) => {
|
|
3304
|
+
register("lookup", lookup);
|
|
3305
|
+
register("vlookup", vlookup);
|
|
3306
|
+
register("index", index);
|
|
3307
|
+
register("match", match);
|
|
3308
|
+
};
|
|
3309
|
+
const sum = (...args) => args.reduce((a, b) => a + (Number(b) || 0), 0);
|
|
3310
|
+
const avg = (...args) => args.length === 0 ? 0 : sum(...args) / args.length;
|
|
3311
|
+
const min = (...args) => Math.min(...args);
|
|
3312
|
+
const max = (...args) => Math.max(...args);
|
|
3313
|
+
const median = (...args) => {
|
|
3314
|
+
if (args.length === 0) return 0;
|
|
3315
|
+
const sorted = [...args].sort((a, b) => a - b);
|
|
3316
|
+
const mid = Math.floor(sorted.length / 2);
|
|
3317
|
+
return sorted.length % 2 !== 0 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
|
|
3318
|
+
};
|
|
3319
|
+
const stdev = (...args) => {
|
|
3320
|
+
if (args.length === 0) return 0;
|
|
3321
|
+
const mean = avg(...args);
|
|
3322
|
+
const squareDiffs = args.map((value) => Math.pow(value - mean, 2));
|
|
3323
|
+
return Math.sqrt(avg(...squareDiffs));
|
|
3324
|
+
};
|
|
3325
|
+
const variance = (...args) => {
|
|
3326
|
+
if (args.length === 0) return 0;
|
|
3327
|
+
const mean = avg(...args);
|
|
3328
|
+
const squareDiffs = args.map((value) => Math.pow(value - mean, 2));
|
|
3329
|
+
return avg(...squareDiffs);
|
|
3330
|
+
};
|
|
3331
|
+
const registerStatsHelpers = (register) => {
|
|
3332
|
+
register("sum", sum);
|
|
3333
|
+
register("avg", avg);
|
|
3334
|
+
register("min", min);
|
|
3335
|
+
register("max", max);
|
|
3336
|
+
register("median", median);
|
|
3337
|
+
register("stdev", stdev);
|
|
3338
|
+
register("var", variance);
|
|
3339
|
+
};
|
|
3340
|
+
const set = (target, val) => {
|
|
3341
|
+
if (target && typeof target === "object" && "value" in target) {
|
|
3342
|
+
target.value = val;
|
|
3343
|
+
} else if (target && typeof target === "function" && "value" in target) {
|
|
3344
|
+
target.value = val;
|
|
3345
|
+
} else if (target && typeof target === "object" && val && typeof val === "object") {
|
|
3346
|
+
Object.assign(target, val);
|
|
3347
|
+
}
|
|
3348
|
+
return val;
|
|
3349
|
+
};
|
|
3350
|
+
const increment = (target, by = 1) => {
|
|
3351
|
+
const hasValue = target && (typeof target === "object" || typeof target === "function") && "value" in target;
|
|
3352
|
+
const current = hasValue ? target.value : 0;
|
|
3353
|
+
const next = Number(current) + Number(by);
|
|
3354
|
+
return set(target, next);
|
|
3355
|
+
};
|
|
3356
|
+
const decrement = (target, by = 1) => {
|
|
3357
|
+
const hasValue = target && (typeof target === "object" || typeof target === "function") && "value" in target;
|
|
3358
|
+
const current = hasValue ? target.value : 0;
|
|
3359
|
+
const next = Number(current) - Number(by);
|
|
3360
|
+
return set(target, next);
|
|
3361
|
+
};
|
|
3362
|
+
const toggle = (target) => {
|
|
3363
|
+
const hasValue = target && (typeof target === "object" || typeof target === "function") && "value" in target;
|
|
3364
|
+
const current = hasValue ? target.value : false;
|
|
3365
|
+
return set(target, !current);
|
|
3366
|
+
};
|
|
3367
|
+
const push = (target, item) => {
|
|
3368
|
+
const current = target && typeof target === "object" && "value" in target ? target.value : [];
|
|
3369
|
+
if (Array.isArray(current)) {
|
|
3370
|
+
const next = [...current, item];
|
|
3371
|
+
return set(target, next);
|
|
3372
|
+
}
|
|
3373
|
+
return current;
|
|
3374
|
+
};
|
|
3375
|
+
const pop = (target) => {
|
|
3376
|
+
const current = target && typeof target === "object" && "value" in target ? target.value : [];
|
|
3377
|
+
if (Array.isArray(current) && current.length > 0) {
|
|
3378
|
+
const next = current.slice(0, -1);
|
|
3379
|
+
set(target, next);
|
|
3380
|
+
}
|
|
3381
|
+
return current;
|
|
3382
|
+
};
|
|
3383
|
+
const assign = (target, obj) => {
|
|
3384
|
+
const current = target && typeof target === "object" && "value" in target ? target.value : {};
|
|
3385
|
+
const next = { ...current, ...obj };
|
|
3386
|
+
return set(target, next);
|
|
3387
|
+
};
|
|
3388
|
+
const clear = (target) => {
|
|
3389
|
+
const current = target && typeof target === "object" && "value" in target ? target.value : null;
|
|
3390
|
+
if (Array.isArray(current)) return set(target, []);
|
|
3391
|
+
if (typeof current === "object" && current !== null) return set(target, {});
|
|
3392
|
+
return set(target, null);
|
|
3393
|
+
};
|
|
3394
|
+
const registerStateHelpers = (register) => {
|
|
3395
|
+
const opts = { pathAware: true };
|
|
3396
|
+
register("set", set, opts);
|
|
3397
|
+
register("increment", increment, opts);
|
|
3398
|
+
register("++", increment, opts);
|
|
3399
|
+
register("decrement", decrement, opts);
|
|
3400
|
+
register("--", decrement, opts);
|
|
3401
|
+
register("toggle", toggle, opts);
|
|
3402
|
+
register("!!", toggle, opts);
|
|
3403
|
+
register("push", push, opts);
|
|
3404
|
+
register("pop", pop, opts);
|
|
3405
|
+
register("assign", assign, opts);
|
|
3406
|
+
register("clear", clear, opts);
|
|
3407
|
+
};
|
|
3408
|
+
const fetchHelper = (url, options = {}) => {
|
|
3409
|
+
const fetchOptions = { ...options };
|
|
3410
|
+
const headers = { ...fetchOptions.headers };
|
|
3411
|
+
let body = fetchOptions.body;
|
|
3412
|
+
if (body !== void 0) {
|
|
3413
|
+
if (body !== null && typeof body === "object") {
|
|
3414
|
+
body = JSON.stringify(body);
|
|
3415
|
+
if (!headers["Content-Type"]) {
|
|
3416
|
+
headers["Content-Type"] = "application/json";
|
|
3417
|
+
}
|
|
3418
|
+
} else {
|
|
3419
|
+
body = String(body);
|
|
3420
|
+
if (!headers["Content-Type"]) {
|
|
3421
|
+
headers["Content-Type"] = "text/plain";
|
|
3422
|
+
}
|
|
3423
|
+
}
|
|
3424
|
+
}
|
|
3425
|
+
fetchOptions.body = body;
|
|
3426
|
+
fetchOptions.headers = headers;
|
|
3427
|
+
return globalThis.fetch(url, fetchOptions);
|
|
3428
|
+
};
|
|
3429
|
+
const registerNetworkHelpers = (register) => {
|
|
3430
|
+
register("fetch", fetchHelper);
|
|
3431
|
+
};
|
|
3432
|
+
registerMathHelpers(registerHelper);
|
|
3433
|
+
registerLogicHelpers(registerHelper);
|
|
3434
|
+
registerStringHelpers(registerHelper);
|
|
3435
|
+
registerArrayHelpers(registerHelper);
|
|
3436
|
+
registerCompareHelpers(registerHelper);
|
|
3437
|
+
registerConditionalHelpers(registerHelper);
|
|
3438
|
+
registerDateTimeHelpers(registerHelper);
|
|
3439
|
+
registerFormatHelpers(registerHelper);
|
|
3440
|
+
registerLookupHelpers(registerHelper);
|
|
3441
|
+
registerStatsHelpers(registerHelper);
|
|
3442
|
+
registerStateHelpers((name, fn) => registerHelper(name, fn, { pathAware: true }));
|
|
3443
|
+
registerNetworkHelpers(registerHelper);
|
|
3444
|
+
registerOperator("increment", "++", "prefix", 80);
|
|
3445
|
+
registerOperator("increment", "++", "postfix", 80);
|
|
3446
|
+
registerOperator("decrement", "--", "prefix", 80);
|
|
3447
|
+
registerOperator("decrement", "--", "postfix", 80);
|
|
3448
|
+
registerOperator("toggle", "!!", "prefix", 80);
|
|
3449
|
+
registerOperator("+", "+", "infix", 50);
|
|
3450
|
+
registerOperator("-", "-", "infix", 50);
|
|
3451
|
+
registerOperator("*", "*", "infix", 60);
|
|
3452
|
+
registerOperator("/", "/", "infix", 60);
|
|
3453
|
+
registerOperator("gt", ">", "infix", 40);
|
|
3454
|
+
registerOperator("lt", "<", "infix", 40);
|
|
3455
|
+
registerOperator("gte", ">=", "infix", 40);
|
|
3456
|
+
registerOperator("lte", "<=", "infix", 40);
|
|
3457
|
+
registerOperator("neq", "!=", "infix", 40);
|
|
3458
|
+
const localStates = /* @__PURE__ */ new WeakMap();
|
|
3459
|
+
const getContext = (node, event = null) => {
|
|
3460
|
+
const chain = [];
|
|
3461
|
+
let cur = node;
|
|
3462
|
+
const ShadowRoot2 = globalThis.ShadowRoot;
|
|
3463
|
+
while (cur) {
|
|
3464
|
+
const local = localStates.get(cur) || (cur && typeof cur === "object" ? cur.__state__ : null);
|
|
3465
|
+
if (local) chain.unshift(local);
|
|
3466
|
+
cur = cur.parentElement || (cur && typeof cur === "object" ? cur.__parent__ : null) || (ShadowRoot2 && cur.parentNode instanceof ShadowRoot2 ? cur.parentNode.host : null);
|
|
3467
|
+
}
|
|
3468
|
+
const globalRegistry = getRegistry$1();
|
|
3469
|
+
const handler = {
|
|
3470
|
+
get(target, prop, receiver) {
|
|
3471
|
+
var _a;
|
|
3472
|
+
if (prop === "$event" || prop === "event") return event;
|
|
3473
|
+
if (prop === "__parent__") return void 0;
|
|
3474
|
+
for (let i = chain.length - 1; i >= 0; i--) {
|
|
3475
|
+
const s = chain[i];
|
|
3476
|
+
if (prop in s) return s[prop];
|
|
3477
|
+
}
|
|
3478
|
+
if (globalRegistry && globalRegistry.has(prop)) return unwrapSignal(globalRegistry.get(prop));
|
|
3479
|
+
const globalState = (_a = globalThis.Lightview) == null ? void 0 : _a.state;
|
|
3480
|
+
if (globalState && prop in globalState) return unwrapSignal(globalState[prop]);
|
|
3481
|
+
return void 0;
|
|
3482
|
+
},
|
|
3483
|
+
set(target, prop, value, receiver) {
|
|
3484
|
+
var _a;
|
|
3485
|
+
for (let i = chain.length - 1; i >= 0; i--) {
|
|
3486
|
+
const s = chain[i];
|
|
3487
|
+
if (prop in s) {
|
|
3488
|
+
s[prop] = value;
|
|
3489
|
+
return true;
|
|
3490
|
+
}
|
|
3491
|
+
}
|
|
3492
|
+
if (chain.length > 0) {
|
|
3493
|
+
chain[chain.length - 1][prop] = value;
|
|
3494
|
+
return true;
|
|
3495
|
+
}
|
|
3496
|
+
const globalState = (_a = globalThis.Lightview) == null ? void 0 : _a.state;
|
|
3497
|
+
if (globalState && prop in globalState) {
|
|
3498
|
+
globalState[prop] = value;
|
|
3499
|
+
return true;
|
|
3500
|
+
}
|
|
3501
|
+
if (globalRegistry && globalRegistry.has(prop)) {
|
|
3502
|
+
const s = globalRegistry.get(prop);
|
|
3503
|
+
if (s && (typeof s === "object" || typeof s === "function") && "value" in s) {
|
|
3504
|
+
s.value = value;
|
|
3505
|
+
return true;
|
|
3506
|
+
}
|
|
3507
|
+
}
|
|
3508
|
+
return false;
|
|
3509
|
+
},
|
|
3510
|
+
has(target, prop) {
|
|
3511
|
+
var _a;
|
|
3512
|
+
const exists = prop === "$event" || prop === "event" || !!chain.find((s) => prop in s);
|
|
3513
|
+
const inGlobal = ((_a = globalThis.Lightview) == null ? void 0 : _a.state) && prop in globalThis.Lightview.state || globalRegistry && globalRegistry.has(prop);
|
|
3514
|
+
return exists || inGlobal;
|
|
3515
|
+
},
|
|
3516
|
+
ownKeys(target) {
|
|
3517
|
+
var _a;
|
|
3518
|
+
const keys = /* @__PURE__ */ new Set();
|
|
3519
|
+
if (event) {
|
|
3520
|
+
keys.add("$event");
|
|
3521
|
+
keys.add("event");
|
|
3522
|
+
}
|
|
3523
|
+
for (const s of chain) {
|
|
3524
|
+
for (const key in s) keys.add(key);
|
|
3525
|
+
}
|
|
3526
|
+
const globalState = (_a = globalThis.Lightview) == null ? void 0 : _a.state;
|
|
3527
|
+
if (globalState) {
|
|
3528
|
+
for (const key in globalState) keys.add(key);
|
|
3529
|
+
}
|
|
3530
|
+
return Array.from(keys);
|
|
3531
|
+
},
|
|
3532
|
+
getOwnPropertyDescriptor(target, prop) {
|
|
3533
|
+
return { enumerable: true, configurable: true };
|
|
3534
|
+
}
|
|
3535
|
+
};
|
|
3536
|
+
return new Proxy({}, handler);
|
|
3537
|
+
};
|
|
3538
|
+
const handleCDOMState = (node) => {
|
|
3539
|
+
var _a;
|
|
3540
|
+
const attr = node["cdom-state"] || node.getAttribute && node.getAttribute("cdom-state");
|
|
3541
|
+
if (!attr || localStates.has(node)) return;
|
|
3542
|
+
try {
|
|
3543
|
+
const data = typeof attr === "object" ? attr : JSON.parse(attr);
|
|
3544
|
+
const s = state(data);
|
|
3545
|
+
localStates.set(node, s);
|
|
3546
|
+
if (node && typeof node === "object") {
|
|
3547
|
+
node.__state__ = s;
|
|
3548
|
+
}
|
|
3549
|
+
} catch (e) {
|
|
3550
|
+
(_a = globalThis.console) == null ? void 0 : _a.error("LightviewCDOM: Failed to parse cdom-state", e);
|
|
3551
|
+
}
|
|
3552
|
+
};
|
|
3553
|
+
const handleCDOMBind = (node) => {
|
|
3554
|
+
const path = node["cdom-bind"] || node.getAttribute("cdom-bind");
|
|
3555
|
+
if (!path) return;
|
|
3556
|
+
const type = node.type || "";
|
|
3557
|
+
const tagName = node.tagName.toLowerCase();
|
|
3558
|
+
let prop = "value";
|
|
3559
|
+
let event = "input";
|
|
3560
|
+
if (type === "checkbox" || type === "radio") {
|
|
3561
|
+
prop = "checked";
|
|
3562
|
+
event = "change";
|
|
3563
|
+
} else if (tagName === "select") {
|
|
3564
|
+
event = "change";
|
|
3565
|
+
}
|
|
3566
|
+
const context = getContext(node);
|
|
3567
|
+
let target = resolvePathAsContext(path, context);
|
|
3568
|
+
if (target && target.isBindingTarget && target.value === void 0) {
|
|
3569
|
+
const val = node[prop];
|
|
3570
|
+
if (val !== void 0 && val !== "") {
|
|
3571
|
+
set(context, { [target.key]: val });
|
|
3572
|
+
target = resolvePathAsContext(path, context);
|
|
3573
|
+
}
|
|
3574
|
+
}
|
|
3575
|
+
effect(() => {
|
|
3576
|
+
const val = unwrapSignal(target);
|
|
3577
|
+
if (node[prop] !== val) {
|
|
3578
|
+
node[prop] = val === void 0 ? "" : val;
|
|
3579
|
+
}
|
|
3580
|
+
});
|
|
3581
|
+
node.addEventListener(event, () => {
|
|
3582
|
+
const val = node[prop];
|
|
3583
|
+
if (target && target.isBindingTarget) {
|
|
3584
|
+
target.value = val;
|
|
3585
|
+
} else {
|
|
3586
|
+
set(context, { [path]: val });
|
|
3587
|
+
}
|
|
3588
|
+
});
|
|
3589
|
+
};
|
|
3590
|
+
const activate = (root = document.body) => {
|
|
3591
|
+
const walk = (node) => {
|
|
3592
|
+
if (node.nodeType === 1) {
|
|
3593
|
+
if (node.hasAttribute("cdom-state")) handleCDOMState(node);
|
|
3594
|
+
if (node.hasAttribute("cdom-bind")) handleCDOMBind(node);
|
|
3595
|
+
}
|
|
3596
|
+
let child = node.firstChild;
|
|
3597
|
+
while (child) {
|
|
3598
|
+
walk(child);
|
|
3599
|
+
child = child.nextSibling;
|
|
3600
|
+
}
|
|
3601
|
+
};
|
|
3602
|
+
walk(root);
|
|
3603
|
+
};
|
|
3604
|
+
const hydrate = (node, parent = null) => {
|
|
3605
|
+
if (!node) return node;
|
|
3606
|
+
if (typeof node === "string" && node.startsWith("$")) {
|
|
3607
|
+
return parseExpression(node, parent);
|
|
3608
|
+
}
|
|
3609
|
+
if (Array.isArray(node)) {
|
|
3610
|
+
return node.map((item) => hydrate(item, parent));
|
|
3611
|
+
}
|
|
3612
|
+
if (node instanceof String) {
|
|
3613
|
+
return node.toString();
|
|
3614
|
+
}
|
|
3615
|
+
if (typeof node === "object" && node !== null) {
|
|
3616
|
+
if (parent && !("__parent__" in node)) {
|
|
3617
|
+
Object.defineProperty(node, "__parent__", {
|
|
3618
|
+
value: parent,
|
|
3619
|
+
enumerable: false,
|
|
3620
|
+
writable: true,
|
|
3621
|
+
configurable: true
|
|
3622
|
+
});
|
|
3623
|
+
}
|
|
3624
|
+
if (!node.tag) {
|
|
3625
|
+
let potentialTag = null;
|
|
3626
|
+
for (const key in node) {
|
|
3627
|
+
if (key === "children" || key === "attributes" || key === "tag" || key.startsWith("cdom-") || key.startsWith("on") || key === "__parent__") {
|
|
3628
|
+
continue;
|
|
3629
|
+
}
|
|
3630
|
+
const attrNames = [
|
|
3631
|
+
// Form/input attributes
|
|
3632
|
+
"type",
|
|
3633
|
+
"name",
|
|
3634
|
+
"value",
|
|
3635
|
+
"placeholder",
|
|
3636
|
+
"step",
|
|
3637
|
+
"min",
|
|
3638
|
+
"max",
|
|
3639
|
+
"pattern",
|
|
3640
|
+
"disabled",
|
|
3641
|
+
"checked",
|
|
3642
|
+
"selected",
|
|
3643
|
+
"readonly",
|
|
3644
|
+
"required",
|
|
3645
|
+
"multiple",
|
|
3646
|
+
"rows",
|
|
3647
|
+
"cols",
|
|
3648
|
+
"size",
|
|
3649
|
+
"maxlength",
|
|
3650
|
+
"minlength",
|
|
3651
|
+
"autocomplete",
|
|
3652
|
+
// Common element attributes
|
|
3653
|
+
"id",
|
|
3654
|
+
"class",
|
|
3655
|
+
"className",
|
|
3656
|
+
"style",
|
|
3657
|
+
"title",
|
|
3658
|
+
"tabindex",
|
|
3659
|
+
"role",
|
|
3660
|
+
"href",
|
|
3661
|
+
"src",
|
|
3662
|
+
"alt",
|
|
3663
|
+
"width",
|
|
3664
|
+
"height",
|
|
3665
|
+
"target",
|
|
3666
|
+
"rel",
|
|
3667
|
+
// Data attributes
|
|
3668
|
+
"data",
|
|
3669
|
+
"label",
|
|
3670
|
+
"text",
|
|
3671
|
+
"description",
|
|
3672
|
+
"content",
|
|
3673
|
+
// Common data property names
|
|
3674
|
+
"price",
|
|
3675
|
+
"qty",
|
|
3676
|
+
"items",
|
|
3677
|
+
"count",
|
|
3678
|
+
"total",
|
|
3679
|
+
"amount",
|
|
3680
|
+
"url"
|
|
3681
|
+
];
|
|
3682
|
+
if (attrNames.includes(key)) {
|
|
3683
|
+
continue;
|
|
3684
|
+
}
|
|
3685
|
+
potentialTag = key;
|
|
3686
|
+
break;
|
|
3687
|
+
}
|
|
3688
|
+
if (potentialTag) {
|
|
3689
|
+
const content = node[potentialTag];
|
|
3690
|
+
if (content !== void 0 && content !== null) {
|
|
3691
|
+
node.tag = potentialTag;
|
|
3692
|
+
if (Array.isArray(content)) {
|
|
3693
|
+
node.children = content;
|
|
3694
|
+
} else if (typeof content === "object") {
|
|
3695
|
+
node.attributes = node.attributes || {};
|
|
3696
|
+
for (const k in content) {
|
|
3697
|
+
if (k === "children") {
|
|
3698
|
+
node.children = content[k];
|
|
3699
|
+
} else if (k.startsWith("cdom-")) {
|
|
3700
|
+
node[k] = content[k];
|
|
3701
|
+
} else {
|
|
3702
|
+
node.attributes[k] = content[k];
|
|
3703
|
+
}
|
|
3704
|
+
}
|
|
3705
|
+
} else {
|
|
3706
|
+
node.children = [content];
|
|
3707
|
+
}
|
|
3708
|
+
delete node[potentialTag];
|
|
3709
|
+
}
|
|
3710
|
+
}
|
|
3711
|
+
}
|
|
3712
|
+
if (node["cdom-state"]) {
|
|
3713
|
+
handleCDOMState(node);
|
|
3714
|
+
}
|
|
3715
|
+
for (const key in node) {
|
|
3716
|
+
const value = node[key];
|
|
3717
|
+
if (key === "cdom-state") {
|
|
3718
|
+
continue;
|
|
3719
|
+
}
|
|
3720
|
+
if (typeof value === "string" && value.startsWith("$")) {
|
|
3721
|
+
if (key.startsWith("on")) {
|
|
3722
|
+
node[key] = (event) => {
|
|
3723
|
+
const element2 = event.currentTarget;
|
|
3724
|
+
const context = getContext(element2, event);
|
|
3725
|
+
const result = resolveExpression(value, context);
|
|
3726
|
+
if (result && typeof result === "object" && result.isLazy && typeof result.resolve === "function") {
|
|
3727
|
+
return result.resolve(event);
|
|
3728
|
+
}
|
|
3729
|
+
return result;
|
|
3730
|
+
};
|
|
3731
|
+
} else if (key === "children") {
|
|
3732
|
+
node[key] = [parseExpression(value, node)];
|
|
3733
|
+
} else {
|
|
3734
|
+
node[key] = parseExpression(value, node);
|
|
3735
|
+
}
|
|
3736
|
+
} else if (key === "attributes" && typeof value === "object" && value !== null) {
|
|
3737
|
+
for (const attrKey in value) {
|
|
3738
|
+
const attrValue = value[attrKey];
|
|
3739
|
+
if (typeof attrValue === "string" && attrValue.startsWith("$")) {
|
|
3740
|
+
if (attrKey.startsWith("on")) {
|
|
3741
|
+
value[attrKey] = (event) => {
|
|
3742
|
+
const element2 = event.currentTarget;
|
|
3743
|
+
const context = getContext(element2, event);
|
|
3744
|
+
const result = resolveExpression(attrValue, context);
|
|
3745
|
+
if (result && typeof result === "object" && result.isLazy && typeof result.resolve === "function") {
|
|
3746
|
+
return result.resolve(event);
|
|
3747
|
+
}
|
|
3748
|
+
return result;
|
|
3749
|
+
};
|
|
3750
|
+
} else {
|
|
3751
|
+
value[attrKey] = parseExpression(attrValue, node);
|
|
3752
|
+
}
|
|
3753
|
+
}
|
|
3754
|
+
}
|
|
3755
|
+
node[key] = value;
|
|
3756
|
+
} else {
|
|
3757
|
+
node[key] = hydrate(value, node);
|
|
3758
|
+
}
|
|
3759
|
+
}
|
|
3760
|
+
return node;
|
|
3761
|
+
}
|
|
3762
|
+
return node;
|
|
3763
|
+
};
|
|
3764
|
+
const LightviewCDOM = {
|
|
3765
|
+
registerHelper,
|
|
3766
|
+
registerOperator,
|
|
3767
|
+
parseExpression,
|
|
3768
|
+
resolvePath,
|
|
3769
|
+
resolvePathAsContext,
|
|
3770
|
+
resolveExpression,
|
|
3771
|
+
parseCDOMC,
|
|
3772
|
+
parseJPRX,
|
|
3773
|
+
unwrapSignal,
|
|
3774
|
+
getContext,
|
|
3775
|
+
handleCDOMState,
|
|
3776
|
+
handleCDOMBind,
|
|
3777
|
+
activate,
|
|
3778
|
+
hydrate,
|
|
3779
|
+
version: "1.0.0"
|
|
3780
|
+
};
|
|
3781
|
+
if (typeof window !== "undefined") {
|
|
3782
|
+
globalThis.LightviewCDOM = LightviewCDOM;
|
|
3783
|
+
}
|
|
3784
|
+
console.log("Lightview Full Bundle Loaded");
|
|
3785
|
+
})();
|