@plentico/pattr 0.0.14 → 0.0.16
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/package.json +1 -1
- package/pattr.js +103 -3
- package/pattr.min.js +1 -1
package/package.json
CHANGED
package/pattr.js
CHANGED
|
@@ -324,6 +324,88 @@ window.Pattr = {
|
|
|
324
324
|
const syncVarsSet = new Set(syncVars);
|
|
325
325
|
const parentTarget = parentScope?._p_target || parentScope;
|
|
326
326
|
|
|
327
|
+
// Track which objects have been wrapped to avoid infinite recursion
|
|
328
|
+
const wrappedObjects = new WeakSet();
|
|
329
|
+
|
|
330
|
+
const createDeepProxy = (obj, isSynced = false, syncKey = null) => {
|
|
331
|
+
if (obj === null || typeof obj !== 'object') {
|
|
332
|
+
return obj;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Avoid re-wrapping the same object
|
|
336
|
+
if (wrappedObjects.has(obj)) {
|
|
337
|
+
return obj;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Don't wrap primitive wrappers, dates, regexes, etc.
|
|
341
|
+
if (obj instanceof Date || obj instanceof RegExp || obj instanceof Map || obj instanceof Set) {
|
|
342
|
+
return obj;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Create wrapper that intercepts get/set on properties
|
|
346
|
+
const wrapper = new Proxy(obj, {
|
|
347
|
+
get: (target, key) => {
|
|
348
|
+
if (key === '_p_target') {
|
|
349
|
+
return target;
|
|
350
|
+
}
|
|
351
|
+
if (key === '_p_syncParent') {
|
|
352
|
+
return parentTarget;
|
|
353
|
+
}
|
|
354
|
+
if (key === '_p_syncKey') {
|
|
355
|
+
return syncKey;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const value = target[key];
|
|
359
|
+
|
|
360
|
+
// For synced objects, wrap nested objects too
|
|
361
|
+
if (isSynced && value !== null && typeof value === 'object') {
|
|
362
|
+
return createDeepProxy(value, true, syncKey);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return value;
|
|
366
|
+
},
|
|
367
|
+
set: (target, key, value) => {
|
|
368
|
+
target[key] = value;
|
|
369
|
+
|
|
370
|
+
// If this is a synced object, propagate to parent
|
|
371
|
+
if (isSynced && parentTarget && syncKey) {
|
|
372
|
+
const parentVal = parentTarget[syncKey];
|
|
373
|
+
if (parentVal && typeof parentVal === 'object') {
|
|
374
|
+
parentVal[key] = value;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
this.walkDom(this.root, this.data, false);
|
|
379
|
+
return true;
|
|
380
|
+
},
|
|
381
|
+
has: (target, key) => {
|
|
382
|
+
return key in target;
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
wrappedObjects.add(obj);
|
|
387
|
+
return wrapper;
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
// Wrap synced variables with deep proxies
|
|
391
|
+
if (parentTarget) {
|
|
392
|
+
for (const syncVar of syncVarsSet) {
|
|
393
|
+
if (syncVar in proxyTarget) {
|
|
394
|
+
const value = proxyTarget[syncVar];
|
|
395
|
+
if (value !== null && typeof value === 'object') {
|
|
396
|
+
proxyTarget[syncVar] = createDeepProxy(value, true);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
// Also wrap the parent's synced object
|
|
400
|
+
if (syncVar in parentTarget) {
|
|
401
|
+
const parentValue = parentTarget[syncVar];
|
|
402
|
+
if (parentValue !== null && typeof parentValue === 'object') {
|
|
403
|
+
parentTarget[syncVar] = createDeepProxy(parentValue, true);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
327
409
|
const proxy = new Proxy(proxyTarget, {
|
|
328
410
|
get: (target, key) => {
|
|
329
411
|
if (key === '_p_target') {
|
|
@@ -332,6 +414,11 @@ window.Pattr = {
|
|
|
332
414
|
return target[key];
|
|
333
415
|
},
|
|
334
416
|
set: (target, key, value) => {
|
|
417
|
+
// If setting a synced object, wrap it
|
|
418
|
+
if (syncVarsSet.has(key) && value !== null && typeof value === 'object') {
|
|
419
|
+
value = createDeepProxy(value, true, key);
|
|
420
|
+
}
|
|
421
|
+
|
|
335
422
|
target[key] = value;
|
|
336
423
|
|
|
337
424
|
// If this is a synced variable, also update the parent scope
|
|
@@ -510,9 +597,22 @@ window.Pattr = {
|
|
|
510
597
|
return parentScope;
|
|
511
598
|
}
|
|
512
599
|
|
|
513
|
-
//
|
|
514
|
-
const pScopeAttr =
|
|
515
|
-
const
|
|
600
|
+
// Check for both p-scope and p-scope:sync on the same element
|
|
601
|
+
const pScopeAttr = el.getAttribute('p-scope');
|
|
602
|
+
const pScopeSyncAttr = Array.from(el.attributes).find(attr => attr.name.startsWith('p-scope') && attr.name.includes('sync'));
|
|
603
|
+
|
|
604
|
+
// Collect all scope expressions (just like in initScope)
|
|
605
|
+
let allExprs = [];
|
|
606
|
+
|
|
607
|
+
if (pScopeAttr) {
|
|
608
|
+
allExprs.push(pScopeAttr);
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
if (pScopeSyncAttr) {
|
|
612
|
+
allExprs.push(el.getAttribute(pScopeSyncAttr.name));
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
const pScopeExpr = allExprs.join('; ');
|
|
516
616
|
|
|
517
617
|
// Check if parent values changed - if so, selectively re-execute p-scope
|
|
518
618
|
if (pScopeExpr && scope._p_target) {
|
package/pattr.min.js
CHANGED
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
* https://github.com/plentico/pattr
|
|
5
5
|
* MIT License
|
|
6
6
|
*/
|
|
7
|
-
window.Pattr={_templateScopeCounter:0,directives:{"p-text":(e,t,r={})=>{let a=String(t);if(r.trim&&r.trim.length>0){const e=parseInt(r.trim[0])||100;a.length>e&&(a=a.substring(0,e)+"...")}e.innerText=a},"p-html":(e,t,r={})=>{let a=t;if(r.allow&&r.allow.length>0){const e=r.allow,t=document.createElement("div");t.innerHTML=a;const s=t=>{if(t.nodeType===Node.ELEMENT_NODE){const r=t.tagName.toLowerCase();if(!e.includes(r)){const e=document.createDocumentFragment();return Array.from(t.childNodes).forEach(t=>{const r=s(t);r&&e.appendChild(r)}),e}const a=t.cloneNode(!1);return Array.from(t.childNodes).forEach(e=>{const t=s(e);t&&a.appendChild(t)}),a}return t.cloneNode()},o=document.createElement("div");Array.from(t.childNodes).forEach(e=>{const t=s(e);t&&o.appendChild(t)}),a=o.innerHTML}if(r.trim&&r.trim.length>0){const e=parseInt(r.trim[0])||100,t=document.createElement("div");t.innerHTML=a;let s=0,o=!1;const n=t=>{if(o)return null;if(t.nodeType===Node.TEXT_NODE){const r=t.textContent,a=e-s;if(r.length<=a)return s+=r.length,t.cloneNode();{o=!0;const e=r.substring(0,a)+"...";return document.createTextNode(e)}}if(t.nodeType===Node.ELEMENT_NODE){const e=t.cloneNode(!1);for(let r of t.childNodes){const t=n(r);if(t&&e.appendChild(t),o)break}return e}return t.cloneNode()},i=document.createElement("div");for(let e of t.childNodes){const t=n(e);if(t&&i.appendChild(t),o)break}a=i.innerHTML}e.innerHTML=a},"p-show":(e,t)=>{e.style.display=t?"":"none"},"p-style":(e,t)=>{"string"==typeof t?e.style.cssText=t:"object"==typeof t&&null!==t&&Object.assign(e.style,t)},"p-class":(e,t,r={})=>{if(void 0!==r.replace)return void("string"==typeof t?e.className=t:Array.isArray(t)?e.className=t.join(" "):"object"==typeof t&&null!==t&&(e.className=Object.keys(t).filter(e=>t[e]).join(" ")));let a=new Set,s=new Set;if("string"==typeof t&&t?t.split(" ").forEach(e=>{e&&(a.add(e),s.add(e))}):Array.isArray(t)?t.forEach(e=>{e&&(a.add(e),s.add(e))}):"object"==typeof t&&null!==t&&Object.keys(t).forEach(e=>{s.add(e),t[e]&&a.add(e)}),!e._p_staticClasses){const t=e.className?e.className.split(" ").filter(e=>e):[];e._p_staticClasses=t.filter(e=>!s.has(e))}e._p_dynamicClasses||(e._p_dynamicClasses=new Set),e._p_dynamicClasses=a;const o=[...e._p_staticClasses,...e._p_dynamicClasses];e.className=o.join(" ")},"p-model":(e,t)=>{Array.isArray(t)?e.value=t.join(", "):e.value=t},"p-attr":(e,t,r={})=>{const a=Object.keys(r);if(a.length>0){const r=a[0];null==t||!1===t?e.removeAttribute(r):e.setAttribute(r,String(t))}else"object"==typeof t&&null!==t&&Object.keys(t).forEach(r=>{const a=t[r];null==a||!1===a?e.removeAttribute(r):e.setAttribute(r,String(a))})}},parseDirectiveModifiers(e){const t=e.split(":"),r=t[0],a={};for(let e=1;e<t.length;e++){const r=t[e].split("."),s=r[0],o=r.slice(1);a[s]=o}return{directive:r,modifiers:a}},async start(){this.root=document.documentElement;const e=document.getElementById("p-root-data")?.textContent;try{this.rawData=JSON.parse(e||"{}")}catch(e){console.error("Error parsing root data JSON:",e)}this.buildScopeData(this.root,this.rawData),this.data=this.observe(this.rawData),this.walkDom(this.root,this.data,!0),this.refreshAllLoops()},generateDomPathId(e){const t=[];let r=e;for(;r&&"HTML"!==r.tagName;){const e=r.parentElement;if(e){const a=Array.from(e.children).indexOf(r);t.unshift(`${r.tagName}[${a}]`)}r=e}return t.join("/")},buildScopeData(e,t){let r=t;const a=Array.from(e.attributes).find(e=>e.name.startsWith("p-scope"));if(a){const s=e.getAttribute("p-id")||this.generateDomPathId(e);t._p_children||(t._p_children={}),t._p_children[s]||(t._p_children[s]={}),r=t._p_children[s],r._p_scope=e.getAttribute(a.name),r._p_id=s}let s=e.firstElementChild;for(;s;)this.buildScopeData(s,r),s=s.nextElementSibling},observe(e,t,r=[]){const a=e;let s=a;t&&(s=Object.create(t._p_target||t),Object.assign(s,a));const o=new Set(r),n=t?._p_target||t;return new Proxy(s,{get:(e,t)=>"_p_target"===t?e:e[t],set:(e,t,r)=>(e[t]=r,o.has(t)&&n&&t in n&&(n[t]=r),this.walkDom(this.root,this.data,!1),!0),has:(e,t)=>t in e})},splitPScopeStatements(e){const t=[];let r="",a=0,s=0,o=!1,n=null;for(let i=0;i<e.length;i++){const c=e[i],l=i>0?e[i-1]:null;'"'!==c&&"'"!==c&&"`"!==c||"\\"===l||(o?n===c&&(o=!1,n=null):(o=!0,n=c)),o||("{"===c?a++:"}"===c?a--:"("===c?s++:")"===c&&s--),";"!==c||o||0!==a||0!==s?r+=c:(r.trim()&&t.push(r.trim()),r="")}return r.trim()&&t.push(r.trim()),t},getPScopeOutputVars(e){const t=[];return this.splitPScopeStatements(e).forEach(e=>{const r=e.match(/^\[([^\]]+)\]\s*=\s*(.+)$/);if(r){const e=r[1].split(",").map(e=>e.trim());return void t.push(...e)}const a=e.match(/^\{([^}]+)\}\s*=\s*(.+)$/);if(a){const e=a[1].split(",").map(e=>e.trim());return void t.push(...e)}const s=e.match(/^(\w+)\s*=\s*(.+)$/);s&&t.push(s[1])}),t},initScope(e,t){const r=e.getAttribute("p-id")||this.generateDomPathId(e),a=t._p_target._p_children[r],s=e.getAttribute("p-scope"),o=Array.from(e.attributes).find(e=>e.name.startsWith("p-scope")&&e.name.includes("sync"));let n=[],i=[];if(s&&n.push(s),o){const t=e.getAttribute(o.name);n.push(t),i=this.getPScopeOutputVars(t)}const c=n.join("; "),l=this.observe(a,t,i);i.length>0&&(e._p_syncVars=new Set(i)),this.executePScopeStatements(l,c);const p=Object.getPrototypeOf(l._p_target);e._parentSnapshot={};for(let t in p)t.startsWith("_p_")||(e._parentSnapshot[t]=p[t]);const h=l._p_target;e._localSnapshot={};for(let t of Object.keys(h))t.startsWith("_p_")||(e._localSnapshot[t]=h[t]);return l},refreshScope(e,t){let r=e._scope;if(!r)return t;const a=Array.from(e.attributes).find(e=>e.name.startsWith("p-scope")),s=a?e.getAttribute(a.name):null;return s&&r._p_target&&this.updateScopeFromParent(e,r,s),r},executePScopeStatements(scope,pScopeExpr){const statements=this.splitPScopeStatements(pScopeExpr),target=scope._p_target,sequentialScope=new Proxy(target,{get:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)?e[t]:scope[t],has:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)||t in scope});for(const stmt of statements){const arrayDestructMatch=stmt.match(/^\[([^\]]+)\]\s*=\s*(.+)$/);if(arrayDestructMatch){const[,vars,expr]=arrayDestructMatch,varNames=vars.split(",").map(e=>e.trim());try{const value=eval(`with (sequentialScope) { (${expr}) }`);Array.isArray(value)&&varNames.forEach((e,t)=>{target[e]=value[t]})}catch(e){console.error(`Error executing p-scope array destructuring "${stmt}":`,e)}continue}const objDestructMatch=stmt.match(/^\{([^}]+)\}\s*=\s*(.+)$/);if(objDestructMatch){const[,vars,expr]=objDestructMatch,varNames=vars.split(",").map(e=>e.trim());try{const value=eval(`with (sequentialScope) { (${expr}) }`);"object"==typeof value&&null!==value&&varNames.forEach(e=>{target[e]=value[e]})}catch(e){console.error(`Error executing p-scope object destructuring "${stmt}":`,e)}continue}const match=stmt.match(/^(\w+)\s*=\s*(.+)$/);if(match){const[,varName,expr]=match;try{const value=eval(`with (sequentialScope) { (${expr}) }`);target[varName]=value}catch(e){console.error(`Error executing p-scope statement "${stmt}":`,e)}}}},updateScopeFromParent(el,scope,pScopeExpr){const parentProto=Object.getPrototypeOf(scope._p_target),target=scope._p_target,changedParentVars=new Set,changedLocalVars=new Set;el._parentSnapshot||(el._parentSnapshot={});for(let e in parentProto)e.startsWith("_p_")||(el._parentSnapshot[e]!==parentProto[e]&&changedParentVars.add(e),el._parentSnapshot[e]=parentProto[e]);el._localSnapshot||(el._localSnapshot={});for(let e of Object.keys(target))e.startsWith("_p_")||(el._localSnapshot[e]!==target[e]&&changedLocalVars.add(e),el._localSnapshot[e]=target[e]);const allChangedVars=new Set([...changedParentVars,...changedLocalVars]);if(0!==allChangedVars.size)try{const statements=this.splitPScopeStatements(pScopeExpr),outputVars=new Set;statements.forEach(e=>{const t=e.match(/^\[([^\]]+)\]\s*=\s*(.+)$/);if(t){return void t[1].split(",").map(e=>e.trim()).forEach(e=>outputVars.add(e))}const r=e.match(/^\{([^}]+)\}\s*=\s*(.+)$/);if(r){return void r[1].split(",").map(e=>e.trim()).forEach(e=>outputVars.add(e))}const a=e.match(/^(\w+)\s*=\s*(.+)$/);a&&outputVars.add(a[1])});const setInThisPass=new Set,sequentialScope=new Proxy(target,{get:(e,t)=>"_p_target"===t||"_p_children"===t||"_p_scope"===t||setInThisPass.has(t)?e[t]:changedParentVars.has(t)?parentProto[t]:changedLocalVars.has(t)||Object.prototype.hasOwnProperty.call(e,t)?e[t]:parentProto[t],set:(e,t,r)=>(e[t]=r,!0),has:(e,t)=>setInThisPass.has(t)||Object.prototype.hasOwnProperty.call(e,t)||t in parentProto});statements.forEach(stmt=>{let shouldExecute=!1;const parts=stmt.split("=");if(parts.length<=1)return;const rhs=parts.slice(1).join("=");if(changedParentVars.forEach(e=>{rhs.includes(e)&&(shouldExecute=!0)}),changedLocalVars.forEach(e=>{!outputVars.has(e)&&rhs.includes(e)&&(shouldExecute=!0)}),shouldExecute||setInThisPass.forEach(e=>{rhs.includes(e)&&(shouldExecute=!0)}),shouldExecute){const arrayMatch=stmt.match(/^\[([^\]]+)\]\s*=\s*(.+)$/);if(arrayMatch){const[,vars,expr]=arrayMatch,varNames=vars.split(",").map(e=>e.trim()),value=eval(`with (sequentialScope) { (${expr}) }`);return void(Array.isArray(value)&&varNames.forEach((e,t)=>{target[e]=value[t],setInThisPass.add(e)}))}const objMatch=stmt.match(/^\{([^}]+)\}\s*=\s*(.+)$/);if(objMatch){const[,vars,expr]=objMatch,varNames=vars.split(",").map(e=>e.trim()),value=eval(`with (sequentialScope) { (${expr}) }`);return void("object"==typeof value&&null!==value&&varNames.forEach(e=>{target[e]=value[e],setInThisPass.add(e)}))}const match=stmt.match(/^(\w+)\s*=\s*(.+)$/);if(match){const[,varName,expr]=match,value=eval(`with (sequentialScope) { (${expr}) }`);target[varName]=value,setInThisPass.add(varName)}}});for(let e of Object.keys(target))e.startsWith("_p_")||(el._localSnapshot[e]=target[e])}catch(e){console.error("Error re-executing p-scope expression:",e)}},registerEventListeners(el){Array.from(el.attributes).forEach(attr=>{if(attr.name.startsWith("p-on:")){const event=attr.name.replace("p-on:","");el.addEventListener(event,()=>{eval(`with (el._scope) { ${attr.value} }`),this.walkDom(this.root,this.data,!1),this.refreshAllLoops()})}})},registerModelBinding(el){const modelAttr=el.getAttribute("p-model");modelAttr&&(el.addEventListener("input",e=>{let value;const type=e.target.type;if("number"===type||"range"===type)value=""===e.target.value?null:Number(e.target.value);else if("checkbox"===type)value=e.target.checked;else if("radio"===type)value=e.target.checked?e.target.value:void 0;else{const currentValue=eval(`with (el._scope) { ${modelAttr} }`);value=Array.isArray(currentValue)?e.target.value.split(",").map(e=>e.trim()).filter(e=>e):e.target.value}void 0!==value&&eval(`with (el._scope) { ${modelAttr} = value }`)}),"checkbox"!==el.type&&"radio"!==el.type||el.addEventListener("change",e=>{let value;value="checkbox"===el.type?e.target.checked:e.target.checked?e.target.value:void 0,void 0!==value&&eval(`with (el._scope) { ${modelAttr} = value }`)}))},evaluateDirectives(el,scope){Array.from(el.attributes).forEach(attr=>{const parsed=this.parseDirectiveModifiers(attr.name);if(Object.keys(this.directives).includes(parsed.directive)){const evalScope=el._scope||scope,value=eval(`with (evalScope) { (${attr.value}) }`);this.directives[parsed.directive](el,value,parsed.modifiers)}})},setForTemplateRecursive(e,t){e._forTemplate=t,Array.from(e.children).forEach(e=>{this.setForTemplateRecursive(e,t)})},refreshAllLoops(e=this.root,t=new Set){if("TEMPLATE"===e.tagName&&e.hasAttribute("p-for")){if(t.has(e))return;return t.add(e),void this.handleFor(e,e._scope||this.data,!1)}let r=e.firstElementChild;for(;r;){const e=r.nextElementSibling;this.refreshAllLoops(r,t),r=e}},handleFor(e,t,r){const a=e.getAttribute("p-for"),s=a.match(/^(?:const|let)?\s*(.+?)\s+(of|in)\s+(.+)$/);if(!s)return void console.error(`Invalid p-for expression: ${a}`);const[,o,n,i]=s;r?this.hydrateLoop(e,t,o,i):this.refreshLoop(e,t,o,i)},getTemplateScopePrefix(e){let t="",r=e.nextElementSibling;if(r&&r.hasAttribute&&r.hasAttribute("p-for-key")){const a=r.getAttribute("p-for-key"),s=a.lastIndexOf(":");if(s>0){const r=a.substring(0,s+1),o=r.lastIndexOf("-");if(o>=0){t=r.substring(0,o+1);const a=r.substring(o+1,r.length-1);e._forScopeId=a}else e._forScopeId=r.substring(0,r.length-1);return r}}if(e._forTemplate){const r=e._forTemplate._forData;if(r&&r.scopePrefix){let r=e.previousElementSibling;for(;r;){if(r.hasAttribute&&r.hasAttribute("p-for-key")){t=r.getAttribute("p-for-key")+"-";break}r=r.previousElementSibling}}}if(!t){let r=e.previousElementSibling;for(;r;){if(r.hasAttribute&&r.hasAttribute("p-for-key")&&r._forTemplate===e._forTemplate){t=r.getAttribute("p-for-key")+"-";break}r=r.previousElementSibling}}if(!t){let r=e.parentElement;for(;r;){if(r.hasAttribute&&r.hasAttribute("p-for-key")){t=r.getAttribute("p-for-key")+"-";break}if(r._forTemplate){const e=r._forTemplate._forData;if(e){const a=e.renderedElements.indexOf(r);if(a>=0){t=(e.scopePrefix||"")+a+"-";break}}}r=r.parentElement}}return e._forScopeId||(e._forScopeId="s"+this._templateScopeCounter++),t+e._forScopeId+":"},hydrateLoop(template,parentScope,varPattern,iterableExpr){template._scope=parentScope;try{const iterable=eval(`with (parentScope) { (${iterableExpr}) }`),scopePrefix=this.getTemplateScopePrefix(template);template._forData={varPattern:varPattern,iterableExpr:iterableExpr,renderedElements:[],scopePrefix:scopePrefix};const existingElementsByKey={};let sibling=template.nextElementSibling;for(;sibling&&sibling.hasAttribute("p-for-key");){const e=sibling.getAttribute("p-for-key"),t=e.startsWith(scopePrefix)||!e.includes(":")&&!e.includes("-");if(t){let t;t=e.startsWith(scopePrefix)?e.substring(scopePrefix.length):e,existingElementsByKey[t]||(existingElementsByKey[t]=[]),existingElementsByKey[t].push(sibling)}sibling=sibling.nextElementSibling}let index=0,lastInserted=template;for(const e of iterable){const t=this.createLoopScope(parentScope,varPattern,e);if(existingElementsByKey[String(index)])existingElementsByKey[String(index)].forEach(e=>{e._scope=t,this.setForTemplateRecursive(e,template),"TEMPLATE"!==e.tagName&&e.setAttribute("p-for-key",scopePrefix+index),this.walkDom(e,t,!0),template._forData.renderedElements.push(e),lastInserted=e});else{const e=template.content.cloneNode(!0),r=Array.from(e.children);r.forEach(e=>{e._scope=t,this.setForTemplateRecursive(e,template),"TEMPLATE"!==e.tagName&&e.setAttribute("p-for-key",scopePrefix+index),this.walkDom(e,t,!0)});const a=document.createDocumentFragment();r.forEach(e=>a.appendChild(e)),lastInserted.parentNode.insertBefore(a,lastInserted.nextSibling),template._forData.renderedElements.push(...r),lastInserted=r[r.length-1]||lastInserted}index++}Object.keys(existingElementsByKey).forEach(e=>{parseInt(e)>=index&&existingElementsByKey[e].forEach(e=>e.remove())})}catch(e){console.error(`Error in p-for hydration: ${iterableExpr}`,e)}},removeLoopElements(e){e.forEach(e=>{if(e._forData&&e._forData.renderedElements&&(this.removeLoopElements(e._forData.renderedElements),e._forData.renderedElements=[]),e.querySelectorAll){e.querySelectorAll("template[p-for]").forEach(e=>{e._forData&&e._forData.renderedElements&&(this.removeLoopElements(e._forData.renderedElements),e._forData.renderedElements=[])})}e.remove()})},refreshLoop(template,parentScope,varPattern,iterableExpr){const forData=template._forData;if(forData)try{const iterable=eval(`with (parentScope._p_target || parentScope) { (${iterableExpr}) }`),scopePrefix=forData.scopePrefix||this.getTemplateScopePrefix(template);this.removeLoopElements(forData.renderedElements),forData.renderedElements=[];let lastInsertedElement=template,index=0;for(const e of iterable){const t=template.content.cloneNode(!0),r=this.createLoopScope(parentScope,forData.varPattern,e),a=Array.from(t.children);a.forEach(e=>{e._scope=r,this.setForTemplateRecursive(e,template),"TEMPLATE"!==e.tagName&&e.setAttribute("p-for-key",scopePrefix+index)});const s=document.createDocumentFragment();a.forEach(e=>s.appendChild(e)),lastInsertedElement.parentNode.insertBefore(s,lastInsertedElement.nextSibling),forData.renderedElements.push(...a),a.forEach(e=>{this.walkDom(e,r,!0)});const o=a[a.length-1];o&&(lastInsertedElement=this.findLastRenderedSibling(o)),index++}}catch(e){console.error(`Error in p-for refresh: ${iterableExpr}`,e)}},findLastRenderedSibling(e){if("TEMPLATE"===e.tagName&&e._forData&&e._forData.renderedElements.length>0){const t=e._forData.renderedElements[e._forData.renderedElements.length-1];return this.findLastRenderedSibling(t)}return e},createLoopScope(e,t,r){const a={};if((t=t.trim()).startsWith("[")){const e=t.slice(1,-1).split(",").map(e=>e.trim());Array.isArray(r)?e.forEach((e,t)=>a[e]=r[t]):a[e[0]]=r}else if(t.startsWith("{")){t.slice(1,-1).split(",").map(e=>e.trim()).forEach(e=>{const[t,s]=e.split(":").map(e=>e.trim());a[s||t]=r[t]})}else a[t]=r;if(!e)return console.error("parentScope is undefined in createLoopScope"),new Proxy({},{get:()=>{},set:()=>!1});const s=e._p_target||e;if(!s||"object"!=typeof s)return console.error("Invalid parentTarget:",s),new Proxy(a,{get:(e,t)=>e[t],set:(e,t,r)=>(e[t]=r,!0)});const o=Object.create(s);Object.assign(o,a);const n=new Proxy(o,{get:(e,t)=>e[t],set:(e,t,r)=>(t in a?e[t]=r:s[t]=r,!0)});return n._p_target=o,n},walkDom(el,parentScope,isHydrating=!1){if("TEMPLATE"===el.tagName&&el.hasAttribute("p-for")){if(!isHydrating&&el._forTemplate)return;return void this.handleFor(el,parentScope,isHydrating)}const preScopeShowAttr=Array.from(el.attributes).find(e=>{const t=this.parseDirectiveModifiers(e.name);return"p-show"===t.directive&&t.modifiers["pre-scope"]});if(preScopeShowAttr&&parentScope){const value=eval(`with (parentScope) { (${preScopeShowAttr.value}) }`);this.directives["p-show"](el,value)}let currentScope=parentScope;const hasPScope=Array.from(el.attributes).some(e=>e.name.startsWith("p-scope"));hasPScope&&(currentScope=isHydrating?this.initScope(el,parentScope):this.refreshScope(el,parentScope)),isHydrating&&(el._scope=currentScope,this.registerEventListeners(el),this.registerModelBinding(el)),currentScope&&Array.from(el.attributes).forEach(attr=>{const parsed=this.parseDirectiveModifiers(attr.name);if(("p-show"!==parsed.directive||!parsed.modifiers["pre-scope"])&&Object.keys(this.directives).includes(parsed.directive)){const evalScope=el._scope||currentScope,value=eval(`with (evalScope) { (${attr.value}) }`);this.directives[parsed.directive](el,value,parsed.modifiers)}});const children=Array.from(el.children);for(const e of children)this.walkDom(e,currentScope,isHydrating)}},window.Pattr.start();
|
|
7
|
+
window.Pattr={_templateScopeCounter:0,directives:{"p-text":(e,t,r={})=>{let s=String(t);if(r.trim&&r.trim.length>0){const e=parseInt(r.trim[0])||100;s.length>e&&(s=s.substring(0,e)+"...")}e.innerText=s},"p-html":(e,t,r={})=>{let s=t;if(r.allow&&r.allow.length>0){const e=r.allow,t=document.createElement("div");t.innerHTML=s;const a=t=>{if(t.nodeType===Node.ELEMENT_NODE){const r=t.tagName.toLowerCase();if(!e.includes(r)){const e=document.createDocumentFragment();return Array.from(t.childNodes).forEach(t=>{const r=a(t);r&&e.appendChild(r)}),e}const s=t.cloneNode(!1);return Array.from(t.childNodes).forEach(e=>{const t=a(e);t&&s.appendChild(t)}),s}return t.cloneNode()},o=document.createElement("div");Array.from(t.childNodes).forEach(e=>{const t=a(e);t&&o.appendChild(t)}),s=o.innerHTML}if(r.trim&&r.trim.length>0){const e=parseInt(r.trim[0])||100,t=document.createElement("div");t.innerHTML=s;let a=0,o=!1;const n=t=>{if(o)return null;if(t.nodeType===Node.TEXT_NODE){const r=t.textContent,s=e-a;if(r.length<=s)return a+=r.length,t.cloneNode();{o=!0;const e=r.substring(0,s)+"...";return document.createTextNode(e)}}if(t.nodeType===Node.ELEMENT_NODE){const e=t.cloneNode(!1);for(let r of t.childNodes){const t=n(r);if(t&&e.appendChild(t),o)break}return e}return t.cloneNode()},i=document.createElement("div");for(let e of t.childNodes){const t=n(e);if(t&&i.appendChild(t),o)break}s=i.innerHTML}e.innerHTML=s},"p-show":(e,t)=>{e.style.display=t?"":"none"},"p-style":(e,t)=>{"string"==typeof t?e.style.cssText=t:"object"==typeof t&&null!==t&&Object.assign(e.style,t)},"p-class":(e,t,r={})=>{if(void 0!==r.replace)return void("string"==typeof t?e.className=t:Array.isArray(t)?e.className=t.join(" "):"object"==typeof t&&null!==t&&(e.className=Object.keys(t).filter(e=>t[e]).join(" ")));let s=new Set,a=new Set;if("string"==typeof t&&t?t.split(" ").forEach(e=>{e&&(s.add(e),a.add(e))}):Array.isArray(t)?t.forEach(e=>{e&&(s.add(e),a.add(e))}):"object"==typeof t&&null!==t&&Object.keys(t).forEach(e=>{a.add(e),t[e]&&s.add(e)}),!e._p_staticClasses){const t=e.className?e.className.split(" ").filter(e=>e):[];e._p_staticClasses=t.filter(e=>!a.has(e))}e._p_dynamicClasses||(e._p_dynamicClasses=new Set),e._p_dynamicClasses=s;const o=[...e._p_staticClasses,...e._p_dynamicClasses];e.className=o.join(" ")},"p-model":(e,t)=>{Array.isArray(t)?e.value=t.join(", "):e.value=t},"p-attr":(e,t,r={})=>{const s=Object.keys(r);if(s.length>0){const r=s[0];null==t||!1===t?e.removeAttribute(r):e.setAttribute(r,String(t))}else"object"==typeof t&&null!==t&&Object.keys(t).forEach(r=>{const s=t[r];null==s||!1===s?e.removeAttribute(r):e.setAttribute(r,String(s))})}},parseDirectiveModifiers(e){const t=e.split(":"),r=t[0],s={};for(let e=1;e<t.length;e++){const r=t[e].split("."),a=r[0],o=r.slice(1);s[a]=o}return{directive:r,modifiers:s}},async start(){this.root=document.documentElement;const e=document.getElementById("p-root-data")?.textContent;try{this.rawData=JSON.parse(e||"{}")}catch(e){console.error("Error parsing root data JSON:",e)}this.buildScopeData(this.root,this.rawData),this.data=this.observe(this.rawData),this.walkDom(this.root,this.data,!0),this.refreshAllLoops()},generateDomPathId(e){const t=[];let r=e;for(;r&&"HTML"!==r.tagName;){const e=r.parentElement;if(e){const s=Array.from(e.children).indexOf(r);t.unshift(`${r.tagName}[${s}]`)}r=e}return t.join("/")},buildScopeData(e,t){let r=t;const s=Array.from(e.attributes).find(e=>e.name.startsWith("p-scope"));if(s){const a=e.getAttribute("p-id")||this.generateDomPathId(e);t._p_children||(t._p_children={}),t._p_children[a]||(t._p_children[a]={}),r=t._p_children[a],r._p_scope=e.getAttribute(s.name),r._p_id=a}let a=e.firstElementChild;for(;a;)this.buildScopeData(a,r),a=a.nextElementSibling},observe(e,t,r=[]){const s=e;let a=s;t&&(a=Object.create(t._p_target||t),Object.assign(a,s));const o=new Set(r),n=t?._p_target||t,i=new WeakSet,c=(e,t=!1,r=null)=>{if(null===e||"object"!=typeof e)return e;if(i.has(e))return e;if(e instanceof Date||e instanceof RegExp||e instanceof Map||e instanceof Set)return e;const s=new Proxy(e,{get:(e,s)=>{if("_p_target"===s)return e;if("_p_syncParent"===s)return n;if("_p_syncKey"===s)return r;const a=e[s];return t&&null!==a&&"object"==typeof a?c(a,!0,r):a},set:(e,s,a)=>{if(e[s]=a,t&&n&&r){const e=n[r];e&&"object"==typeof e&&(e[s]=a)}return this.walkDom(this.root,this.data,!1),!0},has:(e,t)=>t in e});return i.add(e),s};if(n)for(const e of o){if(e in a){const t=a[e];null!==t&&"object"==typeof t&&(a[e]=c(t,!0))}if(e in n){const t=n[e];null!==t&&"object"==typeof t&&(n[e]=c(t,!0))}}return new Proxy(a,{get:(e,t)=>"_p_target"===t?e:e[t],set:(e,t,r)=>(o.has(t)&&null!==r&&"object"==typeof r&&(r=c(r,!0,t)),e[t]=r,o.has(t)&&n&&t in n&&(n[t]=r),this.walkDom(this.root,this.data,!1),!0),has:(e,t)=>t in e})},splitPScopeStatements(e){const t=[];let r="",s=0,a=0,o=!1,n=null;for(let i=0;i<e.length;i++){const c=e[i],l=i>0?e[i-1]:null;'"'!==c&&"'"!==c&&"`"!==c||"\\"===l||(o?n===c&&(o=!1,n=null):(o=!0,n=c)),o||("{"===c?s++:"}"===c?s--:"("===c?a++:")"===c&&a--),";"!==c||o||0!==s||0!==a?r+=c:(r.trim()&&t.push(r.trim()),r="")}return r.trim()&&t.push(r.trim()),t},getPScopeOutputVars(e){const t=[];return this.splitPScopeStatements(e).forEach(e=>{const r=e.match(/^\[([^\]]+)\]\s*=\s*(.+)$/);if(r){const e=r[1].split(",").map(e=>e.trim());return void t.push(...e)}const s=e.match(/^\{([^}]+)\}\s*=\s*(.+)$/);if(s){const e=s[1].split(",").map(e=>e.trim());return void t.push(...e)}const a=e.match(/^(\w+)\s*=\s*(.+)$/);a&&t.push(a[1])}),t},initScope(e,t){const r=e.getAttribute("p-id")||this.generateDomPathId(e),s=t._p_target._p_children[r],a=e.getAttribute("p-scope"),o=Array.from(e.attributes).find(e=>e.name.startsWith("p-scope")&&e.name.includes("sync"));let n=[],i=[];if(a&&n.push(a),o){const t=e.getAttribute(o.name);n.push(t),i=this.getPScopeOutputVars(t)}const c=n.join("; "),l=this.observe(s,t,i);i.length>0&&(e._p_syncVars=new Set(i)),this.executePScopeStatements(l,c);const p=Object.getPrototypeOf(l._p_target);e._parentSnapshot={};for(let t in p)t.startsWith("_p_")||(e._parentSnapshot[t]=p[t]);const h=l._p_target;e._localSnapshot={};for(let t of Object.keys(h))t.startsWith("_p_")||(e._localSnapshot[t]=h[t]);return l},refreshScope(e,t){let r=e._scope;if(!r)return t;const s=e.getAttribute("p-scope"),a=Array.from(e.attributes).find(e=>e.name.startsWith("p-scope")&&e.name.includes("sync"));let o=[];s&&o.push(s),a&&o.push(e.getAttribute(a.name));const n=o.join("; ");return n&&r._p_target&&this.updateScopeFromParent(e,r,n),r},executePScopeStatements(scope,pScopeExpr){const statements=this.splitPScopeStatements(pScopeExpr),target=scope._p_target,sequentialScope=new Proxy(target,{get:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)?e[t]:scope[t],has:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)||t in scope});for(const stmt of statements){const arrayDestructMatch=stmt.match(/^\[([^\]]+)\]\s*=\s*(.+)$/);if(arrayDestructMatch){const[,vars,expr]=arrayDestructMatch,varNames=vars.split(",").map(e=>e.trim());try{const value=eval(`with (sequentialScope) { (${expr}) }`);Array.isArray(value)&&varNames.forEach((e,t)=>{target[e]=value[t]})}catch(e){console.error(`Error executing p-scope array destructuring "${stmt}":`,e)}continue}const objDestructMatch=stmt.match(/^\{([^}]+)\}\s*=\s*(.+)$/);if(objDestructMatch){const[,vars,expr]=objDestructMatch,varNames=vars.split(",").map(e=>e.trim());try{const value=eval(`with (sequentialScope) { (${expr}) }`);"object"==typeof value&&null!==value&&varNames.forEach(e=>{target[e]=value[e]})}catch(e){console.error(`Error executing p-scope object destructuring "${stmt}":`,e)}continue}const match=stmt.match(/^(\w+)\s*=\s*(.+)$/);if(match){const[,varName,expr]=match;try{const value=eval(`with (sequentialScope) { (${expr}) }`);target[varName]=value}catch(e){console.error(`Error executing p-scope statement "${stmt}":`,e)}}}},updateScopeFromParent(el,scope,pScopeExpr){const parentProto=Object.getPrototypeOf(scope._p_target),target=scope._p_target,changedParentVars=new Set,changedLocalVars=new Set;el._parentSnapshot||(el._parentSnapshot={});for(let e in parentProto)e.startsWith("_p_")||(el._parentSnapshot[e]!==parentProto[e]&&changedParentVars.add(e),el._parentSnapshot[e]=parentProto[e]);el._localSnapshot||(el._localSnapshot={});for(let e of Object.keys(target))e.startsWith("_p_")||(el._localSnapshot[e]!==target[e]&&changedLocalVars.add(e),el._localSnapshot[e]=target[e]);const allChangedVars=new Set([...changedParentVars,...changedLocalVars]);if(0!==allChangedVars.size)try{const statements=this.splitPScopeStatements(pScopeExpr),outputVars=new Set;statements.forEach(e=>{const t=e.match(/^\[([^\]]+)\]\s*=\s*(.+)$/);if(t){return void t[1].split(",").map(e=>e.trim()).forEach(e=>outputVars.add(e))}const r=e.match(/^\{([^}]+)\}\s*=\s*(.+)$/);if(r){return void r[1].split(",").map(e=>e.trim()).forEach(e=>outputVars.add(e))}const s=e.match(/^(\w+)\s*=\s*(.+)$/);s&&outputVars.add(s[1])});const setInThisPass=new Set,sequentialScope=new Proxy(target,{get:(e,t)=>"_p_target"===t||"_p_children"===t||"_p_scope"===t||setInThisPass.has(t)?e[t]:changedParentVars.has(t)?parentProto[t]:changedLocalVars.has(t)||Object.prototype.hasOwnProperty.call(e,t)?e[t]:parentProto[t],set:(e,t,r)=>(e[t]=r,!0),has:(e,t)=>setInThisPass.has(t)||Object.prototype.hasOwnProperty.call(e,t)||t in parentProto});statements.forEach(stmt=>{let shouldExecute=!1;const parts=stmt.split("=");if(parts.length<=1)return;const rhs=parts.slice(1).join("=");if(changedParentVars.forEach(e=>{rhs.includes(e)&&(shouldExecute=!0)}),changedLocalVars.forEach(e=>{!outputVars.has(e)&&rhs.includes(e)&&(shouldExecute=!0)}),shouldExecute||setInThisPass.forEach(e=>{rhs.includes(e)&&(shouldExecute=!0)}),shouldExecute){const arrayMatch=stmt.match(/^\[([^\]]+)\]\s*=\s*(.+)$/);if(arrayMatch){const[,vars,expr]=arrayMatch,varNames=vars.split(",").map(e=>e.trim()),value=eval(`with (sequentialScope) { (${expr}) }`);return void(Array.isArray(value)&&varNames.forEach((e,t)=>{target[e]=value[t],setInThisPass.add(e)}))}const objMatch=stmt.match(/^\{([^}]+)\}\s*=\s*(.+)$/);if(objMatch){const[,vars,expr]=objMatch,varNames=vars.split(",").map(e=>e.trim()),value=eval(`with (sequentialScope) { (${expr}) }`);return void("object"==typeof value&&null!==value&&varNames.forEach(e=>{target[e]=value[e],setInThisPass.add(e)}))}const match=stmt.match(/^(\w+)\s*=\s*(.+)$/);if(match){const[,varName,expr]=match,value=eval(`with (sequentialScope) { (${expr}) }`);target[varName]=value,setInThisPass.add(varName)}}});for(let e of Object.keys(target))e.startsWith("_p_")||(el._localSnapshot[e]=target[e])}catch(e){console.error("Error re-executing p-scope expression:",e)}},registerEventListeners(el){Array.from(el.attributes).forEach(attr=>{if(attr.name.startsWith("p-on:")){const event=attr.name.replace("p-on:","");el.addEventListener(event,()=>{eval(`with (el._scope) { ${attr.value} }`),this.walkDom(this.root,this.data,!1),this.refreshAllLoops()})}})},registerModelBinding(el){const modelAttr=el.getAttribute("p-model");modelAttr&&(el.addEventListener("input",e=>{let value;const type=e.target.type;if("number"===type||"range"===type)value=""===e.target.value?null:Number(e.target.value);else if("checkbox"===type)value=e.target.checked;else if("radio"===type)value=e.target.checked?e.target.value:void 0;else{const currentValue=eval(`with (el._scope) { ${modelAttr} }`);value=Array.isArray(currentValue)?e.target.value.split(",").map(e=>e.trim()).filter(e=>e):e.target.value}void 0!==value&&eval(`with (el._scope) { ${modelAttr} = value }`)}),"checkbox"!==el.type&&"radio"!==el.type||el.addEventListener("change",e=>{let value;value="checkbox"===el.type?e.target.checked:e.target.checked?e.target.value:void 0,void 0!==value&&eval(`with (el._scope) { ${modelAttr} = value }`)}))},evaluateDirectives(el,scope){Array.from(el.attributes).forEach(attr=>{const parsed=this.parseDirectiveModifiers(attr.name);if(Object.keys(this.directives).includes(parsed.directive)){const evalScope=el._scope||scope,value=eval(`with (evalScope) { (${attr.value}) }`);this.directives[parsed.directive](el,value,parsed.modifiers)}})},setForTemplateRecursive(e,t){e._forTemplate=t,Array.from(e.children).forEach(e=>{this.setForTemplateRecursive(e,t)})},refreshAllLoops(e=this.root,t=new Set){if("TEMPLATE"===e.tagName&&e.hasAttribute("p-for")){if(t.has(e))return;return t.add(e),void this.handleFor(e,e._scope||this.data,!1)}let r=e.firstElementChild;for(;r;){const e=r.nextElementSibling;this.refreshAllLoops(r,t),r=e}},handleFor(e,t,r){const s=e.getAttribute("p-for"),a=s.match(/^(?:const|let)?\s*(.+?)\s+(of|in)\s+(.+)$/);if(!a)return void console.error(`Invalid p-for expression: ${s}`);const[,o,n,i]=a;r?this.hydrateLoop(e,t,o,i):this.refreshLoop(e,t,o,i)},getTemplateScopePrefix(e){let t="",r=e.nextElementSibling;if(r&&r.hasAttribute&&r.hasAttribute("p-for-key")){const s=r.getAttribute("p-for-key"),a=s.lastIndexOf(":");if(a>0){const r=s.substring(0,a+1),o=r.lastIndexOf("-");if(o>=0){t=r.substring(0,o+1);const s=r.substring(o+1,r.length-1);e._forScopeId=s}else e._forScopeId=r.substring(0,r.length-1);return r}}if(e._forTemplate){const r=e._forTemplate._forData;if(r&&r.scopePrefix){let r=e.previousElementSibling;for(;r;){if(r.hasAttribute&&r.hasAttribute("p-for-key")){t=r.getAttribute("p-for-key")+"-";break}r=r.previousElementSibling}}}if(!t){let r=e.previousElementSibling;for(;r;){if(r.hasAttribute&&r.hasAttribute("p-for-key")&&r._forTemplate===e._forTemplate){t=r.getAttribute("p-for-key")+"-";break}r=r.previousElementSibling}}if(!t){let r=e.parentElement;for(;r;){if(r.hasAttribute&&r.hasAttribute("p-for-key")){t=r.getAttribute("p-for-key")+"-";break}if(r._forTemplate){const e=r._forTemplate._forData;if(e){const s=e.renderedElements.indexOf(r);if(s>=0){t=(e.scopePrefix||"")+s+"-";break}}}r=r.parentElement}}return e._forScopeId||(e._forScopeId="s"+this._templateScopeCounter++),t+e._forScopeId+":"},hydrateLoop(template,parentScope,varPattern,iterableExpr){template._scope=parentScope;try{const iterable=eval(`with (parentScope) { (${iterableExpr}) }`),scopePrefix=this.getTemplateScopePrefix(template);template._forData={varPattern:varPattern,iterableExpr:iterableExpr,renderedElements:[],scopePrefix:scopePrefix};const existingElementsByKey={};let sibling=template.nextElementSibling;for(;sibling&&sibling.hasAttribute("p-for-key");){const e=sibling.getAttribute("p-for-key"),t=e.startsWith(scopePrefix)||!e.includes(":")&&!e.includes("-");if(t){let t;t=e.startsWith(scopePrefix)?e.substring(scopePrefix.length):e,existingElementsByKey[t]||(existingElementsByKey[t]=[]),existingElementsByKey[t].push(sibling)}sibling=sibling.nextElementSibling}let index=0,lastInserted=template;for(const e of iterable){const t=this.createLoopScope(parentScope,varPattern,e);if(existingElementsByKey[String(index)])existingElementsByKey[String(index)].forEach(e=>{e._scope=t,this.setForTemplateRecursive(e,template),"TEMPLATE"!==e.tagName&&e.setAttribute("p-for-key",scopePrefix+index),this.walkDom(e,t,!0),template._forData.renderedElements.push(e),lastInserted=e});else{const e=template.content.cloneNode(!0),r=Array.from(e.children);r.forEach(e=>{e._scope=t,this.setForTemplateRecursive(e,template),"TEMPLATE"!==e.tagName&&e.setAttribute("p-for-key",scopePrefix+index),this.walkDom(e,t,!0)});const s=document.createDocumentFragment();r.forEach(e=>s.appendChild(e)),lastInserted.parentNode.insertBefore(s,lastInserted.nextSibling),template._forData.renderedElements.push(...r),lastInserted=r[r.length-1]||lastInserted}index++}Object.keys(existingElementsByKey).forEach(e=>{parseInt(e)>=index&&existingElementsByKey[e].forEach(e=>e.remove())})}catch(e){console.error(`Error in p-for hydration: ${iterableExpr}`,e)}},removeLoopElements(e){e.forEach(e=>{if(e._forData&&e._forData.renderedElements&&(this.removeLoopElements(e._forData.renderedElements),e._forData.renderedElements=[]),e.querySelectorAll){e.querySelectorAll("template[p-for]").forEach(e=>{e._forData&&e._forData.renderedElements&&(this.removeLoopElements(e._forData.renderedElements),e._forData.renderedElements=[])})}e.remove()})},refreshLoop(template,parentScope,varPattern,iterableExpr){const forData=template._forData;if(forData)try{const iterable=eval(`with (parentScope._p_target || parentScope) { (${iterableExpr}) }`),scopePrefix=forData.scopePrefix||this.getTemplateScopePrefix(template);this.removeLoopElements(forData.renderedElements),forData.renderedElements=[];let lastInsertedElement=template,index=0;for(const e of iterable){const t=template.content.cloneNode(!0),r=this.createLoopScope(parentScope,forData.varPattern,e),s=Array.from(t.children);s.forEach(e=>{e._scope=r,this.setForTemplateRecursive(e,template),"TEMPLATE"!==e.tagName&&e.setAttribute("p-for-key",scopePrefix+index)});const a=document.createDocumentFragment();s.forEach(e=>a.appendChild(e)),lastInsertedElement.parentNode.insertBefore(a,lastInsertedElement.nextSibling),forData.renderedElements.push(...s),s.forEach(e=>{this.walkDom(e,r,!0)});const o=s[s.length-1];o&&(lastInsertedElement=this.findLastRenderedSibling(o)),index++}}catch(e){console.error(`Error in p-for refresh: ${iterableExpr}`,e)}},findLastRenderedSibling(e){if("TEMPLATE"===e.tagName&&e._forData&&e._forData.renderedElements.length>0){const t=e._forData.renderedElements[e._forData.renderedElements.length-1];return this.findLastRenderedSibling(t)}return e},createLoopScope(e,t,r){const s={};if((t=t.trim()).startsWith("[")){const e=t.slice(1,-1).split(",").map(e=>e.trim());Array.isArray(r)?e.forEach((e,t)=>s[e]=r[t]):s[e[0]]=r}else if(t.startsWith("{")){t.slice(1,-1).split(",").map(e=>e.trim()).forEach(e=>{const[t,a]=e.split(":").map(e=>e.trim());s[a||t]=r[t]})}else s[t]=r;if(!e)return console.error("parentScope is undefined in createLoopScope"),new Proxy({},{get:()=>{},set:()=>!1});const a=e._p_target||e;if(!a||"object"!=typeof a)return console.error("Invalid parentTarget:",a),new Proxy(s,{get:(e,t)=>e[t],set:(e,t,r)=>(e[t]=r,!0)});const o=Object.create(a);Object.assign(o,s);const n=new Proxy(o,{get:(e,t)=>e[t],set:(e,t,r)=>(t in s?e[t]=r:a[t]=r,!0)});return n._p_target=o,n},walkDom(el,parentScope,isHydrating=!1){if("TEMPLATE"===el.tagName&&el.hasAttribute("p-for")){if(!isHydrating&&el._forTemplate)return;return void this.handleFor(el,parentScope,isHydrating)}const preScopeShowAttr=Array.from(el.attributes).find(e=>{const t=this.parseDirectiveModifiers(e.name);return"p-show"===t.directive&&t.modifiers["pre-scope"]});if(preScopeShowAttr&&parentScope){const value=eval(`with (parentScope) { (${preScopeShowAttr.value}) }`);this.directives["p-show"](el,value)}let currentScope=parentScope;const hasPScope=Array.from(el.attributes).some(e=>e.name.startsWith("p-scope"));hasPScope&&(currentScope=isHydrating?this.initScope(el,parentScope):this.refreshScope(el,parentScope)),isHydrating&&(el._scope=currentScope,this.registerEventListeners(el),this.registerModelBinding(el)),currentScope&&Array.from(el.attributes).forEach(attr=>{const parsed=this.parseDirectiveModifiers(attr.name);if(("p-show"!==parsed.directive||!parsed.modifiers["pre-scope"])&&Object.keys(this.directives).includes(parsed.directive)){const evalScope=el._scope||currentScope,value=eval(`with (evalScope) { (${attr.value}) }`);this.directives[parsed.directive](el,value,parsed.modifiers)}});const children=Array.from(el.children);for(const e of children)this.walkDom(e,currentScope,isHydrating)}},window.Pattr.start();
|