create-prisma-php-app 2.1.2 → 2.1.4

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.
@@ -20,17 +20,12 @@ export const SRC_DIR = path.join(PROJECT_ROOT, "src");
20
20
  const IMPORTS_FILE = path.join(PROJECT_ROOT, "settings/class-imports.json");
21
21
  const CLASS_LOG_FILE = path.join(PROJECT_ROOT, "settings/class-log.json");
22
22
 
23
- async function loadImportsData(): Promise<Record<string, string>> {
24
- try {
25
- const content = await fs.readFile(IMPORTS_FILE, "utf-8");
26
- return JSON.parse(content);
27
- } catch {
28
- return {};
29
- }
30
- }
31
23
 
32
24
  async function saveImportsData(
33
- data: Record<string, { className: string; filePath: string }>
25
+ data: Record<
26
+ string,
27
+ Array<{ className: string; filePath: string; importer: string }>
28
+ >
34
29
  ) {
35
30
  await fs.writeFile(IMPORTS_FILE, JSON.stringify(data, null, 2), "utf-8");
36
31
  }
@@ -86,16 +81,14 @@ export async function analyzeImportsInFile(
86
81
  } else {
87
82
  // Handle grouped `use` statements
88
83
  if (node.kind === "usegroup" && node.name) {
89
- baseNamespace = node.name.name || node.name; // Set base namespace
84
+ baseNamespace = node.name.name || node.name;
90
85
  for (const useItem of node.items || []) {
91
86
  if (useItem.kind === "useitem" && useItem.name) {
92
- const subNamespace = useItem.name.name || useItem.name; // Sub-namespace
93
- const fqn = combineNamespaces(baseNamespace, subNamespace); // Fully Qualified Namespace
94
- const alias = useItem.alias ? useItem.alias.name : subNamespace; // Alias or default to subNamespace
87
+ const subNamespace = useItem.name.name || useItem.name;
88
+ const fqn = combineNamespaces(baseNamespace, subNamespace);
89
+ const alias = useItem.alias ? useItem.alias.name : subNamespace;
95
90
  if (!imports[alias]) {
96
- // Prevent overwriting
97
- imports[alias] = fqn; // Map alias to FQN
98
- // console.log(`🚀 Adding import: ${alias} -> ${fqn}`);
91
+ imports[alias] = fqn;
99
92
  }
100
93
  }
101
94
  }
@@ -103,12 +96,11 @@ export async function analyzeImportsInFile(
103
96
 
104
97
  // Handle non-grouped `use` statements
105
98
  if (node.kind === "useitem" && node.name) {
106
- const fqn = node.name.name || node.name; // Fully Qualified Namespace
99
+ const fqn = node.name.name || node.name;
107
100
  const alias = node.alias
108
101
  ? node.alias.name
109
102
  : path.basename(fqn.replace(/\\/g, "/"));
110
103
  if (!imports[alias]) {
111
- // Prevent overwriting
112
104
  imports[alias] = fqn;
113
105
  }
114
106
  }
@@ -129,38 +121,56 @@ export async function analyzeImportsInFile(
129
121
  }
130
122
 
131
123
  export async function updateComponentImports() {
132
- // Load existing imports (if any)
133
- const allImports = await loadImportsData();
134
-
135
124
  // Analyze all PHP files for use statements
136
125
  const phpFiles = await getAllPhpFiles(SRC_DIR);
126
+ // Build a mapping: alias -> array of { fqn, importer }
127
+ const allImports: Record<
128
+ string,
129
+ Array<{ fqn: string; importer: string }>
130
+ > = {};
131
+
137
132
  for (const file of phpFiles) {
138
133
  const fileImports = await analyzeImportsInFile(file);
139
- // Merge fileImports into allImports
140
- Object.assign(allImports, fileImports);
134
+ for (const [alias, fqn] of Object.entries(fileImports)) {
135
+ if (allImports[alias]) {
136
+ // Check both fqn and importer to avoid duplicates
137
+ if (
138
+ !allImports[alias].some(
139
+ (entry) => entry.fqn === fqn && entry.importer === file
140
+ )
141
+ ) {
142
+ allImports[alias].push({ fqn, importer: file });
143
+ }
144
+ } else {
145
+ allImports[alias] = [{ fqn, importer: file }];
146
+ }
147
+ }
141
148
  }
142
149
 
143
- // Now filter using class-log.json
150
+ // Load the class log to filter valid imports
144
151
  const classLog = await loadClassLogData();
145
-
146
152
  const filteredImports: Record<
147
153
  string,
148
- { className: string; filePath: string }
154
+ Array<{ className: string; filePath: string; importer: string }>
149
155
  > = {};
150
- for (const [alias, fqn] of Object.entries(allImports)) {
151
- if (classLog[fqn]) {
152
- // console.log(`Including: ${alias} -> ${fqn}`);
153
- filteredImports[alias] = {
154
- className: fqn,
155
- filePath: classLog[fqn].filePath,
156
- };
157
- } else {
158
- // console.log(`Excluding: ${alias} -> ${fqn}`);
156
+
157
+ for (const [alias, entries] of Object.entries(allImports)) {
158
+ for (const entry of entries) {
159
+ if (classLog[entry.fqn]) {
160
+ const importEntry = {
161
+ className: entry.fqn,
162
+ filePath: classLog[entry.fqn].filePath,
163
+ importer: entry.importer,
164
+ };
165
+ if (filteredImports[alias]) {
166
+ filteredImports[alias].push(importEntry);
167
+ } else {
168
+ filteredImports[alias] = [importEntry];
169
+ }
170
+ }
159
171
  }
160
172
  }
161
173
 
162
174
  await saveImportsData(filteredImports);
163
- // console.log(
164
- // "component_imports.json updated with IPHPX/PHPX components only."
165
- // );
175
+ // console.log("component_imports.json updated with importer file path included.");
166
176
  }
@@ -26,12 +26,49 @@ function findComponentsInFile(code: string): string[] {
26
26
 
27
27
  export async function checkComponentImports(
28
28
  filePath: string,
29
- fileImports: Record<string, string>
29
+ fileImports: Record<
30
+ string,
31
+ | Array<{ className: string; filePath: string; importer?: string }>
32
+ | { className: string; filePath: string; importer?: string }
33
+ >
30
34
  ) {
31
35
  const code = await fs.readFile(filePath, "utf-8");
32
36
  const usedComponents = findComponentsInFile(code);
37
+ // Normalize the current file path: replace backslashes, trim, remove trailing slash, and lower-case.
38
+ const normalizedFilePath = filePath
39
+ .replace(/\\/g, "/")
40
+ .trim()
41
+ .replace(/\/+$/, "")
42
+ .toLowerCase();
43
+
33
44
  usedComponents.forEach((component) => {
34
- if (!fileImports[component]) {
45
+ const rawMapping = fileImports[component];
46
+ // Normalize rawMapping to an array
47
+ let mappings: Array<{
48
+ className: string;
49
+ filePath: string;
50
+ importer?: string;
51
+ }> = [];
52
+ if (Array.isArray(rawMapping)) {
53
+ mappings = rawMapping;
54
+ } else if (rawMapping) {
55
+ mappings = [rawMapping];
56
+ }
57
+
58
+ // Check if any mapping's importer matches the current file.
59
+ const found = mappings.some((mapping) => {
60
+ const normalizedImporter = (mapping.importer || "")
61
+ .replace(/\\/g, "/")
62
+ .trim()
63
+ .replace(/\/+$/, "")
64
+ .toLowerCase();
65
+ // Either exact match or the current file path ends with the importer.
66
+ return (
67
+ normalizedFilePath === normalizedImporter ||
68
+ normalizedFilePath.endsWith(normalizedImporter)
69
+ );
70
+ });
71
+ if (!found) {
35
72
  console.warn(
36
73
  chalk.yellow("Warning: ") +
37
74
  chalk.white("Component ") +
@@ -35,7 +35,7 @@ class Auth
35
35
  */
36
36
  private function __construct()
37
37
  {
38
- $this->secretKey = $_ENV['AUTH_SECRET'];
38
+ $this->secretKey = $_ENV['AUTH_SECRET'] ?? 'CD24eEv4qbsC5LOzqeaWbcr58mBMSvA4Mkii8GjRiHkt';
39
39
  self::$cookieName = self::getCookieName();
40
40
  }
41
41
 
@@ -16,7 +16,7 @@ class PHPX implements IPHPX
16
16
  /**
17
17
  * @var mixed The children elements or content to be rendered within the component.
18
18
  */
19
- protected mixed $children;
19
+ public mixed $children;
20
20
 
21
21
  /**
22
22
  * @var string The CSS class for custom styling.
@@ -11,6 +11,7 @@ use DOMElement;
11
11
  use DOMComment;
12
12
  use DOMNode;
13
13
  use RuntimeException;
14
+ use Bootstrap;
14
15
 
15
16
  class TemplateCompiler
16
17
  {
@@ -40,6 +41,7 @@ class TemplateCompiler
40
41
  self::initializeClassMappings();
41
42
  }
42
43
 
44
+
43
45
  $templateContent = self::preprocessBindings($templateContent);
44
46
 
45
47
  $dom = self::convertToXml($templateContent);
@@ -71,7 +73,6 @@ class TemplateCompiler
71
73
  $expression = $matches[3];
72
74
  $afterBinding = $matches[4];
73
75
 
74
- // Escape the binding expression for attributes.
75
76
  $escapedExpression = htmlspecialchars($expression, ENT_QUOTES, 'UTF-8');
76
77
  $placeholder = '%%ATTR_BIND_' . count($attributePlaceholders) . '%%';
77
78
 
@@ -81,17 +82,14 @@ class TemplateCompiler
81
82
  $templateContent
82
83
  );
83
84
 
84
- // Process text {{ ... }} bindings, but skip ones inside attribute values.
85
85
  $textBindingPattern = '/(?:"[^"]*"|\'[^\']*\')(*SKIP)(*FAIL)|{{\s*(.+?)\s*}}/u';
86
86
  $templateContent = preg_replace_callback(
87
87
  $textBindingPattern,
88
88
  function ($matches) {
89
89
  $expr = $matches[1];
90
- // If the expression is a simple word/dot path, use a simple binding.
91
90
  if (preg_match('/^[\w.]+$/u', $expr)) {
92
91
  return "<span pp-bind=\"{$expr}\"></span>";
93
92
  } else {
94
- // Otherwise, encode the expression and use an expression binding.
95
93
  $encodedExpr = htmlspecialchars($expr, ENT_QUOTES, 'UTF-8');
96
94
  return "<span pp-bind-expr=\"{$encodedExpr}\"></span>";
97
95
  }
@@ -219,56 +217,97 @@ class TemplateCompiler
219
217
  if ($node instanceof DOMElement) {
220
218
  $componentName = $node->nodeName;
221
219
  $attributes = [];
222
-
223
220
  foreach ($node->attributes as $attr) {
224
221
  $attributes[$attr->name] = $attr->value;
225
222
  }
226
223
 
227
- $childOutput = [];
228
- foreach ($node->childNodes as $child) {
229
- $childOutput[] = self::processNode($child);
230
- }
231
- $innerContent = implode('', $childOutput);
224
+ if (isset(self::$classMappings[$componentName])) {
225
+ $componentInstance = self::initializeComponentInstance($componentName, $attributes);
232
226
 
233
- $attributes['children'] = $innerContent;
227
+ $childOutput = [];
228
+ foreach ($node->childNodes as $child) {
229
+ $childOutput[] = self::processNode($child);
230
+ }
231
+ $componentInstance->children = implode('', $childOutput);
234
232
 
235
- return self::processComponent($componentName, $attributes);
233
+ $renderedContent = $componentInstance->render();
234
+ if (self::hasComponentTag($renderedContent)) {
235
+ return self::compile($renderedContent);
236
+ }
237
+ return $renderedContent;
238
+ } else {
239
+ $childOutput = [];
240
+ foreach ($node->childNodes as $child) {
241
+ $childOutput[] = self::processNode($child);
242
+ }
243
+ $attributes['children'] = implode('', $childOutput);
244
+ return self::renderAsHtml($componentName, $attributes);
245
+ }
236
246
  } elseif ($node instanceof DOMComment) {
237
247
  return "<!--{$node->textContent}-->";
238
248
  }
239
-
240
249
  return $node->textContent;
241
250
  }
242
251
 
243
- protected static function initializeClassMappings(): void
252
+ protected static function initializeComponentInstance(string $componentName, array $attributes)
244
253
  {
245
- foreach (PrismaPHPSettings::$classLogFiles as $tagName => $fullyQualifiedClassName) {
246
- self::$classMappings[$tagName] = $fullyQualifiedClassName;
247
- }
248
- }
254
+ $importerFile = Bootstrap::$contentToInclude;
255
+ $normalizedImporterFile = str_replace('\\', '/', $importerFile);
249
256
 
250
- protected static function processComponent(string $componentName, array $attributes): string
251
- {
252
- if (isset(self::$classMappings[$componentName])) {
253
- $className = self::$classMappings[$componentName]['className'];
254
- $filePath = self::$classMappings[$componentName]['filePath'];
257
+ $srcPathNormalized = str_replace('\\', '/', SRC_PATH);
258
+ $relativeImporterFile = str_replace($srcPathNormalized . '/', '', $normalizedImporterFile);
255
259
 
256
- require_once str_replace('\\', '/', SRC_PATH . '/' . $filePath);
260
+ if (!isset(self::$classMappings[$componentName])) {
261
+ throw new RuntimeException("Component {$componentName} is not registered.");
262
+ }
257
263
 
258
- if (!class_exists($className)) {
259
- throw new RuntimeException("Class $className does not exist.");
264
+ $mappings = self::$classMappings[$componentName];
265
+ $selectedMapping = null;
266
+
267
+ if (is_array($mappings)) {
268
+ if (isset($mappings[0]) && is_array($mappings[0])) {
269
+ foreach ($mappings as $entry) {
270
+ $entryImporter = isset($entry['importer']) ? str_replace('\\', '/', $entry['importer']) : '';
271
+ $relativeEntryImporter = str_replace($srcPathNormalized . '/', '', $entryImporter);
272
+ if ($relativeEntryImporter === $relativeImporterFile) {
273
+ $selectedMapping = $entry;
274
+ break;
275
+ }
276
+ }
277
+ if ($selectedMapping === null) {
278
+ $selectedMapping = $mappings[0];
279
+ }
280
+ } else {
281
+ $selectedMapping = $mappings;
260
282
  }
283
+ }
261
284
 
262
- $componentInstance = new $className($attributes);
263
- $renderedContent = $componentInstance->render();
285
+ if (!isset($selectedMapping['className']) || !isset($selectedMapping['filePath'])) {
286
+ throw new RuntimeException("Invalid component mapping for {$componentName}.");
287
+ }
264
288
 
265
- if (strpos($renderedContent, '<') !== false) {
266
- return self::compile($renderedContent);
267
- }
268
- return $renderedContent;
289
+ $className = $selectedMapping['className'];
290
+ $filePath = $selectedMapping['filePath'];
291
+
292
+ require_once str_replace('\\', '/', SRC_PATH . '/' . $filePath);
293
+
294
+ if (!class_exists($className)) {
295
+ throw new RuntimeException("Class {$className} does not exist.");
296
+ }
297
+
298
+ return new $className($attributes);
299
+ }
300
+
301
+ protected static function initializeClassMappings(): void
302
+ {
303
+ foreach (PrismaPHPSettings::$classLogFiles as $tagName => $fullyQualifiedClassName) {
304
+ self::$classMappings[$tagName] = $fullyQualifiedClassName;
269
305
  }
306
+ }
270
307
 
271
- return self::renderAsHtml($componentName, $attributes);
308
+ protected static function hasComponentTag(string $templateContent): bool
309
+ {
310
+ return preg_match('/<\/*[A-Z][\w-]*/u', $templateContent) === 1;
272
311
  }
273
312
 
274
313
  protected static function renderAsHtml(string $tagName, array $attributes): string
@@ -1,4 +1,4 @@
1
- (()=>{const e=EventTarget.prototype.addEventListener,t=EventTarget.prototype.removeEventListener,n=new Map;EventTarget.prototype.addEventListener=function(t,s,o){n.has(this)||n.set(this,new Map);const i=n.get(this).get(t)||new Set;i.add(s),n.get(this).set(t,i),e.call(this,t,s,o)},EventTarget.prototype.removeEventListener=function(e,s,o){if(n.has(this)&&n.get(this).has(e)){const t=n.get(this).get(e);t&&(t.delete(s),0===t.size&&n.get(this).delete(e))}t.call(this,e,s,o)},EventTarget.prototype.removeAllEventListeners=function(e){if(n.has(this)&&n.get(this).has(e)){const s=n.get(this).get(e);s&&(s.forEach((n=>{t.call(this,e,n)})),n.get(this).delete(e))}}})();class PPHP{props={};static _instance;eventHandlers;redirectRegex=/redirect_7F834\s*=\s*(\/[^\s]*)/;isNavigating=!1;responseData=null;state={checkedElements:new Set};activeAbortController=null;_rawProps={};constructor(){this.eventHandlers=new Set(["onclick","ondblclick","onmousedown","onmouseup","onmouseover","onmousemove","onmouseout","onwheel","onkeypress","onkeydown","onkeyup","onfocus","onblur","onchange","oninput","onselect","onsubmit","onreset","onresize","onscroll","onload","onunload","onabort","onerror","onbeforeunload","oncopy","oncut","onpaste","ondrag","ondragstart","ondragend","ondragover","ondragenter","ondragleave","ondrop","oncontextmenu","ontouchstart","ontouchmove","ontouchend","ontouchcancel","onpointerdown","onpointerup","onpointermove","onpointerover","onpointerout","onpointerenter","onpointerleave","onpointercancel"]),this.handlePopState(),this.props=this.makeReactive(this._rawProps)}static get instance(){return PPHP._instance||(PPHP._instance=new PPHP),PPHP._instance}makeSafeEvaluator(e){const t=["length","charAt","charCodeAt","codePointAt","concat","includes","endsWith","indexOf","lastIndexOf","localeCompare","match","matchAll","normalize","padEnd","padStart","repeat","replace","replaceAll","search","slice","split","substring","substr","startsWith","toLocaleLowerCase","toLocaleUpperCase","toLowerCase","toString","toUpperCase","trim","trimEnd","trimStart","valueOf"],n=Array.from(new Set((e.match(/\b[a-zA-Z_][a-zA-Z0-9_]*\b/g)||[]).filter((e=>!["true","false","null","undefined"].includes(e))).filter((e=>!t.includes(e))))).map((t=>new RegExp(`\\b${t}\\.`).test(e)?`const ${t} = ctx["${t}"] !== undefined ? ctx["${t}"] : {};`:`const ${t} = ctx["${t}"] !== undefined ? ctx["${t}"] : "";`)).join("\n");return new Function("ctx",`\n "use strict";\n ${n}\n try {\n const result = ${e};\n return result === undefined || result === null ? "" : result;\n } catch(e) {\n return "";\n }\n `)}makeReactive(e,t=[]){const n=this;return e instanceof Map||e instanceof Set?e:new Proxy(e,{get(e,s){const o=e[s];return"object"==typeof o&&null!==o?n.makeReactive(o,[...t,s.toString()]):o},set(e,s,o){e[s]=o;const i=[...t,s.toString()].join(".");return document.querySelectorAll("[pp-bind]").forEach((e=>{const t=e.getAttribute("pp-bind");if(t)if(t===i)e.textContent=o;else try{const s=n.makeSafeEvaluator(t);e.textContent=s(n.props)}catch(e){}})),document.querySelectorAll("[pp-bind-expr]").forEach((e=>{const t=e.getAttribute("pp-bind-expr");if(!t)return;const o=t.match(/\b[a-zA-Z_][a-zA-Z0-9_]*\b/g);if(!o||o.includes(s.toString()))try{const s=n.makeSafeEvaluator(t)(n.props);e.textContent=s}catch(e){}})),document.querySelectorAll("*").forEach((e=>{Array.from(e.attributes).forEach((t=>{if(!t.name.startsWith("pp-bind-"))return;const s=t.value.replace(/&quot;/g,'"').replace(/&#039;/g,"'").replace(/&amp;/g,"&").replace(/^{{\s*|\s*}}$/g,"");if(!s.includes(i))return;const o=t.name.replace(/^(pp-bind-)+/,"");try{const t=n.makeSafeEvaluator(s)(n.props),i=null!=t?t.toString():"",a="value"===o?i:i.trim();let r;if("value"===o)r=a;else{const t=e.getAttribute(`pp-bind-original-data-${o}`)??(()=>{const t=e.getAttribute(o)?.trim()??"";return e.setAttribute(`pp-bind-original-data-${o}`,t),t})();r=t,a&&(r=t?`${t} ${a}`.trim():a)}"value"===o?e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement?e.value=r:e.setAttribute(o,r):"checked"===o&&e instanceof HTMLInputElement?e.checked="true"===r:e.setAttribute(o,r)}catch(e){}}))})),!0}})}handlePopState(){window.addEventListener("popstate",(async()=>{await this.handleNavigation()}))}attachWireFunctionEvents(){this.handleHiddenAttribute();document.querySelectorAll("button, input, select, textarea, a, form, label, div, span").forEach((e=>{if(this.handleAnchorTag(e),Array.from(e.attributes).filter((e=>this.eventHandlers.has(e.name))).forEach((t=>{const n=t.name.slice(2),s=t.value;e instanceof HTMLInputElement&&this.handleInputAppendParams(e,n),s&&(e.removeAttribute(t.name),this.handleDebounce(e,n,s))})),e instanceof HTMLFormElement){const t=e.getAttribute("onsubmit");t&&(e.removeAttribute("onsubmit"),this.handleDebounce(e,"submit",t))}}))}async handleDebounce(e,t,n){e.removeEventListener(t,(()=>{}));const s=e.getAttribute("pp-debounce")||"",o=e.getAttribute("pp-before-request")||"",i=e.getAttribute("pp-after-request")||"",a=async t=>{t.preventDefault();try{o&&await this.invokeHandler(e,o,t),await this.invokeHandler(e,n,t),i&&"@close"!==i&&await this.invokeHandler(e,i,t),this.handlerAutofocusAttribute()}catch(e){}};if(s){const n=this.parseTime(s),o=this.debounce(a,n);e instanceof HTMLFormElement&&"submit"===t?e.addEventListener(t,(e=>{e.preventDefault(),o(e)})):e.addEventListener(t,o)}else e.addEventListener(t,a)}debounce(e,t=300,n=!1){let s;return function(...o){const i=this;s&&clearTimeout(s),s=setTimeout((()=>{s=null,n||e.apply(i,o)}),t),n&&!s&&e.apply(i,o)}}handlerAutofocusAttribute(){const e=document.activeElement;if(e&&e!==document.body)return;const t=this.state?.focusId;if(!t)return;const n=document.querySelectorAll("[pp-autofocus]");let s=!1;n.forEach((e=>{if(s)return;const t=e.getAttribute("pp-autofocus");if(!t||!this.isJsonLike(t))return;const n=this.parseJson(t);if(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement){const t=["text","search","tel","url","password"];if(e instanceof HTMLInputElement)if(t.includes(e.type))if("number"===e.type){e.type="text";const t=e.value.length||0;e.setSelectionRange(t,t),e.type="number"}else this.setCursorPosition(e,n);else;else e instanceof HTMLTextAreaElement&&this.setCursorPosition(e,n)}e.focus(),s=!0}))}async invokeHandler(e,t,n){try{const s=t.match(/^(\w+(\.\w+)*)\((.*)\)$/);if(s){const o=s[1],i=s[3],a=o.split("."),{context:r,methodName:c}=this.resolveContext(a);if("function"==typeof r[c])if(this.isJsonLike(i)){const t=this.parseJson(i);t.element=e,t.event=n;const s=[t];await r[c](...s)}else new Function("event",t).call(e,n);else await this.handleParsedCallback(e,t)}else if(t.includes("=")){const s=t.match(/^\s*([\w\.]+)\s*=/);if(s){const e=s[1];if(e.includes(".")){const t=e.split(".");let n=pphp.props;for(let e=0;e<t.length-1;e++)t[e]in n||(n[t[e]]={}),n=n[t[e]]}else e in pphp.props||(pphp.props[e]=void 0)}new Function("event","props",`\n with (new Proxy(props, {\n get(target, key) {\n return key in target ? target[key] : undefined;\n },\n set(target, key, value) {\n target[key] = value;\n return true;\n }\n })) {\n ${t}\n }\n `).call(e,n,pphp.props)}else await this.handleParsedCallback(e,t)}catch(e){}}async handleParsedCallback(e,t){const{funcName:n,data:s}=this.parseCallback(e,t);if(!n)return;const o=this[n],i=window[n];let a;if("function"==typeof o?a=o:"function"==typeof i&&(a=i),"function"==typeof a){const t=e.hasAttribute("pp-after-request"),n=Array.isArray(s.args)?s.args:[],o=this.responseData?this.parseJson(this.responseData):{response:this.responseData};let i={args:n,element:e,data:s};t&&(i={...i,...o}),await a.call(this,i)}else this.responseData=null,this.responseData=await this.handleUndefinedFunction(e,n,s)}async handleUndefinedFunction(e,t,n){const s={callback:t,...n},o=this.createFetchOptions(s),i=this.createFetchOptions({secondRequestC69CD:!0,...this.getUrlParams()});try{this.saveElementOriginalState(e),this.handleSuspenseElement(e);const s=new URL(window.location.href);let a="",r="",c={success:!1};const l=e.querySelector("input[type='file']");if(l){if(a=await this.fetchFileWithData(s.href,t,l,n),r=this.extractJson(a)||"",r)try{c=this.parseJson(r)}catch(e){}}else{const e=await this.fetch(s.href,o);if(a=await e.text(),this.getRedirectUrl(a))return void await this.redirect(this.getRedirectUrl(a)||"");if(r=this.extractJson(a)||"",r)try{c=this.parseJson(r)}catch(e){}}const h=e.getAttribute("pp-before-request")||"",u=e.getAttribute("pp-after-request")||"";if((h||u&&c.success)&&this.restoreSuspenseElement(e),h||u){let e="";if(c.success){e=a.replace(r,"")}else e=a;if(this.appendAfterbegin(e),!u&&!c.success)return}if(u&&c.success){this.handleAfterRequest(u,r);const e=a.replace(r,"");return this.appendAfterbegin(e),r}if("@close"===u)return c.success?r:void 0;const d=await this.fetch(s.href,i),p=await d.text();if(this.getRedirectUrl(p))return void await this.redirect(this.getRedirectUrl(p)||"");await this.handleResponseRedirectOrUpdate(a,p,r,c)}catch(e){}}handleAfterRequest(e,t){if(!this.isJsonLike(e))return;const n=this.parseJson(e),s=t?this.parseJson(t):null,o=n.targets;Array.isArray(o)&&o.forEach((e=>{const{id:t,...n}=e,o=document.querySelector(t);let i={};if(s){for(const t in n)if(n.hasOwnProperty(t))switch(t){case"innerHTML":case"outerHTML":case"textContent":case"innerText":"response"===n[t]&&(i[t]=e.responseKey?s[e.responseKey]:s.response);break;default:i[t]=n[t];break}}else i=n;o&&this.updateElementAttributes(o,i)}))}async handleResponseRedirectOrUpdate(e,t,n,s){const o=this.getUpdatedHTMLContent(e,n,s),i=(new DOMParser).parseFromString(t,"text/html");o&&i.body.insertAdjacentElement("afterbegin",o),this.updateBodyContent(i.body.outerHTML)}getUpdatedHTMLContent(e,t,n){const s=document.createElement("div");if(s.id="afterbegin-8D95D",n&&t?.success){const t=e.replace(n,"");s.innerHTML=t}else s.innerHTML=e;return s.innerHTML?s:null}async updateBodyContent(e){const t=this.saveScrollPositions();this.saveState();const n=(new DOMParser).parseFromString(e,"text/html");document.removeAllEventListeners("PPBodyLoaded"),await this.appendCallbackResponse(n),this.restoreState(),this.restoreScrollPositions(t),this.attachWireFunctionEvents(),document.dispatchEvent(new Event("PPBodyLoaded"))}restoreState(){if(this.state.focusId){const e=document.getElementById(this.state.focusId)||document.querySelector(`[name="${this.state.focusId}"]`);if(e instanceof HTMLInputElement){const t=e.value.length||0;void 0!==this.state.focusSelectionStart&&null!==this.state.focusSelectionEnd&&e.setSelectionRange(t,t),this.state.focusValue&&("checkbox"===e.type||"radio"===e.type?e.checked=!!this.state.focusChecked:"number"===e.type||"email"===e.type?(e.type="text",e.setSelectionRange(t,t),e.type="number"===e.type?"number":"email"):"date"===e.type||"month"===e.type||"week"===e.type||"time"===e.type||"datetime-local"===e.type||"color"===e.type||"file"===e.type||""!==e.value&&(e.value=this.state.focusValue)),e.focus()}else if(e instanceof HTMLTextAreaElement){const t=e.value.length||0;void 0!==this.state.focusSelectionStart&&null!==this.state.focusSelectionEnd&&e.setSelectionRange(t,t),this.state.focusValue&&""!==e.value&&(e.value=this.state.focusValue),e.focus()}else e instanceof HTMLSelectElement&&(this.state.focusValue&&""!==e.value&&(e.value=this.state.focusValue),e.focus())}this.state.checkedElements.forEach((e=>{const t=document.getElementById(e);t&&(t.checked=!0)}))}async appendCallbackResponse(e){const t=e.getElementById("afterbegin-8D95D");if(t){const e=document.getElementById("afterbegin-8D95D");e?e.innerHTML=t.innerHTML:document.body.insertAdjacentHTML("afterbegin",t.outerHTML)}await this.populateDocumentBody(e)}saveState(){const e=document.activeElement;this.state.focusId=e?.id||e?.name,this.state.focusValue=e?.value,this.state.focusChecked=e?.checked,this.state.focusType=e?.type,this.state.focusSelectionStart=e?.selectionStart,this.state.focusSelectionEnd=e?.selectionEnd,this.state.isSuspense=e.hasAttribute("pp-suspense"),this.state.checkedElements.clear(),document.querySelectorAll('input[type="checkbox"]:checked').forEach((e=>{this.state.checkedElements.add(e.id||e.name)})),document.querySelectorAll('input[type="radio"]:checked').forEach((e=>{this.state.checkedElements.add(e.id||e.name)}))}updateElementAttributes(e,t){for(const n in t)if(t.hasOwnProperty(n))switch(n){case"innerHTML":case"outerHTML":case"textContent":case"innerText":e[n]=this.decodeHTML(t[n]);break;case"insertAdjacentHTML":e.insertAdjacentHTML(t.position||"beforeend",this.decodeHTML(t[n].html));break;case"insertAdjacentText":e.insertAdjacentText(t.position||"beforeend",this.decodeHTML(t[n].text));break;case"setAttribute":e.setAttribute(t.attrName,this.decodeHTML(t[n]));break;case"removeAttribute":e.removeAttribute(t[n]);break;case"className":e.className=this.decodeHTML(t[n]);break;case"classList.add":e.classList.add(...this.decodeHTML(t[n]).split(","));break;case"classList.remove":e.classList.remove(...this.decodeHTML(t[n]).split(","));break;case"classList.toggle":e.classList.toggle(this.decodeHTML(t[n]));break;case"classList.replace":const[s,o]=this.decodeHTML(t[n]).split(",");e.classList.replace(s,o);break;case"dataset":e.dataset[t.attrName]=this.decodeHTML(t[n]);break;case"style":Object.assign(e.style,t[n]);break;case"value":e.value=this.decodeHTML(t[n]);break;case"checked":e.checked=t[n];break;default:e.setAttribute(n,this.decodeHTML(t[n]))}}decodeHTML(e){const t=document.createElement("textarea");return t.innerHTML=e,t.value}appendAfterbegin(e){if(!e)return;const t="afterbegin-8D95D";let n=document.getElementById(t);n?(n.innerHTML=e,document.body.insertAdjacentElement("afterbegin",n)):(n=document.createElement("div"),n.id=t,n.innerHTML=e,document.body.insertAdjacentElement("afterbegin",n))}restoreSuspenseElement(e){const t=e.getAttribute("pp-original-state");if(e.hasAttribute("pp-suspense")&&t){const n=(e,t)=>{for(const n in t)t.hasOwnProperty(n)&&("textContent"===n?e.textContent=t[n]:"innerHTML"===n?e.innerHTML=t[n]:"disabled"===n?!0===t[n]?e.setAttribute("disabled","true"):e.removeAttribute("disabled"):e.setAttribute(n,t[n]));for(const n of Array.from(e.attributes))t.hasOwnProperty(n.name)||e.removeAttribute(n.name)},s=(e,t)=>{for(const s in t)if(t.hasOwnProperty(s))for(const t of Array.from(e.elements))if(t instanceof HTMLInputElement||t instanceof HTMLButtonElement||t instanceof HTMLTextAreaElement||t instanceof HTMLSelectElement){const e=t.getAttribute("pp-original-state")||"";if(e){if(this.isJsonLike(e)){const s=this.parseJson(e);n(t,s)}else o(t,e);t.removeAttribute("pp-original-state")}}},o=(e,t)=>{e instanceof HTMLInputElement?e.value=t:e.textContent=t},i=(e,t)=>{e instanceof HTMLFormElement?s(e,t):n(e,t)};try{const o=this.parseJson(t);if(o)if(e instanceof HTMLFormElement){const t=e.id;if(t){const e=document.querySelector(`[form="${t}"]`);if(e){const t=e.getAttribute("pp-original-state");if(t&&this.isJsonLike(t)){const s=this.parseJson(t);n(e,s)}}}const o=new FormData(e),i={};if(o.forEach(((e,t)=>{i[t]=e})),s(e,i),e.hasAttribute("pp-suspense")){const t=e.getAttribute("pp-suspense")||"";if(this.parseJson(t).disabled)for(const t of Array.from(e.elements))(t instanceof HTMLInputElement||t instanceof HTMLButtonElement||t instanceof HTMLTextAreaElement||t instanceof HTMLSelectElement)&&t.removeAttribute("disabled")}}else if(o.targets){o.targets.forEach((e=>{const{id:t,...n}=e,s=document.querySelector(t);s&&i(s,n)}));const{targets:t,...s}=o;n(e,s)}else{const{empty:t,...s}=o;n(e,s)}}catch(e){}}e.querySelectorAll("[pp-suspense]").forEach((e=>this.restoreSuspenseElement(e))),e.removeAttribute("pp-original-state")}extractJson(e){const t=e?.match(/\{[\s\S]*\}/);return t?t[0]:null}getRedirectUrl(e){const t=e.match(this.redirectRegex);return t?t[1]:null}async fetchFileWithData(e,t,n,s={}){const o=new FormData,i=n.files;if(i)for(let e=0;e<i.length;e++)o.append("file[]",i[e]);o.append("callback",t);for(const e in s)s.hasOwnProperty(e)&&o.append(e,s[e]);const a=await this.fetch(e,{method:"POST",headers:{HTTP_PPHP_WIRE_REQUEST:"true"},body:o});return await a.text()}async handleSuspenseElement(e){let t=e.getAttribute("pp-suspense")||"";const n=(e,t)=>{for(const n in t)if(t.hasOwnProperty(n))for(const t of e.elements)if(t instanceof HTMLInputElement||t instanceof HTMLButtonElement||t instanceof HTMLTextAreaElement||t instanceof HTMLSelectElement){const e=t.getAttribute("pp-suspense")||"";if(e)if(this.isJsonLike(e)){const n=this.parseJson(e);"disabled"!==n.onsubmit&&this.updateElementAttributes(t,n),n.targets&&n.targets.forEach((e=>{const{id:t,...n}=e,s=document.querySelector(t);s&&o(s,n)}))}else s(t,e)}},s=(e,t)=>{e instanceof HTMLInputElement?e.value=t:e.textContent=t},o=(e,t)=>{e instanceof HTMLFormElement?n(e,t):this.updateElementAttributes(e,t)};try{if(t&&this.isJsonLike(t)){const s=this.parseJson(t);if(s)if(e instanceof HTMLFormElement){const t=new FormData(e),o={};t.forEach(((e,t)=>{o[t]=e})),s.disabled&&this.toggleFormElements(e,!0);const{disabled:i,...a}=s;this.updateElementAttributes(e,a),n(e,o)}else if(s.targets){s.targets.forEach((e=>{const{id:t,...n}=e,s=document.querySelector(t);s&&o(s,n)}));const{targets:t,...n}=s;this.updateElementAttributes(e,n)}else{if("disabled"===s.empty&&""===e.value)return;const{empty:t,...n}=s;this.updateElementAttributes(e,n)}}else if(t)s(e,t);else if(e instanceof HTMLFormElement){const t=new FormData(e),s={};t.forEach(((e,t)=>{s[t]=e})),n(e,s)}}catch(e){}}toggleFormElements(e,t){Array.from(e.elements).forEach((e=>{(e instanceof HTMLInputElement||e instanceof HTMLButtonElement||e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement)&&(e.disabled=t)}))}saveElementOriginalState(e){if(e.hasAttribute("pp-suspense")&&!e.hasAttribute("pp-original-state")){const t={};e.textContent&&(t.textContent=e.textContent.trim()),e.innerHTML&&(t.innerHTML=e.innerHTML.trim()),(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement)&&(t.value=e.value);for(let n=0;n<e.attributes.length;n++){const s=e.attributes[n];t[s.name]=s.value}e.setAttribute("pp-original-state",JSON.stringify(t))}if(e instanceof HTMLFormElement){let t=null;const n=e.id;n&&(t=document.querySelector(`[form="${n}"]`)),n&&t||(t=Array.from(e.elements).find((e=>e instanceof HTMLButtonElement||e instanceof HTMLInputElement))),t&&(t.hasAttribute("pp-original-state")||this.saveElementOriginalState(t))}e.querySelectorAll("[pp-suspense]").forEach((e=>this.saveElementOriginalState(e)))}getUrlParams(){const e={};return new URLSearchParams(window.location.search).forEach(((t,n)=>{e[n]=t})),e}createFetchOptions(e){return{method:"POST",headers:{"Content-Type":"application/json",HTTP_PPHP_WIRE_REQUEST:"true"},body:JSON.stringify(e)}}parseCallback(e,t){let n={};const s=e.closest("form");if(s){new FormData(s).forEach(((e,t)=>{n[t]?Array.isArray(n[t])?n[t].push(e):n[t]=[n[t],e]:n[t]=e}))}else e instanceof HTMLInputElement?n=this.handleInputElement(e):(e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement)&&(n[e.name]=e.value);const o=t.match(/(\w+)\((.*)\)/);if(o){const e=o[1];let t=o[2].trim();if(t.startsWith("{")&&t.endsWith("}"))try{const e=this.parseJson(t);"object"==typeof e&&null!==e&&(n={...n,...e})}catch(e){}else{const e=t.split(/,(?=(?:[^'"]*['"][^'"]*['"])*[^'"]*$)/).map((e=>e.trim().replace(/^['"]|['"]$/g,"")));n.args=e}return{funcName:e,data:n}}return{funcName:t,data:n}}handleInputElement(e){let t={};if(e.name)if("checkbox"===e.type)t[e.name]={value:e.value,checked:e.checked};else if("radio"===e.type){const n=document.querySelector(`input[name="${e.name}"]:checked`);t[e.name]=n?n.value:null}else t[e.name]=e.value;else"checkbox"===e.type||"radio"===e.type?t.value=e.checked:t.value=e.value;return t}resolveContext(e){let t=window;for(let n=0;n<e.length-1;n++)if(t=t[e[n]],!t)throw new Error(`Cannot find object ${e[n]} in the context.`);return{context:t,methodName:e[e.length-1]}}setCursorPosition(e,t){if(t.start)e.setSelectionRange(0,0);else if(t.end){const t=e.value.length||0;e.setSelectionRange(t,t)}else if(t.length){const n=parseInt(t.length,10)||0;e.setSelectionRange(n,n)}}handleInputAppendParams(e,t){const n=e.getAttribute("pp-append-params"),s=e.getAttribute("pp-append-params-sync");if("true"===n){if("true"===s){const t=e.name||e.id;if(t){const n=new URL(window.location.href),s=new URLSearchParams(n.search);s.has(t)&&(e.value=s.get(t)||"")}}e.addEventListener(t,(e=>{const t=e.currentTarget,n=t.value,s=new URL(window.location.href),o=new URLSearchParams(s.search),i=t.name||t.id;if(i){n?o.set(i,n):o.delete(i);const e=o.toString()?`${s.pathname}?${o.toString()}`:s.pathname;history.replaceState(null,"",e)}}))}}handleHiddenAttribute(){const e=document.querySelectorAll("[pp-visibility]"),t=document.querySelectorAll("[pp-display]");e.forEach((e=>this.handleVisibilityElementAttribute(e,"pp-visibility",this.handleElementVisibility))),t.forEach((e=>this.handleVisibilityElementAttribute(e,"pp-display",this.handleElementDisplay)))}handleVisibilityElementAttribute(e,t,n){const s=e.getAttribute(t);if(s)if(this.isJsonLike(s)){n(e,this.parseJson(s))}else{const n=this.parseTime(s);if(n>0){const s="pp-visibility"===t?"visibility":"display",o="visibility"===s?"hidden":"none";this.scheduleChange(e,n,s,o)}}}handleElementVisibility(e,t){this.handleElementChange(e,t,"visibility","hidden","visible")}handleElementDisplay(e,t){this.handleElementChange(e,t,"display","none","block")}handleElementChange(e,t,n,s,o){const i=t.start?this.parseTime(t.start):0,a=t.end?this.parseTime(t.end):0;i>0?(e.style[n]=s,this.scheduleChange(e,i,n,o),a>0&&this.scheduleChange(e,i+a,n,s)):a>0&&this.scheduleChange(e,a,n,s)}handleAnchorTag(e){e instanceof HTMLAnchorElement&&e.addEventListener("click",(async e=>{const t=e.currentTarget,n=t.getAttribute("href"),s=t.getAttribute("target");if(n&&"_blank"!==s&&!e.metaKey&&!e.ctrlKey&&(e.preventDefault(),!this.isNavigating)){this.isNavigating=!0;try{if(/^(https?:)?\/\//i.test(n)&&!n.startsWith(window.location.origin))window.location.href=n;else{const e=t.getAttribute("pp-append-params");if(n.startsWith("?")&&"true"===e){const e=new URL(window.location.href),t=new URLSearchParams(e.search);let s="";const[o,i]=n.split("#");i&&(s=`#${i}`);new URLSearchParams(o.split("?")[1]).forEach(((e,n)=>{t.set(n,e)}));const a=`${e.pathname}?${t.toString()}${s}`;history.pushState(null,"",a)}else{const[e,t]=n.split("#"),s=`${e}${t?`#${t}`:""}`;history.pushState(null,"",s)}const s=n.indexOf("#");if(-1!==s){const e=n.slice(s+1),t=document.getElementById(e);if(t)t.scrollIntoView({behavior:"smooth"});else{await this.handleNavigation();const t=document.getElementById(e);t&&t.scrollIntoView({behavior:"smooth"})}}else await this.handleNavigation()}}catch(e){}finally{this.isNavigating=!1}}}))}async handleNavigation(){try{const e=document.getElementById("loading-file-1B87E");if(e){const t=this.findLoadingElement(e,window.location.pathname);t&&await this.updateContentWithTransition(t)}const t=await this.fetch(window.location.href);if(!t.ok)return;const n=await t.text(),s=n.match(this.redirectRegex);if(s&&s[1])return void await this.redirect(s[1]);await this.updateDocumentContent(n)}catch(e){}}findLoadingElement(e,t){let n=t;for(;;){const t=e.querySelector(`div[pp-loading-url='${n}']`);if(t)return t;if("/"===n)break;const s=n.lastIndexOf("/");n=s<=0?"/":n.substring(0,s)}return e.querySelector("div[pp-loading-url='/' ]")}async updateContentWithTransition(e){const t=document.querySelector("[pp-loading-content='true']")||document.body;if(!t)return;const{fadeIn:n,fadeOut:s}=this.parseTransition(e);await this.fadeOut(t,s),t.innerHTML=e.innerHTML,this.fadeIn(t,n)}parseTransition(e){let t=250,n=250;const s=e.querySelector("[pp-loading-transition]")?.getAttribute("pp-loading-transition");if(s)try{const e=this.parseJson(s);t=this.parseTime(e.fadeIn??t),n=this.parseTime(e.fadeOut??n)}catch(e){}return{fadeIn:t,fadeOut:n}}fadeOut(e,t){return new Promise((n=>{e.style.transition=`opacity ${t}ms ease-out`,e.style.opacity="0",setTimeout((()=>{e.style.transition="",n()}),t)}))}fadeIn(e,t){e.style.transition=`opacity ${t}ms ease-in`,e.style.opacity="1",setTimeout((()=>{e.style.transition=""}),t)}async updateDocumentContent(e){const t=this.saveScrollPositions(),n=(new DOMParser).parseFromString(e,"text/html"),s="pp-dynamic-script",o="pp-dynamic-link";document.head.querySelectorAll("[pp-dynamic-meta]").forEach((e=>e.remove()));document.head.querySelectorAll("[pp-dynamic-link]").forEach((e=>e.remove()));document.head.querySelectorAll("[pp-dynamic-script]").forEach((e=>e.remove()));document.removeAllEventListeners("PPBodyLoaded"),await(async e=>{Array.from(e.head.children).forEach((e=>{const t=e.tagName;if("SCRIPT"===t&&e.hasAttribute(s)){const t=document.createElement("script");Array.from(e.attributes).forEach((e=>t.setAttribute(e.name,e.value))),e.textContent&&(t.textContent=e.textContent),document.head.appendChild(t)}else if("META"===t){if(e.getAttribute("charset")||"viewport"===e.getAttribute("name"))return;const t=e.name,n=e.getAttribute("property"),s=document.head.querySelector(t?`meta[name="${t}"]`:`meta[property="${n}"]`),o=document.head.querySelector("title");s?document.head.replaceChild(e.cloneNode(!0),s):o?.nextSibling?document.head.insertBefore(e.cloneNode(!0),o.nextSibling):document.head.appendChild(e.cloneNode(!0))}else if("TITLE"===t){const t=document.head.querySelector("title");t?document.head.replaceChild(e.cloneNode(!0),t):document.head.appendChild(e.cloneNode(!0))}else if("LINK"===t){const t=t=>{const n=document.head.querySelector('link[rel="icon"]');if(n)document.head.replaceChild(e.cloneNode(!0),n);else{const e=document.createElement("link");e.rel="icon",e.href=t,document.head.appendChild(e)}};if("icon"===e.getAttribute("rel")){t(e.href)}else if(e.hasAttribute(o)){const t=e.cloneNode(!0);document.head.appendChild(t)}}})),await this.populateDocumentBody(e)})(n),this.restoreScrollPositions(t),this.attachWireFunctionEvents(),document.dispatchEvent(new Event("PPBodyLoaded"))}restoreScrollPositions(e){requestAnimationFrame((()=>{const t=e.window;t&&window.scrollTo(t.scrollLeft,t.scrollTop),document.querySelectorAll("*").forEach((t=>{const n=this.getElementKey(t);e[n]&&(t.scrollTop=e[n].scrollTop,t.scrollLeft=e[n].scrollLeft)}))}))}async populateDocumentBody(e){try{const t=e.body.cloneNode(!0);this.manageScriptTags(t),document.body.replaceWith(t)}catch(e){}}manageScriptTags(e,t){const n=e.querySelectorAll("script"),s=t?.querySelectorAll("script")||n;n.forEach(((e,t)=>{const n=document.createElement("script"),o=s[t]||e;Array.from(o.attributes).forEach((e=>{n.setAttribute(e.name,e.value)})),o.hasAttribute("src")||(n.textContent=o.textContent),e.parentNode?.replaceChild(n,e)}))}saveScrollPositions(){const e={window:{scrollTop:window.scrollY||document.documentElement.scrollTop,scrollLeft:window.scrollX||document.documentElement.scrollLeft}};return document.querySelectorAll("*").forEach((t=>{(t.scrollTop||t.scrollLeft)&&(e[this.getElementKey(t)]={scrollTop:t.scrollTop,scrollLeft:t.scrollLeft})})),e}getElementKey(e){return e.id||e.className||e.tagName}async redirect(e){if(e)try{const t=new URL(e,window.location.origin);t.origin!==window.location.origin?window.location.href=e:(history.pushState(null,"",e),await this.handleNavigation())}catch(e){}}abortActiveRequest(){this.activeAbortController&&this.activeAbortController.abort()}async fetch(e,t,n=!1){let s;return n?(this.activeAbortController&&this.activeAbortController.abort(),this.activeAbortController=new AbortController,s=this.activeAbortController):s=new AbortController,fetch(e,{...t,signal:s.signal,headers:{...t?.headers,"X-Requested-With":"XMLHttpRequest"}})}isJsonLike(e){return"string"==typeof e&&((e=e.trim()).startsWith("{")&&e.endsWith("}")||e.startsWith("[")&&e.endsWith("]"))}parseJson(e){try{return JSON5.parse(e)}catch(e){return null}}parseTime(e){if("number"==typeof e)return e;const t=e.match(/^(\d+)(ms|s|m)?$/);if(t){const e=parseInt(t[1],10);switch(t[2]||"ms"){case"ms":return e;case"s":return 1e3*e;case"m":return 60*e*1e3;default:return e}}return 0}scheduleChange(e,t,n,s){setTimeout((()=>{requestAnimationFrame((()=>{e.style[n]=s}))}),t)}observeDOMChanges(){new MutationObserver((e=>{for(const t of e)"childList"===t.type&&t.addedNodes.length>0&&this.attachWireFunctionEvents()})).observe(document.body,{childList:!0,subtree:!0})}async fetchFunction(e,t={},n=!1){try{const s={callback:e,...t},o=window.location.href;let i;if(Object.keys(s).some((e=>{const t=s[e];return t instanceof File||t instanceof FileList&&t.length>0}))){const e=new FormData;Object.keys(s).forEach((t=>{const n=s[t];n instanceof File?e.append(t,n):n instanceof FileList?Array.from(n).forEach((n=>e.append(t,n))):e.append(t,n)})),i={method:"POST",headers:{HTTP_PPHP_WIRE_REQUEST:"true"},body:e}}else i=this.createFetchOptions(s);const a=await this.fetch(o,i,n);if(!a.ok)throw new Error(`Fetch failed with status: ${a.status} ${a.statusText}`);const r=await a.text();try{return JSON.parse(r)}catch{return r}}catch(e){throw new Error("Failed to fetch data.")}}async sync(...e){try{const t=this.saveScrollPositions();this.saveState();const n=e.length>0?e.map((e=>`pp-sync="${e}"`)):['pp-sync="true"'],s=this.createFetchOptions({secondRequestC69CD:!0,...this.getUrlParams()}),o=await this.fetch(window.location.href,s),i=await o.text(),a=(new DOMParser).parseFromString(i,"text/html");n.forEach((e=>{const t=document.querySelectorAll(`[${e}]`),n=a.body.querySelectorAll(`[${e}]`);t.forEach(((e,t)=>{const s=n[t];s&&(e.innerHTML=s.innerHTML,this.reRunScripts(e),document.dispatchEvent(new Event("PPBodyLoaded")))}))})),this.restoreState(),this.restoreScrollPositions(t),document.removeAllEventListeners("PPBodyLoaded"),document.dispatchEvent(new Event("PPBodyLoaded"))}catch(e){}}async fetchAndUpdateBodyContent(){const e=this.createFetchOptions({secondRequestC69CD:!0,...this.getUrlParams()});this.abortActiveRequest();const t=await this.fetch(window.location.href,e,!0),n=await t.text();await this.updateBodyContent(n)}reRunScripts(e){e.querySelectorAll("script").forEach((e=>{const t=document.createElement("script");Array.from(e.attributes).forEach((e=>{t.setAttribute(e.name,e.value)})),e.hasAttribute("src")||(t.textContent=e.textContent),e.parentNode?.replaceChild(t,e)}))}copyCode(e,t,n,s,o="img",i=2e3){if(!(e instanceof HTMLElement))return;const a=e.closest(`.${t}`)?.querySelector("pre code"),r=a?.textContent?.trim()||"";r?navigator.clipboard.writeText(r).then((()=>{const t=e.querySelector(o);if(t)for(const[e,n]of Object.entries(s))e in t?t[e]=n:t.setAttribute(e,n);setTimeout((()=>{if(t)for(const[e,s]of Object.entries(n))e in t?t[e]=s:t.setAttribute(e,s)}),i)}),(()=>{alert("Failed to copy command to clipboard")})):alert("Failed to find the code block to copy")}getCookie(e){return document.cookie.split("; ").find((t=>t.startsWith(e+"=")))?.split("=")[1]||null}}class PPHPLocalStore{static instance=null;state;listeners;pphp;STORAGE_KEY;constructor(e={}){this.state=e,this.listeners=[],this.pphp=PPHP.instance,this.STORAGE_KEY=this.pphp.getCookie("pphp_local_store_key")||"pphp_local_store_59e13",this.loadState()}static getInstance(e={}){return PPHPLocalStore.instance||(PPHPLocalStore.instance=new PPHPLocalStore(e)),PPHPLocalStore.instance}setState(e,t=!1){if(this.state={...this.state,...e},this.listeners.forEach((e=>e(this.state))),this.saveState(),t){const e=localStorage.getItem(this.STORAGE_KEY);e&&this.pphp.fetchFunction(this.STORAGE_KEY,{[this.STORAGE_KEY]:e})}}saveState(){localStorage.setItem(this.STORAGE_KEY,JSON.stringify(this.state))}loadState(){const e=localStorage.getItem(this.STORAGE_KEY);e&&(this.state=this.pphp.parseJson(e),this.listeners.forEach((e=>e(this.state))))}resetState(e,t=!1){if(e?(delete this.state[e],this.saveState()):(this.state={},localStorage.removeItem(this.STORAGE_KEY)),this.listeners.forEach((e=>e(this.state))),t){const t=e?localStorage.getItem(this.STORAGE_KEY):null;this.pphp.fetchFunction(this.STORAGE_KEY,{[this.STORAGE_KEY]:t})}}}
1
+ (()=>{const e=EventTarget.prototype.addEventListener,t=EventTarget.prototype.removeEventListener,n=new Map;EventTarget.prototype.addEventListener=function(t,s,i){n.has(this)||n.set(this,new Map);const o=n.get(this).get(t)||new Set;o.add(s),n.get(this).set(t,o),e.call(this,t,s,i)},EventTarget.prototype.removeEventListener=function(e,s,i){if(n.has(this)&&n.get(this).has(e)){const t=n.get(this).get(e);t&&(t.delete(s),0===t.size&&n.get(this).delete(e))}t.call(this,e,s,i)},EventTarget.prototype.removeAllEventListeners=function(e){if(n.has(this)&&n.get(this).has(e)){const s=n.get(this).get(e);s&&(s.forEach((n=>{t.call(this,e,n)})),n.get(this).delete(e))}}})();class PPHP{props={};static _instance;eventHandlers;redirectRegex=/redirect_7F834\s*=\s*(\/[^\s]*)/;isNavigating=!1;responseData=null;state={checkedElements:new Set};activeAbortController=null;rawProps={};builtInProps;constructor(){this.eventHandlers=new Set(["onclick","ondblclick","onmousedown","onmouseup","onmouseover","onmousemove","onmouseout","onwheel","onkeypress","onkeydown","onkeyup","onfocus","onblur","onchange","oninput","onselect","onsubmit","onreset","onresize","onscroll","onload","onunload","onabort","onerror","onbeforeunload","oncopy","oncut","onpaste","ondrag","ondragstart","ondragend","ondragover","ondragenter","ondragleave","ondrop","oncontextmenu","ontouchstart","ontouchmove","ontouchend","ontouchcancel","onpointerdown","onpointerup","onpointermove","onpointerover","onpointerout","onpointerenter","onpointerleave","onpointercancel"]),this.builtInProps=new Set(["length","charAt","charCodeAt","codePointAt","concat","includes","endsWith","indexOf","lastIndexOf","localeCompare","match","matchAll","normalize","padEnd","padStart","repeat","replace","replaceAll","search","slice","split","substring","substr","startsWith","toLocaleLowerCase","toLocaleUpperCase","toLowerCase","toString","toUpperCase","trim","trimEnd","trimStart","valueOf"]),this.handlePopState(),this.props=this.makeReactive(this.rawProps)}static get instance(){return PPHP._instance||(PPHP._instance=new PPHP),PPHP._instance}makeSafeEvaluator(e){const t=Array.from(new Set((e.match(/\b[a-zA-Z_][a-zA-Z0-9_]*\b/g)||[]).filter((e=>!["true","false","null","undefined"].includes(e))).filter((e=>!this.builtInProps.has(e))))).map((t=>`\n const ${t} = ctx["${t}"] !== undefined \n ? ctx["${t}"] \n : (typeof window !== "undefined" && window["${t}"] !== undefined \n ? window["${t}"] \n : ${new RegExp(`\\b${t}\\.`).test(e)?"{}":'""'});\n if (typeof window !== "undefined") window["${t}"] = ${t};\n `)).join("\n");return new Function("ctx",`\n "use strict";\n ${t}\n try {\n const result = ${e};\n return result === undefined || result === null ? "" : result;\n } catch (e) {\n return "";\n }\n `)}makeReactive(e,t=[]){const n=this;return e instanceof Map||e instanceof Set?e:new Proxy(e,{get(e,s){const i=e[s];return"object"==typeof i&&null!==i?n.makeReactive(i,[...t,s.toString()]):i},set(e,s,i){e[s]=i;const o=[...t,s.toString()].join(".");return document.querySelectorAll("[pp-bind]").forEach((e=>{const t=e.getAttribute("pp-bind");if(t)if(t===o)e.textContent=i;else try{const s=n.makeSafeEvaluator(t);e.textContent=s(n.props)}catch(e){}})),document.querySelectorAll("[pp-bind-expr]").forEach((e=>{const t=e.getAttribute("pp-bind-expr");if(!t)return;const i=t.match(/\b[a-zA-Z_][a-zA-Z0-9_]*\b/g);if(!i||i.includes(s.toString()))try{const s=n.makeSafeEvaluator(t)(n.props);e.textContent=s}catch(e){}})),document.querySelectorAll("*").forEach((e=>{Array.from(e.attributes).forEach((t=>{if(!t.name.startsWith("pp-bind-"))return;const s=t.value.replace(/&quot;/g,'"').replace(/&#039;/g,"'").replace(/&amp;/g,"&").replace(/^{{\s*|\s*}}$/g,"");if(!s.includes(o))return;const i=t.name.replace(/^(pp-bind-)+/,"");try{const t=n.makeSafeEvaluator(s)(n.props),o=null!=t?t.toString():"",a="value"===i?o:o.trim();let r;if("value"===i)r=a;else{const t=e.getAttribute(`pp-bind-original-data-${i}`)??(()=>{const t=e.getAttribute(i)?.trim()??"";return e.setAttribute(`pp-bind-original-data-${i}`,t),t})();r=t,a&&(r=t?`${t} ${a}`.trim():a)}"value"===i?e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement?e.value=r:e.setAttribute(i,r):"checked"===i&&e instanceof HTMLInputElement?e.checked="true"===r:e.setAttribute(i,r)}catch(e){}}))})),!0}})}handlePopState(){window.addEventListener("popstate",(async()=>{await this.handleNavigation()}))}attachWireFunctionEvents(){this.handleHiddenAttribute();document.querySelectorAll("button, input, select, textarea, a, form, label, div, span").forEach((e=>{if(this.handleAnchorTag(e),Array.from(e.attributes).filter((e=>this.eventHandlers.has(e.name))).forEach((t=>{const n=t.name.slice(2),s=t.value;e instanceof HTMLInputElement&&this.handleInputAppendParams(e,n),s&&(e.removeAttribute(t.name),this.handleDebounce(e,n,s))})),e instanceof HTMLFormElement){const t=e.getAttribute("onsubmit");t&&(e.removeAttribute("onsubmit"),this.handleDebounce(e,"submit",t))}}))}async handleDebounce(e,t,n){e.removeEventListener(t,(()=>{}));const s=e.getAttribute("pp-debounce")||"",i=e.getAttribute("pp-before-request")||"",o=e.getAttribute("pp-after-request")||"",a=async t=>{t.preventDefault();try{i&&await this.invokeHandler(e,i,t),await this.invokeHandler(e,n,t),o&&"@close"!==o&&await this.invokeHandler(e,o,t),this.handlerAutofocusAttribute()}catch(e){}};if(s){const n=this.parseTime(s),i=this.debounce(a,n);e instanceof HTMLFormElement&&"submit"===t?e.addEventListener(t,(e=>{e.preventDefault(),i(e)})):e.addEventListener(t,i)}else e.addEventListener(t,a)}debounce(e,t=300,n=!1){let s;return function(...i){const o=this;s&&clearTimeout(s),s=setTimeout((()=>{s=null,n||e.apply(o,i)}),t),n&&!s&&e.apply(o,i)}}handlerAutofocusAttribute(){const e=document.activeElement;if(e&&e!==document.body)return;const t=this.state?.focusId;if(!t)return;const n=document.querySelectorAll("[pp-autofocus]");let s=!1;n.forEach((e=>{if(s)return;const t=e.getAttribute("pp-autofocus");if(!t||!this.isJsonLike(t))return;const n=this.parseJson(t);if(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement){const t=["text","search","tel","url","password"];if(e instanceof HTMLInputElement)if(t.includes(e.type))if("number"===e.type){e.type="text";const t=e.value.length||0;e.setSelectionRange(t,t),e.type="number"}else this.setCursorPosition(e,n);else;else e instanceof HTMLTextAreaElement&&this.setCursorPosition(e,n)}e.focus(),s=!0}))}initializeAllReferencedProps(){const e=document.querySelectorAll("*");for(const t of e)for(const e of Array.from(t.attributes)){if(!e.name.startsWith("pp-bind"))continue;let t=e.value.replace(/&quot;/g,'"').replace(/&#039;/g,"'").replace(/&amp;/g,"&").replace(/^{{\s*|\s*}}$/g,"");if(!t.match(/^[a-zA-Z_][a-zA-Z0-9_\.]*$/))continue;if(this.builtInProps.has(t))continue;const n=t.split(".");if(this.builtInProps.has(n[0]))continue;let s=this.props;for(let e=0;e<n.length;e++){const t=n[e],i=e===n.length-1;this.builtInProps.has(t)||(t in s||(s[t]=i?void 0:{}),s=s[t])}}}async invokeHandler(e,t,n){try{const s=t.match(/^(\w+(\.\w+)*)\((.*)\)$/);if(s){const i=s[1],o=s[3],a=i.split("."),{context:r,methodName:c}=this.resolveContext(a);if(this.initializeAllReferencedProps(),"function"==typeof r[c])if(this.isJsonLike(o)){const t=this.parseJson(o);t.element=e,t.event=n;const s=[t];await r[c](...s)}else new Function("event",t).call(e,n);else await this.handleParsedCallback(e,t)}else if(t.includes("=")){const s=t.match(/^\s*([\w\.]+)\s*=/);if(s){const e=s[1];if(e.includes(".")){const t=e.split(".");let n=pphp.props;for(let e=0;e<t.length-1;e++)t[e]in n||(n[t[e]]={}),n=n[t[e]]}else e in pphp.props||(pphp.props[e]=void 0)}new Function("event","props",`\n with (new Proxy(props, {\n get(target, key) {\n return key in target ? target[key] : undefined;\n },\n set(target, key, value) {\n target[key] = value;\n return true;\n }\n })) {\n ${t}\n }\n `).call(e,n,pphp.props)}else this.initializeAllReferencedProps(),await this.handleParsedCallback(e,t)}catch(e){}}async handleParsedCallback(e,t){const{funcName:n,data:s}=this.parseCallback(e,t);if(!n)return;const i=this[n],o=window[n];let a;if("function"==typeof i?a=i:"function"==typeof o&&(a=o),"function"==typeof a){const t=e.hasAttribute("pp-after-request"),n=Array.isArray(s.args)?s.args:[],i=this.responseData?this.parseJson(this.responseData):{response:this.responseData};let o={args:n,element:e,data:s};t&&(o={...o,...i}),await a.call(this,o)}else this.responseData=null,this.responseData=await this.handleUndefinedFunction(e,n,s)}async handleUndefinedFunction(e,t,n){const s={callback:t,...n},i=this.createFetchOptions(s),o=this.createFetchOptions({secondRequestC69CD:!0,...this.getUrlParams()});try{this.saveElementOriginalState(e),this.handleSuspenseElement(e);const s=new URL(window.location.href);let a="",r="",c={success:!1};const l=e.querySelector("input[type='file']");if(l){if(a=await this.fetchFileWithData(s.href,t,l,n),r=this.extractJson(a)||"",r)try{c=this.parseJson(r)}catch(e){}}else{const e=await this.fetch(s.href,i);if(a=await e.text(),this.getRedirectUrl(a))return void await this.redirect(this.getRedirectUrl(a)||"");if(r=this.extractJson(a)||"",r)try{c=this.parseJson(r)}catch(e){}}const h=e.getAttribute("pp-before-request")||"",u=e.getAttribute("pp-after-request")||"";if((h||u&&c.success)&&this.restoreSuspenseElement(e),h||u){let e="";if(c.success){e=a.replace(r,"")}else e=a;if(this.appendAfterbegin(e),!u&&!c.success)return}if(u&&c.success){this.handleAfterRequest(u,r);const e=a.replace(r,"");return this.appendAfterbegin(e),r}if("@close"===u)return c.success?r:void 0;const d=await this.fetch(s.href,o),p=await d.text();if(this.getRedirectUrl(p))return void await this.redirect(this.getRedirectUrl(p)||"");await this.handleResponseRedirectOrUpdate(a,p,r,c)}catch(e){}}handleAfterRequest(e,t){if(!this.isJsonLike(e))return;const n=this.parseJson(e),s=t?this.parseJson(t):null,i=n.targets;Array.isArray(i)&&i.forEach((e=>{const{id:t,...n}=e,i=document.querySelector(t);let o={};if(s){for(const t in n)if(n.hasOwnProperty(t))switch(t){case"innerHTML":case"outerHTML":case"textContent":case"innerText":"response"===n[t]&&(o[t]=e.responseKey?s[e.responseKey]:s.response);break;default:o[t]=n[t];break}}else o=n;i&&this.updateElementAttributes(i,o)}))}async handleResponseRedirectOrUpdate(e,t,n,s){const i=this.getUpdatedHTMLContent(e,n,s),o=(new DOMParser).parseFromString(t,"text/html");i&&o.body.insertAdjacentElement("afterbegin",i),this.updateBodyContent(o.body.outerHTML)}getUpdatedHTMLContent(e,t,n){const s=document.createElement("div");if(s.id="afterbegin-8D95D",n&&t?.success){const t=e.replace(n,"");s.innerHTML=t}else s.innerHTML=e;return s.innerHTML?s:null}async updateBodyContent(e){const t=this.saveScrollPositions();this.saveState();const n=(new DOMParser).parseFromString(e,"text/html");document.removeAllEventListeners("PPBodyLoaded"),await this.appendCallbackResponse(n),this.restoreState(),this.restoreScrollPositions(t),this.attachWireFunctionEvents(),document.dispatchEvent(new Event("PPBodyLoaded"))}restoreState(){if(this.state.focusId){const e=document.getElementById(this.state.focusId)||document.querySelector(`[name="${this.state.focusId}"]`);if(e instanceof HTMLInputElement){const t=e.value.length||0;void 0!==this.state.focusSelectionStart&&null!==this.state.focusSelectionEnd&&e.setSelectionRange(t,t),this.state.focusValue&&("checkbox"===e.type||"radio"===e.type?e.checked=!!this.state.focusChecked:"number"===e.type||"email"===e.type?(e.type="text",e.setSelectionRange(t,t),e.type="number"===e.type?"number":"email"):"date"===e.type||"month"===e.type||"week"===e.type||"time"===e.type||"datetime-local"===e.type||"color"===e.type||"file"===e.type||""!==e.value&&(e.value=this.state.focusValue)),e.focus()}else if(e instanceof HTMLTextAreaElement){const t=e.value.length||0;void 0!==this.state.focusSelectionStart&&null!==this.state.focusSelectionEnd&&e.setSelectionRange(t,t),this.state.focusValue&&""!==e.value&&(e.value=this.state.focusValue),e.focus()}else e instanceof HTMLSelectElement&&(this.state.focusValue&&""!==e.value&&(e.value=this.state.focusValue),e.focus())}this.state.checkedElements.forEach((e=>{const t=document.getElementById(e);t&&(t.checked=!0)}))}async appendCallbackResponse(e){const t=e.getElementById("afterbegin-8D95D");if(t){const e=document.getElementById("afterbegin-8D95D");e?e.innerHTML=t.innerHTML:document.body.insertAdjacentHTML("afterbegin",t.outerHTML)}await this.populateDocumentBody(e)}saveState(){const e=document.activeElement;this.state.focusId=e?.id||e?.name,this.state.focusValue=e?.value,this.state.focusChecked=e?.checked,this.state.focusType=e?.type,this.state.focusSelectionStart=e?.selectionStart,this.state.focusSelectionEnd=e?.selectionEnd,this.state.isSuspense=e.hasAttribute("pp-suspense"),this.state.checkedElements.clear(),document.querySelectorAll('input[type="checkbox"]:checked').forEach((e=>{this.state.checkedElements.add(e.id||e.name)})),document.querySelectorAll('input[type="radio"]:checked').forEach((e=>{this.state.checkedElements.add(e.id||e.name)}))}updateElementAttributes(e,t){for(const n in t)if(t.hasOwnProperty(n))switch(n){case"innerHTML":case"outerHTML":case"textContent":case"innerText":e[n]=this.decodeHTML(t[n]);break;case"insertAdjacentHTML":e.insertAdjacentHTML(t.position||"beforeend",this.decodeHTML(t[n].html));break;case"insertAdjacentText":e.insertAdjacentText(t.position||"beforeend",this.decodeHTML(t[n].text));break;case"setAttribute":e.setAttribute(t.attrName,this.decodeHTML(t[n]));break;case"removeAttribute":e.removeAttribute(t[n]);break;case"className":e.className=this.decodeHTML(t[n]);break;case"classList.add":e.classList.add(...this.decodeHTML(t[n]).split(","));break;case"classList.remove":e.classList.remove(...this.decodeHTML(t[n]).split(","));break;case"classList.toggle":e.classList.toggle(this.decodeHTML(t[n]));break;case"classList.replace":const[s,i]=this.decodeHTML(t[n]).split(",");e.classList.replace(s,i);break;case"dataset":e.dataset[t.attrName]=this.decodeHTML(t[n]);break;case"style":Object.assign(e.style,t[n]);break;case"value":e.value=this.decodeHTML(t[n]);break;case"checked":e.checked=t[n];break;default:e.setAttribute(n,this.decodeHTML(t[n]))}}decodeHTML(e){const t=document.createElement("textarea");return t.innerHTML=e,t.value}appendAfterbegin(e){if(!e)return;const t="afterbegin-8D95D";let n=document.getElementById(t);n?(n.innerHTML=e,document.body.insertAdjacentElement("afterbegin",n)):(n=document.createElement("div"),n.id=t,n.innerHTML=e,document.body.insertAdjacentElement("afterbegin",n))}restoreSuspenseElement(e){const t=e.getAttribute("pp-original-state");if(e.hasAttribute("pp-suspense")&&t){const n=(e,t)=>{for(const n in t)t.hasOwnProperty(n)&&("textContent"===n?e.textContent=t[n]:"innerHTML"===n?e.innerHTML=t[n]:"disabled"===n?!0===t[n]?e.setAttribute("disabled","true"):e.removeAttribute("disabled"):e.setAttribute(n,t[n]));for(const n of Array.from(e.attributes))t.hasOwnProperty(n.name)||e.removeAttribute(n.name)},s=(e,t)=>{for(const s in t)if(t.hasOwnProperty(s))for(const t of Array.from(e.elements))if(t instanceof HTMLInputElement||t instanceof HTMLButtonElement||t instanceof HTMLTextAreaElement||t instanceof HTMLSelectElement){const e=t.getAttribute("pp-original-state")||"";if(e){if(this.isJsonLike(e)){const s=this.parseJson(e);n(t,s)}else i(t,e);t.removeAttribute("pp-original-state")}}},i=(e,t)=>{e instanceof HTMLInputElement?e.value=t:e.textContent=t},o=(e,t)=>{e instanceof HTMLFormElement?s(e,t):n(e,t)};try{const i=this.parseJson(t);if(i)if(e instanceof HTMLFormElement){const t=e.id;if(t){const e=document.querySelector(`[form="${t}"]`);if(e){const t=e.getAttribute("pp-original-state");if(t&&this.isJsonLike(t)){const s=this.parseJson(t);n(e,s)}}}const i=new FormData(e),o={};if(i.forEach(((e,t)=>{o[t]=e})),s(e,o),e.hasAttribute("pp-suspense")){const t=e.getAttribute("pp-suspense")||"";if(this.parseJson(t).disabled)for(const t of Array.from(e.elements))(t instanceof HTMLInputElement||t instanceof HTMLButtonElement||t instanceof HTMLTextAreaElement||t instanceof HTMLSelectElement)&&t.removeAttribute("disabled")}}else if(i.targets){i.targets.forEach((e=>{const{id:t,...n}=e,s=document.querySelector(t);s&&o(s,n)}));const{targets:t,...s}=i;n(e,s)}else{const{empty:t,...s}=i;n(e,s)}}catch(e){}}e.querySelectorAll("[pp-suspense]").forEach((e=>this.restoreSuspenseElement(e))),e.removeAttribute("pp-original-state")}extractJson(e){const t=e?.match(/\{[\s\S]*\}/);return t?t[0]:null}getRedirectUrl(e){const t=e.match(this.redirectRegex);return t?t[1]:null}async fetchFileWithData(e,t,n,s={}){const i=new FormData,o=n.files;if(o)for(let e=0;e<o.length;e++)i.append("file[]",o[e]);i.append("callback",t);for(const e in s)s.hasOwnProperty(e)&&i.append(e,s[e]);const a=await this.fetch(e,{method:"POST",headers:{HTTP_PPHP_WIRE_REQUEST:"true"},body:i});return await a.text()}async handleSuspenseElement(e){let t=e.getAttribute("pp-suspense")||"";const n=(e,t)=>{for(const n in t)if(t.hasOwnProperty(n))for(const t of e.elements)if(t instanceof HTMLInputElement||t instanceof HTMLButtonElement||t instanceof HTMLTextAreaElement||t instanceof HTMLSelectElement){const e=t.getAttribute("pp-suspense")||"";if(e)if(this.isJsonLike(e)){const n=this.parseJson(e);"disabled"!==n.onsubmit&&this.updateElementAttributes(t,n),n.targets&&n.targets.forEach((e=>{const{id:t,...n}=e,s=document.querySelector(t);s&&i(s,n)}))}else s(t,e)}},s=(e,t)=>{e instanceof HTMLInputElement?e.value=t:e.textContent=t},i=(e,t)=>{e instanceof HTMLFormElement?n(e,t):this.updateElementAttributes(e,t)};try{if(t&&this.isJsonLike(t)){const s=this.parseJson(t);if(s)if(e instanceof HTMLFormElement){const t=new FormData(e),i={};t.forEach(((e,t)=>{i[t]=e})),s.disabled&&this.toggleFormElements(e,!0);const{disabled:o,...a}=s;this.updateElementAttributes(e,a),n(e,i)}else if(s.targets){s.targets.forEach((e=>{const{id:t,...n}=e,s=document.querySelector(t);s&&i(s,n)}));const{targets:t,...n}=s;this.updateElementAttributes(e,n)}else{if("disabled"===s.empty&&""===e.value)return;const{empty:t,...n}=s;this.updateElementAttributes(e,n)}}else if(t)s(e,t);else if(e instanceof HTMLFormElement){const t=new FormData(e),s={};t.forEach(((e,t)=>{s[t]=e})),n(e,s)}}catch(e){}}toggleFormElements(e,t){Array.from(e.elements).forEach((e=>{(e instanceof HTMLInputElement||e instanceof HTMLButtonElement||e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement)&&(e.disabled=t)}))}saveElementOriginalState(e){if(e.hasAttribute("pp-suspense")&&!e.hasAttribute("pp-original-state")){const t={};e.textContent&&(t.textContent=e.textContent.trim()),e.innerHTML&&(t.innerHTML=e.innerHTML.trim()),(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement)&&(t.value=e.value);for(let n=0;n<e.attributes.length;n++){const s=e.attributes[n];t[s.name]=s.value}e.setAttribute("pp-original-state",JSON.stringify(t))}if(e instanceof HTMLFormElement){let t=null;const n=e.id;n&&(t=document.querySelector(`[form="${n}"]`)),n&&t||(t=Array.from(e.elements).find((e=>e instanceof HTMLButtonElement||e instanceof HTMLInputElement))),t&&(t.hasAttribute("pp-original-state")||this.saveElementOriginalState(t))}e.querySelectorAll("[pp-suspense]").forEach((e=>this.saveElementOriginalState(e)))}getUrlParams(){const e={};return new URLSearchParams(window.location.search).forEach(((t,n)=>{e[n]=t})),e}createFetchOptions(e){return{method:"POST",headers:{"Content-Type":"application/json",HTTP_PPHP_WIRE_REQUEST:"true"},body:JSON.stringify(e)}}parseCallback(e,t){let n={};const s=e.closest("form");if(s){new FormData(s).forEach(((e,t)=>{n[t]?Array.isArray(n[t])?n[t].push(e):n[t]=[n[t],e]:n[t]=e}))}else e instanceof HTMLInputElement?n=this.handleInputElement(e):(e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement)&&(n[e.name]=e.value);const i=t.match(/(\w+)\((.*)\)/);if(i){const e=i[1];let t=i[2].trim();if(t.startsWith("{")&&t.endsWith("}"))try{const e=this.parseJson(t);"object"==typeof e&&null!==e&&(n={...n,...e})}catch(e){}else{const e=t.split(/,(?=(?:[^'"]*['"][^'"]*['"])*[^'"]*$)/).map((e=>e.trim().replace(/^['"]|['"]$/g,"")));n.args=e}return{funcName:e,data:n}}return{funcName:t,data:n}}handleInputElement(e){let t={};if(e.name)if("checkbox"===e.type)t[e.name]={value:e.value,checked:e.checked};else if("radio"===e.type){const n=document.querySelector(`input[name="${e.name}"]:checked`);t[e.name]=n?n.value:null}else t[e.name]=e.value;else"checkbox"===e.type||"radio"===e.type?t.value=e.checked:t.value=e.value;return t}resolveContext(e){let t=window;for(let n=0;n<e.length-1;n++)if(t=t[e[n]],!t)throw new Error(`Cannot find object ${e[n]} in the context.`);return{context:t,methodName:e[e.length-1]}}setCursorPosition(e,t){if(t.start)e.setSelectionRange(0,0);else if(t.end){const t=e.value.length||0;e.setSelectionRange(t,t)}else if(t.length){const n=parseInt(t.length,10)||0;e.setSelectionRange(n,n)}}handleInputAppendParams(e,t){const n=e.getAttribute("pp-append-params"),s=e.getAttribute("pp-append-params-sync");if("true"===n){if("true"===s){const t=e.name||e.id;if(t){const n=new URL(window.location.href),s=new URLSearchParams(n.search);s.has(t)&&(e.value=s.get(t)||"")}}e.addEventListener(t,(e=>{const t=e.currentTarget,n=t.value,s=new URL(window.location.href),i=new URLSearchParams(s.search),o=t.name||t.id;if(o){n?i.set(o,n):i.delete(o);const e=i.toString()?`${s.pathname}?${i.toString()}`:s.pathname;history.replaceState(null,"",e)}}))}}handleHiddenAttribute(){const e=document.querySelectorAll("[pp-visibility]"),t=document.querySelectorAll("[pp-display]");e.forEach((e=>this.handleVisibilityElementAttribute(e,"pp-visibility",this.handleElementVisibility))),t.forEach((e=>this.handleVisibilityElementAttribute(e,"pp-display",this.handleElementDisplay)))}handleVisibilityElementAttribute(e,t,n){const s=e.getAttribute(t);if(s)if(this.isJsonLike(s)){n(e,this.parseJson(s))}else{const n=this.parseTime(s);if(n>0){const s="pp-visibility"===t?"visibility":"display",i="visibility"===s?"hidden":"none";this.scheduleChange(e,n,s,i)}}}handleElementVisibility(e,t){this.handleElementChange(e,t,"visibility","hidden","visible")}handleElementDisplay(e,t){this.handleElementChange(e,t,"display","none","block")}handleElementChange(e,t,n,s,i){const o=t.start?this.parseTime(t.start):0,a=t.end?this.parseTime(t.end):0;o>0?(e.style[n]=s,this.scheduleChange(e,o,n,i),a>0&&this.scheduleChange(e,o+a,n,s)):a>0&&this.scheduleChange(e,a,n,s)}handleAnchorTag(e){e instanceof HTMLAnchorElement&&e.addEventListener("click",(async e=>{const t=e.currentTarget,n=t.getAttribute("href"),s=t.getAttribute("target");if(n&&"_blank"!==s&&!e.metaKey&&!e.ctrlKey&&(e.preventDefault(),!this.isNavigating)){this.isNavigating=!0;try{if(/^(https?:)?\/\//i.test(n)&&!n.startsWith(window.location.origin))window.location.href=n;else{const e=t.getAttribute("pp-append-params");if(n.startsWith("?")&&"true"===e){const e=new URL(window.location.href),t=new URLSearchParams(e.search);let s="";const[i,o]=n.split("#");o&&(s=`#${o}`);new URLSearchParams(i.split("?")[1]).forEach(((e,n)=>{t.set(n,e)}));const a=`${e.pathname}?${t.toString()}${s}`;history.pushState(null,"",a)}else{const[e,t]=n.split("#"),s=`${e}${t?`#${t}`:""}`;history.pushState(null,"",s)}const s=n.indexOf("#");if(-1!==s){const e=n.slice(s+1),t=document.getElementById(e);if(t)t.scrollIntoView({behavior:"smooth"});else{await this.handleNavigation();const t=document.getElementById(e);t&&t.scrollIntoView({behavior:"smooth"})}}else await this.handleNavigation()}}catch(e){}finally{this.isNavigating=!1}}}))}async handleNavigation(){try{const e=document.getElementById("loading-file-1B87E");if(e){const t=this.findLoadingElement(e,window.location.pathname);t&&await this.updateContentWithTransition(t)}const t=await this.fetch(window.location.href);if(!t.ok)return;const n=await t.text(),s=n.match(this.redirectRegex);if(s&&s[1])return void await this.redirect(s[1]);await this.updateDocumentContent(n)}catch(e){}}findLoadingElement(e,t){let n=t;for(;;){const t=e.querySelector(`div[pp-loading-url='${n}']`);if(t)return t;if("/"===n)break;const s=n.lastIndexOf("/");n=s<=0?"/":n.substring(0,s)}return e.querySelector("div[pp-loading-url='/' ]")}async updateContentWithTransition(e){const t=document.querySelector("[pp-loading-content='true']")||document.body;if(!t)return;const{fadeIn:n,fadeOut:s}=this.parseTransition(e);await this.fadeOut(t,s),t.innerHTML=e.innerHTML,this.fadeIn(t,n)}parseTransition(e){let t=250,n=250;const s=e.querySelector("[pp-loading-transition]")?.getAttribute("pp-loading-transition");if(s)try{const e=this.parseJson(s);t=this.parseTime(e.fadeIn??t),n=this.parseTime(e.fadeOut??n)}catch(e){}return{fadeIn:t,fadeOut:n}}fadeOut(e,t){return new Promise((n=>{e.style.transition=`opacity ${t}ms ease-out`,e.style.opacity="0",setTimeout((()=>{e.style.transition="",n()}),t)}))}fadeIn(e,t){e.style.transition=`opacity ${t}ms ease-in`,e.style.opacity="1",setTimeout((()=>{e.style.transition=""}),t)}async updateDocumentContent(e){const t=this.saveScrollPositions(),n=(new DOMParser).parseFromString(e,"text/html"),s="pp-dynamic-script",i="pp-dynamic-link";document.head.querySelectorAll("[pp-dynamic-meta]").forEach((e=>e.remove()));document.head.querySelectorAll("[pp-dynamic-link]").forEach((e=>e.remove()));document.head.querySelectorAll("[pp-dynamic-script]").forEach((e=>e.remove()));document.removeAllEventListeners("PPBodyLoaded"),await(async e=>{Array.from(e.head.children).forEach((e=>{const t=e.tagName;if("SCRIPT"===t&&e.hasAttribute(s)){const t=document.createElement("script");Array.from(e.attributes).forEach((e=>t.setAttribute(e.name,e.value))),e.textContent&&(t.textContent=e.textContent),document.head.appendChild(t)}else if("META"===t){if(e.getAttribute("charset")||"viewport"===e.getAttribute("name"))return;const t=e.name,n=e.getAttribute("property"),s=document.head.querySelector(t?`meta[name="${t}"]`:`meta[property="${n}"]`),i=document.head.querySelector("title");s?document.head.replaceChild(e.cloneNode(!0),s):i?.nextSibling?document.head.insertBefore(e.cloneNode(!0),i.nextSibling):document.head.appendChild(e.cloneNode(!0))}else if("TITLE"===t){const t=document.head.querySelector("title");t?document.head.replaceChild(e.cloneNode(!0),t):document.head.appendChild(e.cloneNode(!0))}else if("LINK"===t){const t=t=>{const n=document.head.querySelector('link[rel="icon"]');if(n)document.head.replaceChild(e.cloneNode(!0),n);else{const e=document.createElement("link");e.rel="icon",e.href=t,document.head.appendChild(e)}};if("icon"===e.getAttribute("rel")){t(e.href)}else if(e.hasAttribute(i)){const t=e.cloneNode(!0);document.head.appendChild(t)}}})),await this.populateDocumentBody(e)})(n),this.restoreScrollPositions(t),this.attachWireFunctionEvents(),document.dispatchEvent(new Event("PPBodyLoaded"))}restoreScrollPositions(e){requestAnimationFrame((()=>{const t=e.window;t&&window.scrollTo(t.scrollLeft,t.scrollTop),document.querySelectorAll("*").forEach((t=>{const n=this.getElementKey(t);e[n]&&(t.scrollTop=e[n].scrollTop,t.scrollLeft=e[n].scrollLeft)}))}))}async populateDocumentBody(e){try{const t=e.body.cloneNode(!0);this.manageScriptTags(t),document.body.replaceWith(t)}catch(e){}}manageScriptTags(e,t){const n=e.querySelectorAll("script"),s=t?.querySelectorAll("script")||n;n.forEach(((e,t)=>{const n=document.createElement("script"),i=s[t]||e;Array.from(i.attributes).forEach((e=>{n.setAttribute(e.name,e.value)})),i.hasAttribute("src")||(n.textContent=i.textContent),e.parentNode?.replaceChild(n,e)}))}saveScrollPositions(){const e={window:{scrollTop:window.scrollY||document.documentElement.scrollTop,scrollLeft:window.scrollX||document.documentElement.scrollLeft}};return document.querySelectorAll("*").forEach((t=>{(t.scrollTop||t.scrollLeft)&&(e[this.getElementKey(t)]={scrollTop:t.scrollTop,scrollLeft:t.scrollLeft})})),e}getElementKey(e){return e.id||e.className||e.tagName}async redirect(e){if(e)try{const t=new URL(e,window.location.origin);t.origin!==window.location.origin?window.location.href=e:(history.pushState(null,"",e),await this.handleNavigation())}catch(e){}}abortActiveRequest(){this.activeAbortController&&this.activeAbortController.abort()}async fetch(e,t,n=!1){let s;return n?(this.activeAbortController&&this.activeAbortController.abort(),this.activeAbortController=new AbortController,s=this.activeAbortController):s=new AbortController,fetch(e,{...t,signal:s.signal,headers:{...t?.headers,"X-Requested-With":"XMLHttpRequest"}})}isJsonLike(e){return"string"==typeof e&&((e=e.trim()).startsWith("{")&&e.endsWith("}")||e.startsWith("[")&&e.endsWith("]"))}parseJson(e){try{return JSON5.parse(e)}catch(e){return null}}parseTime(e){if("number"==typeof e)return e;const t=e.match(/^(\d+)(ms|s|m)?$/);if(t){const e=parseInt(t[1],10);switch(t[2]||"ms"){case"ms":return e;case"s":return 1e3*e;case"m":return 60*e*1e3;default:return e}}return 0}scheduleChange(e,t,n,s){setTimeout((()=>{requestAnimationFrame((()=>{e.style[n]=s}))}),t)}observeDOMChanges(){new MutationObserver((e=>{for(const t of e)"childList"===t.type&&t.addedNodes.length>0&&this.attachWireFunctionEvents()})).observe(document.body,{childList:!0,subtree:!0})}async fetchFunction(e,t={},n=!1){try{const s={callback:e,...t},i=window.location.href;let o;if(Object.keys(s).some((e=>{const t=s[e];return t instanceof File||t instanceof FileList&&t.length>0}))){const e=new FormData;Object.keys(s).forEach((t=>{const n=s[t];n instanceof File?e.append(t,n):n instanceof FileList?Array.from(n).forEach((n=>e.append(t,n))):e.append(t,n)})),o={method:"POST",headers:{HTTP_PPHP_WIRE_REQUEST:"true"},body:e}}else o=this.createFetchOptions(s);const a=await this.fetch(i,o,n);if(!a.ok)throw new Error(`Fetch failed with status: ${a.status} ${a.statusText}`);const r=await a.text();try{return JSON.parse(r)}catch{return r}}catch(e){throw new Error("Failed to fetch data.")}}async sync(...e){try{const t=this.saveScrollPositions();this.saveState();const n=e.length>0?e.map((e=>`pp-sync="${e}"`)):['pp-sync="true"'],s=this.createFetchOptions({secondRequestC69CD:!0,...this.getUrlParams()}),i=await this.fetch(window.location.href,s),o=await i.text(),a=(new DOMParser).parseFromString(o,"text/html");n.forEach((e=>{const t=document.querySelectorAll(`[${e}]`),n=a.body.querySelectorAll(`[${e}]`);t.forEach(((e,t)=>{const s=n[t];s&&(e.innerHTML=s.innerHTML,this.reRunScripts(e),document.dispatchEvent(new Event("PPBodyLoaded")))}))})),this.restoreState(),this.restoreScrollPositions(t),document.removeAllEventListeners("PPBodyLoaded"),document.dispatchEvent(new Event("PPBodyLoaded"))}catch(e){}}async fetchAndUpdateBodyContent(){const e=this.createFetchOptions({secondRequestC69CD:!0,...this.getUrlParams()});this.abortActiveRequest();const t=await this.fetch(window.location.href,e,!0),n=await t.text();await this.updateBodyContent(n)}reRunScripts(e){e.querySelectorAll("script").forEach((e=>{const t=document.createElement("script");Array.from(e.attributes).forEach((e=>{t.setAttribute(e.name,e.value)})),e.hasAttribute("src")||(t.textContent=e.textContent),e.parentNode?.replaceChild(t,e)}))}copyCode(e,t,n,s,i="img",o=2e3){if(!(e instanceof HTMLElement))return;const a=e.closest(`.${t}`)?.querySelector("pre code"),r=a?.textContent?.trim()||"";r?navigator.clipboard.writeText(r).then((()=>{const t=e.querySelector(i);if(t)for(const[e,n]of Object.entries(s))e in t?t[e]=n:t.setAttribute(e,n);setTimeout((()=>{if(t)for(const[e,s]of Object.entries(n))e in t?t[e]=s:t.setAttribute(e,s)}),o)}),(()=>{alert("Failed to copy command to clipboard")})):alert("Failed to find the code block to copy")}getCookie(e){return document.cookie.split("; ").find((t=>t.startsWith(e+"=")))?.split("=")[1]||null}}class PPHPLocalStore{static instance=null;state;listeners;pphp;STORAGE_KEY;constructor(e={}){this.state=e,this.listeners=[],this.pphp=PPHP.instance,this.STORAGE_KEY=this.pphp.getCookie("pphp_local_store_key")||"pphp_local_store_59e13",this.loadState()}static getInstance(e={}){return PPHPLocalStore.instance||(PPHPLocalStore.instance=new PPHPLocalStore(e)),PPHPLocalStore.instance}setState(e,t=!1){if(this.state={...this.state,...e},this.listeners.forEach((e=>e(this.state))),this.saveState(),t){const e=localStorage.getItem(this.STORAGE_KEY);e&&this.pphp.fetchFunction(this.STORAGE_KEY,{[this.STORAGE_KEY]:e})}}saveState(){localStorage.setItem(this.STORAGE_KEY,JSON.stringify(this.state))}loadState(){const e=localStorage.getItem(this.STORAGE_KEY);e&&(this.state=this.pphp.parseJson(e),this.listeners.forEach((e=>e(this.state))))}resetState(e,t=!1){if(e?(delete this.state[e],this.saveState()):(this.state={},localStorage.removeItem(this.STORAGE_KEY)),this.listeners.forEach((e=>e(this.state))),t){const t=e?localStorage.getItem(this.STORAGE_KEY):null;this.pphp.fetchFunction(this.STORAGE_KEY,{[this.STORAGE_KEY]:t})}}}
2
2
  // Initialize the PPHP instance
3
3
  document.addEventListener("PPBodyLoaded", () => {
4
4
  PPHP.instance.attachWireFunctionEvents();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-prisma-php-app",
3
- "version": "2.1.2",
3
+ "version": "2.1.4",
4
4
  "description": "Prisma-PHP: A Revolutionary Library Bridging PHP with Prisma ORM",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",