@ynck/rendux 0.93.3 → 0.94.0
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/CHANGELOG.md +5 -0
- package/README.md +44 -1
- package/dist/rendux.cjs.min.js +2 -2
- package/dist/rendux.min.js +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v0.94.0
|
|
4
|
+
|
|
5
|
+
- Fixed x-for context propagation: reused nodes with x-key now update context on all descendants, not just the root node
|
|
6
|
+
- Fixed x-for DOM reordering: iterate backwards to ensure correct node positioning when items are moved
|
|
7
|
+
|
|
3
8
|
## v0.93.3
|
|
4
9
|
|
|
5
10
|
- fixed nested x-for rendering
|
package/README.md
CHANGED
|
@@ -465,6 +465,7 @@ The element is completely removed from the DOM (not just hidden) when the condit
|
|
|
465
465
|
### 2. List Rendering (`x-for`)
|
|
466
466
|
|
|
467
467
|
Supports two syntaxes:
|
|
468
|
+
|
|
468
469
|
```html
|
|
469
470
|
<!-- Simple iteration -->
|
|
470
471
|
<template x-for="item of items">
|
|
@@ -477,11 +478,53 @@ Supports two syntaxes:
|
|
|
477
478
|
</template>
|
|
478
479
|
```
|
|
479
480
|
|
|
481
|
+
#### Performance Optimization with `x-key`
|
|
482
|
+
|
|
483
|
+
For improved performance when updating lists, use the `x-key` attribute to enable **per-item diffing**:
|
|
484
|
+
|
|
485
|
+
```html
|
|
486
|
+
<!-- Without x-key: full re-render on every change -->
|
|
487
|
+
<template x-for="(user, index) of users">
|
|
488
|
+
<div render="user.name"></div>
|
|
489
|
+
</template>
|
|
490
|
+
|
|
491
|
+
<!-- With x-key: only changed items are re-rendered -->
|
|
492
|
+
<template x-for="(user, index) of users">
|
|
493
|
+
<div render="user.name" x-key="user.id"></div>
|
|
494
|
+
</template>
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
**How `x-key` works:**
|
|
498
|
+
- Each item is tracked by its unique `x-key` value (e.g., `user.id`, `index`, or any unique expression)
|
|
499
|
+
- When the array changes, `rendux` compares the new items with the old ones by their `x-key`
|
|
500
|
+
- **Reuses existing DOM nodes** for items that haven't changed (only updates their data)
|
|
501
|
+
- **Creates new nodes** only for new items
|
|
502
|
+
- **Removes nodes** only for deleted items
|
|
503
|
+
- **Reorders nodes** efficiently when items are moved
|
|
504
|
+
|
|
505
|
+
**Performance benefits:**
|
|
506
|
+
- ✅ **Faster updates**: Only changed items are processed, not the entire list
|
|
507
|
+
- ✅ **Preserves DOM state**: Input focus, scroll position, and animations are maintained
|
|
508
|
+
- ✅ **Reduces layout thrashing**: Minimal DOM manipulation
|
|
509
|
+
- ✅ **Better for large lists**: Scales well with thousands of items
|
|
510
|
+
|
|
511
|
+
**When to use `x-key`:**
|
|
512
|
+
- Lists that frequently update (add/remove/reorder items)
|
|
513
|
+
- Large lists (100+ items)
|
|
514
|
+
- Lists with user input (forms, checkboxes, text fields)
|
|
515
|
+
- Lists with animations or transitions
|
|
516
|
+
|
|
517
|
+
**Best practices:**
|
|
518
|
+
- Use a **unique, stable identifier** like `user.id` or `item.uuid`
|
|
519
|
+
- Avoid using `index` if items can be reordered or filtered
|
|
520
|
+
- The `x-key` expression is evaluated for each item and should return a primitive value (string, number)
|
|
521
|
+
|
|
480
522
|
Features:
|
|
481
523
|
- Uses `<template>` tag to define the repeatable content
|
|
482
524
|
- Maintains its own render cache per iteration
|
|
483
525
|
- Supports deep change detection for arrays
|
|
484
526
|
- Provides iteration context to nested elements
|
|
527
|
+
- **Per-item diffing with `x-key` for optimal performance**
|
|
485
528
|
|
|
486
529
|
### 3. Class Binding (`x-class`)
|
|
487
530
|
|
|
@@ -810,7 +853,7 @@ This security model makes rendux suitable for applications handling user-generat
|
|
|
810
853
|
|
|
811
854
|
rendux has been designed and audited to ensure maximum security for web applications:
|
|
812
855
|
|
|
813
|
-
#### Core Engine Security
|
|
856
|
+
#### Core Engine Security
|
|
814
857
|
|
|
815
858
|
**No Dangerous Functions**
|
|
816
859
|
- ✓ No `eval()` or `Function()` constructor used
|
package/dist/rendux.cjs.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! rendux v0.
|
|
2
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});const e={Math:Math,Date:Date,Number:Number,String:String,Boolean:Boolean,JSON:JSON,parseInt:parseInt,parseFloat:parseFloat,isFinite:isFinite,Array:Array};function t(t,r={}){const n=function(e){const t=[];let r=0;for(;r<e.length;){let n=e[r];if(/\s/.test(n)){r++;continue}if('"'===n||"'"===n){const o=n;let s="";for(r++;r<e.length&&e[r]!==o;)"\\"===e[r]?(r++,r<e.length&&(s+=e[r++])):s+=e[r++];r++,t.push({type:"string",value:s});continue}if(/[0-9]/.test(n)||"."===n&&/[0-9]/.test(e[r+1])){let n=r;for(;r<e.length&&/[0-9]/.test(e[r]);)r++;if("."===e[r])for(r++;r<e.length&&/[0-9]/.test(e[r]);)r++;const o=parseFloat(e.slice(n,r));t.push({type:"number",value:o});continue}if(/[a-zA-Z_$]/.test(n)){let n=r;for(r++;r<e.length&&/[a-zA-Z0-9_$]/.test(e[r]);)r++;const o=e.slice(n,r);"true"===o||"false"===o?t.push({type:"boolean",value:"true"===o}):"null"===o?t.push({type:"null",value:null}):t.push({type:"identifier",value:o});continue}const o=e.substr(r,2),s=e.substr(r,3);if(["===","!=="].includes(s))t.push({type:"operator",value:s}),r+=3;else if(["==","!=",">=","<=","&&","||"].includes(o))t.push({type:"operator",value:o}),r+=2;else{if(!["+","-","*","/","%",">","<","!","?",":","(",")","[","]",".",","].includes(n))throw new Error(`Invalid character '${n}' in expression`);t.push({type:"operator",value:n}),r++}}return t.push({type:"EOF"}),t}(t);let o=0;function s(){return n[o]||{type:"EOF"}}function l(){return n[o++]||{type:"EOF"}}function a(e,t){const r=s();if(r.type!==e||void 0!==t&&r.value!==t)throw new Error(`Expected ${t||e} but got ${r.value}`);return l(),r}function i(e){const t=s();return"operator"===t.type&&t.value===e}const c=u();if("EOF"!==s().type)throw new Error(`Unexpected token: ${s().value}`);return c;function u(){let e=function(){let e=f();for(;i("||");){l();const t=f();e=e||t}return e}();if(i("?")){l();const t=u();a("operator",":");const r=u();e=e?t:r}return e}function f(){let e=d();for(;i("&&");){l();const t=d();e=e&&t}return e}function d(){let e=h();for(;["==","!=","===","!=="].includes(s().value);){const t=l().value,r=h();switch(t){case"==":e=e==r;break;case"!=":e=e!=r;break;case"===":e=e===r;break;case"!==":e=e!==r}}return e}function h(){let e=p();for(;[">","<",">=","<="].includes(s().value);){const t=l().value,r=p();switch(t){case">":e=e>r;break;case"<":e=e<r;break;case">=":e=e>=r;break;case"<=":e=e<=r}}return e}function p(){let e=x();for(;["+","-"].includes(s().value);){const t=l().value,r=x();e="+"===t?e+r:e-r}return e}function x(){let e=g();for(;["*","/","%"].includes(s().value);){const t=l().value,r=g();switch(t){case"*":e*=r;break;case"/":e/=r;break;case"%":e%=r}}return e}function g(){if(["!","+","-"].includes(s().value)){const e=l().value,t=g();switch(e){case"!":return!t;case"+":return+t;case"-":return-t}}return function(){const t=s();if("number"===t.type||"string"===t.type||"boolean"===t.type||"null"===t.type)return l(),t.value;if("identifier"===t.type){l();let n=function(t){if(t in r)return r[t];if(t in e)return e[t];if(null!=r.this&&t in r.this)return r.this[t];throw new Error(`Unknown identifier: ${t}`)}(t.value);for(;;)if(i(".")){l();const e=a("identifier").value;n=null==n?void 0:n[e]}else if(i("[")){l();const e=u();a("operator","]"),n=null==n?void 0:n[e]}else{if(!i("("))break;{l();const e=[];if(!i(")"))do{e.push(u())}while(i(",")&&l());if(a("operator",")"),"function"!=typeof n)throw new Error(`'${t.value}' is not a function`);n=n.apply(r.this,e)}}return n}if(i("(")){l();const e=u();return a("operator",")"),e}throw new Error(`Unexpected token: ${t.value}`)}()}}const r=new Map;function n(e){if(!e||!e.name)throw new Error("Invalid plugin");r.set(e.name,e)}function o(e,t={}){const n=e.match(/^([a-zA-Z_$][\w$]*)\s*\(\s*(.*)\s*\)$/);if(!n)return null;const o=n[1],s=r.get(o);if(!s)return null;const l=n[2].trim();if(""===l)return{plugin:s,args:[]};return{plugin:s,args:l.split(/\s*,\s*/).map(e=>{if(e.startsWith('"')&&e.endsWith('"')||e.startsWith("'")&&e.endsWith("'"))return e.slice(1,-1);if(/^-?\d+(?:\.\d+)?$/.test(e))return parseFloat(e);if(e in t)return t[e];throw new Error(`Unknown identifier: ${e}`)})}}async function s(e=document,t={}){const n=Array.from(e.querySelectorAll("*")).filter(e=>Array.from(e.attributes).some(e=>e.name.startsWith("render.")));for(const e of n)for(const n of Array.from(e.attributes)){if(!n.name.startsWith("render."))continue;const s=n.name,l=n.value.trim();let a,i,c;if("render.plugin"===s){let e;try{e=o(l,t)}catch(e){console.error(e);continue}if(!e)continue;a=e.plugin,i=e.args}else{const e=s.slice(7);if(a=r.get(e),!a)continue;if(l.startsWith(e+"(")){let e;try{e=o(l,t)}catch(e){console.error(e);continue}if(!e)continue;a=e.plugin,i=e.args}else i=[l]}"function"==typeof a.onBeforeExecute&&a.onBeforeExecute(e,l,t);try{c=a.execute(...i)}catch(e){continue}e.textContent=null==c?"":String(c),"function"==typeof a.onAfterExecute&&a.onAfterExecute(e,l,t)}for(const n of r.values())"function"==typeof n.onAfterRender&&await n.onAfterRender(e,t)}function rendux(e,n){const o=e,l=n;let a=n.shadowRoot||n;if(!a)throw new Error("rendux requires a DOM element as the second argument");for(const e of r.values())"function"==typeof e.onBeforeRender&&e.onBeforeRender(a,o);const i=document,c=l.getAttribute&&l.getAttribute("logs"),u=Boolean(c),f=c?new Set(c.split(",").map(e=>e.trim().toLowerCase())):new Set,d=e=>f.has("all")||f.has(e.toLowerCase())||f.has(("x-"+e).toLowerCase()),h=u&&f.has("plugins"),p=(...e)=>console.warn(...e);l._xRenderCache||(l._xRenderCache=new Map),l._xRenderOriginalText||(l._xRenderOriginalText=new WeakMap),l._xIfData||(l._xIfData=new WeakMap),l._cloneContext||(l._cloneContext=new WeakMap),l._xClassCache||(l._xClassCache=new Map),l._xForCache||(l._xForCache=new WeakMap),l.__mirrorContainer||(l.__mirrorContainer=i.createDocumentFragment());const x={};function g(e){let t=e;for(;t;){const e=l._cloneContext.get(t);if(e)return l.getAttribute&&l.getAttribute("logs")&&l.getAttribute("logs").includes("plugins")&&console.log("Found context for element:",t,e),e;t=t.parentNode}return l.getAttribute&&l.getAttribute("logs")&&l.getAttribute("logs").includes("plugins")&&console.log("Using default component context:",o),o}function y(e,r){if(!e)return!0;const n=g(r);try{return t(e,{this:n,...x})}catch(t){return void p(`[evaluate] "${e}" failed in`,n,t)}}function m(e,t){const r=g(t),n=e.match(/([^[.\]]+)|\[(\d+)\]/g);if(n)return n.reduce((e,t)=>{if(null!=e){if(t.startsWith("[")){const r=parseInt(t.slice(1,-1),10);return Array.isArray(e)?e[r]:void 0}return e[t]}},r)}function A(e){const t=e.match(/^\s*(?:\(\s*([^,\s]+)\s*,\s*([^,\s]+)\s*\)|([^,\s()]+))\s+(?:in|of)\s+(.+)$/);if(!t)throw new Error("Invalid x-for: "+e);return{loopVar:t[1]||t[3],indexVar:t[2]||null,arrayPath:t[4].trim()}}function C(e,t,r,n,o){return new Proxy(e,{has:(e,r)=>r===t||n&&r===n||r in e,get:(e,s)=>s===t?r:n&&s===n?o:e[s]})}function _(e,t){l._cloneContext.set(e,t),e.querySelectorAll("*").forEach(e=>l._cloneContext.set(e,t))}l&&Object.getPrototypeOf(l)&&Object.getOwnPropertyNames(Object.getPrototypeOf(l)).forEach(e=>{"function"==typeof l[e]&&"constructor"!==e&&(x[e]=l[e].bind(l))}),x.plugins=r;const E=u&&d("for");function b(e){try{const t=new WeakSet;return JSON.stringify(e,(e,r)=>{if("function"!=typeof r&&!e.startsWith("$")){if("object"==typeof r&&null!==r){if(t.has(r))return"[Circular]";t.add(r)}return r}})}catch(t){return`${e.length}-${e[0]?.name||""}-${e[e.length-1]?.name||""}`}}E&&console.groupCollapsed("x-for");let v=new Set,w=!0;for(;w;){const e=Array.from(a.querySelectorAll("template[x-for]")).concat(Array.from(l.__mirrorContainer.querySelectorAll("template[x-for]"))).filter(e=>!v.has(e));if(0===e.length){w=!1;break}e.forEach(e=>{let r,n,s;v.add(e),e._xForMeta||(e._xForMeta={parent:e.parentNode,next:e.nextSibling},l.__mirrorContainer.appendChild(e));try{({loopVar:r,indexVar:n,arrayPath:s}=A(e.getAttribute("x-for")))}catch(e){return void p("[x-for]",e.message)}const a=m(s,e);if(!Array.isArray(a))return void p(`[x-for] expected array at ${s}`,a);E&&console.log(`iterating ${s} → length ${a.length}`);const c=e.content.cloneNode(!0).querySelector("*"),u=c&&c.hasAttribute("x-key");if(!u){const t=b(a),r=l._xForCache.get(e);if(r&&r.arrayRef===a&&r.length===a.length&&r.signature===t)return void(E&&console.log(" → skipped (no change)"));l._xForCache.set(e,{arrayRef:a,length:a.length,signature:t})}if(u&&e._forClones&&e._forClones.length>0){E&&console.log(" → using x-key diffing");const s=c.getAttribute("x-key"),u=new Map;e._forClones.forEach(e=>{if(1===e.nodeType){const t=e.getAttribute("x-key");t&&u.set(t,e)}});const f=[],d=new Set;a.forEach((a,c)=>{E&&console.groupCollapsed(` index ${c}`);const h=C(o,r,a,n,c);let g;try{g=t(s,{this:h,...x})}catch(e){p("[x-for] Error evaluating x-key:",e),g=c}const y=String(g);if(u.has(y)){const e=u.get(y);d.add(e),E&&console.log(` → reusing node for key: ${y}`),l._cloneContext.set(e,h),f.push(e)}else{E&&console.log(` → creating new node for key: ${y}`);const t=i.createDocumentFragment();t.appendChild(e.content.cloneNode(!0));const r=t.firstElementChild;if(r){t.removeChild(r),r.setAttribute("x-key",y),_(r,h);(r.hasAttribute("render")?[r,...r.querySelectorAll("[render]")]:r.querySelectorAll("[render]")).forEach(e=>{const t=e.getAttribute("render")?.trim();t&&(l._xRenderCache.set(e,t),l._xRenderOriginalText.set(e,e.textContent))});(r.hasAttribute("x-class")?[r,...r.querySelectorAll("[x-class]")]:r.querySelectorAll("[x-class]")).forEach(e=>{const t=e.getAttribute("x-class");null!=t&&l._xClassCache.set(e,t)}),f.push(r)}}E&&console.groupEnd()}),e._forClones.forEach(e=>{if(!d.has(e)){if(E&&console.log(" → removing unused node"),1===e.nodeType){(e.hasAttribute("render")?[e,...e.querySelectorAll("[render]")]:e.querySelectorAll("[render]")).forEach(e=>{l._xRenderCache.delete(e),l._xRenderOriginalText.delete(e)});(e.hasAttribute("x-class")?[e,...e.querySelectorAll("[x-class]")]:e.querySelectorAll("[x-class]")).forEach(e=>{l._xClassCache.delete(e),l._xClassDynamicValues.delete(e)})}e.remove()}}),f.forEach((t,r)=>{const n=e._xForMeta.parent,o=r<f.length-1?f[r+1]:e._xForMeta.next;t.parentNode&&t.nextSibling===o||n.insertBefore(t,o)}),e._forClones=f}else E&&u&&console.log(" → first render with x-key"),E&&!u&&console.log(" → no x-key, full re-render"),e._forClones&&e._forClones.forEach(e=>{if(1===e.nodeType){(e.hasAttribute("render")?[e,...e.querySelectorAll("[render]")]:e.querySelectorAll("[render]")).forEach(e=>{l._xRenderCache.delete(e),l._xRenderOriginalText.delete(e)});(e.hasAttribute("x-class")?[e,...e.querySelectorAll("[x-class]")]:e.querySelectorAll("[x-class]")).forEach(e=>{l._xClassCache.delete(e),l._xClassDynamicValues.delete(e)})}e.remove()}),e._forClones=[],a.forEach((s,a)=>{E&&console.groupCollapsed(` index ${a}`);const c=i.createDocumentFragment();c.appendChild(e.content.cloneNode(!0));const f=C(o,r,s,n,a);if(_(c,f),u){const e=c.firstElementChild;if(e){const r=e.getAttribute("x-key");if(r)try{const n=t(r,{this:f,...x});e.setAttribute("x-key",String(n))}catch(t){e.setAttribute("x-key",String(a))}}}for(;c.firstChild;){const t=c.firstChild;if(e._xForMeta.parent.insertBefore(t,e._xForMeta.next),e._forClones.push(t),1===t.nodeType){(t.hasAttribute("render")?[t,...t.querySelectorAll("[render]")]:t.querySelectorAll("[render]")).forEach(e=>{const t=e.getAttribute("render")?.trim();t&&(l._xRenderCache.set(e,t),l._xRenderOriginalText.set(e,e.textContent))});(t.hasAttribute("x-class")?[t,...t.querySelectorAll("[x-class]")]:t.querySelectorAll("[x-class]")).forEach(e=>{const t=e.getAttribute("x-class");null!=t&&l._xClassCache.set(e,t)})}}E&&console.groupEnd()})})}E&&console.groupEnd();const S=u&&d("if");Array.from(a.querySelectorAll("[x-if]")).concat(Array.from(l.__mirrorContainer.querySelectorAll("[x-if]"))).forEach(e=>{const t=e.getAttribute("x-if")?.trim(),r=!t||y(t,e);S&&console.groupCollapsed("x-if",e,t,"→",r);let n=l._xIfData.get(e);n||(n={placeholder:i.createComment("x-if placeholder"),isHidden:!1},l._xIfData.set(e,n)),r||n.isHidden?r&&n.isHidden&&(n.placeholder.parentNode.replaceChild(e,n.placeholder),n.isHidden=!1):(e.parentNode.replaceChild(n.placeholder,e),l.__mirrorContainer.appendChild(e),n.isHidden=!0),S&&console.groupEnd()}),Array.from(a.querySelectorAll("[render]")).forEach(e=>{if(!l._xRenderCache.has(e)){const t=e.getAttribute("render")?.trim();t&&(l._xRenderCache.set(e,t),l._xRenderOriginalText.set(e,e.textContent))}}),Array.from(a.querySelectorAll("[x-class]")).forEach(e=>{const t=e.getAttribute("x-class");null==t||l._xClassCache.has(e)||l._xClassCache.set(e,t)});const $=u&&d("attr");Array.from(a.querySelectorAll("*")).forEach(e=>{Array.from(e.attributes).forEach(t=>{if(t.name.startsWith("x-")&&!["x-for","x-key","x-class","x-if","x-hidden"].includes(t.name)){const n=t.name,s=r.get(n);if(s&&"attribute"===s.target){const r=y(t.value.trim(),e);try{h&&console.log("[plugin]",`Executing ${n} with:`,{element:e,value:r,component:o}),s.execute(e,r,o)}catch(e){h&&console.error("[plugin]",`Error executing ${n}:`,e)}}else{const r=t.name.slice(2),n=y(t.value.trim(),e);$&&console.groupCollapsed("x-attr",e,r,"=",n),n?e.setAttribute(r,String(n)):e.removeAttribute(r),$&&console.groupEnd()}}})});const k=u&&d("class");k&&console.groupCollapsed("x-class");for(const[e,t]of l._xClassCache){k&&console.log("element →",e);const r=t.trim();if(r.includes("(")){const t=/\(\s*([^,]+?)\s*,\s*([^)]+?)\s*\)/g;l._xClassDynamicValues||(l._xClassDynamicValues=new Map);(l._xClassDynamicValues.get(e)||[]).forEach(t=>e.classList.remove(t));const n=new Set;let o;for(;o=t.exec(r);){const t=o[1].trim(),r=o[2].trim();let s;s=/^[\w\-\s]+$/.test(t)?t:y(t,e);const l=Boolean(y(r,e));let a=[];"string"==typeof s?a=s.split(/\s+/).filter(Boolean):Array.isArray(s)?a=s:s&&"object"==typeof s&&(a=Object.keys(s).filter(e=>s[e])),l&&a.forEach(t=>e.classList.add(t)),a.forEach(e=>n.add(e)),k&&console.log(` ${t} → [${a.join(" ")}] (= ${l})`)}l._xClassDynamicValues.set(e,Array.from(n))}else{l._xClassDynamicValues||(l._xClassDynamicValues=new Map);let t;(l._xClassDynamicValues.get(e)||[]).forEach(t=>e.classList.remove(t));let n=!0;if(!r.includes(",")&&/[?:]/.test(r))t=y(r,e);else{const o=r.indexOf(","),s=o>=0?r.slice(0,o).trim():r,l=o>=0?r.slice(o+1).trim():"true";n=Boolean(y(l,e)),t=s}const o=[];"string"==typeof t?o.push(...t.split(/\s+/).filter(Boolean)):Array.isArray(t)?o.push(...t):t&&"object"==typeof t&&o.push(...Object.keys(t).filter(e=>t[e])),o.forEach(t=>{n?e.classList.add(t):e.classList.remove(t)}),k&&console.log(` x-class ${r} →`,o,`ok=${n}`),l._xClassDynamicValues.set(e,o)}}k&&console.groupEnd();const q=u&&d("render");q&&console.groupCollapsed("render");for(const[e,t]of l._xRenderCache){const r=l._xIfData.get(e);if(r&&r.isHidden)continue;q&&console.log("element →",e,"expr=",t);const n=t.indexOf(","),o=n<0?t:t.slice(0,n).trim(),s=y(n<0?"true":t.slice(n+1).trim(),e);let a;if(s){let t=y(o,e);if(void 0===t)a=l._xRenderOriginalText.get(e)||"";else if(null!=t&&"object"==typeof t)try{a=JSON.stringify(t,null,2)}catch{a=String(t)}else a=null==t||"boolean"==typeof t?"":String(t)}else a=l._xRenderOriginalText.get(e)||"";e.textContent!==a&&(e.textContent=a),q&&console.log(` → "${a}" (cond=${s})`)}q&&console.groupEnd(),Array.from(a.querySelectorAll("*")).forEach(e=>{const t=l._xIfData.get(e);t&&t.isHidden||[["render","render"]].forEach(([t,r])=>{e.hasAttribute(t)&&!d(r)&&e.removeAttribute(t)})}),function e(r){Array.from(r.querySelectorAll("*")).forEach(e=>{Array.from(e.attributes).forEach(r=>{if(r.name.startsWith("@")){const n=r.name.slice(1),s=r.value.trim();e._xEventListeners&&e._xEventListeners[n]&&e.removeEventListener(n,e._xEventListeners[n]),e._xEventListeners||(e._xEventListeners={});const l=g(e),a=new Proxy(l,{get:(e,t)=>t in e?e[t]:o[t]}),i=function(e){try{return t(s,{this:a,event:e,...x})}catch(e){p(`[rendux @${n}] Error evaluating: ${s}`,e)}};e.addEventListener(n,i),e._xEventListeners[n]=i}})}),Array.from(r.querySelectorAll("slot")).forEach(t=>{(t.assignedElements?t.assignedElements({flatten:!0}):[]).forEach(t=>{e(t)})})}(a),s(a,o)}rendux.use=function(e){return n(e),rendux},"undefined"!=typeof module&&module.exports&&(module.exports={rendux:rendux,use:n,process:s,plugins:r,parsePluginCall:o}),exports.parsePluginCall=o,exports.plugins=r,exports.process=s,exports.rendux=rendux,exports.use=n;
|
|
1
|
+
/*! rendux v0.94.0 | Copyright (c) JULY 2025 Yannick J.A. CHARLERY | This software is licensed for non-commercial use only. Commercial licensing available upon request. For license details: https://github.com/ynck-chrl/rendux */
|
|
2
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});const e={Math:Math,Date:Date,Number:Number,String:String,Boolean:Boolean,JSON:JSON,parseInt:parseInt,parseFloat:parseFloat,isFinite:isFinite,Array:Array};function t(t,r={}){const n=function(e){const t=[];let r=0;for(;r<e.length;){let n=e[r];if(/\s/.test(n)){r++;continue}if('"'===n||"'"===n){const o=n;let s="";for(r++;r<e.length&&e[r]!==o;)"\\"===e[r]?(r++,r<e.length&&(s+=e[r++])):s+=e[r++];r++,t.push({type:"string",value:s});continue}if(/[0-9]/.test(n)||"."===n&&/[0-9]/.test(e[r+1])){let n=r;for(;r<e.length&&/[0-9]/.test(e[r]);)r++;if("."===e[r])for(r++;r<e.length&&/[0-9]/.test(e[r]);)r++;const o=parseFloat(e.slice(n,r));t.push({type:"number",value:o});continue}if(/[a-zA-Z_$]/.test(n)){let n=r;for(r++;r<e.length&&/[a-zA-Z0-9_$]/.test(e[r]);)r++;const o=e.slice(n,r);"true"===o||"false"===o?t.push({type:"boolean",value:"true"===o}):"null"===o?t.push({type:"null",value:null}):t.push({type:"identifier",value:o});continue}const o=e.substr(r,2),s=e.substr(r,3);if(["===","!=="].includes(s))t.push({type:"operator",value:s}),r+=3;else if(["==","!=",">=","<=","&&","||"].includes(o))t.push({type:"operator",value:o}),r+=2;else{if(!["+","-","*","/","%",">","<","!","?",":","(",")","[","]",".",","].includes(n))throw new Error(`Invalid character '${n}' in expression`);t.push({type:"operator",value:n}),r++}}return t.push({type:"EOF"}),t}(t);let o=0;function s(){return n[o]||{type:"EOF"}}function l(){return n[o++]||{type:"EOF"}}function a(e,t){const r=s();if(r.type!==e||void 0!==t&&r.value!==t)throw new Error(`Expected ${t||e} but got ${r.value}`);return l(),r}function i(e){const t=s();return"operator"===t.type&&t.value===e}const c=u();if("EOF"!==s().type)throw new Error(`Unexpected token: ${s().value}`);return c;function u(){let e=function(){let e=f();for(;i("||");){l();const t=f();e=e||t}return e}();if(i("?")){l();const t=u();a("operator",":");const r=u();e=e?t:r}return e}function f(){let e=d();for(;i("&&");){l();const t=d();e=e&&t}return e}function d(){let e=h();for(;["==","!=","===","!=="].includes(s().value);){const t=l().value,r=h();switch(t){case"==":e=e==r;break;case"!=":e=e!=r;break;case"===":e=e===r;break;case"!==":e=e!==r}}return e}function h(){let e=p();for(;[">","<",">=","<="].includes(s().value);){const t=l().value,r=p();switch(t){case">":e=e>r;break;case"<":e=e<r;break;case">=":e=e>=r;break;case"<=":e=e<=r}}return e}function p(){let e=x();for(;["+","-"].includes(s().value);){const t=l().value,r=x();e="+"===t?e+r:e-r}return e}function x(){let e=g();for(;["*","/","%"].includes(s().value);){const t=l().value,r=g();switch(t){case"*":e*=r;break;case"/":e/=r;break;case"%":e%=r}}return e}function g(){if(["!","+","-"].includes(s().value)){const e=l().value,t=g();switch(e){case"!":return!t;case"+":return+t;case"-":return-t}}return function(){const t=s();if("number"===t.type||"string"===t.type||"boolean"===t.type||"null"===t.type)return l(),t.value;if("identifier"===t.type){l();let n=function(t){if(t in r)return r[t];if(t in e)return e[t];if(null!=r.this&&t in r.this)return r.this[t];throw new Error(`Unknown identifier: ${t}`)}(t.value);for(;;)if(i(".")){l();const e=a("identifier").value;n=null==n?void 0:n[e]}else if(i("[")){l();const e=u();a("operator","]"),n=null==n?void 0:n[e]}else{if(!i("("))break;{l();const e=[];if(!i(")"))do{e.push(u())}while(i(",")&&l());if(a("operator",")"),"function"!=typeof n)throw new Error(`'${t.value}' is not a function`);n=n.apply(r.this,e)}}return n}if(i("(")){l();const e=u();return a("operator",")"),e}throw new Error(`Unexpected token: ${t.value}`)}()}}const r=new Map;function n(e){if(!e||!e.name)throw new Error("Invalid plugin");r.set(e.name,e)}function o(e,t={}){const n=e.match(/^([a-zA-Z_$][\w$]*)\s*\(\s*(.*)\s*\)$/);if(!n)return null;const o=n[1],s=r.get(o);if(!s)return null;const l=n[2].trim();if(""===l)return{plugin:s,args:[]};return{plugin:s,args:l.split(/\s*,\s*/).map(e=>{if(e.startsWith('"')&&e.endsWith('"')||e.startsWith("'")&&e.endsWith("'"))return e.slice(1,-1);if(/^-?\d+(?:\.\d+)?$/.test(e))return parseFloat(e);if(e in t)return t[e];throw new Error(`Unknown identifier: ${e}`)})}}async function s(e=document,t={}){const n=Array.from(e.querySelectorAll("*")).filter(e=>Array.from(e.attributes).some(e=>e.name.startsWith("render.")));for(const e of n)for(const n of Array.from(e.attributes)){if(!n.name.startsWith("render."))continue;const s=n.name,l=n.value.trim();let a,i,c;if("render.plugin"===s){let e;try{e=o(l,t)}catch(e){console.error(e);continue}if(!e)continue;a=e.plugin,i=e.args}else{const e=s.slice(7);if(a=r.get(e),!a)continue;if(l.startsWith(e+"(")){let e;try{e=o(l,t)}catch(e){console.error(e);continue}if(!e)continue;a=e.plugin,i=e.args}else i=[l]}"function"==typeof a.onBeforeExecute&&a.onBeforeExecute(e,l,t);try{c=a.execute(...i)}catch(e){continue}e.textContent=null==c?"":String(c),"function"==typeof a.onAfterExecute&&a.onAfterExecute(e,l,t)}for(const n of r.values())"function"==typeof n.onAfterRender&&await n.onAfterRender(e,t)}function rendux(e,n){const o=e,l=n;let a=n.shadowRoot||n;if(!a)throw new Error("rendux requires a DOM element as the second argument");for(const e of r.values())"function"==typeof e.onBeforeRender&&e.onBeforeRender(a,o);const i=document,c=l.getAttribute&&l.getAttribute("logs"),u=Boolean(c),f=c?new Set(c.split(",").map(e=>e.trim().toLowerCase())):new Set,d=e=>f.has("all")||f.has(e.toLowerCase())||f.has(("x-"+e).toLowerCase()),h=u&&f.has("plugins"),p=(...e)=>console.warn(...e);l._xRenderCache||(l._xRenderCache=new Map),l._xRenderOriginalText||(l._xRenderOriginalText=new WeakMap),l._xIfData||(l._xIfData=new WeakMap),l._cloneContext||(l._cloneContext=new WeakMap),l._xClassCache||(l._xClassCache=new Map),l._xForCache||(l._xForCache=new WeakMap),l.__mirrorContainer||(l.__mirrorContainer=i.createDocumentFragment());const x={};function g(e){let t=e;for(;t;){const e=l._cloneContext.get(t);if(e)return l.getAttribute&&l.getAttribute("logs")&&l.getAttribute("logs").includes("plugins")&&console.log("Found context for element:",t,e),e;t=t.parentNode}return l.getAttribute&&l.getAttribute("logs")&&l.getAttribute("logs").includes("plugins")&&console.log("Using default component context:",o),o}function y(e,r){if(!e)return!0;const n=g(r);try{return t(e,{this:n,...x})}catch(t){return void p(`[evaluate] "${e}" failed in`,n,t)}}function m(e,t){const r=g(t),n=e.match(/([^[.\]]+)|\[(\d+)\]/g);if(n)return n.reduce((e,t)=>{if(null!=e){if(t.startsWith("[")){const r=parseInt(t.slice(1,-1),10);return Array.isArray(e)?e[r]:void 0}return e[t]}},r)}function A(e){const t=e.match(/^\s*(?:\(\s*([^,\s]+)\s*,\s*([^,\s]+)\s*\)|([^,\s()]+))\s+(?:in|of)\s+(.+)$/);if(!t)throw new Error("Invalid x-for: "+e);return{loopVar:t[1]||t[3],indexVar:t[2]||null,arrayPath:t[4].trim()}}function C(e,t,r,n,o){return new Proxy(e,{has:(e,r)=>r===t||n&&r===n||r in e,get:(e,s)=>s===t?r:n&&s===n?o:e[s]})}function _(e,t){l._cloneContext.set(e,t),e.querySelectorAll("*").forEach(e=>l._cloneContext.set(e,t))}l&&Object.getPrototypeOf(l)&&Object.getOwnPropertyNames(Object.getPrototypeOf(l)).forEach(e=>{"function"==typeof l[e]&&"constructor"!==e&&(x[e]=l[e].bind(l))}),x.plugins=r;const E=u&&d("for");function b(e){try{const t=new WeakSet;return JSON.stringify(e,(e,r)=>{if("function"!=typeof r&&!e.startsWith("$")){if("object"==typeof r&&null!==r){if(t.has(r))return"[Circular]";t.add(r)}return r}})}catch(t){return`${e.length}-${e[0]?.name||""}-${e[e.length-1]?.name||""}`}}E&&console.groupCollapsed("x-for");let v=new Set,w=!0;for(;w;){const e=Array.from(a.querySelectorAll("template[x-for]")).concat(Array.from(l.__mirrorContainer.querySelectorAll("template[x-for]"))).filter(e=>!v.has(e));if(0===e.length){w=!1;break}e.forEach(e=>{let r,n,s;v.add(e),e._xForMeta||(e._xForMeta={parent:e.parentNode,next:e.nextSibling},l.__mirrorContainer.appendChild(e));try{({loopVar:r,indexVar:n,arrayPath:s}=A(e.getAttribute("x-for")))}catch(e){return void p("[x-for]",e.message)}const a=m(s,e);if(!Array.isArray(a))return void p(`[x-for] expected array at ${s}`,a);E&&console.log(`iterating ${s} → length ${a.length}`);const c=e.content.cloneNode(!0).querySelector("*"),u=c&&c.hasAttribute("x-key");if(!u){const t=b(a),r=l._xForCache.get(e);if(r&&r.arrayRef===a&&r.length===a.length&&r.signature===t)return void(E&&console.log(" → skipped (no change)"));l._xForCache.set(e,{arrayRef:a,length:a.length,signature:t})}if(u&&e._forClones&&e._forClones.length>0){E&&console.log(" → using x-key diffing");const s=c.getAttribute("x-key"),u=new Map;e._forClones.forEach(e=>{if(1===e.nodeType){const t=e.getAttribute("x-key");t&&u.set(t,e)}});const f=[],d=new Set;a.forEach((a,c)=>{E&&console.groupCollapsed(` index ${c}`);const h=C(o,r,a,n,c);let g;try{g=t(s,{this:h,...x})}catch(e){p("[x-for] Error evaluating x-key:",e),g=c}const y=String(g);if(u.has(y)){const e=u.get(y);d.add(e),E&&console.log(` → reusing node for key: ${y}`),_(e,h),f.push(e)}else{E&&console.log(` → creating new node for key: ${y}`);const t=i.createDocumentFragment();t.appendChild(e.content.cloneNode(!0));const r=t.firstElementChild;if(r){t.removeChild(r),r.setAttribute("x-key",y),_(r,h);(r.hasAttribute("render")?[r,...r.querySelectorAll("[render]")]:r.querySelectorAll("[render]")).forEach(e=>{const t=e.getAttribute("render")?.trim();t&&(l._xRenderCache.set(e,t),l._xRenderOriginalText.set(e,e.textContent))});(r.hasAttribute("x-class")?[r,...r.querySelectorAll("[x-class]")]:r.querySelectorAll("[x-class]")).forEach(e=>{const t=e.getAttribute("x-class");null!=t&&l._xClassCache.set(e,t)}),f.push(r)}}E&&console.groupEnd()}),e._forClones.forEach(e=>{if(!d.has(e)){if(E&&console.log(" → removing unused node"),1===e.nodeType){(e.hasAttribute("render")?[e,...e.querySelectorAll("[render]")]:e.querySelectorAll("[render]")).forEach(e=>{l._xRenderCache.delete(e),l._xRenderOriginalText.delete(e)});(e.hasAttribute("x-class")?[e,...e.querySelectorAll("[x-class]")]:e.querySelectorAll("[x-class]")).forEach(e=>{l._xClassCache.delete(e),l._xClassDynamicValues.delete(e)})}e.remove()}});for(let t=f.length-1;t>=0;t--){const r=f[t],n=e._xForMeta.parent,o=t<f.length-1?f[t+1]:e._xForMeta.next;r.parentNode&&r.nextSibling===o||n.insertBefore(r,o)}e._forClones=f}else E&&u&&console.log(" → first render with x-key"),E&&!u&&console.log(" → no x-key, full re-render"),e._forClones&&e._forClones.forEach(e=>{if(1===e.nodeType){(e.hasAttribute("render")?[e,...e.querySelectorAll("[render]")]:e.querySelectorAll("[render]")).forEach(e=>{l._xRenderCache.delete(e),l._xRenderOriginalText.delete(e)});(e.hasAttribute("x-class")?[e,...e.querySelectorAll("[x-class]")]:e.querySelectorAll("[x-class]")).forEach(e=>{l._xClassCache.delete(e),l._xClassDynamicValues.delete(e)})}e.remove()}),e._forClones=[],a.forEach((s,a)=>{E&&console.groupCollapsed(` index ${a}`);const c=i.createDocumentFragment();c.appendChild(e.content.cloneNode(!0));const f=C(o,r,s,n,a);if(_(c,f),u){const e=c.firstElementChild;if(e){const r=e.getAttribute("x-key");if(r)try{const n=t(r,{this:f,...x});e.setAttribute("x-key",String(n))}catch(t){e.setAttribute("x-key",String(a))}}}for(;c.firstChild;){const t=c.firstChild;if(e._xForMeta.parent.insertBefore(t,e._xForMeta.next),e._forClones.push(t),1===t.nodeType){(t.hasAttribute("render")?[t,...t.querySelectorAll("[render]")]:t.querySelectorAll("[render]")).forEach(e=>{const t=e.getAttribute("render")?.trim();t&&(l._xRenderCache.set(e,t),l._xRenderOriginalText.set(e,e.textContent))});(t.hasAttribute("x-class")?[t,...t.querySelectorAll("[x-class]")]:t.querySelectorAll("[x-class]")).forEach(e=>{const t=e.getAttribute("x-class");null!=t&&l._xClassCache.set(e,t)})}}E&&console.groupEnd()})})}E&&console.groupEnd();const S=u&&d("if");Array.from(a.querySelectorAll("[x-if]")).concat(Array.from(l.__mirrorContainer.querySelectorAll("[x-if]"))).forEach(e=>{const t=e.getAttribute("x-if")?.trim(),r=!t||y(t,e);S&&console.groupCollapsed("x-if",e,t,"→",r);let n=l._xIfData.get(e);n||(n={placeholder:i.createComment("x-if placeholder"),isHidden:!1},l._xIfData.set(e,n)),r||n.isHidden?r&&n.isHidden&&(n.placeholder.parentNode.replaceChild(e,n.placeholder),n.isHidden=!1):(e.parentNode.replaceChild(n.placeholder,e),l.__mirrorContainer.appendChild(e),n.isHidden=!0),S&&console.groupEnd()}),Array.from(a.querySelectorAll("[render]")).forEach(e=>{if(!l._xRenderCache.has(e)){const t=e.getAttribute("render")?.trim();t&&(l._xRenderCache.set(e,t),l._xRenderOriginalText.set(e,e.textContent))}}),Array.from(a.querySelectorAll("[x-class]")).forEach(e=>{const t=e.getAttribute("x-class");null==t||l._xClassCache.has(e)||l._xClassCache.set(e,t)});const $=u&&d("attr");Array.from(a.querySelectorAll("*")).forEach(e=>{Array.from(e.attributes).forEach(t=>{if(t.name.startsWith("x-")&&!["x-for","x-key","x-class","x-if","x-hidden"].includes(t.name)){const n=t.name,s=r.get(n);if(s&&"attribute"===s.target){const r=y(t.value.trim(),e);try{h&&console.log("[plugin]",`Executing ${n} with:`,{element:e,value:r,component:o}),s.execute(e,r,o)}catch(e){h&&console.error("[plugin]",`Error executing ${n}:`,e)}}else{const r=t.name.slice(2),n=y(t.value.trim(),e);$&&console.groupCollapsed("x-attr",e,r,"=",n),n?e.setAttribute(r,String(n)):e.removeAttribute(r),$&&console.groupEnd()}}})});const k=u&&d("class");k&&console.groupCollapsed("x-class");for(const[e,t]of l._xClassCache){k&&console.log("element →",e);const r=t.trim();if(r.includes("(")){const t=/\(\s*([^,]+?)\s*,\s*([^)]+?)\s*\)/g;l._xClassDynamicValues||(l._xClassDynamicValues=new Map);(l._xClassDynamicValues.get(e)||[]).forEach(t=>e.classList.remove(t));const n=new Set;let o;for(;o=t.exec(r);){const t=o[1].trim(),r=o[2].trim();let s;s=/^[\w\-\s]+$/.test(t)?t:y(t,e);const l=Boolean(y(r,e));let a=[];"string"==typeof s?a=s.split(/\s+/).filter(Boolean):Array.isArray(s)?a=s:s&&"object"==typeof s&&(a=Object.keys(s).filter(e=>s[e])),l&&a.forEach(t=>e.classList.add(t)),a.forEach(e=>n.add(e)),k&&console.log(` ${t} → [${a.join(" ")}] (= ${l})`)}l._xClassDynamicValues.set(e,Array.from(n))}else{l._xClassDynamicValues||(l._xClassDynamicValues=new Map);let t;(l._xClassDynamicValues.get(e)||[]).forEach(t=>e.classList.remove(t));let n=!0;if(!r.includes(",")&&/[?:]/.test(r))t=y(r,e);else{const o=r.indexOf(","),s=o>=0?r.slice(0,o).trim():r,l=o>=0?r.slice(o+1).trim():"true";n=Boolean(y(l,e)),t=s}const o=[];"string"==typeof t?o.push(...t.split(/\s+/).filter(Boolean)):Array.isArray(t)?o.push(...t):t&&"object"==typeof t&&o.push(...Object.keys(t).filter(e=>t[e])),o.forEach(t=>{n?e.classList.add(t):e.classList.remove(t)}),k&&console.log(` x-class ${r} →`,o,`ok=${n}`),l._xClassDynamicValues.set(e,o)}}k&&console.groupEnd();const q=u&&d("render");q&&console.groupCollapsed("render");for(const[e,t]of l._xRenderCache){const r=l._xIfData.get(e);if(r&&r.isHidden)continue;q&&console.log("element →",e,"expr=",t);const n=t.indexOf(","),o=n<0?t:t.slice(0,n).trim(),s=y(n<0?"true":t.slice(n+1).trim(),e);let a;if(s){let t=y(o,e);if(void 0===t)a=l._xRenderOriginalText.get(e)||"";else if(null!=t&&"object"==typeof t)try{a=JSON.stringify(t,null,2)}catch{a=String(t)}else a=null==t||"boolean"==typeof t?"":String(t)}else a=l._xRenderOriginalText.get(e)||"";e.textContent!==a&&(e.textContent=a),q&&console.log(` → "${a}" (cond=${s})`)}q&&console.groupEnd(),Array.from(a.querySelectorAll("*")).forEach(e=>{const t=l._xIfData.get(e);t&&t.isHidden||[["render","render"]].forEach(([t,r])=>{e.hasAttribute(t)&&!d(r)&&e.removeAttribute(t)})}),function e(r){Array.from(r.querySelectorAll("*")).forEach(e=>{Array.from(e.attributes).forEach(r=>{if(r.name.startsWith("@")){const n=r.name.slice(1),s=r.value.trim();e._xEventListeners&&e._xEventListeners[n]&&e.removeEventListener(n,e._xEventListeners[n]),e._xEventListeners||(e._xEventListeners={});const l=g(e),a=new Proxy(l,{get:(e,t)=>t in e?e[t]:o[t]}),i=function(e){try{return t(s,{this:a,event:e,...x})}catch(e){p(`[rendux @${n}] Error evaluating: ${s}`,e)}};e.addEventListener(n,i),e._xEventListeners[n]=i}})}),Array.from(r.querySelectorAll("slot")).forEach(t=>{(t.assignedElements?t.assignedElements({flatten:!0}):[]).forEach(t=>{e(t)})})}(a),s(a,o)}rendux.use=function(e){return n(e),rendux},"undefined"!=typeof module&&module.exports&&(module.exports={rendux:rendux,use:n,process:s,plugins:r,parsePluginCall:o}),exports.html=(e,...t)=>String.raw({raw:e},...t),exports.parsePluginCall=o,exports.plugins=r,exports.process=s,exports.rendux=rendux,exports.use=n;
|
package/dist/rendux.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! rendux v0.
|
|
2
|
-
const e={Math:Math,Date:Date,Number:Number,String:String,Boolean:Boolean,JSON:JSON,parseInt:parseInt,parseFloat:parseFloat,isFinite:isFinite,Array:Array};function t(t,r={}){const n=function(e){const t=[];let r=0;for(;r<e.length;){let n=e[r];if(/\s/.test(n)){r++;continue}if('"'===n||"'"===n){const o=n;let s="";for(r++;r<e.length&&e[r]!==o;)"\\"===e[r]?(r++,r<e.length&&(s+=e[r++])):s+=e[r++];r++,t.push({type:"string",value:s});continue}if(/[0-9]/.test(n)||"."===n&&/[0-9]/.test(e[r+1])){let n=r;for(;r<e.length&&/[0-9]/.test(e[r]);)r++;if("."===e[r])for(r++;r<e.length&&/[0-9]/.test(e[r]);)r++;const o=parseFloat(e.slice(n,r));t.push({type:"number",value:o});continue}if(/[a-zA-Z_$]/.test(n)){let n=r;for(r++;r<e.length&&/[a-zA-Z0-9_$]/.test(e[r]);)r++;const o=e.slice(n,r);"true"===o||"false"===o?t.push({type:"boolean",value:"true"===o}):"null"===o?t.push({type:"null",value:null}):t.push({type:"identifier",value:o});continue}const o=e.substr(r,2),s=e.substr(r,3);if(["===","!=="].includes(s))t.push({type:"operator",value:s}),r+=3;else if(["==","!=",">=","<=","&&","||"].includes(o))t.push({type:"operator",value:o}),r+=2;else{if(!["+","-","*","/","%",">","<","!","?",":","(",")","[","]",".",","].includes(n))throw new Error(`Invalid character '${n}' in expression`);t.push({type:"operator",value:n}),r++}}return t.push({type:"EOF"}),t}(t);let o=0;function s(){return n[o]||{type:"EOF"}}function l(){return n[o++]||{type:"EOF"}}function a(e,t){const r=s();if(r.type!==e||void 0!==t&&r.value!==t)throw new Error(`Expected ${t||e} but got ${r.value}`);return l(),r}function i(e){const t=s();return"operator"===t.type&&t.value===e}const c=u();if("EOF"!==s().type)throw new Error(`Unexpected token: ${s().value}`);return c;function u(){let e=function(){let e=f();for(;i("||");){l();const t=f();e=e||t}return e}();if(i("?")){l();const t=u();a("operator",":");const r=u();e=e?t:r}return e}function f(){let e=d();for(;i("&&");){l();const t=d();e=e&&t}return e}function d(){let e=h();for(;["==","!=","===","!=="].includes(s().value);){const t=l().value,r=h();switch(t){case"==":e=e==r;break;case"!=":e=e!=r;break;case"===":e=e===r;break;case"!==":e=e!==r}}return e}function h(){let e=p();for(;[">","<",">=","<="].includes(s().value);){const t=l().value,r=p();switch(t){case">":e=e>r;break;case"<":e=e<r;break;case">=":e=e>=r;break;case"<=":e=e<=r}}return e}function p(){let e=x();for(;["+","-"].includes(s().value);){const t=l().value,r=x();e="+"===t?e+r:e-r}return e}function x(){let e=g();for(;["*","/","%"].includes(s().value);){const t=l().value,r=g();switch(t){case"*":e*=r;break;case"/":e/=r;break;case"%":e%=r}}return e}function g(){if(["!","+","-"].includes(s().value)){const e=l().value,t=g();switch(e){case"!":return!t;case"+":return+t;case"-":return-t}}return function(){const t=s();if("number"===t.type||"string"===t.type||"boolean"===t.type||"null"===t.type)return l(),t.value;if("identifier"===t.type){l();let n=function(t){if(t in r)return r[t];if(t in e)return e[t];if(null!=r.this&&t in r.this)return r.this[t];throw new Error(`Unknown identifier: ${t}`)}(t.value);for(;;)if(i(".")){l();const e=a("identifier").value;n=null==n?void 0:n[e]}else if(i("[")){l();const e=u();a("operator","]"),n=null==n?void 0:n[e]}else{if(!i("("))break;{l();const e=[];if(!i(")"))do{e.push(u())}while(i(",")&&l());if(a("operator",")"),"function"!=typeof n)throw new Error(`'${t.value}' is not a function`);n=n.apply(r.this,e)}}return n}if(i("(")){l();const e=u();return a("operator",")"),e}throw new Error(`Unexpected token: ${t.value}`)}()}}const r=new Map;function n(e){if(!e||!e.name)throw new Error("Invalid plugin");r.set(e.name,e)}function o(e,t={}){const n=e.match(/^([a-zA-Z_$][\w$]*)\s*\(\s*(.*)\s*\)$/);if(!n)return null;const o=n[1],s=r.get(o);if(!s)return null;const l=n[2].trim();if(""===l)return{plugin:s,args:[]};return{plugin:s,args:l.split(/\s*,\s*/).map(e=>{if(e.startsWith('"')&&e.endsWith('"')||e.startsWith("'")&&e.endsWith("'"))return e.slice(1,-1);if(/^-?\d+(?:\.\d+)?$/.test(e))return parseFloat(e);if(e in t)return t[e];throw new Error(`Unknown identifier: ${e}`)})}}async function s(e=document,t={}){const n=Array.from(e.querySelectorAll("*")).filter(e=>Array.from(e.attributes).some(e=>e.name.startsWith("render.")));for(const e of n)for(const n of Array.from(e.attributes)){if(!n.name.startsWith("render."))continue;const s=n.name,l=n.value.trim();let a,i,c;if("render.plugin"===s){let e;try{e=o(l,t)}catch(e){console.error(e);continue}if(!e)continue;a=e.plugin,i=e.args}else{const e=s.slice(7);if(a=r.get(e),!a)continue;if(l.startsWith(e+"(")){let e;try{e=o(l,t)}catch(e){console.error(e);continue}if(!e)continue;a=e.plugin,i=e.args}else i=[l]}"function"==typeof a.onBeforeExecute&&a.onBeforeExecute(e,l,t);try{c=a.execute(...i)}catch(e){continue}e.textContent=null==c?"":String(c),"function"==typeof a.onAfterExecute&&a.onAfterExecute(e,l,t)}for(const n of r.values())"function"==typeof n.onAfterRender&&await n.onAfterRender(e,t)}function rendux(e,n){const o=e,l=n;let a=n.shadowRoot||n;if(!a)throw new Error("rendux requires a DOM element as the second argument");for(const e of r.values())"function"==typeof e.onBeforeRender&&e.onBeforeRender(a,o);const i=document,c=l.getAttribute&&l.getAttribute("logs"),u=Boolean(c),f=c?new Set(c.split(",").map(e=>e.trim().toLowerCase())):new Set,d=e=>f.has("all")||f.has(e.toLowerCase())||f.has(("x-"+e).toLowerCase()),h=u&&f.has("plugins"),p=(...e)=>console.warn(...e);l._xRenderCache||(l._xRenderCache=new Map),l._xRenderOriginalText||(l._xRenderOriginalText=new WeakMap),l._xIfData||(l._xIfData=new WeakMap),l._cloneContext||(l._cloneContext=new WeakMap),l._xClassCache||(l._xClassCache=new Map),l._xForCache||(l._xForCache=new WeakMap),l.__mirrorContainer||(l.__mirrorContainer=i.createDocumentFragment());const x={};function g(e){let t=e;for(;t;){const e=l._cloneContext.get(t);if(e)return l.getAttribute&&l.getAttribute("logs")&&l.getAttribute("logs").includes("plugins")&&console.log("Found context for element:",t,e),e;t=t.parentNode}return l.getAttribute&&l.getAttribute("logs")&&l.getAttribute("logs").includes("plugins")&&console.log("Using default component context:",o),o}function y(e,r){if(!e)return!0;const n=g(r);try{return t(e,{this:n,...x})}catch(t){return void p(`[evaluate] "${e}" failed in`,n,t)}}function m(e,t){const r=g(t),n=e.match(/([^[.\]]+)|\[(\d+)\]/g);if(n)return n.reduce((e,t)=>{if(null!=e){if(t.startsWith("[")){const r=parseInt(t.slice(1,-1),10);return Array.isArray(e)?e[r]:void 0}return e[t]}},r)}function A(e){const t=e.match(/^\s*(?:\(\s*([^,\s]+)\s*,\s*([^,\s]+)\s*\)|([^,\s()]+))\s+(?:in|of)\s+(.+)$/);if(!t)throw new Error("Invalid x-for: "+e);return{loopVar:t[1]||t[3],indexVar:t[2]||null,arrayPath:t[4].trim()}}function C(e,t,r,n,o){return new Proxy(e,{has:(e,r)=>r===t||n&&r===n||r in e,get:(e,s)=>s===t?r:n&&s===n?o:e[s]})}function _(e,t){l._cloneContext.set(e,t),e.querySelectorAll("*").forEach(e=>l._cloneContext.set(e,t))}l&&Object.getPrototypeOf(l)&&Object.getOwnPropertyNames(Object.getPrototypeOf(l)).forEach(e=>{"function"==typeof l[e]&&"constructor"!==e&&(x[e]=l[e].bind(l))}),x.plugins=r;const E=u&&d("for");function b(e){try{const t=new WeakSet;return JSON.stringify(e,(e,r)=>{if("function"!=typeof r&&!e.startsWith("$")){if("object"==typeof r&&null!==r){if(t.has(r))return"[Circular]";t.add(r)}return r}})}catch(t){return`${e.length}-${e[0]?.name||""}-${e[e.length-1]?.name||""}`}}E&&console.groupCollapsed("x-for");let v=new Set,w=!0;for(;w;){const e=Array.from(a.querySelectorAll("template[x-for]")).concat(Array.from(l.__mirrorContainer.querySelectorAll("template[x-for]"))).filter(e=>!v.has(e));if(0===e.length){w=!1;break}e.forEach(e=>{let r,n,s;v.add(e),e._xForMeta||(e._xForMeta={parent:e.parentNode,next:e.nextSibling},l.__mirrorContainer.appendChild(e));try{({loopVar:r,indexVar:n,arrayPath:s}=A(e.getAttribute("x-for")))}catch(e){return void p("[x-for]",e.message)}const a=m(s,e);if(!Array.isArray(a))return void p(`[x-for] expected array at ${s}`,a);E&&console.log(`iterating ${s} → length ${a.length}`);const c=e.content.cloneNode(!0).querySelector("*"),u=c&&c.hasAttribute("x-key");if(!u){const t=b(a),r=l._xForCache.get(e);if(r&&r.arrayRef===a&&r.length===a.length&&r.signature===t)return void(E&&console.log(" → skipped (no change)"));l._xForCache.set(e,{arrayRef:a,length:a.length,signature:t})}if(u&&e._forClones&&e._forClones.length>0){E&&console.log(" → using x-key diffing");const s=c.getAttribute("x-key"),u=new Map;e._forClones.forEach(e=>{if(1===e.nodeType){const t=e.getAttribute("x-key");t&&u.set(t,e)}});const f=[],d=new Set;a.forEach((a,c)=>{E&&console.groupCollapsed(` index ${c}`);const h=C(o,r,a,n,c);let g;try{g=t(s,{this:h,...x})}catch(e){p("[x-for] Error evaluating x-key:",e),g=c}const y=String(g);if(u.has(y)){const e=u.get(y);d.add(e),E&&console.log(` → reusing node for key: ${y}`),l._cloneContext.set(e,h),f.push(e)}else{E&&console.log(` → creating new node for key: ${y}`);const t=i.createDocumentFragment();t.appendChild(e.content.cloneNode(!0));const r=t.firstElementChild;if(r){t.removeChild(r),r.setAttribute("x-key",y),_(r,h);(r.hasAttribute("render")?[r,...r.querySelectorAll("[render]")]:r.querySelectorAll("[render]")).forEach(e=>{const t=e.getAttribute("render")?.trim();t&&(l._xRenderCache.set(e,t),l._xRenderOriginalText.set(e,e.textContent))});(r.hasAttribute("x-class")?[r,...r.querySelectorAll("[x-class]")]:r.querySelectorAll("[x-class]")).forEach(e=>{const t=e.getAttribute("x-class");null!=t&&l._xClassCache.set(e,t)}),f.push(r)}}E&&console.groupEnd()}),e._forClones.forEach(e=>{if(!d.has(e)){if(E&&console.log(" → removing unused node"),1===e.nodeType){(e.hasAttribute("render")?[e,...e.querySelectorAll("[render]")]:e.querySelectorAll("[render]")).forEach(e=>{l._xRenderCache.delete(e),l._xRenderOriginalText.delete(e)});(e.hasAttribute("x-class")?[e,...e.querySelectorAll("[x-class]")]:e.querySelectorAll("[x-class]")).forEach(e=>{l._xClassCache.delete(e),l._xClassDynamicValues.delete(e)})}e.remove()}}),f.forEach((t,r)=>{const n=e._xForMeta.parent,o=r<f.length-1?f[r+1]:e._xForMeta.next;t.parentNode&&t.nextSibling===o||n.insertBefore(t,o)}),e._forClones=f}else E&&u&&console.log(" → first render with x-key"),E&&!u&&console.log(" → no x-key, full re-render"),e._forClones&&e._forClones.forEach(e=>{if(1===e.nodeType){(e.hasAttribute("render")?[e,...e.querySelectorAll("[render]")]:e.querySelectorAll("[render]")).forEach(e=>{l._xRenderCache.delete(e),l._xRenderOriginalText.delete(e)});(e.hasAttribute("x-class")?[e,...e.querySelectorAll("[x-class]")]:e.querySelectorAll("[x-class]")).forEach(e=>{l._xClassCache.delete(e),l._xClassDynamicValues.delete(e)})}e.remove()}),e._forClones=[],a.forEach((s,a)=>{E&&console.groupCollapsed(` index ${a}`);const c=i.createDocumentFragment();c.appendChild(e.content.cloneNode(!0));const f=C(o,r,s,n,a);if(_(c,f),u){const e=c.firstElementChild;if(e){const r=e.getAttribute("x-key");if(r)try{const n=t(r,{this:f,...x});e.setAttribute("x-key",String(n))}catch(t){e.setAttribute("x-key",String(a))}}}for(;c.firstChild;){const t=c.firstChild;if(e._xForMeta.parent.insertBefore(t,e._xForMeta.next),e._forClones.push(t),1===t.nodeType){(t.hasAttribute("render")?[t,...t.querySelectorAll("[render]")]:t.querySelectorAll("[render]")).forEach(e=>{const t=e.getAttribute("render")?.trim();t&&(l._xRenderCache.set(e,t),l._xRenderOriginalText.set(e,e.textContent))});(t.hasAttribute("x-class")?[t,...t.querySelectorAll("[x-class]")]:t.querySelectorAll("[x-class]")).forEach(e=>{const t=e.getAttribute("x-class");null!=t&&l._xClassCache.set(e,t)})}}E&&console.groupEnd()})})}E&&console.groupEnd();const S=u&&d("if");Array.from(a.querySelectorAll("[x-if]")).concat(Array.from(l.__mirrorContainer.querySelectorAll("[x-if]"))).forEach(e=>{const t=e.getAttribute("x-if")?.trim(),r=!t||y(t,e);S&&console.groupCollapsed("x-if",e,t,"→",r);let n=l._xIfData.get(e);n||(n={placeholder:i.createComment("x-if placeholder"),isHidden:!1},l._xIfData.set(e,n)),r||n.isHidden?r&&n.isHidden&&(n.placeholder.parentNode.replaceChild(e,n.placeholder),n.isHidden=!1):(e.parentNode.replaceChild(n.placeholder,e),l.__mirrorContainer.appendChild(e),n.isHidden=!0),S&&console.groupEnd()}),Array.from(a.querySelectorAll("[render]")).forEach(e=>{if(!l._xRenderCache.has(e)){const t=e.getAttribute("render")?.trim();t&&(l._xRenderCache.set(e,t),l._xRenderOriginalText.set(e,e.textContent))}}),Array.from(a.querySelectorAll("[x-class]")).forEach(e=>{const t=e.getAttribute("x-class");null==t||l._xClassCache.has(e)||l._xClassCache.set(e,t)});const $=u&&d("attr");Array.from(a.querySelectorAll("*")).forEach(e=>{Array.from(e.attributes).forEach(t=>{if(t.name.startsWith("x-")&&!["x-for","x-key","x-class","x-if","x-hidden"].includes(t.name)){const n=t.name,s=r.get(n);if(s&&"attribute"===s.target){const r=y(t.value.trim(),e);try{h&&console.log("[plugin]",`Executing ${n} with:`,{element:e,value:r,component:o}),s.execute(e,r,o)}catch(e){h&&console.error("[plugin]",`Error executing ${n}:`,e)}}else{const r=t.name.slice(2),n=y(t.value.trim(),e);$&&console.groupCollapsed("x-attr",e,r,"=",n),n?e.setAttribute(r,String(n)):e.removeAttribute(r),$&&console.groupEnd()}}})});const k=u&&d("class");k&&console.groupCollapsed("x-class");for(const[e,t]of l._xClassCache){k&&console.log("element →",e);const r=t.trim();if(r.includes("(")){const t=/\(\s*([^,]+?)\s*,\s*([^)]+?)\s*\)/g;l._xClassDynamicValues||(l._xClassDynamicValues=new Map);(l._xClassDynamicValues.get(e)||[]).forEach(t=>e.classList.remove(t));const n=new Set;let o;for(;o=t.exec(r);){const t=o[1].trim(),r=o[2].trim();let s;s=/^[\w\-\s]+$/.test(t)?t:y(t,e);const l=Boolean(y(r,e));let a=[];"string"==typeof s?a=s.split(/\s+/).filter(Boolean):Array.isArray(s)?a=s:s&&"object"==typeof s&&(a=Object.keys(s).filter(e=>s[e])),l&&a.forEach(t=>e.classList.add(t)),a.forEach(e=>n.add(e)),k&&console.log(` ${t} → [${a.join(" ")}] (= ${l})`)}l._xClassDynamicValues.set(e,Array.from(n))}else{l._xClassDynamicValues||(l._xClassDynamicValues=new Map);let t;(l._xClassDynamicValues.get(e)||[]).forEach(t=>e.classList.remove(t));let n=!0;if(!r.includes(",")&&/[?:]/.test(r))t=y(r,e);else{const o=r.indexOf(","),s=o>=0?r.slice(0,o).trim():r,l=o>=0?r.slice(o+1).trim():"true";n=Boolean(y(l,e)),t=s}const o=[];"string"==typeof t?o.push(...t.split(/\s+/).filter(Boolean)):Array.isArray(t)?o.push(...t):t&&"object"==typeof t&&o.push(...Object.keys(t).filter(e=>t[e])),o.forEach(t=>{n?e.classList.add(t):e.classList.remove(t)}),k&&console.log(` x-class ${r} →`,o,`ok=${n}`),l._xClassDynamicValues.set(e,o)}}k&&console.groupEnd();const q=u&&d("render");q&&console.groupCollapsed("render");for(const[e,t]of l._xRenderCache){const r=l._xIfData.get(e);if(r&&r.isHidden)continue;q&&console.log("element →",e,"expr=",t);const n=t.indexOf(","),o=n<0?t:t.slice(0,n).trim(),s=y(n<0?"true":t.slice(n+1).trim(),e);let a;if(s){let t=y(o,e);if(void 0===t)a=l._xRenderOriginalText.get(e)||"";else if(null!=t&&"object"==typeof t)try{a=JSON.stringify(t,null,2)}catch{a=String(t)}else a=null==t||"boolean"==typeof t?"":String(t)}else a=l._xRenderOriginalText.get(e)||"";e.textContent!==a&&(e.textContent=a),q&&console.log(` → "${a}" (cond=${s})`)}q&&console.groupEnd(),Array.from(a.querySelectorAll("*")).forEach(e=>{const t=l._xIfData.get(e);t&&t.isHidden||[["render","render"]].forEach(([t,r])=>{e.hasAttribute(t)&&!d(r)&&e.removeAttribute(t)})}),function e(r){Array.from(r.querySelectorAll("*")).forEach(e=>{Array.from(e.attributes).forEach(r=>{if(r.name.startsWith("@")){const n=r.name.slice(1),s=r.value.trim();e._xEventListeners&&e._xEventListeners[n]&&e.removeEventListener(n,e._xEventListeners[n]),e._xEventListeners||(e._xEventListeners={});const l=g(e),a=new Proxy(l,{get:(e,t)=>t in e?e[t]:o[t]}),i=function(e){try{return t(s,{this:a,event:e,...x})}catch(e){p(`[rendux @${n}] Error evaluating: ${s}`,e)}};e.addEventListener(n,i),e._xEventListeners[n]=i}})}),Array.from(r.querySelectorAll("slot")).forEach(t=>{(t.assignedElements?t.assignedElements({flatten:!0}):[]).forEach(t=>{e(t)})})}(a),s(a,o)}rendux.use=function(e){return n(e),rendux},"undefined"!=typeof module&&module.exports&&(module.exports={rendux:rendux,use:n,process:s,plugins:r,parsePluginCall:o});export{o as parsePluginCall,r as plugins,s as process,rendux,n as use};
|
|
1
|
+
/*! rendux v0.94.0 | Copyright (c) JULY 2025 Yannick J.A. CHARLERY | This software is licensed for non-commercial use only. Commercial licensing available upon request. For license details: https://github.com/ynck-chrl/rendux */
|
|
2
|
+
const e={Math:Math,Date:Date,Number:Number,String:String,Boolean:Boolean,JSON:JSON,parseInt:parseInt,parseFloat:parseFloat,isFinite:isFinite,Array:Array},t=(e,...t)=>String.raw({raw:e},...t);function r(t,r={}){const n=function(e){const t=[];let r=0;for(;r<e.length;){let n=e[r];if(/\s/.test(n)){r++;continue}if('"'===n||"'"===n){const o=n;let s="";for(r++;r<e.length&&e[r]!==o;)"\\"===e[r]?(r++,r<e.length&&(s+=e[r++])):s+=e[r++];r++,t.push({type:"string",value:s});continue}if(/[0-9]/.test(n)||"."===n&&/[0-9]/.test(e[r+1])){let n=r;for(;r<e.length&&/[0-9]/.test(e[r]);)r++;if("."===e[r])for(r++;r<e.length&&/[0-9]/.test(e[r]);)r++;const o=parseFloat(e.slice(n,r));t.push({type:"number",value:o});continue}if(/[a-zA-Z_$]/.test(n)){let n=r;for(r++;r<e.length&&/[a-zA-Z0-9_$]/.test(e[r]);)r++;const o=e.slice(n,r);"true"===o||"false"===o?t.push({type:"boolean",value:"true"===o}):"null"===o?t.push({type:"null",value:null}):t.push({type:"identifier",value:o});continue}const o=e.substr(r,2),s=e.substr(r,3);if(["===","!=="].includes(s))t.push({type:"operator",value:s}),r+=3;else if(["==","!=",">=","<=","&&","||"].includes(o))t.push({type:"operator",value:o}),r+=2;else{if(!["+","-","*","/","%",">","<","!","?",":","(",")","[","]",".",","].includes(n))throw new Error(`Invalid character '${n}' in expression`);t.push({type:"operator",value:n}),r++}}return t.push({type:"EOF"}),t}(t);let o=0;function s(){return n[o]||{type:"EOF"}}function l(){return n[o++]||{type:"EOF"}}function a(e,t){const r=s();if(r.type!==e||void 0!==t&&r.value!==t)throw new Error(`Expected ${t||e} but got ${r.value}`);return l(),r}function i(e){const t=s();return"operator"===t.type&&t.value===e}const c=u();if("EOF"!==s().type)throw new Error(`Unexpected token: ${s().value}`);return c;function u(){let e=function(){let e=f();for(;i("||");){l();const t=f();e=e||t}return e}();if(i("?")){l();const t=u();a("operator",":");const r=u();e=e?t:r}return e}function f(){let e=d();for(;i("&&");){l();const t=d();e=e&&t}return e}function d(){let e=h();for(;["==","!=","===","!=="].includes(s().value);){const t=l().value,r=h();switch(t){case"==":e=e==r;break;case"!=":e=e!=r;break;case"===":e=e===r;break;case"!==":e=e!==r}}return e}function h(){let e=p();for(;[">","<",">=","<="].includes(s().value);){const t=l().value,r=p();switch(t){case">":e=e>r;break;case"<":e=e<r;break;case">=":e=e>=r;break;case"<=":e=e<=r}}return e}function p(){let e=x();for(;["+","-"].includes(s().value);){const t=l().value,r=x();e="+"===t?e+r:e-r}return e}function x(){let e=g();for(;["*","/","%"].includes(s().value);){const t=l().value,r=g();switch(t){case"*":e*=r;break;case"/":e/=r;break;case"%":e%=r}}return e}function g(){if(["!","+","-"].includes(s().value)){const e=l().value,t=g();switch(e){case"!":return!t;case"+":return+t;case"-":return-t}}return function(){const t=s();if("number"===t.type||"string"===t.type||"boolean"===t.type||"null"===t.type)return l(),t.value;if("identifier"===t.type){l();let n=function(t){if(t in r)return r[t];if(t in e)return e[t];if(null!=r.this&&t in r.this)return r.this[t];throw new Error(`Unknown identifier: ${t}`)}(t.value);for(;;)if(i(".")){l();const e=a("identifier").value;n=null==n?void 0:n[e]}else if(i("[")){l();const e=u();a("operator","]"),n=null==n?void 0:n[e]}else{if(!i("("))break;{l();const e=[];if(!i(")"))do{e.push(u())}while(i(",")&&l());if(a("operator",")"),"function"!=typeof n)throw new Error(`'${t.value}' is not a function`);n=n.apply(r.this,e)}}return n}if(i("(")){l();const e=u();return a("operator",")"),e}throw new Error(`Unexpected token: ${t.value}`)}()}}const n=new Map;function o(e){if(!e||!e.name)throw new Error("Invalid plugin");n.set(e.name,e)}function s(e,t={}){const r=e.match(/^([a-zA-Z_$][\w$]*)\s*\(\s*(.*)\s*\)$/);if(!r)return null;const o=r[1],s=n.get(o);if(!s)return null;const l=r[2].trim();if(""===l)return{plugin:s,args:[]};return{plugin:s,args:l.split(/\s*,\s*/).map(e=>{if(e.startsWith('"')&&e.endsWith('"')||e.startsWith("'")&&e.endsWith("'"))return e.slice(1,-1);if(/^-?\d+(?:\.\d+)?$/.test(e))return parseFloat(e);if(e in t)return t[e];throw new Error(`Unknown identifier: ${e}`)})}}async function l(e=document,t={}){const r=Array.from(e.querySelectorAll("*")).filter(e=>Array.from(e.attributes).some(e=>e.name.startsWith("render.")));for(const e of r)for(const r of Array.from(e.attributes)){if(!r.name.startsWith("render."))continue;const o=r.name,l=r.value.trim();let a,i,c;if("render.plugin"===o){let e;try{e=s(l,t)}catch(e){console.error(e);continue}if(!e)continue;a=e.plugin,i=e.args}else{const e=o.slice(7);if(a=n.get(e),!a)continue;if(l.startsWith(e+"(")){let e;try{e=s(l,t)}catch(e){console.error(e);continue}if(!e)continue;a=e.plugin,i=e.args}else i=[l]}"function"==typeof a.onBeforeExecute&&a.onBeforeExecute(e,l,t);try{c=a.execute(...i)}catch(e){continue}e.textContent=null==c?"":String(c),"function"==typeof a.onAfterExecute&&a.onAfterExecute(e,l,t)}for(const r of n.values())"function"==typeof r.onAfterRender&&await r.onAfterRender(e,t)}function rendux(e,t){const o=e,s=t;let a=t.shadowRoot||t;if(!a)throw new Error("rendux requires a DOM element as the second argument");for(const e of n.values())"function"==typeof e.onBeforeRender&&e.onBeforeRender(a,o);const i=document,c=s.getAttribute&&s.getAttribute("logs"),u=Boolean(c),f=c?new Set(c.split(",").map(e=>e.trim().toLowerCase())):new Set,d=e=>f.has("all")||f.has(e.toLowerCase())||f.has(("x-"+e).toLowerCase()),h=u&&f.has("plugins"),p=(...e)=>console.warn(...e);s._xRenderCache||(s._xRenderCache=new Map),s._xRenderOriginalText||(s._xRenderOriginalText=new WeakMap),s._xIfData||(s._xIfData=new WeakMap),s._cloneContext||(s._cloneContext=new WeakMap),s._xClassCache||(s._xClassCache=new Map),s._xForCache||(s._xForCache=new WeakMap),s.__mirrorContainer||(s.__mirrorContainer=i.createDocumentFragment());const x={};function g(e){let t=e;for(;t;){const e=s._cloneContext.get(t);if(e)return s.getAttribute&&s.getAttribute("logs")&&s.getAttribute("logs").includes("plugins")&&console.log("Found context for element:",t,e),e;t=t.parentNode}return s.getAttribute&&s.getAttribute("logs")&&s.getAttribute("logs").includes("plugins")&&console.log("Using default component context:",o),o}function y(e,t){if(!e)return!0;const n=g(t);try{return r(e,{this:n,...x})}catch(t){return void p(`[evaluate] "${e}" failed in`,n,t)}}function m(e,t){const r=g(t),n=e.match(/([^[.\]]+)|\[(\d+)\]/g);if(n)return n.reduce((e,t)=>{if(null!=e){if(t.startsWith("[")){const r=parseInt(t.slice(1,-1),10);return Array.isArray(e)?e[r]:void 0}return e[t]}},r)}function A(e){const t=e.match(/^\s*(?:\(\s*([^,\s]+)\s*,\s*([^,\s]+)\s*\)|([^,\s()]+))\s+(?:in|of)\s+(.+)$/);if(!t)throw new Error("Invalid x-for: "+e);return{loopVar:t[1]||t[3],indexVar:t[2]||null,arrayPath:t[4].trim()}}function C(e,t,r,n,o){return new Proxy(e,{has:(e,r)=>r===t||n&&r===n||r in e,get:(e,s)=>s===t?r:n&&s===n?o:e[s]})}function _(e,t){s._cloneContext.set(e,t),e.querySelectorAll("*").forEach(e=>s._cloneContext.set(e,t))}s&&Object.getPrototypeOf(s)&&Object.getOwnPropertyNames(Object.getPrototypeOf(s)).forEach(e=>{"function"==typeof s[e]&&"constructor"!==e&&(x[e]=s[e].bind(s))}),x.plugins=n;const E=u&&d("for");function b(e){try{const t=new WeakSet;return JSON.stringify(e,(e,r)=>{if("function"!=typeof r&&!e.startsWith("$")){if("object"==typeof r&&null!==r){if(t.has(r))return"[Circular]";t.add(r)}return r}})}catch(t){return`${e.length}-${e[0]?.name||""}-${e[e.length-1]?.name||""}`}}E&&console.groupCollapsed("x-for");let v=new Set,w=!0;for(;w;){const e=Array.from(a.querySelectorAll("template[x-for]")).concat(Array.from(s.__mirrorContainer.querySelectorAll("template[x-for]"))).filter(e=>!v.has(e));if(0===e.length){w=!1;break}e.forEach(e=>{let t,n,l;v.add(e),e._xForMeta||(e._xForMeta={parent:e.parentNode,next:e.nextSibling},s.__mirrorContainer.appendChild(e));try{({loopVar:t,indexVar:n,arrayPath:l}=A(e.getAttribute("x-for")))}catch(e){return void p("[x-for]",e.message)}const a=m(l,e);if(!Array.isArray(a))return void p(`[x-for] expected array at ${l}`,a);E&&console.log(`iterating ${l} → length ${a.length}`);const c=e.content.cloneNode(!0).querySelector("*"),u=c&&c.hasAttribute("x-key");if(!u){const t=b(a),r=s._xForCache.get(e);if(r&&r.arrayRef===a&&r.length===a.length&&r.signature===t)return void(E&&console.log(" → skipped (no change)"));s._xForCache.set(e,{arrayRef:a,length:a.length,signature:t})}if(u&&e._forClones&&e._forClones.length>0){E&&console.log(" → using x-key diffing");const l=c.getAttribute("x-key"),u=new Map;e._forClones.forEach(e=>{if(1===e.nodeType){const t=e.getAttribute("x-key");t&&u.set(t,e)}});const f=[],d=new Set;a.forEach((a,c)=>{E&&console.groupCollapsed(` index ${c}`);const h=C(o,t,a,n,c);let g;try{g=r(l,{this:h,...x})}catch(e){p("[x-for] Error evaluating x-key:",e),g=c}const y=String(g);if(u.has(y)){const e=u.get(y);d.add(e),E&&console.log(` → reusing node for key: ${y}`),_(e,h),f.push(e)}else{E&&console.log(` → creating new node for key: ${y}`);const t=i.createDocumentFragment();t.appendChild(e.content.cloneNode(!0));const r=t.firstElementChild;if(r){t.removeChild(r),r.setAttribute("x-key",y),_(r,h);(r.hasAttribute("render")?[r,...r.querySelectorAll("[render]")]:r.querySelectorAll("[render]")).forEach(e=>{const t=e.getAttribute("render")?.trim();t&&(s._xRenderCache.set(e,t),s._xRenderOriginalText.set(e,e.textContent))});(r.hasAttribute("x-class")?[r,...r.querySelectorAll("[x-class]")]:r.querySelectorAll("[x-class]")).forEach(e=>{const t=e.getAttribute("x-class");null!=t&&s._xClassCache.set(e,t)}),f.push(r)}}E&&console.groupEnd()}),e._forClones.forEach(e=>{if(!d.has(e)){if(E&&console.log(" → removing unused node"),1===e.nodeType){(e.hasAttribute("render")?[e,...e.querySelectorAll("[render]")]:e.querySelectorAll("[render]")).forEach(e=>{s._xRenderCache.delete(e),s._xRenderOriginalText.delete(e)});(e.hasAttribute("x-class")?[e,...e.querySelectorAll("[x-class]")]:e.querySelectorAll("[x-class]")).forEach(e=>{s._xClassCache.delete(e),s._xClassDynamicValues.delete(e)})}e.remove()}});for(let t=f.length-1;t>=0;t--){const r=f[t],n=e._xForMeta.parent,o=t<f.length-1?f[t+1]:e._xForMeta.next;r.parentNode&&r.nextSibling===o||n.insertBefore(r,o)}e._forClones=f}else E&&u&&console.log(" → first render with x-key"),E&&!u&&console.log(" → no x-key, full re-render"),e._forClones&&e._forClones.forEach(e=>{if(1===e.nodeType){(e.hasAttribute("render")?[e,...e.querySelectorAll("[render]")]:e.querySelectorAll("[render]")).forEach(e=>{s._xRenderCache.delete(e),s._xRenderOriginalText.delete(e)});(e.hasAttribute("x-class")?[e,...e.querySelectorAll("[x-class]")]:e.querySelectorAll("[x-class]")).forEach(e=>{s._xClassCache.delete(e),s._xClassDynamicValues.delete(e)})}e.remove()}),e._forClones=[],a.forEach((l,a)=>{E&&console.groupCollapsed(` index ${a}`);const c=i.createDocumentFragment();c.appendChild(e.content.cloneNode(!0));const f=C(o,t,l,n,a);if(_(c,f),u){const e=c.firstElementChild;if(e){const t=e.getAttribute("x-key");if(t)try{const n=r(t,{this:f,...x});e.setAttribute("x-key",String(n))}catch(t){e.setAttribute("x-key",String(a))}}}for(;c.firstChild;){const t=c.firstChild;if(e._xForMeta.parent.insertBefore(t,e._xForMeta.next),e._forClones.push(t),1===t.nodeType){(t.hasAttribute("render")?[t,...t.querySelectorAll("[render]")]:t.querySelectorAll("[render]")).forEach(e=>{const t=e.getAttribute("render")?.trim();t&&(s._xRenderCache.set(e,t),s._xRenderOriginalText.set(e,e.textContent))});(t.hasAttribute("x-class")?[t,...t.querySelectorAll("[x-class]")]:t.querySelectorAll("[x-class]")).forEach(e=>{const t=e.getAttribute("x-class");null!=t&&s._xClassCache.set(e,t)})}}E&&console.groupEnd()})})}E&&console.groupEnd();const S=u&&d("if");Array.from(a.querySelectorAll("[x-if]")).concat(Array.from(s.__mirrorContainer.querySelectorAll("[x-if]"))).forEach(e=>{const t=e.getAttribute("x-if")?.trim(),r=!t||y(t,e);S&&console.groupCollapsed("x-if",e,t,"→",r);let n=s._xIfData.get(e);n||(n={placeholder:i.createComment("x-if placeholder"),isHidden:!1},s._xIfData.set(e,n)),r||n.isHidden?r&&n.isHidden&&(n.placeholder.parentNode.replaceChild(e,n.placeholder),n.isHidden=!1):(e.parentNode.replaceChild(n.placeholder,e),s.__mirrorContainer.appendChild(e),n.isHidden=!0),S&&console.groupEnd()}),Array.from(a.querySelectorAll("[render]")).forEach(e=>{if(!s._xRenderCache.has(e)){const t=e.getAttribute("render")?.trim();t&&(s._xRenderCache.set(e,t),s._xRenderOriginalText.set(e,e.textContent))}}),Array.from(a.querySelectorAll("[x-class]")).forEach(e=>{const t=e.getAttribute("x-class");null==t||s._xClassCache.has(e)||s._xClassCache.set(e,t)});const $=u&&d("attr");Array.from(a.querySelectorAll("*")).forEach(e=>{Array.from(e.attributes).forEach(t=>{if(t.name.startsWith("x-")&&!["x-for","x-key","x-class","x-if","x-hidden"].includes(t.name)){const r=t.name,s=n.get(r);if(s&&"attribute"===s.target){const n=y(t.value.trim(),e);try{h&&console.log("[plugin]",`Executing ${r} with:`,{element:e,value:n,component:o}),s.execute(e,n,o)}catch(e){h&&console.error("[plugin]",`Error executing ${r}:`,e)}}else{const r=t.name.slice(2),n=y(t.value.trim(),e);$&&console.groupCollapsed("x-attr",e,r,"=",n),n?e.setAttribute(r,String(n)):e.removeAttribute(r),$&&console.groupEnd()}}})});const k=u&&d("class");k&&console.groupCollapsed("x-class");for(const[e,t]of s._xClassCache){k&&console.log("element →",e);const r=t.trim();if(r.includes("(")){const t=/\(\s*([^,]+?)\s*,\s*([^)]+?)\s*\)/g;s._xClassDynamicValues||(s._xClassDynamicValues=new Map);(s._xClassDynamicValues.get(e)||[]).forEach(t=>e.classList.remove(t));const n=new Set;let o;for(;o=t.exec(r);){const t=o[1].trim(),r=o[2].trim();let s;s=/^[\w\-\s]+$/.test(t)?t:y(t,e);const l=Boolean(y(r,e));let a=[];"string"==typeof s?a=s.split(/\s+/).filter(Boolean):Array.isArray(s)?a=s:s&&"object"==typeof s&&(a=Object.keys(s).filter(e=>s[e])),l&&a.forEach(t=>e.classList.add(t)),a.forEach(e=>n.add(e)),k&&console.log(` ${t} → [${a.join(" ")}] (= ${l})`)}s._xClassDynamicValues.set(e,Array.from(n))}else{s._xClassDynamicValues||(s._xClassDynamicValues=new Map);let t;(s._xClassDynamicValues.get(e)||[]).forEach(t=>e.classList.remove(t));let n=!0;if(!r.includes(",")&&/[?:]/.test(r))t=y(r,e);else{const o=r.indexOf(","),s=o>=0?r.slice(0,o).trim():r,l=o>=0?r.slice(o+1).trim():"true";n=Boolean(y(l,e)),t=s}const o=[];"string"==typeof t?o.push(...t.split(/\s+/).filter(Boolean)):Array.isArray(t)?o.push(...t):t&&"object"==typeof t&&o.push(...Object.keys(t).filter(e=>t[e])),o.forEach(t=>{n?e.classList.add(t):e.classList.remove(t)}),k&&console.log(` x-class ${r} →`,o,`ok=${n}`),s._xClassDynamicValues.set(e,o)}}k&&console.groupEnd();const q=u&&d("render");q&&console.groupCollapsed("render");for(const[e,t]of s._xRenderCache){const r=s._xIfData.get(e);if(r&&r.isHidden)continue;q&&console.log("element →",e,"expr=",t);const n=t.indexOf(","),o=n<0?t:t.slice(0,n).trim(),l=y(n<0?"true":t.slice(n+1).trim(),e);let a;if(l){let t=y(o,e);if(void 0===t)a=s._xRenderOriginalText.get(e)||"";else if(null!=t&&"object"==typeof t)try{a=JSON.stringify(t,null,2)}catch{a=String(t)}else a=null==t||"boolean"==typeof t?"":String(t)}else a=s._xRenderOriginalText.get(e)||"";e.textContent!==a&&(e.textContent=a),q&&console.log(` → "${a}" (cond=${l})`)}q&&console.groupEnd(),Array.from(a.querySelectorAll("*")).forEach(e=>{const t=s._xIfData.get(e);t&&t.isHidden||[["render","render"]].forEach(([t,r])=>{e.hasAttribute(t)&&!d(r)&&e.removeAttribute(t)})}),function e(t){Array.from(t.querySelectorAll("*")).forEach(e=>{Array.from(e.attributes).forEach(t=>{if(t.name.startsWith("@")){const n=t.name.slice(1),s=t.value.trim();e._xEventListeners&&e._xEventListeners[n]&&e.removeEventListener(n,e._xEventListeners[n]),e._xEventListeners||(e._xEventListeners={});const l=g(e),a=new Proxy(l,{get:(e,t)=>t in e?e[t]:o[t]}),i=function(e){try{return r(s,{this:a,event:e,...x})}catch(e){p(`[rendux @${n}] Error evaluating: ${s}`,e)}};e.addEventListener(n,i),e._xEventListeners[n]=i}})}),Array.from(t.querySelectorAll("slot")).forEach(t=>{(t.assignedElements?t.assignedElements({flatten:!0}):[]).forEach(t=>{e(t)})})}(a),l(a,o)}rendux.use=function(e){return o(e),rendux},"undefined"!=typeof module&&module.exports&&(module.exports={rendux:rendux,use:o,process:l,plugins:n,parsePluginCall:s});export{t as html,s as parsePluginCall,n as plugins,l as process,rendux,o as use};
|